SSH-Zertifikate sind ein sehr leistungsfähiges Werkzeug . Zunächst haben
step-ca
wir im Zertifizierungscenter nur einen minimalen Satz von Funktionen für die Authentifizierung mithilfe von Benutzer- und Hostzertifikaten implementiert. Dann haben wir X.509-Zertifikatvorlagen und im August letzten Jahres SSH-Vorlagen in Version 0.15.2 hinzugefügt. Schließlich haben wir diese Funktion dokumentiert und sind bereit, darüber zu sprechen.
Die Vorlagen für SSH-Zertifikate funktionieren ähnlich wie die X.509-Vorlagen: Es handelt sich um in Go geschriebene JSON-Dateien
text/template
. Sie werden verwendet, um die von ihr ausgestellten SSH-Zertifikate zu konfigurieren
step-ca
. Schauen wir uns an, was diese Vorlagen sind und wie Sie sie verwenden können.
Standardmäßig sieht eine benutzerdefinierte SSH-Zertifikatvorlage folgendermaßen aus:
{
"type": {{ toJson .Type }},
"keyId": {{ toJson .KeyID }},
"principals": {{ toJson .Principals }},
"extensions": {{ toJson .Extensions }},
"criticalOptions": {{ toJson .CriticalOptions }}
}
Und hier ist das SSH-Zertifikat, das nach diesem Muster ausgestellt wurde:
$ step ssh inspect id_ct-cert.pub
id_ct-cert.pub:
Type: ecdsa-sha2-nistp256-cert-v01@openssh.com user certificate
Public key: ECDSA-CERT SHA256:iczSh1XiBBE36yfJcDidgp6fqY3qWx1RtEwFfAN9jDs
Signing CA: ECDSA SHA256:MKwRQ/SDKk/pCJbbCk5bfhZACjSjv7uZXLyc5n4Wx6k
Key ID: "carl@smallstep.com"
Serial: 2831574724231262409
Valid: from 2020-11-17T16:48:11 to 2020-11-18T08:49:11
Principals:
carl
carl@smallstep.com
Critical Options: (none)
Extensions:
permit-X11-forwarding
permit-agent-forwarding
permit-port-forwarding
permit-pty
permit-user-rc
Der Benutzer
carl
(oder
carl@smallstep.com
) kann sich bei jedem SSH-Host authentifizieren, der meiner SSH-Zertifizierungsstelle vertraut. Das Zertifikat enthält einige grundlegende Erweiterungen:
permit-x11-forwarding
: Aktiviert die X11-Weiterleitung (mitssh -X
), um Remote-X11-Programme auf dem lokalen Display auszuführen.
permit-agent-forwarding
: Ermöglicht der Agentenumleitung (mitssh -A
) das Weiterleiten von Schlüsseln vom lokalen SSH-Agenten an den Remote-Host (weitere Informationen zum SSH-Agenten finden Sie hier ).
permit-port-forwarding
: Ermöglicht die Portweiterleitung (Tunneling) von lokal zu remote port (ssh -L
) oder remote zu local (ssh -R
).
permit-pty
: Eine sehr wichtige Erweiterung. Wenn Sie eine interaktive Sitzung in der Konsole öffnen möchten, muss der Host Ihnen eine Pty (Pseudo-Tty) zuweisen. Andernfalls wird keine Interaktivität bereitgestellt. Um beispielsweise die SSH-Authentifizierung auf GitHub zu testen, kann sie ausgeführt werdenssh -T git@github.com
(-T
deaktiviert die Pty-Anforderung).
permit-user-rc
: Führen Sie nach dem Herstellen der Verbindung eine persönliche RC-Datei aus (~/.ssh/rc
auf dem Remote-Host).
Benutzer- und Hostzertifikate unterstützen Erweiterungen und kritische Parameter, OpenSSH definiert jedoch keine integrierten Erweiterungen oder kritischen Parameter für Hostzertifikate. Daher geschieht das Interessanteste mit Benutzerzertifikaten. In diesem Artikel werden daher nur diese Zertifikate betrachtet.
Beispiele für Zertifikatvorlagen
Nehmen wir einige Änderungen an der Standardvorlage vor.
Verbot der Weiterleitung von Agenten und Ports
Wenn Benutzer über den Bastion-Host eine Verbindung zu internen Hosts herstellen , ist es aus Sicherheitsgründen hilfreich, die Portweiterleitung zu deaktivieren. Sie möchten nicht, dass Benutzer Datenverkehr vom MySQL-Produktionsserver zu ihrem lokalen Host umleiten. Ebenso birgt die Agentenumleitung ein Sicherheitsrisiko . Hier ist eine Vorlage, mit der diese beiden Erweiterungen einfach aus SSH-Zertifikaten entfernt werden:{
"type": {{ toJson .Type }},
"keyId": {{ toJson .KeyID }},
"principals": {{ toJson .Principals }},
"extensions": {
"permit-x11-forwarding": "",
"permit-pty": "",
"permit-user-rc": ""
},
"criticalOptions": {{ toJson .CriticalOptions }}
}
Einbetten der Force-Command-Direktive
ForceCommand
Ist eine serverseitige SSHD-Konfigurationsanweisung, die anstelle eines interaktiven Terminals einen alternativen Befehl auf dem Host ausführt. Mit dem gleichen Effekt können Sie es jedoch
force-command
direkt in das Zertifikat einbetten - in den Abschnitt
Critical Options:
. Dies kann für Dienstkonten hilfreich sein, die nur einen Befehl ausführen müssen, z. B. eine Aufgabe auf einem Remote-System starten.
Verbindungen nach Adressen einschränken
Um den Umfang eines Zertifikats einzuschränken, kann eine Liste zulässiger IP-Adressen (CIDR-Blöcke) darin eingebettet werden.Hier ist eine Zertifikatvorlage, die beide
source-address
und verwendet
force-command
.
{
"type": {{ toJson .Type }},
"keyId": {{ toJson .KeyID }},
"principals": {{ toJson .Principals }},
"extensions": {{ toJson .Extensions }},
"criticalOptions": {
"force-command": "echo \"Hello World\"",
"source-address": "10.20.30.0/24,1.1.1.1/32"
}
}
Dies ist ein normales Beispiel, aber hier ist die IP-Liste starr festgelegt und ändert sich nicht. Und normalerweise möchten wir unterschiedliche Adresslisten für unterschiedliche Benutzer verwenden. Lass es uns versuchen…
Fügen Sie unterschiedliche Werte für unterschiedliche Benutzer ein
Offensichtlich können Benutzer nicht das Recht erhalten, den Adressbereich zu bearbeiten. Daher müssen dynamische Werte aus einer zuverlässigen Quelle stammen.Zu diesem
step-ca
Zweck können Sie über den OpenID Connect (OIDC) -Anbieter den OAuth-Anbieter so konfigurieren, dass dem Token mit CIRD-Adressblöcken, die wir dem Zertifikat dieses Benutzers hinzufügen möchten, benutzerdefinierte Ansprüche hinzugefügt werden.
Der OIDC-Anbieter ist der perfekte Weg, um SSH-Zertifikate an step-ca auszustellen. In dem Artikel DIY Single Sign-On für SSH wurde erläutert, wie eine SSH-Zertifizierungsstelle so konfiguriert wird, dass kurzfristige SSH-Zertifikate mithilfe von ID-Token eines vertrauenswürdigen OAuth-Anbieters ausgestellt werden. Wenn eine
step-ca
Als vertrauenswürdiger OAuth-Client konfiguriert, liest er das Feld
email
aus dem ID-Token und ruft von dort die Liste der SSH-Zertifikatprinzipale ab (z. B.
carl@smallstep.com
Zertifikate für das Feld
carl
und wird von diesem generiert
carl@smallstep.com
).
OIDC ermöglicht jedoch das Lesen von IDs und anderen Feldern von Token über Vorlagen . Hier beginnt die wahre Magie. Daher fügen wir dem Benutzerverzeichnis auf der Seite des Identitätsanbieters ein separates Feld hinzu
source_address
- und spiegeln es in unserem ID-Token wider. Anschließend können Sie über die SSH-Vorlage den Wert aus dem Token in das Zertifikat eingeben. Hier ist die Vorlage:
{
"type": {{ toJson .Type }},
"keyId": {{ toJson .KeyID }},
"principals": {{ toJson .Principals }},
"extensions": {{ toJson .Extensions }},
{{ if .Token.source_address }}
"criticalOptions": {
"source-address": "{{ .Token.source_address }}"
}
{{ else }}
"criticalOptions": {{ toJson .CriticalOptions }}
{{ end }}
}
GitHub-Authentifizierung durch Zertifikat
Schauen wir uns ein weiteres Beispiel für einen benutzerdefinierten Anspruch an. Mit GitHub Enterprise Cloud oder GitHub Enterprise Server können Sie GitHub für die Verwendung von SSH-Zertifikaten konfigurieren. Insbesondere vertraut GitHub Ihrer SSH-Zertifizierungsstelle . Damit alles funktioniert, müssen Sie für jeden Benutzer ein separates SSH-Zertifikat mit einer Erweiterung erstellenlogin@github.com
, die den Benutzernamen auf GitHub angibt. Mit dieser Erweiterung authentifiziert das Zertifikat den Benutzer bei GitHub Enterprise. Und es ist großartig: Mit demselben Zertifikat können Sie sowohl über SSH eine Verbindung zu Ihrem Server herstellen als auch den Code an GitHub senden.
Hier ist eine Zertifikatvorlage mit Unterstützung für benutzerdefinierte GitHub-Erweiterungen:
{
"type": {{ toJson .Type }},
"keyId": {{ toJson .KeyID }},
"principals": {{ toJson .Principals }},
"criticalOptions": {{ toJson .CriticalOptions }},
{{ if .Token.ghu }}
"extensions": {
"login@github.com": {{ toJson .Token.ghu }}
}
{{ else }}
"extensions": {{ toJson .Extensions }}
{{ end }}
}
Um die Vorlage zu verwenden, müssen Sie den OIDC-Identifikationstoken eine individuelle Anforderung
ghu
(„GitHub-Benutzername“) hinzufügen . Schauen wir uns genauer an, wie Sie diesen benutzerdefinierten Anspruch mit Ihrem OAuth-Anbieter erstellen.
Registrieren einer Anwendung bei einem Identitätsanbieter
Nicht alle Identitätsanbieter unterstützen individuelle Anforderungen, aber wenn doch, ist der Prozess ziemlich ähnlich. So geht's mit Okta:- Fügen Sie die OAuth-App zu Okta hinzu und vertrauen Sie sie dem OIDC-Anbieter an,
step-ca
wie im Artikel DIY SSO für SSH beschrieben .
- Fügen Sie Ihrem Okta-Benutzerverzeichnis ein neues Feld hinzu (zum Beispiel
GitHub Username
)
- Fügen Sie dem OIDC-Token eine individuelle Anforderung hinzu , z. B. einen Kurznamen
ghu
- Jetzt füllen wir das Feld für den Testbenutzer aus und überprüfen die Anforderung. Okta verfügt über ein Tool zum Testen von ID-Token. Oder kann verwendet werden
step
, um den gesamten OAuth-Fluss zu validieren:
OIDC_ENDPOINT="https://[your organization].okta.com/oauth2/default/.well-known/openid-configuration" CLIENT_ID="[your OAuth client ID]" CLIENT_SECRET="[your OAuth client secret]" step oauth --oidc --provider $OIDC_ENDPOINT \ --client-id $CLIENT_ID --client-secret $CLIENT_SECRET \ --listen=":10000" --bare | step crypto jwt inspect --insecure
- Schließlich,
step-ca
um dieses Muster zu verwenden. Die Provider-Konfiguration sollte auf die Vorlagendatei verweisen:
{ "provisioners": [ { "type": "OIDC", "name": "Okta", "clientID": "[your OAuth client ID]", "clientSecret": "[your OAuth client secret]", "configurationEndpoint": "https://[your organization].okta.com/oauth2/default/.well-known/openid-configuration", "listenAddress": ":10000", "options": { "ssh": { "templateFile": "templates/certs/ssh/github.tpl" } } }, ... ] }
Was weiter
Wir haben der Dokumentation einen Abschnitt zu SSH-Vorlagen hinzugefügt , in dem alle Parameter und Variablen ausführlicher beschrieben werden.
Wenn Sie Fragen haben, zögern Sie nicht zu fragen .