SSH Authentication with a CA
This article describes how to use a SSH CA to authenticate to SSH servers. This is particularly useful when you have a lot of servers to manage and you want to avoid the hassle of managing a lot of SSH keys.
The basic idea is to have a CA (Certificate Authority) that will sign the public keys of the users. Then, the users will be able to authenticate to the servers using their signed public key. This way, you don't have to manage the public keys of the users on the servers, you only have to manage the public keys of the CA. You can also limit the validity of the signed public keys to a certain amount of time or to a certain set of servers and users.
Prerequisites
This article assumes that you have a basic knowledge of SSH and that you have a SSH server running on a Linux machine.
The theory
What is a SSH CA ?
A SSH CA is simply an basic SSH key pair (public and private) that is used to sign other SSH public keys. The public key of the CA is then distributed to the servers and the private key is kept secret.
How does it work ?
When a user wants to authenticate to a server, the server will ask the user to provide a public key. The user will then provide a public key that has been signed by the CA. The server will then check the signature of the public key using the public key of the CA. If the signature is valid, the user will be authenticated.
The practice
Generate the CA key pair
The first step is to generate the CA key pair. To do so, you can use the ssh-keygen
command:
Parameter | Description |
---|---|
-t |
The algorithm to use to generate the key pair. |
-b |
The size (in bits) of the key pair. |
-f |
The output file name (without the extensions). |
This will generate two files: my_ssh_ca
and my_ssh_ca.pub
. The first one is the private key of the CA and the second one is the public key of the CA.
Generate a personal SSH key pair (optional)
This step assumes that you already have a personal SSH key pair. If you don't, you can generate one using the ssh-keygen
command:
Parameter | Description |
---|---|
-t |
The algorithm to use to generate the key pair. |
-b |
The size (in bits) of the key pair. |
-f |
The output file name (without the extensions). |
Distribute the CA public key
Configure the SSH server
First, you need to configure the SSH server to accept the SSH CA public key. To do so, you need to authenticate to the server and become root. Then, you need to edit the /etc/ssh/sshd_config
file and add the following line at the end of the file:
Match Address 192.168.42.*
TrustedUserCAKeys /etc/ssh/ssh_user_ca
AuthorizedPrincipalsFile /etc/ssh/authorized_principals/%u
RevokedKeys /etc/ssh/revoked_keys
Parameter | Description |
---|---|
Match Address 192.168.42.* |
This line is used to apply the following configuration only to the clients that match the given address. In this case, we only want to apply the following configuration to the clients that match the 192.168.42.* address. |
TrustedUserCAKeys |
The path to the SSH CA public key. |
AuthorizedPrincipalsFile |
The path to the file containing the list of SSH principals allowed to authenticate to users. |
RevokedKeys |
The path to the file containing the list of revoked SSH public keys. |
Then, you need to create the /etc/ssh/ssh_user_ca
file and add the public key of the SSH CA to it:
For now we don't have any SSH CA public key to revoke, so we only need to create an empty file for the RevokedKeys
parameter:
Finally, we need to create the /etc/ssh/authorized_principals
directory to store the list of SSH principals allowed to authenticate to users:
Configure principal-based authentication
As an example, we will configure the SSH server to allow me to authenticate to the wabbit
user. To do so, we need to create the /etc/ssh/authorized_principals/wabbit
file and add the following line to it:
This will allow me to authenticate to the wabbit
user using the wabbit_ops
principal. Attention, a principal is not a username, it's just a name that will be used to identify the user or a role. You can use whatever name you want, but it's better to use a name that is easy to remember.
Apply the configuration
Once the configuration is done, you need to restart the SSH server to apply the changes:
Configure the SSH client
Now that the SSH server is configured, we need to configure the SSH client to use the SSH CA to authenticate to the SSH server.
Sign the personal SSH public key
First, we need to sign the personal SSH public key using the CA private key. To do so, we need to use the ssh-keygen
command:
Parameter | Description |
---|---|
-s |
The path to the CA private key. |
-I |
The identity of the signed public key. This is used to identify the signed public key. It's a good idea to use the username, the hostname and the name of the server. It doesn't have any impact on the authentication. |
-n |
The principal allowed during the authentication. |
-V |
The validity of the signed public key. |
my_ssh_key.pub |
The path to the public key to sign. |
This will generate a my_ssh_key-cert.pub
file that contains the signed public key.
To check the signature of the signed public key, you can use the ssh-keygen
command:
Parameter | Description |
---|---|
-L |
Check the signature of the public key. |
-f |
The path to the public key to check. |
This will print the following output:
my_ssh_key-cert.pub:
Type: ssh-ed25519-cert-v01@openssh.com user certificate
Public key: ED25519-CERT SHA256:Nbe7SXv788c0t3g8D8GQ/5dwHXX4zXtoaEC7r97h5oM
Signing CA: RSA SHA256:jitBsmIydxjgdW7DttD9piKIWmb4RPQQ7i7wfQ+M4Vg (using rsa-sha2-512)
Key ID: "lunik@my_server"
Serial: 0
Valid: from 2023-09-19T19:13:00 to 2023-09-20T19:14:07
Principals:
wabbit_ops
Critical Options: (none)
Extensions:
permit-X11-forwarding
permit-agent-forwarding
permit-port-forwarding
permit-pty
permit-user-rc
Authenticate to the SSH server
Now that the SSH client is configured, we can authenticate to the SSH server using the signed public key. To do so, we need to use the ssh
command:
Parameter | Description |
---|---|
-i |
The path to the private key to use to authenticate. |
wabbit@my_server |
The username and the hostname of the SSH server. |