using `ansible` through a bastion host

are you trying to use `ansible` through a bastion host? me too.

we use bastion hosts in order to access servers which are part of a controlled network segment, due to a particular compliance regime.

alex bilbie wrote a good piece about how to get `ansible` working with a bastion host. the only problem with his piece is that it mandates that all hosts in your `ansible` inventory file use that same bastion host.

we have a mix of hosts. some that need to go through the bastion host, some that definitely don’t. i needed a solution that let me do both. here’s one way to do it.

  1. first up, make sure you have `nc` (netcat) installed on your bastion host.
  2. create an `ssh` configuration file which contains:
Host bastion+*
Port 22
ProxyCommand ssh jump "nc $(echo %h | sed 's/^bastion+//g') %p"

this assumes that your bastion host‘s hostname is `jump`.

save this configuration as`/etc/ansible/ssh.config` or something.

this configuration file kicks into action when `ssh` is fed a hostname which starts with `bastion+`. for those particular hostnames, we connect first to the bastion host and then pass straight through to the hostname represented by *.

3. add the following under the `[ssh_connection]` configuration area in `/etc/ansible/ansible.cfg`:

ssh_args = -F /etc/ansible/ssh.config

here, we tell `ansible` that we always want to use a special `ssh` configuration file. the important thing is that the configuration file is benign enough to allow “normal” connections to pass through!

this is also the place to add things such as `-o StrictHostKeyChecking=no` and other miscellaneous options, if that’s your style.

4. populate your `/etc/ansible/hosts` file appropriately

# cat /etc/ansible/hosts
[no_bastion_host]
host1
host2
[via_bastion_host]
host3 ansible_ssh_host="bastion+host3"
host4 ansible_ssh_host="bastion+host4"

5. test it out!

hey, great! we can hit all of our hosts, even those we routed through the bastion host to get to! nice!

my test playbook connects to each server in turn and returns its hostname. the very fact that i can hit `host3` and `host4` means i’ve succeeded. on my network, they live in a seperate network, firewalled off from everything else.

anyways, i hope that this helps somebody out.