Jump to: navigation, search

Difference between revisions of "Satori/SSHModuleProposal"

m
Line 1: Line 1:
 
== SSH Module Proposal ==
 
== SSH Module Proposal ==
  
<big>As an initial platform to enable [[Satori/glossary|data plane discovery]], implement an SSH module using [https://github.com/paramiko/paramiko paramiko] by extending its [http://www.lag.net/paramiko/docs/paramiko.SSHClient-class.html SSHClient class]. </big>
+
<big>Implement an SSH wrapper module to enable logging on to servers so we can do [[Satori/glossary|data plane discovery]]</big>
  
  
 
==== Desired Interface ====
 
==== Desired Interface ====
  >>> from satori.common.ssh import SSH
+
  >>> from satori import ssh
  >>> client = SSH(host="123.456.789.11", host_password="pa$$word", host_username="Tobias")
+
>>> creds = {"username": "Tobias", "password": "pa$$word"}
 +
  >>> client = ssh.connect("123.456.789.11", credentials=creds) # see signature in implementation section
 
  >>> output = client.remote_execute("sudo echo hello", with_exit_code=True)
 
  >>> output = client.remote_execute("sudo echo hello", with_exit_code=True)
 
  >>> print output
 
  >>> print output
Line 13: Line 14:
  
 
==== Requirements ====
 
==== Requirements ====
 +
 +
Support the following login methods:
 +
** password/username
 +
** private key/username
 +
** private key file/username
 +
** for all the above methods, the module should support using a proxy (i.e. bastion)
 +
 +
 +
Note: basically, support the options as would commonly be used through the ssh command-line.
 +
 +
 +
The main functions needed are:
 +
 +
* remote_execute: to execute a remote command and return stderr and stdout
 +
* test_connection: to test that a connection can be made
 +
 +
Additionally:
 +
* Implement an instance property,  <code>platform_info</code>, that will return the remote host's platform info using (python >=2.4)'s [http://docs.python.org/2/library/platform.html platform module]
 +
 +
 +
==== Implementation ====
 +
* Use [https://github.com/paramiko/paramiko paramiko] and extend its [http://www.lag.net/paramiko/docs/paramiko.SSHClient-class.html SSHClient class]. Wrap paramiko to make it simpler to use and understand the code from other parts of satori.
 
* Accept a password string, private key string, or path to private key file for auth. Paramiko will automatically check in the standard places for ssh keys if nothing else is provided.
 
* Accept a password string, private key string, or path to private key file for auth. Paramiko will automatically check in the standard places for ssh keys if nothing else is provided.
 
* Manage authentication mechanisms, retry authenticating, and prefer SSH keys.
 
* Manage authentication mechanisms, retry authenticating, and prefer SSH keys.
Line 22: Line 45:
 
* Support ssh proxy connections<ref name="sshproxy_connections"/>, and create an implementation that provides the same behavior whether connecting through a proxy or connecting to the remote host directly.
 
* Support ssh proxy connections<ref name="sshproxy_connections"/>, and create an implementation that provides the same behavior whether connecting through a proxy or connecting to the remote host directly.
 
* Implement an instance property,  <code>platform_info</code>, that will return the remote host's platform info using (python >=2.4)'s [http://docs.python.org/2/library/platform.html platform module]
 
* Implement an instance property,  <code>platform_info</code>, that will return the remote host's platform info using (python >=2.4)'s [http://docs.python.org/2/library/platform.html platform module]
** Remote system requires python>=2.4
+
 
** architecture, distro, version
+
For the platform requirements:
** e.g. Ubuntu 12.04 x86_64 would return
+
* Remote system requires python>=2.4
*** <code>{'arch': 'x86_64', 'dist': 'ubuntu', 'version': '12.04'}</code>
+
* architecture, distro, version
 +
* e.g. Ubuntu 12.04 x86_64 would return
 +
** <code>{'arch': 'x86_64', 'dist': 'ubuntu', 'version': '12.04'}</code>
 +
 
 +
 
 +
  # function signature
 +
  def connect(host, credentials, port=22, timeout=None, proxy=None):
 +
      """Connect to remote host over SSH and return a client connection.
 +
     
 +
      credentials can have:
 +
          username (required)
 +
          password
 +
          private_key
 +
          private_key_file
 +
      proxy can have:
 +
          host (required if proxy supplied)
 +
          username (required if proxy supplied)
 +
          port
 +
          timeout
 +
          password
 +
          private_key
 +
          private_key_file
 +
      """
  
 
<ref name="get_pty"> [https://github.com/paramiko/paramiko/blob/master/paramiko/channel.py#L122-L155 paramiko.channel.Channel.get_pty] See <tt>get_pty()</tt>.</ref>
 
<ref name="get_pty"> [https://github.com/paramiko/paramiko/blob/master/paramiko/channel.py#L122-L155 paramiko.channel.Channel.get_pty] See <tt>get_pty()</tt>.</ref>
 
<ref name="sshproxy_connections"> [https://github.com/paramiko/paramiko/blob/master/paramiko/client.py#L210-L212 paramiko.client.SSHClient.connect] See <tt>sock</tt> keyword argument.</ref>
 
<ref name="sshproxy_connections"> [https://github.com/paramiko/paramiko/blob/master/paramiko/client.py#L210-L212 paramiko.client.SSHClient.connect] See <tt>sock</tt> keyword argument.</ref>
 
<references />
 
<references />

Revision as of 19:58, 7 March 2014

SSH Module Proposal

Implement an SSH wrapper module to enable logging on to servers so we can do data plane discovery


Desired Interface

>>> from satori import ssh
>>> creds = {"username": "Tobias", "password": "pa$$word"}
>>> client = ssh.connect("123.456.789.11", credentials=creds)  # see signature in implementation section
>>> output = client.remote_execute("sudo echo hello", with_exit_code=True)
>>> print output
{'stdout': 'hello', 'stderr': '', 'exit_code': 0}


Requirements

Support the following login methods:

    • password/username
    • private key/username
    • private key file/username
    • for all the above methods, the module should support using a proxy (i.e. bastion)


Note: basically, support the options as would commonly be used through the ssh command-line.


The main functions needed are:

  • remote_execute: to execute a remote command and return stderr and stdout
  • test_connection: to test that a connection can be made

Additionally:

  • Implement an instance property, platform_info, that will return the remote host's platform info using (python >=2.4)'s platform module


Implementation

  • Use paramiko and extend its SSHClient class. Wrap paramiko to make it simpler to use and understand the code from other parts of satori.
  • Accept a password string, private key string, or path to private key file for auth. Paramiko will automatically check in the standard places for ssh keys if nothing else is provided.
  • Manage authentication mechanisms, retry authenticating, and prefer SSH keys.
    • Implement/override a connect() method to do this.
  • Provide a method, test_connection(), for doing just that.
  • Manage connecting and disconnecting when remote_execute() is called. (Lazy load the auth object)
  • Attempt to handle password prompts for non-passwordless sudoers
  • Attempt to handle hiccups with pty/tty rules by retrying the command with a pty channel[1] if the system responds with "sudo requires a tty" or similar
  • Support ssh proxy connections[2], and create an implementation that provides the same behavior whether connecting through a proxy or connecting to the remote host directly.
  • Implement an instance property, platform_info, that will return the remote host's platform info using (python >=2.4)'s platform module

For the platform requirements:

  • Remote system requires python>=2.4
  • architecture, distro, version
  • e.g. Ubuntu 12.04 x86_64 would return
    • {'arch': 'x86_64', 'dist': 'ubuntu', 'version': '12.04'}


 # function signature
 def connect(host, credentials, port=22, timeout=None, proxy=None):
     """Connect to remote host over SSH and return a client connection.
     
     credentials can have:
         username (required)
         password
         private_key
         private_key_file
     proxy can have:
         host (required if proxy supplied)
         username (required if proxy supplied)
         port
         timeout
         password
         private_key
         private_key_file
     """

[1] [2]

  1. 1.0 1.1 paramiko.channel.Channel.get_pty See get_pty().
  2. 2.0 2.1 paramiko.client.SSHClient.connect See sock keyword argument.