Recipe15.10.Performing Remote Logins with SSH


Recipe 15.10. Performing Remote Logins with SSH

Credit: Peter Cogolo, Anna Martelli Ravenscroft

Problem

You need to send commands, using the SSH protocol, to one or more logins that can be on a local machine or a remote machine.

Solution

SSH is a secure replacement for the old Telnet protocol. One way to use SSH from a Python program is with the third-party paramiko package:

# auto_ssh.py - remote control via ssh import os, sys, paramiko from getpass import getpass paramiko.util.log_to_file('auto_ssh.log', 0) def parse_user(user, default_host, default_port):     ''' given name[@host[:port]], returns name, host, int(port),         applying defaults for hose and/or port if necessary     '''     if '@' not in user:         return user, default_host, default_port     user, host = user.split('@', 1)     if ':' in host:         host, port = host.split(':', 1)     else:         port = default_port     return user, host, int(port) def autoSsh(users, cmds, host='localhost', port=22, timeout=5.0,             maxsize=2000, passwords=None):     ''' run commands for given users, w/default host, port, and timeout,         emitting to standard output all given commands and their         responses (no more than 'maxsize' characters of each response).     '''     if passwords is None:         passwords = {  }     for user in users:         if user not in passwords:             passwords[user] = getpass("Enter user '%s' password: " % user)     for user in users:         user, host, port = parse_user(user, default_host, default_port)         try:             transport = paramiko.Transport((host, port))             transport.connect(username=user, password=passwords[user])             channel = transport.open_session( )             if timeout: channel.settimeout(timeout)             for cmd in cmd_list:                 channel.exec_command(cmd)                 response = channel.recv(max_size)                 print 'CMD %r(%r) -> %s' % (cmd, user, response)         except Exception, err:             print "ERR: unable to process %r: %s" % (user, err) if _ _name_ _ == '_ _main_ _':     logname = os.environ.get("LOGNAME", os.environ.get("USERNAME"))     host = 'localhost'     port = 22     usage = """ usage: %s [-h host] [-p port] [-f cmdfile] [-c "command"] user1 user2 ...     -c  command     -f  command file     -h  default host  (default: localhost)     -p  default host  (default: 22) Example:  %s -c "echo $HOME" %s same as:  %s -c "echo $HOME" %s@localhost:22 """ % (sys.argv[0], sys.argv[0], logname, sys.argv[0], logname)     import getopt     optlist, user_list = getopt.getopt(sys.argv[1:], 'c:f:h:p:')     if not user_list:         print usage         sys.exit(1)     cmd_list = [  ]     for opt, optarg in optlist:         if opt == '-f':             for r in open(optarg, 'rU'):                 if r.rstrip( ):                     cmd_list.append(r)         elif opt == '-c':             command = optarg             if command[0] == '"' and command[-1] == '"':                 command = command[1:-1]             cmd_list.append(command)         elif opt == '-h':             host = optarg         elif opt == '-p':             port = optarg         else:             print 'unknown option %r' % opt             print usage             sys.exit(1)     autoSsh(user_list, cmd_list, host=host, port=port)

Discussion

The third-party extension paramiko package lets you easily automate access to all sorts of SSH services, even from non-Unix machines. paramiko even lets you write your own SSH servers in Python. In this recipe, however, we use paramiko on the client side, as a more secure alternative to the similar use of telnetlib shown previously in Recipe 15.9.

Production code generally has to be made more robust, but this recipe should be enough to get you started in the right direction. The recipe's autoSsh function first ensures it knows passwords for all the users (asking interactively for the passwords of users it doesn't know about). Then, it loops over all the users, parsing strings such as foo@bar:2222 to mean user foo at host bar, port 2222, and defaulting the host and port values, if necessary.

The loop body relies on two types of objects supplied by paramiko, transport and Channel. The transport is constructed by giving it the (host, port) pair and then a connection is made with a username and password. (Alternatively, depending on the SSH server, one might connect using a private key, but this recipe uses just a password.) The channel is obtained from the transport, and the recipe then sets a timeout (by default, 6 seconds) to ensure that no long-term hanging occurs in case of problems with an SSH server or the network path to it. Finally, an inner loop over all commands sends each command, receives a response (up to a maximum length in bytes, 2000 by default), and prints the command and response.

SSH, the Secure Shell

The SSH protocol is secure, powerful, and flexible. No password ever travels on the network in the clear, and the connection stream itself gets encrypted. Besides single commands (as used in this recipe) and entire interactive shell sessions, SSH allows secure copying of files in either direction and secure remote tunneling of X11 GUI sessions and other TCP/IP-based network protocols. Moreover, unlike other secure transport-level protocols such as SSL/TLS, SSH does not require certificates signed by some kind of "central authority". You can learn more about SSH from the OpenSSH's web page at http://www.openssh.com/, Steve Allen's pages at http://www.ucolick.org/~sla/ssh/, and Kimmon Suominen's tutorial at http://kimmo.suominen.com/docs/ssh/as well as from Richard Silverman and Daniel J. Barrett, SSH: The Secure Shell, The Definitive Guide (O'Reilly).


See Also

paramiko's home page at http://www.lag.net/~robey/paramiko/; paramiko requires another third-party extension to Python, the Python Cryptography Toolkit, whose home page is at http://www.amk.ca/python/code/crypto; docs on SSH at http://www.openssh.com/, http://www.ucolick.org/~sla/ssh/, http://kimmo.suominen.com/docs/ssh/; Richard Silverman and Daniel J. Barrett, SSH: The Secure Shell, The Definitive Guide (O'Reilly); Recipe 15.9.



Python Cookbook
Python Cookbook
ISBN: 0596007973
EAN: 2147483647
Year: 2004
Pages: 420

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net