OpenSSH Certificate Cheatsheet

Almost all SSH users are familiar with public key authentication and use SSH private keys to authenticate themselves when logging into a remote machine. The SSH key mechanism is relatively simple; the user generates a private key and shares his public key with the administrators of the devices he wants to access. A device administrator places the user’s key in the target accounts authorized_keys file to allow access.

In practice, this mechanism does not scale well. So, the OpenSSH developers introduced a certificate-based solution that uses trust in a certificate authority rather than individual public keys.

What is an SSH Certificate?

A certificate is a file that encodes a public key with information about a user’s identity and other options relevant to the use of the public key it contains.

What is a Certificate Authority?

A certificate authority is a public/private key that signs certificates. By trusting the certificate authority key, you can also trust the user’s credentials with a certificate signed by it.

How does it work?

Instead of the administrator configuring authorized_key files with each user’s public key, they can configure the SSH server to trust a certificate authority key.

They can then distribute private keys and certificates signed by the authority to allow access to any of the server’s accounts automatically.

Creating an SSH Certificate Authority

An SSH certificate authority is just a plain SSH public/private key pair. You can generate one using the ssh-keygen command. Store this securely for later use in signing certificates.

ssh-keygen -t ed25519 -f id_ca

Configuring an SSH Server to Trust an SSH Certificate Authority

Copy the public key file of your CA to the SSH server and enable the TrustedUserCAKeys directive in /etc/ssh/sshd_config

TrustedUserCAKeys /etc/ssh/id_ca.pub

Creating User Certificates

Again, using ssh-keygen, you should first make the user a public/private key pair.

ssh-keygen -t ed25519 -f id_user

You can then sign this with the CA key.

ssh-keygen -s id_ca -I lee -n lee id_user.pub

This command creates a key that is valid for the account lee. You can add more accounts to the certificate by modifying the -n argument and adding a comma-separated list of principals that this certificate can use.

ssh-keygen -s id_ca -I lee -n lee,admin id_user.pub

So far, the certificates created will not expire. To create a certificate that expires, use the additional -V argument. For example, to make it valid for one year, we could use.

ssh-keygen -s id_ca -I lee -n lee,admin -V +365d id_user.pub

Or

ssh-keygen -s id_ca -I lee -n lee,admin -V +52w id_user.pub

If you want to assign each certificate a unique serial number, you can use the -z argument. This value needs to be numeric, it will default to zero if omitted.

ssh-keygen -s id_ca -I lee -n lee,admin -V +52w -z 12345 id_user.pub

You can print out the contents of a certificate.

ssh-keygen -L -f id_user-cert.pub
id_user-cert.pub:
     Type: ssh-ed25519-cert-v01@openssh.com user certificate
     Public key: ED25519-CERT SHA256:BJLn251h7NTo/KZv35zHBWmSVRvk/T7zWc1ftNh4Yhg
     Signing CA: ED25519 SHA256:R/rWKMUga78Y8omb115t9Z4kzXu4MgsNx24xJzrvzz0
     Key ID: "lee"
     Serial: 12345
     Valid: from 2020-08-27T12:49:00 to 2021-08-26T12:50:01
     Principals:
              lee
              admin
     Critical Options: (none)
     Extensions:
              permit-X11-forwarding
              permit-agent-forwarding
              permit-port-forwarding
              permit-pty
              permit-user-rc

Creating Host Certificates

We have, until now, dealt with user certificates for user authentication. However, you can also use OpenSSH certificates for host keys.

It’s general practice to maintain a separate CA key for host keys.

ssh-keygen -t ed25519 -f id_host_ca

Now we can generate a host key.

ssh-keygen -t ed25519 -f ssh_host_ed25519

We have to use the -h command-line switch to sign the host key because the user and host keys are separate and not interchangeable.

ssh-keygen -s id_host_ca -I server1.example.com -n server1.example.com -h ssh_host_ed25519.pub

Configure the Server to use the Host Certificate

Now we have the certificate, we can configure the server to present this when users connect by adding the HostCertificate sshd_config directive.

HostCertificate ssh_host_ed25519-cert.pub

Configure the Client to Trust the Certificate Authority

Users can trust all the hosts signed by a CA by adding a known_hosts entry using the @cert-authority tag in the known_hosts file.

@cert-authority *.example.com <PUBLICKEY>

Where <PUBLICKEY> is the contents of the CA public key file id_host_ca.pub that we generated in the first step in this section.

You can also add this to /etc/ssh/ssh_known_hosts on any system to have the CA trusted by all users.