Was es löst
Bei einfachen Schlüsseln führt jeder Server eine Liste erlaubter Schlüssel, und jeder Laptop eine Liste von Host-Schlüsseln. Bei 50 Servern bedeutet das Hinzufügen oder Entfernen einer Person, 50 Dateien zu ändern, und alte Schlüssel bleiben gern für immer.
Bei Zertifikaten vertrauen die Server einem einzigen CA-Schlüssel. Sie signieren den öffentlichen Schlüssel einer Person für eine bestimmte Zeit, und wenn das Zertifikat abläuft, endet der Zugang. Das sind OpenSSH-Zertifikate, nicht die X.509-Art, die für Websites verwendet wird, und Sie brauchen weder eine externe Firma noch einen externen Dienst.
Die CA erstellen
ssh-keygen -t ed25519 -f user_ca -C "user-ca"
Das ist ein normales Schlüsselpaar. Wer die private Hälfte user_ca besitzt, kann sich auf jedem Server, der ihr vertraut, als jeder beliebige Benutzer anmelden. Geben Sie ihr daher eine starke Passphrase und halten Sie sie von Ihrem Alltagsrechner und von den Servern fern. Verwenden Sie für Hosts eine getrennte CA, wie unten gezeigt.
Den öffentlichen Schlüssel eines Benutzers signieren
Die Person schickt Ihnen id_ed25519.pub, niemals den privaten Schlüssel:
ssh-keygen -s user_ca -I "alice@example.com" -n deploy,alice -V +8h id_ed25519.pub
| Option | Bedeutung |
|---|---|
-s user_ca | Der private CA-Schlüssel zum Signieren. |
-I | Die Schlüssel-ID. Sie steht bei jeder Anmeldung im Server-Log, sie sollte also die Person benennen. |
-n | Die Principals: die Namen, für die dieses Zertifikat gilt. |
-V | Die Gültigkeit. +8h, +1d oder ein Bereich wie -5m:+1d, der auch einen Server abdeckt, dessen Uhr etwas nachgeht. |
Das Ergebnis ist id_ed25519-cert.pub. Geben Sie es der Person zurück, die es neben den privaten Schlüssel legt. ssh findet es dann am Namen, ohne zusätzliche Konfiguration. Liegt es woanders, braucht es eine Zeile CertificateFile in ~/.ssh/config. So lesen Sie eines aus:
ssh-keygen -L -f id_ed25519-cert.pub
Ohne -V läuft ein Zertifikat nie ab, was einen großen Teil des Nutzens zunichtemacht.
Den Server der CA vertrauen lassen
Kopieren Sie user_ca.pub, nur den öffentlichen Teil, nach /etc/ssh/user_ca.pub auf dem Server. Tragen Sie dies in die sshd-Konfiguration ein, führen Sie dann sudo sshd -t aus und laden Sie neu:
TrustedUserCAKeys /etc/ssh/user_ca.pub
Der Benutzer kann sich jetzt ohne Zeile in authorized_keys anmelden. Das Server-Log zeigt, wer es war:
Accepted publickey for deploy from 203.0.113.50 port 56276 ssh2: ED25519-CERT SHA256:... ID alice@example.com (serial 0) CA ED25519 SHA256:...
Principals
Standardmäßig verlangt der Server, dass der Kontoname einer der Principals des Zertifikats ist. Ein Zertifikat für alice öffnet das Konto deploy nicht.
Um statt Kontonamen Rollen zu verwenden, listen Sie für jedes Konto die akzeptierten Principals auf:
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
Dann enthält /etc/ssh/auth_principals/deploy einen Namen pro Zeile, zum Beispiel ops, und Sie signieren mit -n ops. Mit dieser Einstellung wird der Kontoname nicht mehr automatisch akzeptiert: Nur die Namen in der Datei zählen, und ein Konto ohne Datei lehnt Zertifikate ab.
Beschränken, was ein Zertifikat darf
Optionen werden beim Signieren gesetzt. Hier funktioniert das Zertifikat nur aus einem Netz und kann kein Terminal öffnen:
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 entfernt alle Standardrechte, und Sie können dann die gewünschten wieder hinzufügen, zum Beispiel -O clear -O permit-pty.
Wenn eine Anmeldung fehlschlägt
Der Client sagt nur Permission denied (publickey). Der Grund steht im Server-Log:
| Log-Zeile | Ursache |
|---|---|
Certificate invalid: name is not a listed principal | Das Konto steht nicht in der -n-Liste des Zertifikats. |
Certificate invalid: expired | Das Enddatum ist überschritten. Signieren Sie es neu. |
Refused by certificate options | Eine Beschränkung wie source-address passt nicht. |
Authentication key ... revoked by file ... | Der Schlüssel steht auf der Sperrliste. |
Ein Zertifikat vor Ablauf sperren
Halten Sie Zertifikate kurz, dann brauchen Sie das selten. Für den dringenden Fall erstellen Sie aus dem öffentlichen Schlüssel eine Key Revocation List und kopieren sie auf jeden Server:
ssh-keygen -k -f revoked.krl id_ed25519.pub
ssh-keygen -Q -f revoked.krl id_ed25519.pub
RevokedKeys /etc/ssh/revoked.krl
Weitere Schlüssel fügen Sie mit -u derselben Liste hinzu. Gehen Sie mit dieser Datei sorgfältig um: Kann sshd sie nicht lesen, wird die Anmeldung per öffentlichem Schlüssel für alle Benutzer abgelehnt.
Für Schlüssel ohne Zertifikat siehe wie Sie einen SSH-Schlüssel beim Weggang widerrufen.
Host-Zertifikate
Host-Zertifikate lösen die andere Richtung. Ihre Benutzer sehen die Abfrage zu einem unbekannten Host nicht mehr, weil sie einer CA vertrauen und nicht jedem einzelnen Host-Schlüssel. Signieren Sie den öffentlichen Host-Schlüssel des Servers mit -h und listen Sie die Namen auf, mit denen man sich verbindet:
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
Auf dem Server, mit 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
Fügen Sie auf jedem Client eine Zeile in ~/.ssh/known_hosts ein, mit dem Inhalt von host_ca.pub:
@cert-authority *.example.com ssh-ed25519 AAAA...
Das Muster muss zu dem Namen passen, mit dem Sie sich verbinden. Tut es das nicht, ignoriert ssh die Zeile und behandelt den Host als unbekannt, oder lehnt ihn ab, wenn StrictHostKeyChecking auf yes steht. Auch Host-Zertifikate laufen ab, erneuern Sie sie also vor diesem Datum. Wie der Rest dieser Datei funktioniert, steht in known_hosts erklärt.
Wann sich Zertifikate lohnen
Für wenige Server und wenige Personen sind einfache Schlüssel unkomplizierter. Zertifikate zahlen sich aus, wenn oft Personen kommen und gehen, oder wenn Sie kurzlebigen Zugang mit einem Namen im Log wollen. Der schwierige Teil ist der Prozess um die CA: wer signieren darf, wo der private Schlüssel liegt und wie eine Person jeden Tag ein neues Zertifikat bekommt. ssh-keygen liefert das Signieren, nicht diesen Prozess.
Fragen
Was ist der Unterschied zwischen SSH-Schlüssel und SSH-Zertifikat?
Ein Zertifikat ist ein öffentlicher Schlüssel, den eine CA signiert hat, mit einer Liste erlaubter Benutzernamen und einem Ablaufdatum. Ein Server, der der CA vertraut, akzeptiert es ohne Eintrag in authorized_keys für diesen Schlüssel.
Wie sehe ich, wann ein SSH-Zertifikat abläuft?
Führen Sie ssh-keygen -L -f id_ed25519-cert.pub aus. Die Zeile Valid zeigt Beginn und Ende der Gültigkeit.
Ersetzen SSH-Zertifikate authorized_keys?
Für Anmeldungen per Zertifikat ja: Der Server braucht nur TrustedUserCAKeys. Normale Schlüssel in authorized_keys funktionieren daneben weiter.
Quellen
- ssh-keygen(1), CERTIFICATES section, OpenBSD manual
- sshd_config(5), OpenBSD manual
- sshd(8), SSH_KNOWN_HOSTS FILE FORMAT, OpenBSD manual