diff options
author | Sander Vrijders <sander.vrijders@ugent.be> | 2017-10-24 18:08:44 +0200 |
---|---|---|
committer | Sander Vrijders <sander.vrijders@ugent.be> | 2017-10-24 18:08:44 +0200 |
commit | d91a601494ba14172b6c239aa6c28e6256c62ca7 (patch) | |
tree | 2d14bc314dc10ea4e0b865305187357f0e0fefd4 | |
parent | c09a71b756ab3208ac02a006f9a4d54792b803b5 (diff) | |
download | rumba-d91a601494ba14172b6c239aa6c28e6256c62ca7.tar.gz rumba-d91a601494ba14172b6c239aa6c28e6256c62ca7.zip |
ssh_support: Use native Paramiko API for Proxy
This uses the native paramiko API for proxycommands instead of
invoking OpenSSH on the host after connecting to it since that gives
race conditons with Paramiko.
-rw-r--r-- | rumba/model.py | 6 | ||||
-rw-r--r-- | rumba/ssh_support.py | 57 | ||||
-rw-r--r-- | rumba/testbeds/jfed.py | 6 |
3 files changed, 31 insertions, 38 deletions
diff --git a/rumba/model.py b/rumba/model.py index 62125a6..7d7e214 100644 --- a/rumba/model.py +++ b/rumba/model.py @@ -192,12 +192,12 @@ class NormalDIF(DIF): # SSH Configuration # class SSHConfig: - def __init__(self, hostname, port=22, proxy_command=None): + def __init__(self, hostname, port=22, proxy_server=None): self.username = None self.password = None self.hostname = hostname self.port = port - self.proxy_command = proxy_command + self.proxy_server = proxy_server def set_username(self, username): self.username = username @@ -778,7 +778,7 @@ class Experiment: self.testbed.username, node.ssh_config.hostname, node.ssh_config.port, - node.ssh_config.proxy_command)) + node.ssh_config.proxy_server)) f.close() # Examine the nodes and DIFs, compute the registration and enrollment diff --git a/rumba/ssh_support.py b/rumba/ssh_support.py index 8ceee55..eff837d 100644 --- a/rumba/ssh_support.py +++ b/rumba/ssh_support.py @@ -57,16 +57,30 @@ def _print_stream(stream): logger.debug(oi) return o.rstrip() -def ssh_connect(ssh_client, hostname, port, username, password, time_out, - proxy): +def ssh_connect(hostname, port, username, password, time_out, proxy_server): retry = 0 max_retries = 10 while retry < max_retries: time.sleep(retry * 5) + try: + if proxy_server is not None: + proxy_client = get_ssh_client() + # Assume port 22 for the proxy server for now + proxy_client.connect(proxy_server, 22, username, password, + look_for_keys=True, timeout=time_out) + + trans = proxy_client.get_transport() + proxy = trans.open_channel('direct-tcpip', + (hostname, port), ('127.0.0.1', 0)) + else: + proxy = None + + ssh_client = get_ssh_client() + ssh_client.connect(hostname, port, username, password, look_for_keys=True, timeout=time_out, sock=proxy) - return + return ssh_client except (paramiko.ssh_exception.SSHException, EOFError): retry += 1 logger.error('Failed to connect to host, retrying: ' + @@ -76,7 +90,7 @@ def ssh_connect(ssh_client, hostname, port, username, password, time_out, logger.error(hostname + ' has a mismatching entry in ' + '~/.ssh/known_hosts') logger.error('If you are sure this is not a man in the ' + - 'middle attack, edit that file to remove the' + + 'middle attack, edit that file to remove the ' + 'entry and then hit return to try again.') input('Hit Enter when ready') if retry == max_retries: @@ -139,15 +153,10 @@ def execute_commands(testbed, ssh_config, commands, time_out=3): no result received in given number of seconds, the value None can be used when no timeout is needed """ - if ssh_config.proxy_command is not None: - proxy = paramiko.ProxyCommand(ssh_config.proxy_command) - else: - proxy = None - - ssh_client = get_ssh_client() - ssh_connect(ssh_client, ssh_config.hostname, ssh_config.port, - testbed.username, testbed.password, time_out, proxy) + ssh_client = ssh_connect(ssh_config.hostname, ssh_config.port, + testbed.username, testbed.password, time_out, + ssh_config.proxy_server) o = "" for command in commands: @@ -200,15 +209,10 @@ def write_text_to_file(testbed, ssh_config, text, file_name): @param text: string to be written in file @param file_name: file name (including full path) on the host """ - ssh_client = get_ssh_client() - if ssh_config.proxy_command is not None: - proxy = paramiko.ProxyCommand(ssh_config.proxy_command) - else: - proxy = None - - ssh_connect(ssh_client, ssh_config.hostname, ssh_config.port, - testbed.username, testbed.password, None, proxy) + ssh_client = ssh_connect(ssh_config.hostname, ssh_config.port, + testbed.username, testbed.password, None, + ssh_config.proxy_server) cmd = "touch " + file_name + "; chmod a+rwx " + file_name @@ -238,19 +242,12 @@ def copy_files_to_testbed(testbed, ssh_config, paths, destination): @param paths: source paths (local) as an iterable @param destination: destination folder name (remote) """ - ssh_client = get_ssh_client() - - if ssh_config.proxy_command is not None: - proxy = paramiko.ProxyCommand(ssh_config.proxy_command) - else: - proxy = None - if destination is not '' and not destination.endswith('/'): destination = destination + '/' - - ssh_connect(ssh_client, ssh_config.hostname, ssh_config.port, - testbed.username, testbed.password, None, proxy) + ssh_client = ssh_connect(ssh_config.hostname, ssh_config.port, + testbed.username, testbed.password, None, + ssh_config.proxy_server) try: sftp_client = ssh_client.open_sftp() diff --git a/rumba/testbeds/jfed.py b/rumba/testbeds/jfed.py index 7182143..3235ca2 100644 --- a/rumba/testbeds/jfed.py +++ b/rumba/testbeds/jfed.py @@ -206,11 +206,7 @@ class Testbed(mod.Testbed): node.ssh_config.hostname = \ node.name + "." + self.exp_name + "." + \ auth_name_r + "." + self.auth_name - node.ssh_config.proxy_command = "ssh -i '" + self.cert_file + \ - "' -o StrictHostKeyChecking=no " + \ - self.username + \ - "@bastion.test.iminds.be nc " + \ - node.ssh_config.hostname + " 22" + node.ssh_config.proxy_server = "bastion.test.iminds.be" node.ssh_config.username = self.username node.ssh_config.password = self.password |