Pourquoi et comment utiliser un certificat SSH utilisateur

22-12-2023

Passé la toute première connexion (et le potentiel TOFU), l’usage de SSH est lié à un utilisateur : c’est l’utilisateur qui cherche à se connecter pour faire ses opérations sur le serveur distant.

Pour cette connexion, on connaît habituellement deux options : le mot de passe et la clé SSH, mais puisqu’un mot de passe ne sera jamais aussi sécurisé qu’une clé SSH, on favorise cette dernière. Mais même elle a des défauts notables.

Le problème de la clé SSH

Le cycle de vie d’une clé SSH se déroule de la façon suivante :

  1. Création par ssh-keygen
  2. Copie sur le serveur distant par ssh-copy-id ou par un tiers pré-établi
  3. Usage

Ce cycle de vie souffre de plusieurs problèmes : tout d’abord, la clé doit être copiée sur tous les serveurs où l’on veut se connecter, ce qui est un vrai frein à l’industrialisation. Ensuite, et c’est le plus grave puisqu’il touche à la sécurité : la clé ne vit pas. Une clé SSH est éternelle, ce qui pose question en cas de perte / vol, de départ de l’employé de l’entreprise ou de la péremption de l’algorithme de sécurité.

Dans tous les cas, changer de clé signifie recommencer tout le processus puisque chaque serveur est responsable de ses propres accès.

Pour passer à l’échelle et nous assurer que le temps soit toujours à notre avantage, on va choisir une meilleure option. La bonne nouvelle, c’est qu’à l’instar du certificat d’hôte que nous avions précédemment vu, il existe un certificat SSH utilisateur.

Techniquement, qu’est-ce-que ça change vis-à-vis d’une clé simple ? Voyons ça :

comparaison cinétique clé et certificat ssh

NB: nous ne rentrerons pas dans le détail du handshaking ou du partage de clé de session.

Comme on le voit, bien que le processus général semble identique (contact, publication d’identifiant, challenge, entrée), sous le manteau il n’en est rien : en passant par un certificat, le serveur évalue plus de critères pour certifier l’accès, y compris un TTL (Time To Live, une durée de vie). L’identification est plus précise et donc plus sécurisée.

De plus, il n’est pas nécessaire d’installer quoi que ce soit sur le serveur pour la reconnaissance du client, ce qui est plutôt pratique pour l’industrialisation. Comment cela peut-il marcher ? C’est ce que nous allons voir dans la partie suivante.

Mettre en place un certificat SSH utilisateur

Le client

Un certificat étant une clé publique SSH avec quelques options en plus, nous allons commencer par créer une bi-clé pour notre utilisateur :

> cd ~/.ssh
> ssh-keygen -f rsa_root
> ssh-keygen -lf rsa_root.pub
3072 SHA256:ILCFjk8HcDOmwSpx7Z/O0RiK9FVr7U2L18fhfjizB/U root@client-ssh (RSA)

La clé publique sera alors signée par une autorité de certification pour devenir un certificat. Cette signature est l’étape la plus sensible puisque c’est sur elle que repose toute la sécurité, on la réalise donc sur le serveur d’autorité pour garantir une confidentialité maximale. Nous n’aborderons pas dans ce billet-ci les différentes possibilités de publication de la clé vers l’autorité.

L’autorité

Nous voilà sur l’autorité avec une clé transmise par l’utilisateur :

> ls /tmp/
rsa_root.pub

Comme nous l’avons vu plus haut, qui dit « certificat » dit « certification », commençons donc par créer la clé servant à authentifier les utilisateurs :

> mkdir -p /root/.ssh/authority && cd /root/.ssh/authority
> ssh-keygen -f user_ca -C "users authentication"
> ssh-keygen -lf user_ca.pub
3072 SHA256:JbsSc159zTpZJTfXseScMyFsSdyJbtROwyf6DPQ8u3A users authentication (RSA)

Puis signons la clé que le client nous a envoyée :

> cd /tmp
> ssh-keygen -s /root/.ssh/authority/user_ca -I 'CA' -n root -V +60m  ./rsa_root.pub

Le certificat ./rsa_root-cert.pub est automatiquement généré. Observons ce qu’il contient :

> ssh-keygen -Lf ./rsa_root-cert.pub
rsa_root-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:ILCFjk8HcDOmwSpx7Z/O0RiK9FVr7U2L18fhfjizB/U
        Signing CA: RSA SHA256:JbsSc159zTpZJTfXseScMyFsSdyJbtROwyf6DPQ8u3A (using rsa-sha2-512)
        Key ID: "CA"
        Serial: 0
        Valid: from 2023-12-16T12:48:00 to 2023-12-16T12:54:51
        Principals:
                root
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

Où :

  • le « principal » est l’utilisateur cible du certificat (on verra cela un peu plus loin),
  • notre certificat possède bien un TTL,
  • l’empreinte de la clé publique correspond à celle de l’utilisateur,
  • l’empreinte de la clé de signature correspond à celle de l’autorité.

Il ne nous reste plus qu’à dire à notre serveur SSH de reconnaître l’autorité de signature pour les connexions utilisateurs :

echo "TrustedUserCAKeys /root/.ssh/authority/user_ca.pub" >> /etc/ssh/sshd_config
> systemctl restart sshd

/!\ L’autorité de certification est le point central de la sécurité des certificats, veillez donc à lui apporter une sécurité maximale.

Retour sur le client

Ici encore, partons du principe que le certificat a été reçu par le client via un moyen sécurisé quelconque :

ls /root/.ssh/
rsa_root  rsa_root-cert.pub  rsa_root.pub

La connexion s’opère de la façon suivante (on ne se préoccupe pas du TOFU ici) :

> ssh -o CertificateFile=/root/.ssh/rsa_root-cert.pub -i /root/.ssh/rsa_root user-ca-ssh
[...]
System services are namespaced; to access, use `ctr -n services.linuxkit ...`
(ns: sshd) user-ca-ssh:~# hostname
user-ca-ssh

On se connecte bien sur le serveur cible ! Et ceci sans avoir publié la moindre clé publique sur le serveur (le fichier authorized_keys est absent du serveur).

Qui, quoi, combien de temps ?

Puisqu’il n’y a rien d’installé sur le serveur, comment la correspondance de l’utilisateur peut fonctionner ? C’est tout simple, votre prétendue identité s’appuie sur le binôme clé privée / certificat et le principal du certificat sert à atteindre un utilisateur précis sur le serveur cible. Ainsi, tout ce que vous avez à faire pour un certificat donné, c’est que l’utilisateur existe bien là-bas. Dans le cas contraire, la connexion est refusée.

De la même façon, le TTL du certificat ne vous permet plus d’entrer une fois le délai passé. En conséquence, la bonne pratique est de définir des TTLs très court (< 1j). De toute façon, on redemandera un nouveau certificat en cas de besoin.

En termes de sécurité, le mainteneur du processus peut interdire la création de certificat pour un démissionnaire ou pour une clé corrompue. Dans le même temps, le déploiement est facile, qu’importe le nombre de serveurs et de clients.

En définitive, les certificats SSH sont plus pratiques et gagneraient à être davantage utilisés. Comme le dit l’un des articles en sources : « Si vous n’utilisez pas de certificat SSH, vous vous y prenez mal ! ». C’est un brin provocateur, mais je pense que c’est vrai. S’arrêter à la clé SSH c’est ne faire que la moitié du travail : c’est à la fois défaillant en termes de sécurité (tôt ou tard, votre protocole deviendra faible) et en termes d’industrialisation du déploiement.

Comme d’habitude, vous pouvez retrouver le code pour essayer par vous-même sur le dépôt d’exemple.


Sources :


    Ce billet vous a plu ? Inscrivez-vous à notre newsletter pour ne manquer aucun article (Si vous ne voyez pas le formulaire, désactivez temporairement uBlock).