September 23, 2019

SSH CA

Administering multiple users and their SSH keys across multiple machines can become a hassle. One thing we can do to ease management and allow easier scaling is to create an SSH CA.

Creating an SSH Certificate Authority allows us to authenticate hosts to users and vice-versa, no longer needing to verify via TOFU on every new machine, having to sync multiple user keys across multiple servers, and managing associated authorized_keys files. With a few caveats;

The CA keypair is generated the same as a normal ssh keypair;

ssh-keygen -f /etc/ssh/ca

From here we can sign existing keys with the -s option:

# For user keys:
# Note that principals (-n) must match the username on the remote machine.
# Otherwise you can override with the 'AuthorizedPrincipalsFile' sshd_config option on the remote host.
ssh-keygen -s /etc/ssh/ca -I $(whoami) -n $(whoami) ~/.ssh/*.pub
ssh-add ~/.ssh/*.pub

# And host sshd keys:
ssh-keygen -s /etc/ssh/ca -I $(hostname) -n $(hostname) -h /etc/ssh/*.pub
for i in /etc/ssh/*-cert.pub; do echo "HostCertificate $i" >> /etc/ssh/sshd_config; done
# and restart sshd

There are a few options to add some security, used above is -n to restrict which users and hosts the key is valid to authenticate, also of note is -V to specify a validity period.

At a minimum, you should specify -n when signing host keys, otherwise said key becomes valid for any host.

You will have to distribute the CA pubkey to all hosts you wish to use it for verification on. As this is a public key, it doesn’t need to be protected from reading, just tampering, and can be hosted on something like a trusted fileserver.

Now we need to tell ssh that we want to use our CA for authentication, we can do this either at the system or user level:

# For host verification:
 # System-wide:
 echo "@cert-authority * $(cat /etc/ssh/ca.pub)" >>/etc/ssh/ssh_known_hosts
 # Per user:
 echo "@cert-authority * $(cat /etc/ssh/ca.pub)" >>~/.ssh/known_hosts


# For client verification:
 # System-wide:
 echo "TrustedUserCAKeys /etc/ssh/ca.pub" >>/etc/ssh/sshd_config

 # Per user:
 echo "cert-authority,principals=$(whoami) $(cat /etc/ssh/ca.pub)" >>~/.ssh/authorized_keys

Finally, signed keys can be revoked if needed:

# System-wide:
	echo "RevokedKeys /etc/ssh/revoked_keys" >> /etc/ssh/sshd_config
	echo @revoked $(cat $key_to_revoke.pub) >> /etc/ssh/revoked_keys

# Per user:
	echo @revoked $(cat $public_key_to_revoke) >> ~/.ssh/known_hosts

Or via ssh-keygen:

echo "RevokedKeys /etc/ssh/revoked_keys" >> /etc/ssh/sshd_config
ssh-keygen -k -f /etc/ssh/revoked_keys -u -s /etc/ssh/ca $key_to_revoke.pub

References

This post is to be considered a public draft as I continue to mess with SSH CAs and learn the quirks