Quantcast
Viewing latest article 21
Browse Latest Browse All 29

Python script to run remote SSH commands with sudo permission

I created a Python script to run remote SSH command with sudo permission. Linux SSH command doesn’t support password as command option, you have to use expect script to connect to multiple servers for automation. plink tool in Windows support password as command option.
The trick to accept sudo password is ‘-S’ option in sudo, which accept sudo password piped from stdin.It seems to be safe, I turned on debug and I couldn’t see the password recorded in secure/messages logs.
There are two versions of the script: the command line one and the class/module one.

The command line version.

if the clear text password is an concern, you can wrap the script by getpasswd module in Python,which read password from stdin.Read password once and apply the password to multiple servers.
[root@~]# ./pyssh.py  -s server1 -u admin -p Passwd123 date
Thu Oct 30 15:36:27 EST 2014

#'service sshd status' command ran successfully with sudo enabled '-t'
[root@~]# ./pyssh.py -t -s server1 -u admin -p Passwd123 'service sshd status'
openssh-daemon (pid 15686) is running...

#!/usr/bin/env python
import sys
import paramiko
import argparse
import socket
parser = argparse.ArgumentParser()
parser.add_argument("-s", "--servername", help="hostname or IP", required=True)
parser.add_argument("-P", "--port", help="ssh port default=22", default=22)
parser.add_argument("-t", "--sudo", help="enable sudo,sudo password will use the value of --password",action='store_true')
parser.add_argument("-u","--username",help="username",required=True)
parser.add_argument("-p","--password",help="password",required=True)
parser.add_argument("cmd",help="command to run")
args=parser.parse_args()

host = args.servername
port = args.port
user = args.username
password = args.password
cmd = args.cmd
if args.sudo:
fullcmd="echo " + password + " | sudo -S -p ''" + cmd
else:
fullcmd=cmd

#if __name__ == "__main__":
client = paramiko.SSHClient()
#Don't use host key auto add policy for production servers
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.load_system_host_keys()
try:
client.connect(host,port,user,password)
transport=client.get_transport()
except (socket.error,paramiko.AuthenticationException) as message:
print "ERROR: SSH connection to "+host+" failed: " +str(message)
sys.exit(1)
session=transport.open_session()
session.set_combine_stderr(True)
if args.sudo:
session.get_pty()
session.exec_command(fullcmd)
stdout = session.makefile('rb', -1)
print stdout.read()
transport.close()
client.close() 

The  class version

The class version allow multiple commands to run in an existing SSH transport,which is more efficient.To use the class,copy pyssh.sh to a folder and create a new script to import the class 'from pyssh import PySSH',then reference the code in MAIN section without if statement.
#!/usr/bin/env python
import sys
import socket
import paramiko
#=================================
# Class: PySSH
#=================================
class PySSH(object):


def __init__ (self):
self.ssh = None
self.transport = None

def disconnect (self):
if self.transport is not None:
self.transport.close()
if self.ssh is not None:
self.ssh.close()

def connect(self,hostname,username,password,port=22):
self.hostname = hostname
self.username = username
self.password = password

self.ssh = paramiko.SSHClient()
#Don't use host key auto add policy for production servers
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh.load_system_host_keys()
try:
self.ssh.connect(hostname,port,username,password)
self.transport=self.ssh.get_transport()
except (socket.error,paramiko.AuthenticationException) as message:
print "ERROR: SSH connection to "+self.hostname+" failed: " +str(message)
sys.exit(1)
return self.transport is not None

def runcmd(self,cmd,sudoenabled=False):
if sudoenabled:
fullcmd="echo " + self.password + " | sudo -S -p ''" + cmd
else:
fullcmd=cmd
if self.transport is None:
return "ERROR: connection was not established"
session=self.transport.open_session()
session.set_combine_stderr(True)
#print "fullcmd ==== "+fullcmd
if sudoenabled:
session.get_pty()
session.exec_command(fullcmd)
stdout = session.makefile('rb', -1)
#print stdout.read()
output=stdout.read()
session.close()
return output

#===========================================
# MAIN
#===========================================
if __name__ == '__main__':
hostname = 'server1'
username = 'admin'
password = 'password123'
ssh = PySSH()
ssh.connect(hostname,username,password)
output=ssh.runcmd('date')
print output
output=ssh.runcmd('service sshd status',True)
print output
ssh.disconnect()



Viewing latest article 21
Browse Latest Browse All 29

Trending Articles