Ansible ssh key connection
Refer to https://nicodevlog.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