Ansible ssh key connection
Refer to https://codetodevops.com/2022/05/21/public-key-authentication-on-linux-best-practices-a-more-secure-way-to-connect-to-your-hosts-without-login-and-password/
The advantages of an ssh key over a basic authentication are:
- no raw password (but you can encrypt passwords using ansible vault)
- one unique private key to connect to several nodes (but of course if somebody steal your private key… that’s the reason why you must use a pass phrase to encrypt your private key)
Ansible ssh key through bastion (ProxyJump / Jump host)
The best practice since OpenSSH 7.3 (appearance of the -J option)

When you have some nodes that are behind a bastion, you have to define only once this bastion and not several times in your inventory. Because if the characteristics of the bastion change, you’ll have to change your inventory at multiple places (and then multiple risks of manual errors when modifying these characteristics).
Then the best way is to define the bastion in the ~/.ssh/config file, for example:
# ~/.ssh/config
#
Host *
#Port 22 => don't specify the port here, because it's the first match that overwrite all the others
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
ServerAliveInterval 60
ServerAliveCountMax 30
# Define your bastion
Host bastion
Port 2222
Hostname hostname.ofyourbastion.com
User ansibleuser
IdentityFile ~/.ssh/mykey
# Define which nodes go through the bastion here not in your inventory
Host host-nodeA
Hostname 192.168.100.30
ProxyJump bastion:2222
Host host-nodeB
Hostname 192.168.100.31
ProxyJump bastion:2222
Host host-nodeC
Hostname 192.168.100.33
ProxyJump bastion:2222
Now you can ssh to your bastion in the CLI like this:
ssh bastion
# ssh to the nodes behind the bastion:
# (note: it will ask for the user password because you don't specify an ssh key in the following lines
ssh someuser@host-nodeA
ssh someuser@host-nodeB
ssh someuser@host-nodeC
In your ansible inventory you’ll have this:
nodeA ansible_host=host-nodeA ansible_connection=ssh ansible_user=someuser ansible_ssh_private_key_file=~/.ssh/mykey
nodeB ansible_host=host-nodeA ansible_connection=ssh ansible_user=someuser ansible_ssh_private_key_file=~/.ssh/mykey
nodeC ansible_host=host-nodeA ansible_connection=ssh ansible_user=someuser ansible_ssh_private_key_file=~/.ssh/mykey
Or you can extract the node part from ~/.ssh/config and add it into the inventory like this. Then you have this ~/.ssh/config file:
# ~/.ssh/config
#
Host *
#Port 22 => don't specify the port here, because it's the first match that overwrite all the others
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
ServerAliveInterval 60
ServerAliveCountMax 30
# Define your bastion
Host bastion
Port 2222
Hostname hostname.ofyourbastion.com
User ansibleuser
IdentityFile ~/.ssh/mykey
[group1:vars]
ansible_ssh_common_args='-J bastion'
[group1]
nodeA ansible_host=192.168.100.30 ansible_connection=ssh ansible_user=someuser ansible_ssh_private_key_file=~/.ssh/mykey
nodeB ansible_host=192.168.100.31 ansible_connection=ssh ansible_user=someuser ansible_ssh_private_key_file=~/.ssh/mykey
nodeC ansible_host=192.168.100.32 ansible_connection=ssh ansible_user=someuser ansible_ssh_private_key_file=~/.ssh/mykey
As you can see you loose the advantage of naming your IP.
Copy you public key to your target host through the bastion
It is as simple as explained in this post.
For instance here (no risk to copy private key, ssh-copy-id prevent this):
ssh-copy-id -i ~/.ssh/mykey someuser@nodeC
Leave a Reply