Mastering SSH Certificates: A Comprehensive Guide
SSH certificates offer a powerful and secure alternative to traditional key-based authentication. In this guide, we'll walk you through the process of implementing SSH certificate authentication, from creating a Certificate Authority (CA) to configuring servers and clients. We'll also provide practical tips and tricks to make your journey smoother.
Overall Process Flow
The process of implementing SSH certificate authentication involves several key steps:
- Create a Certificate Authority (CA)
- Configure the remote server
- Sign the user's public SSH key with the CA
- Use the new certificate for authentication
Let's dive into each step with examples.
1. Create a Certificate Authority (CA)
The first step is to generate a CA key pair. This will be used to sign both host and user certificates.
1ssh-keygen -t ed25519 -f ca-key -m PEM
This command creates two files: ca-key (private key) and ca-key.pub (public key). Keep the private key secure and distribute the public key to your servers.
2. Configure the Remote Server
Next, we need to configure the SSH server to trust our new CA. Here's how:
Update Trusted SSH CA Public Key
Navigate to the SSH directory and create a file containing the SSH CA public key:
1cd /etc/ssh
2sudo echo "ssh-ed25519 YOUR_CA_PUBLIC_KEY_HERE" > my-org-trusted-CA.pem
Create AuthorizedPrincipalsFile Structure
Set up the AuthorizedPrincipalsFile to control which SSH principals are accepted:
1cd /etc/ssh
2mkdir auth_principals/
3cd auth_principals
4sudo echo "superuser" > admin
5sudo echo "operator" > ubuntu
This will allow the users to login as admin if they have the superuser principal in their certificate and they'll be able to login as ubuntu if the certificate is signed with the operator principal. Of course if the certificate has both(In my experimentation a scert can have upt 254 principals assigned) then the user can login as either.
Note on Sudo Access Control It's important to be aware that SSH certificate authentication doesn't natively provide a way to control sudo access. However, if you need fine-grained sudo access control based on SSH certificates, consider exploring Uber's PAM SSH Certificates module. This open-source project extends the functionality of SSH certificates to manage sudo permissions. Learn more about Uber's PAM SSH Certificates module - https://github.com/uber/pam-ussh
Update sshd_config
Add the following to your sshd_config file:
1AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
2ChallengeResponseAuthentication no
3PasswordAuthentication no
4TrustedUserCAKeys /etc/ssh/my-org-trusted-CA.pem
Don't forget to restart the SSH service:
1sudo service sshd restart
3. Sign the User's Public SSH Key
Now that our CA is set up and the server is configured, we can sign user keys:
1ssh-keygen -s ca-key -I "username@hostname user key" -n "username,superusers" -V -5m:+3650d ~/.ssh/id_rsa.pub
This command signs the user's public key, creating a certificate valid for 10 years (adjust as needed).
4. Use the New Certificate for Authentication
The user can now use their new certificate to authenticate. They don't need to do anything special - their SSH client will automatically use the certificate.
Advanced Tips and Tricks
Inspecting Certificates
To inspect a user's SSH certificate:
1ssh-keygen -Lf path/to/user-cert.pub
This will show details like principals, validity period, and signing CA.
Creating and Signing Host Keys
For host keys:
-
Create the key:
1ssh-keygen -f ssh_host_rsa_key -N '' -b 4096 -t rsa -
Sign it:
1ssh-keygen -s ca-key -I host.example.com -h -n host.example.com,127.0.0.1 -V +52w ssh_host_rsa_key.pub
Extracting Public Keys
To extract a public key from a private key:
1ssh-keygen -y -e -f ssh_key
Testing with Docker
For development and testing, you can use a Docker container as an SSH server. Here's how:
- Create a
Dockerfile:
1FROM ubuntu:latest
2
3RUN apt update && apt install openssh-server sudo -y
4
5RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u 1000 ubuntu
6RUN echo 'ubuntu:test' | chpasswd
7
8EXPOSE 22
9
10COPY script.sh /script.sh
- Create a
script.sh:
1#!/bin/bash
2mkdir -p /etc/ssh/auth_principals/
3cp /tmp/principals/* /etc/ssh/auth_principals/
4chmod 644 /etc/ssh/auth_principals/*
5
6cp /tmp/sshd_config /etc/ssh/
7cp /tmp/myCA.pub /etc/ssh/myCA.pub
8
9while true; do
10 /usr/sbin/sshd -Dddd -p 22 &
11 pid=$!
12 wait $pid
13 echo "sshd exited, restarting..."
14done
- Build and run the container:
1docker build . -t ssh-server
2docker run -it --rm \
3 --name=openssh-server \
4 --hostname=openssh-server \
5 -p 2222:22 \
6 -v $(pwd)/ca-users.pub:/tmp/myCA.pub \
7 -v $(pwd)/sshd_config:/tmp/sshd_config \
8 -v $(pwd)/principal_file:/tmp/principals/ubuntu \
9 -v $(pwd)/ssh_host_rsa_key:/etc/ssl/ssh_host_rsa_key \
10 -v $(pwd)/ssh_host_rsa_key.pub:/etc/ssl/ssh_host_rsa_key.pub \
11 ssh-server bash script.sh
This setup allows you to quickly test your SSH certificate configuration in a controlled environment.