Hello,

Si comme moi vous aimez jouer avec la sécurité et avez peur de vous faire voler vos clés, il est intéressant de gérer plusieurs clés. Le soucis, c’est que pour chaque clé publique/privée que vous possédez, vous devez mettre à jour le fichier .ssh/authorized_keys sur les serveurs.

Si vous en avez 2 ou s’ils sont gérés automatiquement, ça va. Mais dès que vous commencez à avoir plusieurs dizaines de serveurs, c’est compliqué, voire décourageant.

Mais j’ai la solution ! Une fonctionnalité ajoutée dans OpenSSH 5.7 : la clé Certificate Authority.

Il s’agit d’une clé ordinaire (qui ne devra pas changer, c’est primordial) qui servira à signer vos autres clés. Seule cette clé sera présente sur les serveurs Cette signature pourra contenir une durée de validité (optionnelle, de quelques secondes à plusieurs années).

Dans mon cas, j’ai déjà une clé SSH dans ~/.ssh/id_rsa que j’utilise.

Étape 1: Générer le certificat, dans ~/.ssh/ssh_ca. Vous pouvez définir une passphrase, et je vous le recommande !

$ ssh-keygen -t ed25519 -f .ssh/ssh_ca
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in .ssh/ssh_ca.
Your public key has been saved in .ssh/ssh_ca.pub.
The key fingerprint is:
SHA256:SdBGz/qpFnrxLigQct4ljcECkchhAIEVLj+Fd/L7e+8 me@me
The key's randomart image is:
+--[ED25519 256]--+
|%O+o  .o.        |
|=o..o  .oo       |
|. o.++... o      |
|.oooo+o. o       |
| +oo o. S        |
|  o..  .o. .     |
|   .  .o +o      |
|    . o.+.o      |
|     . o+=.oE    |
+----[SHA256]-----+

Oh le joli palmier !

Étape 2: Placer le certificat sur la machine.

$ cat .ssh/ssh_ca.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIZPYggoD7jgezlDW0Vr0scXQSGUXTaYkUdGxxGbKKqp me@me

Sur la machine, dans le fichier .ssh/authorized_keys, on inscrit cette clé précédée de la mention cert-authority.

C’est à dire:

cert-authority ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIZPYggoD7jgezlDW0Vr0scXQSGUXTaYkUdGxxGbKKqp me@me

C’est bien, c’est court. Vive ed25519 ! (Pourquoi est-ce que court c’est bien ? Vive les champs TXT !)

Étape 3: Signer sa propre clé SSH.

$ ssh-keygen -s ~/.ssh/ssh_ca -I id_cle .ssh/id_rsa
Enter passphrase:
Signed user key .ssh/id_rsa-cert.pub: id "id_cle" serial 0 valid forever

L’id_cle est utilisé par le serveur et stocké dans les logs.

C’est sur cette commande que l’on peut ajouter les options de validité (et autre ;D).

Étape 4: Inspecter un certificat (bonus) Voilà, vous avez un fichier -cert.pub, mais vous avez oublié ce qu’il permettait de faire. Ah ces jeunes.

$ ssh-keygen -L -f ~/.ssh/id_rsa-cert.pub
/Users/me/.ssh/id_rsa-cert.pub:
        Type: ssh-ed25519-cert-v01@openssh.com user certificate
        Public key: ED25519-CERT SHA256:9x64M5e7vEsW4QZUrAz54KZ3xXF32Sqi6PkbvXRc16I
        Signing CA: ED25519 SHA256:OxUHTLxeKbsQu73k1jV/MxH2z9VxEkZLaN/Ib/QWZKc
        Key ID: "ma_clé"
        Serial: 0
        Valid: forever
        Principals: (none)
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

On peut voir tout ce que la clé autorise, sa durée de validité, le certificat utilisé … bien pratique !


Durée de validité:

Une durée de validité prend deux arguments : une date de début et une date de fin. L’usage courant est de spécifier uniquement la date de fin. Les deux exemples de la documentation sont :

  • +52w1d : valide 52 semaines et un jour

  • +4w:+8w valide pendant 8 semaines à partir du mois prochain (4 semaines) [Peut-être utile si vous préparez une clé par mois de l’année, par exemple !]

On précise cette option avec -V, avant le -s

Options:

Là, c’est super intéressant, donc suivez bien ! Un cas d’utilisation serait de générer une clé (permanente?) utilisée par votre système de backup sans avoir à toucher au fichier authorized_keys.

Le hic, c’est qu’il y a plein de combinaisons et plein de choses à dire… :( Dans l’ordre d’utilité:

  • clear: interdit tout. Radical Il faut alors utiliser permit-* et non no-*
  • no-pty: permet de désactiver l’attribution de pty. Pas le plus utile, mais permet d’interdire les shells (en autorisant sftp)
  • no-port-forwarding: interdit l’utilisation de SSH comme un proxy. (peut-être utile si SSH permet l’accès à d’autres hosts sur un réseau ‘privé’)
  • no-x11-forwarding: interdit l’interface graphique X11 (ça existe encore ça ?!)
  • force-command=command: force l’exécution de la commande SSH précisée ! <3
  • source-address=address_list: restreint les connexions aux adresses dans cette liste [séparateur: la virgule], au format IP (9.10.11.12) ou CIDR (1.2.3.432) ou même avec un nom d’hôte ou même un wildcard-nom-d’hôte.

Par exemple, pour autoriser toutes les machines du réseau SFR (avec le hostname par défaut), on utiliserait source-address=*.rev.sfr.net.

Ceux que j’utilise moins:

  • no-agent-forwarding empêche ssh-agent d’être transmis (si vous lui trouvez une utilité, faites moi signe)
  • no-user-rc empêche l’execution de ~/.ssh/rc (désactivé côté serveur pour ma part)

Les options sont séparées par une virgule et on les passe avec -O. Pareil, avant l’option -s.

Et c’est tout, vous pouvez utiliser votre clé SSH pour vous connecter : la clé privée/publique sont inchangées, et le fichier clé-cert.pub précise au serveur que le certificat a bien été utilisé.

Mon cas d’utilisation

J’utilise ce système pour gérer de manière centralisée mes accès aux machines. J’ai en ma possession un Raspberry Pi2 (que je considère extra-sûr, il n’a pas d’accès au réseau et je conserve précieusement la carte micro-SD), qui stocke mon certificat et me permet de générer les signatures (-cert.pub). J’ai sur mon ordinateur la clé publique du certificat (pour faciliter la copie) et les clés privées/publiques (j’en ai besoin pour me connecter …), une par mois, et elles sont toutes valides un mois … et pré-générées en avance. Sur mon téléphone, je conserve des clés SSH valides une semaine ou un mois (selon l’usage que je prévois) Mon serveur de backup a accès en SFTP (root) à mes machines, avec restriction de source-address. Je cherche encore comment autoriser uniquement l’accès en lecture, même si je considère (pour l’instant) que ma machine backups est sûre. Sa clé SSH est valide par périodes de 3 mois.

De manière générale, je n’utilise pas de passphrase sur mes clés SSH, à l’exception des clés de mon téléphone (que j’utilise peu) et du certificat. Je trouve ça inutile, casser une passphrase s’effectue en local sans limitation de vitesse, et il est je pense plus important de s’assurer de la sécurité de la private key.

Les points positifs

  • C’est génial ! Une fois que l’accès m’est autorisé à une machine, je gère mes privilèges selon mes appareils, sans déranger la gestion du fichier : une seule ligne m’appartient, elle est simple et lisible (on voit directement mon nom en bout de ligne).
  • Je gère les permissions au niveau du certificat et non au niveau des machines, donc si j’autorise “id_rsa” depuis “127.0.0.1”, c’est vrai pour toutes les machines.
  • Je peux révoquer une clé avec la liste de révocation (c’est pas simple, mais ça peut se faire)
  • C’est pas encore à la mode, mais ça change petit à petit ! :D
  • Il y a encore plein d’options à explorer ! Dans mon cas, je gère UN unique compte sur la machine (root quand tu nous tiens), mais il est possible d’utiliser un fichier de certificats centralisé et de signer les clés de chaque utilisateur … (Ainsi, on peut signer une clé et l’autoriser sur plusieurs comptes, même si ceux-ci n’ont pas de $HOME)

Les points négatifs

  • Il n’est pas possible d’utiliser plusieurs certificats pour signer la même clé.
  • Il n’est pas non plus possible de signer un certificat avec un certificat (ce qui résoudrait le premier point) … j’attends ceci avec impatience !
  • Beaucoup de services (Github, OVH Cloud, …) ne supportent pas ce format de clé (qui commence par cert-authorithy et non ssh-). Espérons que ça change.
  • Si vous utilisez OpenSSH-Server dans une ancienne version (vous ne devriez pas ;D), adieu ce support.
  • C’est hype. :D