summaryrefslogtreecommitdiff
path: root/bupper/_ssh_client.py
diff options
context:
space:
mode:
Diffstat (limited to 'bupper/_ssh_client.py')
-rw-r--r--bupper/_ssh_client.py45
1 files changed, 45 insertions, 0 deletions
diff --git a/bupper/_ssh_client.py b/bupper/_ssh_client.py
new file mode 100644
index 0000000..f1c9e23
--- /dev/null
+++ b/bupper/_ssh_client.py
@@ -0,0 +1,45 @@
+import paramiko.client as pmc
+
+from ._sshfp_policy import SSHFPPolicy
+
+class SSHConnection:
+ """
+ An SSH client connection to a remote server, with support for a proxy "jump"
+ host, like OpenSSH's 'ssh -J'. Uses only SSHFP for host key verification.
+
+ May be used as a context manager.
+
+ :param SSHRemote remote: Remote host to connect to.
+ """
+ _proxy_conn = None
+ _client = None
+
+ def __init__(self, remote):
+ sock = None
+ if remote.proxy_remote is not None:
+ self._proxy_conn = SSHConnection(remote.proxy_remote)
+ t = self._proxy_conn.get_transport()
+ sock = t.open_channel('direct-tcpip', (remote.host, remote.port), ('localhost', 0))
+
+ self._client = pmc.SSHClient()
+ self._client.set_missing_host_key_policy(SSHFPPolicy())
+ self._client.connect(remote.host, remote.port, remote.username,
+ sock = sock)
+
+ def close(self):
+ if self._client:
+ self._client.close()
+ self._client = None
+ if self._proxy_conn:
+ self._proxy_conn.close()
+ self._proxy_conn = None
+
+ def exec_command(self, *args, **kwargs):
+ return self._client.exec_command(*args, **kwargs)
+ def get_transport(self):
+ return self._client.get_transport()
+
+ def __enter__(self):
+ return self
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.close()