On SSH Key Management
Feb 2, 2018 by Ev Kontsevoy
This is going to be a quick read. Ever since diving into the infrastructure security space I started to get this question often:
So what’s the right way to manage SSH keys for our team?
Friends, Romans, countrymen, .. you are asking the wrong question. A world-class ops team should not be “managing SSH keys”. While valid in theory, key-based authentication is probably not the best approach to SSH security in practice. Indeed, if not properly “managed”, SSH keys can be no more safe than good old passwords.
Below I’ll try to explain why, but the TL;DR version is that “key management” can get complicated, and
complexity makes you exposed to errors in configuration and makes it hard to reason about security.
There’s a much simpler way.
The need for SSH Key Management
Let’s do a quick overview of SSH key authentication. Any authentication scheme based on asymmetric cryptography, including SSH, uses a pair of keys:
- A private key which is never shared with anyone. Usually users generate their
private SSH key using the
ssh-keygenutility which stores private keys in a user’s
- A public key, which is algorithmically derived from that private key. A public key is safe to share with everyone.
In a key-based system all users and even all servers must have their own private keys. Servers generate their own private keys usually when an SSH server is installed on them. When a user logs into an SSH server, two things happen:
- A server needs to authenticate this user. This works by a user presenting her public key, so a server can look into a list of public keys it trusts and accept or reject the connection.
- A user must also ensure that a server can be trusted. What if an attacker somehow managed to assign a well-known, trusted IP address to a rogue machine? A server must present its public key to a user, so a user can check her known_hosts file to decide either this server can be trusted.
It is easy to see that for this to work well, two things must be true:
- Every user must have a list of public keys of all servers.
- Every server must have a list of public keys of all users.
This critical list of trusted public keys also needs to be updated on a regular basis, because servers and users change all the time. This is why you may be thinking that you need an “SSH key management” solution.
But you don’t. You should be using short lived, automatically expiring SSH certificates instead.
Enter SSH Certificates
An SSH certificate is simply a public key signed by a well-known, trusted entity called a certificate authority (“CA”). A certificate authority is the ultimate grantor of trust in an organization. This means that copying keys around is no longer necessary; users and servers simply must agree on which CA to trust.
SSH Certificates have a few important properties:
- A “certificate” is a public key bundled with its digital signature algorithmically derived from a CA’s private key. This means that only a CA can issue a certificate.
- A certificate can be supplied with a date range for when it’s considered valid. This means that certificates can automatically expire.
- A certificate can contain arbitrary cryptographically signed metadata, which allows a CA to encode additional instructions to how a certificate must be handled. For example, one can think of encoding various SSH options into it, like “do not allow port forwarding”.
When a user tries to connect to a server, there is no need for users and servers to know each other’s public keys ahead of time. Instead, they exchange their certificates and validate that they are signed by the same certificate authority (CA).
SSH Certificates in Production
How would using SSH certificates work in practice?
- When a new server is provisioned, it must receive its own certificate from a trusted fleet-wide corporate CA.
- When a user shows up for work, she must also receive her user certificate from the same trusted corporate CA.
- All users and all servers must trust certificates signed by the corporate CA, assuming the certificates have not expired.
This diagram illustrates that servers and users must periodically request their certificates from a mutually trusted corporate CA:
Logging in with a Certificate
Once both a server and a user have their certificates, authentication becomes simply the process of showing each other a certificate and validating that it’s signed by the trusted CA:
Open Source SSH Servers that Support Certificates
Certificate-based authentication can be implemented using OpenSSH. RedHat has an excellent guide on how to do this, so we are not repeating it here. OpenSSH is the undisputed champ of the SSH world and comes by default with every Linux system and supports every SSH authentication method, i.e. it needs to be carefully configured and locked down for certificate-based access.
Another open source alternative is Teleport, a relatively new addition to the world of SSH servers.
Teleport makes SSH certificates its sole purpose, i.e. its user experience and ease of configuration are optimized specifically for certificate-based authentication, i.e. Teleport defaults make it easy to reason about certificate-based SSH security.