Unit 4: Users and groups · Lesson 7 of 7 · 20 min

SSH certificates instead of key sprawl

Sign short-lived certificates with a CA so access expires on its own and nobody edits authorized_keys again.

mission

You are
You are piloting SSH certificates for web01.
Situation
dana's authorized_keys still trusts a key from a 2019 CI job. With certificates, the server trusts one CA and every login key expires.
Goal
Count the keys trusted today, then issue an eight-hour certificate and read it.
Hand in
A certificate for learner, valid for one working day.
01

Inventory today's trusted keys

learner@root-lab
for f in /home/*/.ssh/authorized_keys; do echo "$f $(grep -c . $f)"; done 2>/dev/null
/home/dana/.ssh/authorized_keys 2
ssh-keygen -l -f /home/dana/.ssh/authorized_keys | awk '{print $NF, $(NF-1)}'
(ED25519) dana@laptop
(ED25519) deploy@ci-2019

you should see Two keys for dana, one of them from a CI job in 2019. Nobody could tell you if it is still needed.

echo
Prints its arguments. Built into Linux and macOS.
grep
Prints the lines of text that match a pattern. Built into Linux and macOS.
ssh-keygen
Creates SSH keys and shows their fingerprints. Comes with OpenSSH, built into Linux, macOS and Windows 10 and later.
awk
Splits each line into fields and prints or counts the ones you ask for. Built into Linux and macOS.
02

Create a CA and a user key

In real life the CA key lives in a vault or HSM, not in a home folder.

learner@root-lab
mkdir -p ~/ssh-ca && cd ~/ssh-ca
ssh-keygen -q -t ed25519 -N '' -C 'web01 user CA' -f user_ca
ssh-keygen -q -t ed25519 -N '' -C 'learner laptop' -f learner_key
ls
learner_key
learner_key.pub
user_ca
user_ca.pub

you should see Two key pairs.

mkdir
Creates folders. Built into Linux and macOS.
cd
Changes the current folder. A command built into the bash shell.
ls
Lists the files in a folder. Built into Linux and macOS.
03

Sign a one-day certificate

-n sets who the certificate may log in as. -V sets the validity window.

learner@root-lab
ssh-keygen -s user_ca -I learner-2026-10-22 -n learner -V 20261022:20261023 learner_key.pub 2>&1 | sed 's/ for .*//'
Signed user key learner_key-cert.pub: id "learner-2026-10-22" serial 0
ssh-keygen -L -f learner_key-cert.pub | grep -E 'Key ID|Valid|Principals' -A1 | grep -v '^--'
        Key ID: "learner-2026-10-22"
        Serial: 0
        Valid: from 2026-10-22T00:00:00 to 2026-10-23T00:00:00
        Principals:
                learner

you should see Valid for one day and only as learner.

sed
Edits text as it streams past, for example to replace or delete lines. Built into Linux and macOS.
04

Tell sshd to trust the CA

On the server this is one line in sshd_config, plus copying user_ca.pub to the path it names. After that, authorized_keys files can go.

you should see TrustedUserCAKeys /etc/ssh/user_ca.pub

Two ways to grant access

authorized_keys
~dana/.ssh/authorized_keys
ssh-ed25519 ... dana@laptop
ssh-ed25519 ... deploy@ci-2019

Keys never expire and pile up per user

Certificates
TrustedUserCAKeys /etc/ssh/user_ca.pub
cert: learner, valid 2026-10-22 only

One CA to trust, every login expires

What a defender takes away

  1. 1Inventory authorized_keys on every server.
  2. 2Certificates expire, keys do not.
  3. 3Protect the CA key like the keys to every server, because it is.

Questions

0 of 3 solved

Answer each one from what you find on your lab machine.