Skip to content

$ cat ./posts/security/ssh-certificate-authentication.conf

-rw-r--r-- 1.7K #security #ssh

SSH certificate authentication

by chris · 2 min read · /security


Every fleet reaches a point where authorized_keys files have drifted and nobody can say which key belongs to whom. Certificates fix this: hosts trust one CA, and access is granted by signing a key with an expiry.

1. Create a CA and trust it

ssh-keygen -t ed25519 -f user_ca -C 'user CA'

# on every host
echo "TrustedUserCAKeys /etc/ssh/user_ca.pub" >> /etc/ssh/sshd_config

2. Sign a key with an expiry

ssh-keygen -s user_ca -I 'chris@laptop' 
  -n chris,deploy -V +8h 
  -O clear -O permit-pty -O permit-agent-forwarding 
  id_ed25519.pub

-V +8h is the whole point. An eight-hour certificate cannot be found on an old laptop two years later and used. -O clear drops every default permission so the ones granted are explicit.

3. Verify what you issued

ssh-keygen -L -f id_ed25519-cert.pub

Read the principals and the validity window before handing it over. A certificate with permit-port-forwarding left on is a tunnel into the network that outlives the session it was issued for.

4. Host certificates too

The same mechanism removes the “unknown host key” prompt that everyone types yes to without reading. Sign the host keys with a host CA, put @cert-authority * ssh-ed25519 ... in known_hosts, and a genuine man-in-the-middle warning becomes a signal rather than noise.

5. Revocation

Short lifetimes are the primary control, but keep a revocation list for the case that cannot wait:

ssh-keygen -k -f revoked_keys -s user_ca id_ed25519.pub
# sshd_config: RevokedKeys /etc/ssh/revoked_keys
← cd .. fris@linux:~/blog$ man security