Une compilation de documentations   { en , fr }

Présentation et utilisation des certificats SSH

Étiquettes:
Créé en:
Auteur:
Xavier Béguin

Utilisation habituelle des clefs SSH

La role de la confiance entre client et serveur

Les clefs SSH sont des outils puissants permettant notamment de garantir l'identité d'un interlocuteur sur le réseau sans avoir à échanger de secret partagé.

Pour se connecter à un serveur par SSH, il est nécessaire que le client ait confiance en l'identité de ce serveur (pour éviter les attaques de type attaque de l'homme du milieu). Et, bien entendu, avant d'accorder l'accès au système, le serveur doit avoir confiance en l'identité du client qui se connecte, pour n'autoriser l'accès au serveur qu'aux personnes autorisées.

La plupart du temps, ces deux types indépendants de vérification d'identité sont réalisés grâce aux clefs SSH de la manière que nous allons décrire ci-dessous avant de nous intéresser à l'utilisation des certificats SSH pour ces mêmes opérations.

Authentification du client par le serveur

Pour que le serveur fasse confiance au client qui tente de se connecter, l'administrateur du système doit placer la clef SSH publique de chaque utilisateur⋅rice dans le fichier ~/.ssh/authorized_keys du compte.

Lorsque le client se connecte, celui-ci utilise la clef SSH privée de l'utilisateur⋅rice, dont le serveur peut vérifier l'authenticité grâce à la clef publique correspondante conservée dans le fichier ~/.ssh/authorized_keys du compte auquel le client tente de se connecter.

Authentification du serveur par le client

Lors de sa première connexion à un serveur, le client enregistre une clef publique fournie par le serveur en supposant qu'il s'agit bien de la clef serveur de l'hôte auquel il cherche à se connecter.

Avant de lui faire confiance cependant, le client va demander à l'utilisateur⋅rice d'accepter la connexion et l'enregistrement de la clef du serveur. Cela se présente de cette manière :

~$ ssh lab.example.org
The authenticity of host 'lab.example.org (192.168.1.3)' can't be established.
ECDSA key fingerprint is SHA256:wxocsOPNEfYuuTcXGuitKR8RUowpGbgpXTEsXXirAFI.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'lab.example.org' (ECDSA) to the list of known hosts.

Si l'utilisateur⋅rice accepte de se connecter à ce serveur, le client va enregistrer la clef du serveur dans son fichier ~/.ssh/known_hosts (indexée avec une valeur de hashage calculée avec le nom du serveur tel qu'il a été donné au client SSH).

La commande ssh-keygen -F <hôte> permet de rechercher la clef d'une machine dans le fichier ~/.ssh/known_hosts. Par exemple :

~$ ssh-keygen -F lab.example.org
# Host lab.example.org found: line 133
|1|4M/wUtH5ptcDaJ7BwKPcpci6iZA=|Ba7Gk24pQ4qdIg4hR5KVIjdGo7Y= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNo(...)3+Ciz9DgKW2yAX7g26E73LWSI=

Lors des connexions suivantes, le client va rechercher de la même façon dans le fichier ~/.ssh/known_hosts la clef publique du serveur. Si la clef publique ainsi conservée correspond bien à la clef privée utilisée par le serveur, le client va faire confiance au serveur et procéder ensuite à sa propre authentification. Si ce n'est pas le cas, le client interrompt la connexion et affiche à l'utilisateur⋅rice un message lui indiquant que le serveur auquel il ou elle tente de se connecter n'a plus la même clef SSH que lors de sa dernière connexion, ce qui indique que le serveur n'est peut-être pas celui auquel il ou elle souhaite se connecter.

On remarque qu'une faiblesse du protocole existe à ce niveau puisqu'à la première connexion, l'utilisateur⋅rice qui accepte aveuglément la clef SSH du serveur prend le risque de se connecter à un serveur qui n'est pas celui qu'il croit être.

Ce risque peut être écarté si les clefs publiques des serveurs sont distribuées par d'autres moyens aux utilisateur⋅rice⋅s pour les ajouter à leur fichier known_hosts, leur permettant ainsi d'authentifier le serveur dès leur première connexion.

Une variante de cette solution est facilitée dans les versions récentes d'OpenSSH où, comme on le voit dans l'exemple ci-dessus, au lieu de répondre yes ou no à la question du client demandant s'il faut se connecter à ce serveur, celui-ci donne la possibilité de fournir l'empreinte de la clef SSH attendue. La connexion se fera alors uniquement si celle-ci correspond bien à l'empreinte de la clef donnée par le serveur (ce qui est plus fiable que de vérifier visuellement l'empreinte affichée par le client).

Utilisation de SSH basée sur les certificats

Comme on vient de la voir ci-dessus, dans l'utilisation habituelle des clefs SSH :

  • le serveur authentifie les clients à l'aide de clefs SSH conservées dans les fichiers ~/.ssh/authorized_keys des comptes utilisateur⋅rice⋅s ;
  • le client authentifie le serveur auxquel il se connecte grâce à la clef publique présentée par le serveur à la première connexion et conservée ensuite dans un fichier known_hosts.

Avec les certificats, le serveur comme le client continuent d'utiliser leur paire de clefs, mais chacun utilise en plus un certificat qui consiste en une signature de la clef SSH à laquelle le certificat est associé, faite par une clef représentant l'autorité de certification, augmentée d'une identité, d'un nom-clé (c'est la traduction que je propose d'utiliser dans ce document pour le terme technique anglais principal), et de quelques options.

Ainsi, au lieu d'accorder leur confiance aux clefs publiques conservées dans les fichiers authorized_keys, le serveur n'aura à accorder sa confiance qu'à une seule clef publique, représentant l'autorité de certification qui crée ces certificats et permet de vérifier l'authenticité des clefs SSH.

De même, au lieu que le client ait à maintenir une liste de clefs publiques de confiance des serveurs dans son fichier known_host, il n'aura qu'à faire confiance à la clef publique de l'autorité de certification qui fournit les certificats SSH.

Mise en œuvre pratique des certificats

Deux autorités de certifications distinctes

En pratique, la paire de clefs représentant l'autorité de certification qui génère les certificats n'est qu'une simple paire de clefs SSH, comme celles utilisées pour l'authentification des serveurs ou des clients.

Il est conseillé d'utiliser une paire de clefs d'autorité de certification différente pour les serveurs et les clients. Rien n'y oblige, mais c'est une mesure cohérente puisque l'authentification des serveurs et celle des clients, bien qu'utilisant la même méthode, sont deux opérations indépendantes.

Génération des clefs des autorités de certification

On génère tout d'abord les deux paires de clefs qui nous serviront d'autorités de certification (AC), l'une pour les certificats serveurs, l'autre pour les certificats clients, à l'aide de la commande ssh-keygen, comme on le fait pour toute clef SSH.

Ces clefs peuvent être de n'importe quel type, nous utiliserons ici ed25519 (ecdsa ou d'autres types peuvent aussi être utilisés). L'option -C utilisée ci-dessous nous permet de bien différencier les deux clefs publiques en précisant un commentaire :

ssh-keygen -a 256 -t ed25519 -C 'AC serveurs' -f ac_serveurs
ssh-keygen -a 256 -t ed25519 -C 'AC clients' -f ac_clients

Il est conseillé d'utiliser une longue phrase de passe pour protéger correctement ces clefs particulièrement sensibles, et de ne les utiliser que sur un serveur correctement isolé.

L'option -a utilisée dans les commandes ci-dessus n'est pas strictement nécessaire mais permet de préciser le nombre d'applications de la fonction de dérivation de clef (KDF, key derivation function) utilisé pour protéger la clef privée par sa phrase de passe.

Lorsque cette option n'est pas précisée, par défaut 16 applications sont effectuées. Comme l'indique la page de manuel ssh-keygen(1), (en anglais), « un nombre plus important résulte en une vérification de la phrase de passe plus lente et une meilleure résistance au déchiffrement par force brute du mot de passe (au cas où les clefs étaient volées) ». La phrase de passe n'étant vérifiée que lors du chargement de la clef et le ralentissement de cette vérification étant peu important, il est recommandé d'augmenter ce nombre.

Voici par exemple ce qu'afficherait une de ces commandes lors de son utilisation :

# ssh-keygen -a 256 -t ed25519 -C 'AC serveurs' -f ac_serveurs
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ac_serveurs
Your public key has been saved in ac_serveurs.pub
The key fingerprint is:
SHA256:e7wnSbMmyStx4K0+Mk3dj/03m/bI4Fk823EL0WdD8l4 AC serveurs
The key's randomart image is:
+--[ED25519 256]--+
|                 |
|                 |
|             . . |
|      .       =  |
|     . +S.   . +E|
|      + +o+  .o.+|
|     o =.ooB..+o.|
|    o = +.*o+=.B*|
|     +.o.+.oo.*=*|
+----[SHA256]-----+

Création d'un certificat client

Un certificat est généré pour un client en signant, à l'aide de la clef de l'autorité de certification (ac_clients dans notre cas), la clef publique générée par l'utilisateur⋅rice :

ssh-keygen -s /chemin/vers/ac_clients -I id_clef -n identifiant /chemin/vers/clef_utilisateur.pub

Dans cette commande :

  • -s /chemin/vers/ac_clients indique le chemin vers la clef privée représentant l'autorité de certification à utiliser pour les certificats clients ;
  • -I id_clef indique une identité qui peut être choisie librement et contenir des espaces (les caractères accentués ne sont toutefois pas correctement affichés). Elle sera consignée dans les journaux système lors de l'utilisation du certificat et pourra être utilisée en cas de révocation du certificat si celui-ci n'a pas de numéro de série (voir mon article « Les listes de révocation de clefs sous OpenSSH ») ;
  • -n nom1,nom2,… précise un ou plusieurs noms-clés (principals en anglais) dans le certificat :
    • pour un certificat client, au moins un nom-clé doit être précisé pour désigner le nom du compte sous lesquels l'utilisateur⋅rice pourra se connecter (on peut en préciser plusieurs, séparés par des virgules),
    • si le nom du compte utilisateur⋅rice cible n'est pas présent dans les noms-clés du certificat, l'authentification échouera et vous retrouverez une erreur du type « error: Certificate invalid: name is not a listed principal » dans les journaux du système (auth.log sous Debian),
    • si aucun nom-clé n'est présent dans le certificat, l'authentification va échouer avec une erreur du type « error: Certificate lacks principal list » dans les journaux système (auth.log sous Debian). (bien que ceci paraisse en contraction avec le manuel ssh-keygen(1) qui indique que « par défaut, les certificats générés sont valables pour tous les utilisateur⋅rice⋅s et tous les hôtes. ») ;
  • /chemin/vers/clef_utilisateur.pub est l'argument qui désigne la clef publique de l'utilisateur⋅rice à laquelle correspondra le certificat.

Exemple de génération d'un certificat à partir de la clef publique id_ed25519.pub pour un⋅e utilisateur⋅rice (la phrase de passe demandée ci-dessous est celle qui protège la clef privée ac_clients) :

# ssh-keygen -s ac_clients -I "Herschel Krustofski" -n krusty id_ed25519.pub
Enter passphrase:
Signed user key id_ed25519-cert.pub: id "Herschel Krustofski" serial 0 valid forever

Le certificat créé par cette opération sera écrit dans le fichier id_ed25519-cert.pub du même répertoire que celui de la clef fournie en argument (ici, il s'agit du répertoire courant).

Un certificat peut être examiné à l'aide de l'option -L de ssh-keygen :

$ ssh-keygen -L -f id_ed25519-cert.pub
id_ed25519-cert.pub:
        Type: ssh-ed25519-cert-v01@openssh.com user certificate
        Public key: ED25519-CERT SHA256:QfLKGkjku0mCMS9bTJPtuCkie3Cr158kb9C7axTYXRE
        Signing CA: ED25519 SHA256:iuqKv2w9iXf+Cj3+0+/EqPxghEYAbWJQuReDkZXtBYs (using ssh-ed25519)
        Key ID: "Herschel Krustofski"
        Serial: 0
        Valid: forever
        Principals:
                krusty
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

Utilisation d'un certificat client

Côté serveur SSH

Pour que le serveur SSH reconnaisse la validité des signatures dans les certificats présentés par les clients SSH qui se connectent à lui, il doit disposer de la clef publique du certificat qui a servi à les générer (dans notre exemple, il s'agit donc de la clef conservée dans le fichier ac_clients.pub).

Cette clef doit figurer dans un fichier qui doit être référencé dans le fichier de configuration du serveur SSH (/etc/ssh/sshd_config sous les systèmes Debian GNU/Linux), à l'aide de la directive TrustedUserCAKeys :

TrustedUserCAKeys /etc/ssh/clefs_ac_clients

Ce fichier peut contenir plusieurs clefs ayant servi à générer des certificats clients. Nous pouvons y ajouter celle de notre exemple :

cat ac_clients.pub >> /etc/ssh/clefs_ac_clients

Le serveur SSH doit ensuite être redémarré pour tenir compte de cette nouvelle configuration :

service ssh restart

Un certificat présenté par un client ne sera par défaut considéré que lorsque sa liste de noms-clés (donnée par l'option -n lors de sa génération) contient le nom du compte auquel il tente de se connecter.

Il est cependant aussi possible d'accepter, pour chaque compte, une liste de noms-clés différents de ce nom de compte.

Il faut pour cela fournir un fichier spécifique à chaque compte qui sera consulté pour trouver la liste des noms-clés acceptés pour ce compte. Ces fichiers doivent être désignés à l'aide de la directive AuthorizedPrincipalsFile dans sshd_config.

L'argument de cette directive peut utiliser %u pour désigner l'identifiant du compte, %U pour l'uid du compte, et %h pour son répertoire personnel. Par exemple, pour utiliser un fichier pour chaque utilisateur⋅rice dans le répertoire /etc/ssh/auth_principals, on pourrait utiliser :

AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u

Au lieu d'utiliser un fichier, il est également possible de générer dynamiquement une liste de noms-clés acceptés pour un compte à l'aide d'une commande personnalisée qu'on devra désigner par une directive AuthorizedPrincipalsCommand et qui sera exécutée par l'utilisateur⋅rice désigné⋅e par AuthorizedPrincipalsCommandUser. Pour plus de détails, réferrez-vous à la description de ces directives dans le manuel sshd_config(5) (en anglais).

Côté client

Côté client, l'utilisateur⋅rice doit fournir sa clef SSH publique, id_ed25519.pub dans notre exemple, à l'administrateur⋅rice du serveur et il recevra en retour le certificat id_ed25519-cert.pub généré à partir de celle-ci et signé par l'autorité de certification client.

Elle ou il doit simplement placer ce fichier id_ed25519-cert.pub dans le même répertoire que le fichier id_ed25519 de sa clef SSH. Lors d'une connexion utilisant cette clef id_ed25519, le client SSH présentera alors automatiquement le certificat au serveur.

On peut aussi constater que notre agent SSH local charge automatiquement le certificat lorsqu'on y ajoute la clef :

~$ ssh-add -l
The agent has no identities.
~$ ssh-add ~/.ssh/id_ed25519
Enter passphrase for /home/herschel/.ssh/id_ed25519:
Identity added: /home/herschel/.ssh/id_ed25519 (herschel@laptop)
Certificate added: /home/herschel/.ssh/id_ed25519-cert.pub (Herschel Krustofski)
~$ ssh-add -l
256 SHA256:QfLKGkjku0mCMS9bTJPtuCkie3Cr158kb9C7axTYXRE herschel@laptop (ED25519)
256 SHA256:QfLKGkjku0mCMS9bTJPtuCkie3Cr158kb9C7axTYXRE herschel@laptop (ED25519-CERT)

L'utilisateur⋅rice n'a donc pas besoin de changer sa configuration par rapport à l'utilisation de sa clef SSH seule. Il suffit de la mentionner comme d'habitude :

  • avec l'option -i de ssh en ligne de commande, par exemple :
    ssh -i ~/.ssh/id_ed25519 lab.exemple.org
    
  • ou avec une directive IdentityFile dans son fichier de configuration client ~/.ssh/config (généralement dans une section Host), par exemple :
    IdentityFile ~/.ssh/id_ed25519
    

En supposant que le fichier ~/.ssh/authorized_keys du compte cible sur le serveur auquel on se connecte en utilisant la clef SSH soit vide, on constate que le serveur autorise malgré tout l'authentification par clef SSH grâce au certificat :

$ ssh -i ~/.ssh/id_ed25519 lab.exemple.org
Linux lab 5.10.0-22-amd64 #1 SMP Debian 5.10.178-3 (2023-04-22) x86_64
Last login: Thu May 11 11:05:23 2023 from 192.168.1.42
~$

On peut vérifier l'utilisation du certificat avec l'option -v du client ssh lors de la connexion :

$ ssh -v -i ~/.ssh/id_ed25519 lab.exemple.org
...
debug1: Will attempt key: /home/herschel/.ssh/id_ed25519 ED25519 SHA256:QfLKGkjku0mCMS9bTJPtuCkie3Cr158kb9C7axTYXRE explicit agent
debug1: Will attempt key: /home/herschel/.ssh/id_ed25519 ED25519-CERT SHA256:QfLKGkjku0mCMS9bTJPtuCkie3Cr158kb9C7axTYXRE explicit agent
...
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Offering public key: /home/herschel/.ssh/id_ed25519 ED25519 SHA256:QfLKGkjku0mCMS9bTJPtuCkie3Cr158kb9C7axTYXRE explicit agent
debug1: Authentications that can continue: publickey,password
debug1: Offering public key: /home/herschel/.ssh/id_ed25519 ED25519-CERT SHA256:QfLKGkjku0mCMS9bTJPtuCkie3Cr158kb9C7axTYXRE explicit agent
debug1: Server accepts key: /home/herschel/.ssh/id_ed25519 ED25519-CERT SHA256:QfLKGkjku0mCMS9bTJPtuCkie3Cr158kb9C7axTYXRE explicit agent
debug1: Authentication succeeded (publickey).
...
Linux lab 5.10.0-22-amd64 #1 SMP Debian 5.10.178-3 (2023-04-22) x86_64
Last login: Thu May 11 11:05:23 2023 from 192.168.1.42
~$

On remarque dans ces lignes de debuggage fournie par ssh que la clef SSH est d'abord fournie au serveur sans certificat. Puisqu'elle n'a pas été autorisée dans le fichier ~/.ssh/authorized_keys du compte distant, l'authentification échoue, et le client essaye à nouveau en présentant aussi le certificat, ce qui débouche cette fois sur une authentification réussie.

Ceci montre que l'utilisation « habituelle » des clefs SSH basée sur authorized_keys reste possible en même temps que l'utilisation du certificat, et qu'elle est tentée avant celle-ci par le client SSH.

Côté serveur, en cas de succès de l'authentification, on trouvera un message similaire à celui-ci dans les journaux système :

Accepted publickey for herschel from 192.168.1.42 port 40160 ssh2: ED25519-CERT SHA256:QfLKGkjku0mCMS9bTJPtuCkie3Cr158kb9C7axTYXRE ID Herschel Krustofski (serial 0) CA ED25519 SHA256:iuqKv2w9iXf+Cj3+0+/EqPxghEYAbWJQuReDkZXtBYs

Création d'un certificat serveur

Un certificat est généré pour un serveur en signant une de ses clefs publiques à l'aide de la clef de l'autorité de certification (ac_serveurs dans notre exemple) :

ssh-keygen -s /chemin/vers/ac_serveurs -I id_clef -h -n identifiant /chemin/vers/clef_hôte.pub

Dans cette commande :

  • -s /chemin/vers/ac_serveurs indique le chemin vers la clef privée représentant l'autorité de certification à utiliser pour les certificats serveurs ;
  • -I id_clef indique une identité qui peut être choisie librement et contenir des espaces (les caractères accentués ne sont toutefois pas correctement affichés). Elle sera mentionnée dans les informations émises par le client en mode verbeux (avec l'option -v de ssh) lors de l'utilisation du certificat et peut être utilisée en cas de révocation du certificat si celui-ci n'a pas de numéro de série (voir l'article « Révoquer des clefs et certificats SSH ») ;
  • -h doit être utilisée pour générer des certificats pour serveurs, contrairement aux certificats pour clients (si cette option est oubliée, le client refusera le certificat avec l'erreur « Certificate invalid: not a host certificate ») ;
  • -n nom1,nom2,… précise un ou plusieurs noms-clés (principals en anglais) à inclure dans le certificat. Pour un certificat serveur, ces identifiants doivent être le ou les noms DNS du serveur pour lesquels le certificat doit être valide (séparés par une virgule). Si aucun nom-clé n'est précisé, les clients SSH vont accepter le certificat pour n'importe serveur (tant qu'il est issu d'une autorité de certification de confiance, bien sûr).

Exemple de génération d'un certificat à partir de la clef publique ssh_host_ecdsa_key.pub pour un serveur lab.example.org (la phrase de passe demandée est celle qui protège la clef privée ac_serveurs) :

# ssh-keygen -s ac_serveurs -I "Serveur de test" -h -n lab.example.org,w1.example.org ssh_host_ecdsa_key.pub
Enter passphrase:
Signed host key ssh_host_ecdsa_key-cert.pub: id "Serveur de test" serial 0 for lab.example.org valid forever

Le certificat généré par cette opération sera écrit dans le fichier ssh_host_ecdsa_key-cert.pub du même répertoire que celui de la clef fournie en argument (ici, il s'agit du répertoire courant).

Ce certificat peut là encore être vérifié à l'aide de la commande ssh-keygen -L :

# ssh-keygen -L -f ssh_host_ecdsa_key-cert.pub
ssh_host_ecdsa_key-cert.pub:
        Type: ecdsa-sha2-nistp256-cert-v01@openssh.com host certificate
        Public key: ECDSA-CERT SHA256:wxocsORNEfXuuTcXGwitKR8RUompGbgpXTEsXXirAFI
        Signing CA: ED25519 SHA256:e7wnSbMmyStx4K0+Mk3dj/03m/bI4Fk823EL0WdD8l4 (using ssh-ed25519)
        Key ID: "Serveur de test"
        Serial: 0
        Valid: forever
        Principals:
                lab.example.org
                w1.example.org
        Critical Options: (none)
        Extensions: (none)

Utilisation du certificat serveur

Côté serveur SSH

Le certificat ainsi généré doit être référencé dans la configuration du serveur SSH (son fichier sshd_config) à l'aide d'une directive HostCertificate :

HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub

Ce certificat doit correspondre à l'une des clefs désignées explicitement ou implicitement (par ses valeurs par défaut) par une directive HostKey. Dans notre cas, le certificat correspond bien à la clef /etc/ssh/ssh_host_ed25519_key utilisée par défaut par le serveur SSH.

Comme après toute modification de la configuration du serveur SSH, celui-ci doit être redémarré pour tenir compte de sa nouvelle configuration :

service ssh restart

Le serveur SSH propose aux clients qui se connectent des clefs d'hôte utilisant différents types de clefs (chacun basé sur un algorithme différent), et le client va choisir le type qu'il préfère utiliser selon une liste précisée dans sa configuration (définie par la directive HostKeyAlgorithms).

Notez que, par défaut, cette liste prend en compte les certificats avant toute clef. Cela signifie que la sélection des types de certificats par le client est indépendante de celle des types de clefs.

Côté client

Le client reçoit un certificat fourni par le serveur SSH lors de sa connexion. Il a alors besoin de la clef publique de l'autorité de certification ayant servi à l'établir pour pouvoir vérifier que la signature de la clef publique du serveur incluse dans le certificat a bien été réalisée par cette autorité.

Il est donc nécessaire de désigner au client la clef publique de l'autorité de certification. Ceci doit être fait dans le fichier de configuration du client SSH ~/.ssh/known_hosts.

Cette désignation est effectuée à l'aide d'une ligne commençant par @cert-authority :

  • un motif ou une liste de motifs séparés par des virgules doit être fourni en premier paramètre pour indiquer à quels serveurs s'applique cette clef d'autorité ;
  • dans ces motifs, * correspond à une série de caractères, et ? à un caractère quelconque ;
  • le motif « * » utilisé seul indique que cette clef peut signer les certificats de n'importe quel serveur ;
  • le reste de la ligne fournit le type de clef et la clef encodée en base64.

Voici quelques exemples désignant des clefs d'autorités de certification :

@cert-authority * ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICSsDZABRKynUuiV5kyfDEgmwEgZ8a1pCsuRficEksDU Autorité de certification
@cert-authority *.sub.example.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICSsDZABRKynUuiV5kyfDEgmwEgZ8a1pCsuRficEksDU Autre autorité de certification
@cert-authority *.example.com,*.example.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICSsDZABRKynUuiV5kyfDEgmwEgZ8a1pCsuRficEksDU AC de Bidon SARL

Une fois la clef publique de l'autorité de certification précisée, le client pourra automatiquement authentifier les serveurs présentant un certificat qu'elle a créé.

L'utilisation du mot-clef @cert-authority dans un fichier known_hosts est décrite dans la section SSH_KNOWN_HOSTS FILE FORMAT du manuel sshd(8) (en anglais).

Cette section précise notamment que le client SSH compare le motif donné en argument du mot-clef @cert-authority avec :

  • le nom du serveur tel qu'il a été fourni par l'utilisateur⋅rice ;
  • ou le nom désigné par la directive HostKeyAlias si la connexion a été configurée dans le fichier ~/.ssh/ssh_config et qu'une telle directive a été utilisée ;
  • ou encore avec le nom canonique du serveur si la directive CanonicalizeHostname a été utilisée dans ~/.ssh/ssh_config.

L'option -v de la commande ssh permet de vérifier si nécessaire que le certificat a bien été utilisé par le client SSH, et donne des informations utiles si ce n'est pas le cas. Voici des exemples de messages affichés par ssh dans différents cas de figure :

  • dans le cas positif où le nom du serveur auquel on cherche à se connecter correspond bien au motif d'une ligne @cert-authority, que le certificat donné par le serveur comprend bien le nom complet du serveur dans ses noms-clés (ou qu'il n'a aucun nom-clé), et que la signature de la clef est valable, tout fonctionnera comme voulu et la commande affichera les messages suivants (avant de s'authentifier lui-même auprès du serveur) :
    ~$ ssh -v lab.example.org
    OpenSSH_8.4p1 Debian-5+deb11u1, OpenSSL 1.1.1n  15 Mar 2022
    ...
    debug1: Server host certificate: ecdsa-sha2-nistp256-cert-v01@openssh.com SHA256:wxocsORNEfXuuTcXGwitKR8RUompGbgpXTEsXXirAFI, serial 0 ID "Serveur de test" CA ssh-ed25519 SHA256:e7wnS
    bMmyStx4K0+Mk3dj/03m/bI4Fk823EL0WdD8l4 valid forever
    debug1: Host 'lab.example.org' is known and matches the ECDSA-CERT host certificate.
    debug1: Found CA key in /home/herschel/.ssh/known_hosts:1
    ...
    [suivent les messages relatifs à l'authentification de l'utilisateur⋅rice]
    
  • dans le cas où aucun motif donné avec un mot-clef @cert-authority ne correspond au nom du serveur, ou que le certificat qui correspond n'a pas été établi par la clef d'autorité configurée, le message « No matching CA found » sera indiqué et le client va utiliser la méthode habituelle de validation de la clef publique du serveur en la cherchant dans le fichier known_hosts et en proposant à l'utilisateur⋅rice de l'y ajouter si elle n'y est pas :
    ~$ ssh -v lab.example.org
    ...
    debug1: Server host certificate: ecdsa-sha2-nistp256-cert-v01@openssh.com SHA256:wxocsORNEfXuuTcXGwitKR8RUompGbgpXTEsXXirAFI, serial 0 ID "Serveur de test" CA ssh-ed25519 SHA256:e7wnS
    bMmyStx4K0+Mk3dj/03m/bI4Fk823EL0WdD8l4 valid forever
    debug1: No matching CA found. Retry with plain key
    The authenticity of host 'lab.example.org (192.168.1.3)' can't be established.
    ECDSA key fingerprint is SHA256:wxocsORNEfXuuTcXGwitKR8RUompGbgpXTEsXXirAFI.
    Are you sure you want to continue connecting (yes/no/[fingerprint])?
    
  • enfin, si le nom-clé du certificat est example.org et qu'on cherche à se connecter à lab.example.org (ou tout autre nom ne figurant pas dans les noms-clés), on obtiendra en plus le message « Certificate invalid: name is not a listed principal » (à moins que la liste de noms-clefs soit vide, auquel cas le client acceptera tout certificat valide) :
    ~$ ssh -v lab.example.org
    ...
    debug1: Server host certificate: ecdsa-sha2-nistp256-cert-v01@openssh.com SHA256:wxocsORNEfXuuTcXGwitKR8RUompGbgpXTEsXXirAFI, serial 0 ID "Serveur de test" CA ssh-ed25519 SHA256:e7wnS
    bMmyStx4K0+Mk3dj/03m/bI4Fk823EL0WdD8l4 valid forever
    debug1: Host 'lab.example.org' is known and matches the ECDSA-CERT host certificate.
    debug1: Found CA key in /home/herschel/.ssh/known_hosts:1
    Certificate invalid: name is not a listed principal
    debug1: No matching CA found. Retry with plain key
    ...
    

Options supplémentaires acceptées dans les certificats

Numéro de série

On a pu voir dans les exemples d'affichage de certificats (avec ssh-keygen -L) ci-dessus que des options supplémentaires sont acceptées dans ces certificats, en plus de celles décrites dans les sections précédentes.

Parmi celles-ci, un numéro de série (indiqué par Serial: lors de l'affichage des certificats) peut être précisé lors de la génération du certificat grâce à l'option -z de la commande ssh-keygen. Il permettra de distinguer le certificat des autres certificats générés par l'autorité de certification (ce qui peut notamment être utile pour désigner un certificat dans une liste de révocation de clefs – Key Revocation Lists, ou KRLs, décrits dans mon article « Les listes de révocation de clefs sous OpenSSH »).

Intervalle de validité

La validité (indiquée par Valid: dans les affichages de certificats plus haut) peut être précisée à l'aide de l'option -V de ssh-keygen. Si une seule spécification de temps est fournie, alors le certificat sera valable entre le moment présent et la date précisée. Si deux spécifications de temps sont fournies, séparés par un deux-points :, alors le certificat sera valable uniquement dans cet intervalle.

Une spécification de temps peut être une date précisée au format YYYYMMDD ou YYYYMMDD-HHMM[SS], ou une date relative au temps présent, telles que décrites à la section TIME FORMATS du manuel sshd_config(5) (en anglais), par exemple « -15d » pour 15 jours dans le passé, ou « +5w3d » pour 5 semaines et 3 jours dans le futur.

Le temps de départ peut aussi être always pour indiquer que le certificat n'a pas de date de début de validité, et celui de fin peut être forever pour indiquer que le certificat n'a pas de date d'expiration. Ces deux mots-clefs représentent les valeurs par défaut si aucun interval de validité n'est précisé.

Autres options

Des options supplémentaires peuvent être précisées avec l'option -O option qui permettent de préciser des limitations d'utilisation du certificat selon son usage. Référez-vous à la section CERTIFICATES dans ssh-keygen(1) (en anglais) pour une description plus détaillée. Elles peuvent être utilisées pour interdire le transfert de port, d'agent, d'écran, forcer une commande, etc., comme on peut le faire avec les options des clefs SSH dans le fichier ~/.ssh/authorized_keys.