This question already has an answer here:
-
SSH to remote server using ansible
1 answer
I'm fairly certain I've seen a feature in the ansible documentation where you can tell it that to connect to certain hosts it first needs to tunnel through a DMZ host. I can't however seem to find any documentation outside of some debates on the mailing lists.
I'm aware of hacking this in with an ssh config like on this page http://alexbilbie.com/2014/07/using-ansible-with-a-bastion-host/ however that's an overcomplicated kludge for an extremely common requirement in any kind of mildly regulated environment.
Is there a way to do this without using custom ssh config includes and voodoo netcat sorcery?
With Ansible 2, this is a built-in option:
How do I configure a jump host to access servers that I have no direct access to?
With Ansible 2, you can set a ProxyCommand in the ansible_ssh_common_args inventory variable. Any arguments specified in this variable are added to the sftp/scp/ssh command line when connecting to the relevant host(s). Consider the following inventory group:
[gatewayed]
foo ansible_host=192.0.2.1
bar ansible_host=192.0.2.2
You can create group_vars/gatewayed.yml with the following contents:
ansible_ssh_common_args: '-o ProxyCommand="ssh -W %h:%p -q user@gateway.example.com"'
Ansible will append these arguments to the command line when trying to connect to any hosts in the group gatewayed. (These arguments are used in addition to any ssh_args from ansible.cfg, so you do not need to repeat global ControlPersist settings in ansible_ssh_common_args.)
Note that ssh -W is available only with OpenSSH 5.4 or later. With older versions, it’s necessary to execute nc %h:%p or some equivalent command on the bastion host.
If your jump box needs a private key file to connect (even if it's the same key as the one used for the private subnet instances), use this instead:
ansible_ssh_common_args: '-o ProxyCommand="ssh -i <path-to-pem-file> -W %h:%p -q user@gateway.example.com"'
I spent hours trying to fix a problem that now seems like a simple and obvious solution.
As Ansible uses SSH, you can specify a bastion host in the standard SSH config way:
e.g. to connect through a bastion host for all servers that have a name like "*.amazonaws.com":
Host *.amazonaws.com
ProxyCommand ssh -W %h:%p my_bastion_host.example.org
When ansible
or ansible-playbook
runs, it will read in your SSH configuration file and apply it for connections. You can also specify which SSH configuration file is read by using the ANSIBLE_SSH_ARGS
environmental variable or by using the -F
flag when calling the command.
You are also able to specify more SSH arguments in the ansible.cfg.