diff --git a/docsite/rst/intro_configuration.rst b/docsite/rst/intro_configuration.rst index ccfb456ed9..7f21c2e1f6 100644 --- a/docsite/rst/intro_configuration.rst +++ b/docsite/rst/intro_configuration.rst @@ -739,6 +739,17 @@ instead. Setting it to False will improve performance and is recommended when h record_host_keys=True +.. _paramiko_proxy_command + +proxy_command +============= + +.. versionadded:: 2.1 + +Use an OpenSSH like ProxyCommand for proxying all Paramiko SSH connections through a bastion or jump host. Requires a minimum of Paramiko version 1.9.0. On Enterprise Linux 6 this is provided by ``python-paramiko1.10`` in the EPEL repository:: + + proxy_command = ssh -W "%h:%p" bastion + .. _openssh_settings: OpenSSH Specific Settings diff --git a/lib/ansible/constants.py b/lib/ansible/constants.py index 5df9602246..7d6a76a19e 100644 --- a/lib/ansible/constants.py +++ b/lib/ansible/constants.py @@ -244,6 +244,7 @@ ANSIBLE_SSH_CONTROL_PATH = get_config(p, 'ssh_connection', 'control_path', ANSIBLE_SSH_PIPELINING = get_config(p, 'ssh_connection', 'pipelining', 'ANSIBLE_SSH_PIPELINING', False, boolean=True) ANSIBLE_SSH_RETRIES = get_config(p, 'ssh_connection', 'retries', 'ANSIBLE_SSH_RETRIES', 0, integer=True) PARAMIKO_RECORD_HOST_KEYS = get_config(p, 'paramiko_connection', 'record_host_keys', 'ANSIBLE_PARAMIKO_RECORD_HOST_KEYS', True, boolean=True) +PARAMIKO_PROXY_COMMAND = get_config(p, 'paramiko_connection', 'proxy_command', 'ANSIBLE_PARAMIKO_PROXY_COMMAND', None) # obsolete -- will be formally removed diff --git a/lib/ansible/plugins/connection/paramiko_ssh.py b/lib/ansible/plugins/connection/paramiko_ssh.py index ab9ce90db9..ea6ca3809d 100644 --- a/lib/ansible/plugins/connection/paramiko_ssh.py +++ b/lib/ansible/plugins/connection/paramiko_ssh.py @@ -158,6 +158,24 @@ class Connection(ConnectionBase): pass # file was not found, but not required to function ssh.load_system_host_keys() + sock_kwarg = {} + if C.PARAMIKO_PROXY_COMMAND: + replacers = { + '%h': self._play_context.remote_addr, + '%p': port, + '%r': self._play_context.remote_user + } + proxy_command = C.PARAMIKO_PROXY_COMMAND + for find, replace in replacers.items(): + proxy_command = proxy_command.replace(find, str(replace)) + try: + sock_kwarg = {'sock': paramiko.ProxyCommand(proxy_command)} + display.vvv("CONFIGURE PROXY COMMAND FOR CONNECTION: %s" % proxy_command, host=self._play_context.remote_addr) + except AttributeError: + display.warning('Paramiko ProxyCommand support unavailable. ' + 'Please upgrade to Paramiko 1.9.0 or newer. ' + 'Not using configured ProxyCommand') + ssh.set_missing_host_key_policy(MyAddPolicy(self._new_stdin, self)) allow_agent = True @@ -179,6 +197,7 @@ class Connection(ConnectionBase): password=self._play_context.password, timeout=self._play_context.timeout, port=port, + **sock_kwarg ) except Exception as e: msg = str(e)