Les certificats SSH sont un outil très puissant . Au départ, dans le centre de certification,
step-ca
nous n'avons implémenté qu'un ensemble minimal de fonctions pour l'authentification à l'aide de certificats d'utilisateur et d'hôte. Ensuite, nous avons ajouté des modèles de certificats X.509 et en août de l'année dernière - et des modèles SSH, dans la version 0.15.2. Enfin, nous avons documenté cette fonctionnalité et sommes prêts à en parler.
Les modèles de certificats SSH fonctionnent de la même manière que les modèles X.509: ce sont des fichiers JSON écrits en Go
text/template
. Ils sont utilisés pour configurer les certificats SSH qu'il émet
step-ca
. Jetons un coup d'œil à ce que sont ces modèles et comment vous pouvez les utiliser.
Par défaut, un modèle de certificat SSH personnalisé ressemble à ceci:
{
"type": {{ toJson .Type }},
"keyId": {{ toJson .KeyID }},
"principals": {{ toJson .Principals }},
"extensions": {{ toJson .Extensions }},
"criticalOptions": {{ toJson .CriticalOptions }}
}
Et voici le certificat SSH émis en utilisant ce modèle:
$ 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
Il permet à l'utilisateur
carl
(ou
carl@smallstep.com
) de s'authentifier auprès de tout hôte SSH qui fait confiance à mon autorité de certification SSH. Le certificat comprend quelques extensions de base:
permit-x11-forwarding
: Active le transfert X11 (avecssh -X
) pour exécuter des programmes X11 distants sur l'écran local.
permit-agent-forwarding
: Permet à la redirection de l'agent (à l'aide dessh -A
) de transférer les clés de l'agent SSH local vers l'hôte distant (pour plus d'informations sur l'agent SSH, voir ici ).
permit-port-forwarding
: Permet la redirection de port (tunneling) du port local vers le port distant (ssh -L
) ou distant vers local (ssh -R
).
permit-pty
: Une extension très importante. Si vous souhaitez ouvrir une session interactive dans la console, l'hôte doit vous allouer un pty (pseudo-tty). Sinon, aucune interactivité n'est fournie. Par exemple, pour tester l'authentification SSH sur GitHub, on peut exécuterssh -T git@github.com
(-T
désactive la requête pty).
permit-user-rc
: Exécutez un fichier RC personnel après la connexion (situé~/.ssh/rc
sur l'hôte distant).
Les certificats utilisateur et hôte prennent en charge les extensions et les paramètres critiques, mais OpenSSH ne définit aucune extension intégrée ni aucun paramètre critique pour les certificats hôte. Ainsi, tout ce qui est le plus intéressant se produit avec les certificats d'utilisateurs, donc dans cet article, nous ne les considérerons que.
Exemples de modèles de certificats
Apportons quelques modifications au modèle par défaut.
Interdiction d'agent et de redirection de port
Si les utilisateurs se connectent aux hôtes internes via l'hôte bastion , il serait bon de désactiver la redirection de port pour des raisons de sécurité. Vous ne voulez pas que les utilisateurs redirigent le trafic du serveur de production MySQL vers leur hôte local. De même, la redirection d'agent comporte un risque de sécurité . Voici un modèle qui supprime simplement ces deux extensions des certificats SSH:{
"type": {{ toJson .Type }},
"keyId": {{ toJson .KeyID }},
"principals": {{ toJson .Principals }},
"extensions": {
"permit-x11-forwarding": "",
"permit-pty": "",
"permit-user-rc": ""
},
"criticalOptions": {{ toJson .CriticalOptions }}
}
Intégration de la directive force-command
ForceCommand
Est une directive de configuration SSHD côté serveur qui exécute une commande alternative sur l'hôte au lieu d'un terminal interactif. Mais avec le même effet, vous pouvez l'intégrer
force-command
directement dans le certificat - dans la section
Critical Options:
. Cela peut être utile pour les comptes de service qui n'ont besoin d'exécuter qu'une seule commande, par exemple, démarrer une tâche sur un système distant.
Restriction des connexions par adresses
Pour restreindre la portée d'un certificat, une liste d'adresses IP autorisées (blocs CIDR) peut y être intégrée.Voici un modèle de certificat qui utilise à la fois
source-address
et
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"
}
}
C'est un exemple normal, mais ici la liste IP est fixée de manière rigide et ne change pas. Et nous souhaitons généralement utiliser différentes listes d'adresses pour différents utilisateurs. Essayons…
Insérer des valeurs différentes pour différents utilisateurs
De toute évidence, les utilisateurs ne peuvent pas avoir le droit de modifier la plage d'adresses. Par conséquent, les valeurs dynamiques doivent provenir d'une source fiable.Pour ce faire,
step-ca
via le fournisseur OpenID Connect (OIDC), vous pouvez configurer le fournisseur OAuth pour ajouter des revendications personnalisées au jeton contenant les blocs d'adresses CIRD que nous voulons ajouter au certificat de cet utilisateur.
Le fournisseur OIDC est le moyen idéal pour émettre des certificats SSH à step-ca. Dans l'article DIY Single Sign-On pour SSH , j'ai expliqué comment configurer une autorité de certification SSH pour émettre des certificats SSH à court terme à l'aide de jetons d'identification d'un fournisseur OAuth de confiance. Si un
step-ca
configuré en tant que client OAuth de confiance, il lira le champ à
email
partir du jeton d'ID et récupérera la liste des principaux de certificat SSH à partir de là (par exemple, les
carl@smallstep.com
certificats pour
carl
et seront générés par le champ
carl@smallstep.com
).
Mais OIDC permet de lire l'ID et d' autres champs à partir de jetons via des modèles . C'est là que la vraie magie commence. Ainsi, nous ajoutons un champ séparé à l'annuaire des utilisateurs du côté du fournisseur d'identité
source_address
- et le reflétons dans notre jeton d'identification. Ensuite, via le modèle SSH, vous pouvez entrer la valeur du jeton dans le certificat. Voici le modèle:
{
"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 }}
}
Authentification GitHub par certificat
Examinons un autre exemple de revendication personnalisée. À l'aide de GitHub Enterprise Cloud ou de GitHub Enterprise Server, vous pouvez configurer GitHub pour utiliser des certificats SSH. Plus précisément, GitHub fera confiance à votre autorité de certification SSH . Mais pour que tout fonctionne, vous devez créer un certificat SSH distinct pour chaque utilisateur avec une extensionlogin@github.com
qui spécifie le nom d'utilisateur sur GitHub. Avec cette extension, le certificat authentifie l'utilisateur auprès de GitHub Enterprise. Et c'est génial: le même certificat vous permet à la fois de vous connecter à votre serveur via SSH et de pousser le code vers GitHub.
Voici un modèle de certificat avec prise en charge de l'extension GitHub personnalisée:
{
"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 }}
}
Pour utiliser le modèle, vous devez ajouter une exigence individuelle
ghu
(«GitHub Username») aux jetons d'identification OIDC . Examinons de plus près comment créer cette revendication personnalisée à l'aide de votre fournisseur OAuth.
Enregistrement d'une application auprès d'un fournisseur d'identité
Tous les fournisseurs d'identité ne prennent pas en charge les exigences individuelles, mais s'ils le font, le processus est assez similaire. Voici comment procéder avec Okta:- Ajouter l'application OAuth à Okta et la confiance avec le fournisseur OIDC dans
step-ca
tel que décrit dans le bricolage SSO pour SSH article .
- Ajoutez un nouveau champ à votre répertoire d'utilisateurs Okta (par exemple
GitHub Username
)
- Ajouter une exigence individuelle au jeton OIDC , par exemple, avec un nom court
ghu
- Maintenant, nous remplissons le champ pour l'utilisateur du test et vérifions l'exigence. Okta dispose d'un outil de test de jeton d'identification. Ou peut être utilisé
step
pour valider l'ensemble du flux OAuth:
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
- Enfin,
step-ca
pour utiliser ce modèle. La configuration du fournisseur doit référencer le fichier modèle:
{ "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" } } }, ... ] }
Et après
Nous avons ajouté une section sur les modèles SSH à la documentation qui donne plus de détails sur tous les paramètres et variables.
Si vous avez des questions, n'hésitez pas à les poser .