Ansible with dedicated SSH Keys
- 4 minutes read - 826 wordsIf you use Ansible to manage servers, you should probably use ssh keys to do so. Ssh keys are a way of authenticating to a server, like passwords are. Ssh keys can be protected with passwords or they can be passwordless. If you’re using them for automation, you might need to use passwordless ssh keys, but otherwise, it’s a good practice to protect the keys as well.
You can create a key, or really a ssh key pair with the command
ssh-keygen -f <keyfile>
Key files are usually stored in ~/.ssh
and their names tend to start with
id_
, so the command above could be ssh-keygen -f ~/.ssh/id_work
for your
work computers. It doesn’t cost to create separate key files for separate
contexts, so go wild and create a key pair for your public git project, your
home servers and whatever you care for. For this article though, don’t go
overboard and create a separate key file for each server just yet… until after
reading the article and you know what you’re doing.
A key consists of two parts; a public file and a private file. Like the name
implies, you can freely distribute the public part but you should keep the
private key files strictly to yourself. The files tend to have the same name (by
convention), except that the public file ends in .pub
.
Now you can distribute (the public half of) your key to the server you want to log in to with
ssh-copy-id -f <keyfile> <servername>
Then edit the file ~/.ssh/config
to list the servers you want your side of the
ssh pipeline to attempt using ssh keys:
Host servername anotherserver *
IdentityFile ~/.ssh/<keyfile>
You can use the *
wildcard where it makes sense. You can also say User <username>
under the Host line if your username on the remote server is
different from the one on your computer.
For a seasoned systems administrator, this should be nothing new. So let’s up the context.
If you value security and/or there are several of you who share the joy of configuring servers, you might want a key for logging in as yourself to servers as a normal part of your work, and a separate key to use for Ansible work. You might even administer servers under a different username than your normal login name. This might be especially true if several of you share the server admin duties (though from a security perspective, it’s even better if you do so using per-admin usernames).
Let’s assume the ansible work is done using the unimaginatively named user
ansible
.
ssh-key -f ~/.ssh/id_ansible
ssh-copy-id ~/.ssh/id_ansible ansible@<servername>
(In a perfect environment where chicken and eggs evolve in parallel, you distribute ssh keys using key management or Ansible itself, and never log in to servers as that ansible user, but that’s for a post somewhere else.)
As a friend of security, you did add passwords to your ssh keys, right? If not, create new ones with passwords. This post will wait.
You now need the ssh-agent
. Ssh-agent will cache the passwords you created
above so that you don’t need to enter them by hand, for example when running
Ansible jobs. Check that it’s running by running ssh-agent
. Then to add
passwords to the agent, use
ssh-add <filename>
If you’re really lazy, just say ssh-add ~/.ssh/*
to add all of your keys.
ssh-agent will prompt for the passwords and remember them until you log out or
power off.
ssh keys and Ansible
Finally, to the beef: using a different ssh key and a different username for
ansible than for regular ssh. You’d think that you can add this configuration to
the ansible.cfg
file, but alas you’d be wrong (don’t worry, i was too, and i
still think both of us should be right). The ssh username and key file
configuration belongs to variables that relate to the servers you connect to.
There are two places you might add these to: the inventory
or your
goup_vars
.
As a well structured admin, you probably have all your inventory in an
inventory/
directory and not a flat file. Create a file there, say
inventory/ssh.config
which says something along the lines of
[all:vars]
ansible_user=ansible
ansible_ssh_private_key_file=~/.ssh/id_ansible
The file inventory/ssh.config
will look, smell and sound like an inventory
file, but in fact, it’s just a variable declaration to all your targets. Of
course, edit as necessary; you might have machines that you don’t use those
usernames and key files to acces. This is but a simplified example.
You can also use your group_vars
files for this. The corresponding
configuration for above would be
# group_vars/all
---
ansible_user: ansible
ansible_ssh_private_key_file: ~/.ssh/id_ansible
The benefit of using *_vars
files is that you can have cascading
configuration, so that you can have a different username for your bone headed
switch which thinks the username must be admin
, or different ssh key files for
some reason or another.
So yeah, that’s what i learned this week. Using dedicated keys for Ansible.