The way the OpenSSH Certificate Authority works depends on a few components. First, there needs to be one trusted signing authority. This can be any system, and it does NOT have to actively be connected to the network for the client/server handshake to take place using the CA signed keys. There should also be a Key Revocation List, as well as a means for keeping the KRL updated. A proper Identity and Access Management (IAM) platform could possibly handle this. A close second would be a proper Configuration Management / Server Automation tool such as Puppet, Chef, Salt, or Ansible. We will not cover using either of these tools in this series, but we will (most likely) cover an alternative solution when neither of the prior recommendations is available. That’s for another day, though. Today, we’re only going to introduce the basic concepts and fundamentals of how the OpenSSH Certificate Authority works.
Let’s set up the players. There is a person (User_A) that needs to log into a target machine (Server_A) as himself. He is coming from his laptop (Workstation_A.) Normally, User_A would generate his key pair, log into Server_A as himself, and place the public key into the authorized_keys file in his home directory. Instead, we’re going to pull in a new player that acts as a trusted third party. This will be the Certificate Authority (CA.) The CA should be run by a non privileged user on a server that is either not directly connected to the network, or is heavily protected. The actual privilege of signing should also be restricted to a small team of people with a job role title that allows for this type of provisioning. For our example, we will assume it is network isolated.
We are assuming the CA is already set up, but here are the steps that should have been taken to do so. Create the non privileged user (and group) for signing. Switch to that user and create the CA signing directory structure(s.) Use ssh-keygen to create the certificate signing key(s.)
There are two types of certificates that can be signed. The user certificate authenticates users to servers. The host certificate authenticates hosts to users. Why do we need both?
A host certificate gives us the ability to stand up a new server in our environment, sign its host keys with the certificate authority, and then the client knows that the new key is okay without prompting the user to trust the key first. This reduces some of the issues with managing the known_hosts file.
A user certificate gives us the ability to tell the server that our key is okay without having to place the key on the server first. This removes some of the issues with managing key distribution.
A signed user certificate can place restrictions on the signed public key, including all of the restrictions we discussed with the pre-amble section to the authorized_keys entries.
Let’s look at the broad overview work flow for today. Next week, we will cover the commands needed to stand up that certificate authority structure listed above, plus the commands to sign both host and user certificates.
Work flow scenario: a new machine is built. The host keys are regenerated (if for example this is a cloned virtual machine) and signed by the Certificate Authority. This signed certificate is placed back onto the new machine, and that’s all that is needed, as long as the clients are configured correctly. For the client to take advantage of this, the client needs a special known_hosts entry that begins with @cert-authority and is followed by the public key for the signed host certificates. When the user goes to log into the new machine, the connection flow will include the server presenting a host certificate to the client, who then checks that the known_hosts “@cert-authority” entry can decipher the host certificate, and the connection is then accepted on success. This helps prevent confusion on intentionally newly built systems when IP or hostnames change regularly.
Work flow scenario: a new user needs access to a system. The user generates their key, sends the public key to be signed, and when the certificate is received, places it in their .ssh directory with the rest of the key related files. The host machines have already been configured to trust the certificate authority in the sshd_config file. When the user goes to connect with ssh, the client presents the signed certificate to the target machine. The target machine’s sshd opens the TrustedUserCAKeys entry to open the appropriate public key to decode the certificate. If this is successfully decoded, the connection is trusted as if the key were in authorized_keys for that user. This helps reduce the heavy work load of managing multiple authorized_keys files per user.
Of course, there is more to it than this, but we’ll go into the finer details over the next few weeks. Next week will be an explanation of the commands needed to set up the CA, (including revocation lists, and why they are important.)
Thanks for reading!
Thank you for the pingback! There’s a shout out at the bottom of tomorrow’s post (continuation of this series.)
Thank you for the pingback! I’ll leave a shout out in Monday’s continuation.