Che problema risolve
Con le chiavi semplici, ogni server tiene un elenco di chiavi permesse, e ogni portatile tiene un elenco di chiavi host. Con 50 server, aggiungere o togliere una persona significa modificare 50 file, e le vecchie chiavi tendono a restare per sempre.
Con i certificati, i server si fidano di una sola chiave CA. Firmi la chiave pubblica di una persona per un tempo stabilito, e quando il certificato scade l'accesso finisce. Sono certificati OpenSSH, non quelli X.509 usati per i siti web, e non ti serve nessuna azienda o servizio esterno.
Creare la CA
ssh-keygen -t ed25519 -f user_ca -C "user-ca"
È una normale coppia di chiavi. Chiunque abbia la metà privata user_ca può fare login come chiunque su ogni server che si fida di lei, quindi dalle una passphrase robusta e tienila fuori dalla macchina di tutti i giorni e dai server. Usa una CA separata per gli host, come mostrato più avanti.
Firmare la chiave pubblica di un utente
La persona ti invia id_ed25519.pub, mai la chiave privata:
ssh-keygen -s user_ca -I "alice@example.com" -n deploy,alice -V +8h id_ed25519.pub
| Opzione | Significato |
|---|---|
-s user_ca | La chiave privata della CA usata per firmare. |
-I | L'ID della chiave. Viene scritto nel log del server a ogni login, quindi fai in modo che indichi la persona. |
-n | I principal: i nomi per cui questo certificato è valido. |
-V | La validità. +8h, +1d, o un intervallo come -5m:+1d, che copre anche un server con l'orologio un po' indietro. |
Il risultato è id_ed25519-cert.pub. Restituiscilo alla persona, che lo mette accanto alla chiave privata. ssh lo trova poi dal nome, senza altra configurazione. Se sta altrove, serve una riga CertificateFile in ~/.ssh/config. Per leggerne uno:
ssh-keygen -L -f id_ed25519-cert.pub
Senza -V, un certificato non scade mai, il che elimina gran parte del vantaggio.
Far fidare il server della CA
Copia user_ca.pub, solo la parte pubblica, in /etc/ssh/user_ca.pub sul server. Aggiungi questo alla configurazione di sshd, poi esegui sudo sshd -t e ricarica:
TrustedUserCAKeys /etc/ssh/user_ca.pub
L'utente ora può fare login senza alcuna riga in authorized_keys. Il log del server mostra chi era:
Accepted publickey for deploy from 203.0.113.50 port 56276 ssh2: ED25519-CERT SHA256:... ID alice@example.com (serial 0) CA ED25519 SHA256:...
Principal
Di default, il server richiede che il nome dell'account sia uno dei principal del certificato. Un certificato per alice non apre l'account deploy.
Per usare ruoli al posto dei nomi account, elenca i principal accettati per ogni account:
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
Allora /etc/ssh/auth_principals/deploy contiene un nome per riga, per esempio ops, e firmi con -n ops. Con questa impostazione attiva, il nome dell'account non viene più accettato automaticamente: contano solo i nomi nel file, e un account senza file rifiuta i certificati.
Limitare cosa può fare un certificato
Le opzioni si impostano al momento della firma. Qui il certificato funziona solo da una rete e non può aprire un terminale:
ssh-keygen -s user_ca -I alice -n ops -V +1h -O source-address=203.0.113.0/24 -O no-pty id_ed25519.pub
-O clear rimuove tutti i permessi predefiniti, e puoi poi riaggiungere quelli che vuoi, per esempio -O clear -O permit-pty.
Quando un login fallisce
Il client dice solo Permission denied (publickey). Il motivo sta nel log del server:
| Riga di log | Causa |
|---|---|
Certificate invalid: name is not a listed principal | L'account non è nell'elenco -n del certificato. |
Certificate invalid: expired | Oltre la data di fine. Firmalo di nuovo. |
Refused by certificate options | Un limite come source-address non corrisponde. |
Authentication key ... revoked by file ... | La chiave è nella lista di revoca. |
Revocare un certificato prima della scadenza
Tieni i certificati brevi, così raramente ti serve. Per il caso urgente, crea una lista di revoca delle chiavi dalla chiave pubblica e copiala su ogni server:
ssh-keygen -k -f revoked.krl id_ed25519.pub
ssh-keygen -Q -f revoked.krl id_ed25519.pub
RevokedKeys /etc/ssh/revoked.krl
Aggiungi altre chiavi alla stessa lista con -u. Fai attenzione a questo file: se sshd non riesce a leggerlo, il login con chiave pubblica viene rifiutato per tutti gli utenti.
Per le chiavi senza certificato, vedi come revocare una chiave SSH quando qualcuno se ne va.
Certificati host
I certificati host risolvono la direzione opposta. I tuoi utenti smettono di vedere la richiesta di host sconosciuto, perché si fidano di una CA e non di ogni chiave host. Firma la chiave host pubblica del server con -h, ed elenca i nomi con cui le persone si connettono:
ssh-keygen -t ed25519 -f host_ca -C "host-ca"
ssh-keygen -s host_ca -I server1 -h -n server1.example.com -V +52w ssh_host_ed25519_key.pub
Sul server, con ssh_host_ed25519_key-cert.pub in /etc/ssh/:
HostKey /etc/ssh/ssh_host_ed25519_key
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
Su ogni client, aggiungi una riga a ~/.ssh/known_hosts, con il contenuto di host_ca.pub:
@cert-authority *.example.com ssh-ed25519 AAAA...
Il pattern deve corrispondere al nome con cui ti connetti. Quando non corrisponde, ssh ignora la riga e tratta l'host come sconosciuto, o lo rifiuta se StrictHostKeyChecking è yes. Anche i certificati host scadono, quindi rinnovali prima di quella data. Vedi known_hosts spiegato per come funziona il resto di quel file.
Quando i certificati valgono la pena
Per pochi server e poche persone, le chiavi semplici sono più semplici. I certificati cominciano a ripagare quando le persone entrano ed escono spesso, o quando vuoi un accesso a breve durata con un nome nel log. La parte difficile è il processo intorno alla CA: chi può firmare, dove vive la chiave privata e come una persona ottiene ogni giorno un nuovo certificato. ssh-keygen ti dà la firma, non quel processo.
Domande
Che differenza c'è tra una chiave SSH e un certificato SSH?
Un certificato è una chiave pubblica firmata da una CA, con un elenco di nomi utente ammessi e una scadenza. Un server che si fida della CA lo accetta senza una riga in authorized_keys per quella chiave.
Come vedo quando scade un certificato SSH?
Esegui ssh-keygen -L -f id_ed25519-cert.pub. La riga Valid mostra inizio e fine della validità.
I certificati SSH sostituiscono authorized_keys?
Per i login con certificato sì: al server basta TrustedUserCAKeys. Le chiavi normali elencate in authorized_keys continuano a funzionare accanto.
Fonti
- ssh-keygen(1), sezione CERTIFICATES, manuale OpenBSD
- sshd_config(5), manuale OpenBSD
- sshd(8), SSH_KNOWN_HOSTS FILE FORMAT, manuale OpenBSD