Mutiple `ssh` Identities
I was quickly setting up a Google Compute Engine (GCE) on the Google Cloud Platform (GCP), when, out of laziness I copied over my default ssh
public key which I had created many months ago principally to ssh
into a local Raspberry Pi. To make things more convenient for me back then I had opted not to use a passphrase when setting up that particular rsa
key-pair; the logic being that the Pi was never to leave my local network and I had promised myself not to use that encryption key for any other purpose.
While that quickly got me into the GCE, my mind had registered what I had done, and although the risk of a breach was smaller than using a password login method, I still woke up in the middle of that night in cold sweat.
Never create an ssh keypair without a passphrase!
There is really no need to create an ssh
identity with no passphrase: if you want to have the convenience of a connection without having to type in a passphrase all the time, there is an app for that. It’s part of the ssh
suite and is called ssh-agent
.
Once you launch ssh-agent
, it runs as a daemon. Then all you need is to add your ssh
identities to it, giving it your passphrase only once. The daemon will know you entered the right passphrase because the identity was accepted, and until it is killed, will allow passphrase-less ssh
logins.
But first, about multiple identities.
The Many Me’s
I had, for a long time, thought that there was no need to have multiple ssh
identities. After all, if one of the machines you ssh
into is compromised and your public-key is exposed, no damage has been done. That is, after all, why we use public-keys.
Your private keys are safe as long as you leave it where it was created and leave the permissions (600) alone. Even root doesn’t have access to it.
But then I started creating VMs with multiple users. For instance on this blog the VM was created with my Google Account which gave it the first user. I then created another user specifically for the blogging operations, called something like “blogger”. This is good practice if you have public-facing services. So if my account gets hacked, at least only files in that account (in this case “blogger”) would be compromised.
At this point I needed more than one ssh
identity.
I tie my identities to my username rather than machines or machine-username combinations. This way, I can use the same ssh
identity across several machines as long as the usernames are the same.
Generate a new identity using1 :
$ ssh-keygen -t rsa -b 4096 -C "<username>"
The -C
flag is a “comment” flag and is how the user (actually user@host) is transmitted in the public-key. If you use many host machines, it is a good idea to keep the user@host format otherwise a few months down, you’ll be looking at GCP ssh
metadata and wondering which one belongs to which of your many daily-drivers.
ssh-keygen
will ask where you want to save the key-pair. The way I do it is to keep the id_rsa
and add the username after it. Hence for “blogger” it’s id_rsa_blogger
, and I leave all my identities in ~/.ssh/
. Make sure your passphrase is unique for each identity.
Now to ssh
to your VM:
$ ssh -i ~/.ssh/id_rsa_blogger blogger@12.13.15.17
The -i
option is of course how you chose which identity to use. You will be prompted for your passphrase.
To alias or not to alias
If you have to log into more than one server-identity combination, then you will have several variants of the above ssh
command to type. With bash
or zsh
’s history search feature (bck-i-search
) this is not a problem: you can recall the exact command with a few keystrokes.2 You could alias these commands, but there is a better way: you could set up an ssh
config
file to handle each machine-identity pair.
This file sits in ~/.ssh/
and is called, simply, config
. If it does not exist, create it. The entries look like:
Host saturn
Port 22
hostname 12.14.15.12
User bowman
IdentityFile ~/.ssh/id_rsa_bowman
Host blog
hostname 12.13.15.17
User blogger
IdentityFile ~/.ssh/id_rsa_blogger
et cetera. Now all you need is to invoke:
$ ssh blog
to open a connection to the machine, use the specified identity and user to sign in.
Single Sign On?
If you are like me, I don’t mind typing out my long passphrases but would jump at a method that saves me from doing it without compromising security. This is where the ssh-agent
comes in.
The agent is a daemon that runs on your local machine where the ssh
keys reside. It can remember identities that you add to it successfully. Identities are only added successfully if you key in the correct passphrase while adding it. Henceforth, when using that identity, the agent provides the trust element, telling the ssh
server that you are kosher.
First you have to make sure that the agent is running. A simple way is to attempt to list the identities the agent might be holding. If it fails it means that the agent is not running:
% ssh-add -l
Could not open a connection to your authentication agent.
If it is not running, here’s how to start it. Type:
$ ssh-agent
If the agent is not running you will get something like:
SSH_AUTH_SOCK=/tmp/ssh-5FhM8gsgL8Pp/agent.16567; export SSH_AUTH_SOCK;
SSH_AGENT_PID=16567; export SSH_AGENT_PID;
echo Agent pid 16567;
Believe it or not, that long series of expressions is the script that you need to get the daemon running! There are a couple of ways to do this. One way is to copy that output into a file and source
it:
$ ssh-agent > ssh-agent.sh
$ source ssh-agent.sh
Note that the ssh-agent
expressions above are sh
-based shell specific. This is the default when ssh-agent
is used in a sh
-based shell such as bash
. If you used the command in a csh
-like environment, it will adjust to use setenv
instead. This is the same as passing a -c
option to ssh-agent
Or, a much simpler way is to just type the following:
$ eval "$(ssh-agent)"
eval
is a builtin that constructs a command from the arguments presented to it (exactly what we needed to do to the above expression spouted into stdout
from typing ssh-agent
) and executes it.
Once the agent is running, add identities to it simply using:
$ ssh-add ~/.ssh/id_rsa_blogger
The agent will ask for the passphrase. Once added, you have performed your Single Sign On. From now onwards, whenever you use that identity, you will not be asked for your passphrase. This is until the agent process is killed.