Exemples d'utilisation intelligente des modèles SSH





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 (avec ssh -X



    ) pour exécuter des programmes X11 distants sur l'écran local.

  • permit-agent-forwarding



    : Permet à la redirection de l'agent (à l'aide de ssh -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écuter ssh -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 extension login@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:



  1. 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 .





  2. Ajoutez un nouveau champ à votre répertoire d'utilisateurs Okta (par exemple GitHub Username



    )

  3. Ajouter une exigence individuelle au jeton OIDC , par exemple, avec un nom courtghu





  4. 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
          
          





  5. 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 .



All Articles