Journal GnuPG et authentification SSH

Posté par  . Licence CC By‑SA.
Étiquettes :
22
26
juil.
2015

Vous avez maintenant votre clé PGP et la traînez un peu partout avec vous. Il s'agirait maintenant de mettre cette clé unique à profit. Et quoi de mieux que de commencer avec l'authentification SSH ?

Ça tombe bien, l'agent GnuPG peut aussi agir comme agent SSH et ainsi servir d'intermédiaire entre SSH et votre clé PGP stockée sur votre clé physique.

On va d'abord commencer par changer un peu la configuration de GnuPG afin d'afficher l'usage réservé aux clés. Ça permettra de retrouver facilement la clé d'authentification. Il suffit d'ajouter la ligne suivante dans le fichier ~/.gnupg/gpg.conf :

list-options show-usage

Voilà maintenant la commande gpg2 -k listera les clés ainsi que leur usage. S pour signature, E pour chiffrement et A pour authentification. C'est cette dernière qui nous intéresse.

La prochaine étape est d'indiquer à GnuPG qu'il pourra utiliser notre clé d'authentification pour SSH. Pour cela on rajoute la poignée de la clé (keygrip) dans le fichier ~/.gnupg/sshcontrol.

$ gpg2 -k --with-keygrip 
/home/jdoe/.gnupg/pubring.gpg
------------------------------
pub   rsa4096/AABBCCDD 2015-XX-XX [SC] [expire : 2018-XX-XX]
 Empreinte de la clef = AABB CCEE XXXX XXXX XXXX  XXXX XXXX XXXX XXXX FFGG
      Keygrip = AABBCCXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXDD
uid       [ultimate] John Doe <john.doe@example.com>
uid       [ultimate] [jpeg image of size 47XX]
sub   rsa2048/BBCCDDEE 2015-XX-XX [S] [expire : 2016-XX-XX]
      Keygrip = BBCCDDXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXEE
sub   rsa2048/CCDDEEFF 2015-XX-XX [E] [expire : 2016-XX-XX]
      Keygrip = CCDDEEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXFF
sub   rsa2048/DDEEFFGG 2015-XX-XX [A] [expire : 2016-XX-XX]
      Keygrip = DDEEFFXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXGG

On repère la clé d'authentification DDEEFFGG avec la poignée associée que la va rajouter au fichier ~/.gnupg/sshcontrol.

$ echo "DDEEFFXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXGG 0" >> ~/.gnupg/sshcontrol

Le chiffre après la poignée est la durée en seconde que l'agent pourra garder la clé en mémoire. Si 0 la valeur par défaut est utilisée qui est de 30 minutes.

Il faut maintenant activer le support SSH dans l'agent GnuPG. Pour cela, on édite le fichier ~/.gnupg/gpg-agent.conf et on y insère les lignes suivantes :

enable-ssh-support
pinentry-program /usr/bin/pinentry-gtk
#allow-emacs-pinentry

Pour ceux qui utilisent Emacs, la dernière ligne peut être utile. L'interface pinentry est aussi disponible en Qt ou curses. Consultez votre gestionnaire de paquets pour installer l'interface qui vous convient.

Si vous utilisez systemd et une unité utilisateur, il faudra relancer l'agent afin de prendre en compte la nouvelle configuration.

$ systemctl --user restart gpg-agent.service

La dernière étape est de configurer votre environnent afin de permettre à SSH de trouver l'agent GnuPG. Il suffit d'exporter les bonnes variable d'environnement dans le script d'initialisation de votre shell.

export GPG_TTY=$(tty)
unset SSH_AGENT_PID
if [ "${gnupg_SSH_AUTH_SOCK_by:-0}" -ne $$ ]; then
  export SSH_AUTH_SOCK="${HOME}/.gnupg/S.gpg-agent.ssh"
fi

J'ai aussi eu un petit soucis avec SSH ne sachant pas sur quelle affichage demander le code PIN. Il faut donc aussi lors de l'initialisation du shell indiquer l'affichage à utiliser. La ligne suivante devrait faire l'affaire :

echo "UPDATESTARTUPTTY" | gpg-connect-agent > /dev/null 2&>1

Voilà, tout est prêt sauf un petit détails. Où trouver la clé publique au format reconnu par OpenSSH ? ssh-add -L est ton ami. L'empreinte de la clé sera indiquée avec le label cardno:_#SERIE_. Il suffit ensuite d'ajouter cette empreinte au fichier ~/.ssh/authorized_keys sur le serveur distant comme à l'accoutumé.

Vous pouvez maintenant profiter de l'authentification SSH par clé publique avec votre clé PGP.

  • # Compléments

    Posté par  (site web personnel) . Évalué à 10.

    Comme d’habitude, je vais chipoter apporter quelques précisions.

    La prochaine étape est d'indiquer à GnuPG qu'il pourra utiliser notre clé d'authentification pour SSH. Pour cela on rajoute la poignée de la clé (keygrip) dans le fichier ~/.gnupg/sshcontrol.

    Attention, cela n’est possible qu’à partir de GnuPG 2.1 (que vous devriez sérieusement envisager d’utiliser si vous en êtes encore à GnuPG 2.0 — et encore plus si vous êtes resté à GnuPG 1.4).

    Si malgré tout vous devez utiliser GnuPG 2.0, la procédure pour charger une clef OpenPGP dans l’agent est plus tordue, puisqu’il faut d’abord convertir la clef dans un format utilisable par SSH. On peut pour ça utiliser l’outil openpgp2ssh, fourni par le projet Monkeysphere.

    Le chiffre après la poignée est la durée en seconde que l'agent pourra garder la clé en mémoire. Si 0 la valeur par défaut est utilisée qui est de 30 minutes.

    Ce n’est pas la clef que l’agent garde en mémoire, mais la phrase de passe nécessaire pour la déprotéger.

    C’est d’ailleurs une différence de comportement par rapport à l’agent SSH « standard » (ssh-agent, tel que fourni par OpenSSH) qu’il est utile de noter, surtout pour ceux qui utilisaient déjà cet agent auparavant :

    • L’agent OpenSSH ne garde les clefs qu’en mémoire, sous une forme déchiffrée. Conséquemment, il faut charger les clefs dans l’agent à chaque session, et la phrase de passe ne doit être fournie qu’une fois, lors du chargement.

    • L’agent GnuPG garde les clefs sur disque sous une forme chiffrée, et cache en mémoire les phrases de passe. Une clef ne doit être chargée dans l’agent qu’une fois pour toutes. La phrase de passe doit être fournie lors de la première utilisation de la clef, et devra éventuellement être saisie à nouveau pour une utilisation ultérieure si le cache a expiré entre-temps.

    Vous pouvez maintenant profiter de l'authentification SSH par clé publique avec votre clé PGP.

    Il peut être utile de préciser que l’agent GnuPG permet aussi d’utiliser des clefs SSH « classiques » (celles générées avec ssh-keygen par exemple). Il suffit de les charger dans l’agent GnuPG de la même façon qu’on le ferait avec l’agent OpenSSH, c’est-à-dire avec ssh-add.

    • [^] # Re: Compléments

      Posté par  (site web personnel) . Évalué à 3.

      Je n’avais pas fait vu ça :

      L'empreinte de la clé sera indiquée avec le label cardno:_#SERIE_

      Tu parlais d’une clef stockée sur une carte OpenPGP ? (Dans le fond c’est logique, vu que c’est la suite de ton journal précédent).

      Alors dans ce cas, ajouter le keygrip de la clef dans le fichier ~/.gnupg/sshcontrol n’est pas nécessaire (même si ce n’est pas gênant) : lorsque l’agent GnuPG détecte une clef dans le slot d’authentification de la carte, il la rend automatiquement disponible pour SSH.

      On pourrait penser qu’ajouter explicitement le keygrip de la clef permet tout de même de préciser la durée pendant laquelle l’agent GnuPG doit garder le PIN en cache (en le spécifiant après le keygrip comme dans l’exemple donné dans le journal), mais il n’en est rien : l’agent GnuPG ne cache jamais le PIN d’une carte à puce (en fait, avec des clefs stockées sur une carte, tous les paramètres de l’agent GnuPG relatifs au cache sont sans effets).

      • [^] # Re: Compléments

        Posté par  . Évalué à 3. Dernière modification le 27 juillet 2015 à 13:30.

        Merci pour tes précisions, c'est toujours bon à prendre. Je voulais en effet éviter l'usage de openpgp2ssh ou gpgkey2ssh car la multiplication des copies de ma clé privée, c'est exactement ce que je cherchais à éviter en créant une carte OpenPGP.

        Une petite question, si tu as la réponse. Je trouve dommage de renseigner directement la clé d'authentification sur les serveurs distants. Si je perds ma sous-clé, je me retrouve coincé dehors.

        Ce sera ma prochaine étape d'investigation mais saurais-tu si l'on peut renseigner la clé primaire et autoriser toutes sous-clés d'authentification valides liées à celle-ci ? Ainsi, je peux révoquer et recréer une sous-clé sans crainte.

        Du petit bout de la lorgnette, cela ressemble fort à un module PAM qu'il faudra mettre en place.

        • [^] # Re: Compléments

          Posté par  (site web personnel) . Évalué à 4.

          Si je perds ma sous-clé, je me retrouve coincé dehors.

          C’est pour ça que générer les sous-clefs (particulièrement la sous-clef d’authentification) directement sur la carte n’est pas forcément une bonne idée à mon avis, puisqu’il n’y a aucune sauvegarde possible.

          Ce sera ma prochaine étape d'investigation mais saurais-tu si l'on peut renseigner la clé primaire et autoriser toutes sous-clés d'authentification valides liées à celle-ci ?

          Pas à ma connaissance, et je doute que ce soit possible en l’état.

          Il faut bien voir que le démon SSH, en face, ne voit rien d’autre qu’une clef SSH tout ce qu’il y a de plus habituelle. Il n’a aucune prise en charge pour OpenPGP, et les notions de clefs primaires et de sous-clefs (qui sont propres à OpenPGP) lui sont donc totalement étrangères.

          Il est peut-être possible de faire quelque chose d’approchant avec Monkeysphere, mais

          • ça ne fonctionne plus avec n’importe quel serveur SSH (il faut obligatoirement Monkeysphere sur le serveur) ;
          • je n’ai jamais essayé.

          Une autre approche serait d’utiliser des certificats SSH : tu génères une clef SSH servant d’autorité de certification, et tu l’utilises pour signer les clefs d’authentification. Sur le serveur, tu peux dès lors ne mettre dans le fichier ~/.ssh/authorized_keys que la clef publique de l’autorité de certification, et toutes les clefs signées par celle-ci seront acceptées (supprimant ainsi la nécessité de mettre à jour le fichier ~/.ssh/authorized_keys à chaque changement de clef). Idéalement, la clef de signature sera stockée sur un support hors-ligne dont tu ne la sors qu’au moment de signer une nouvelle clef (et tu feras ça sur une machine « air-gappée »).

          L’avantage de cette approche est qu’elle ne nécessite pas de modification côté serveur (les certificats SSH, comme leur nom le laisse supposer, sont pris en charge nativement par OpenSSH). L’inconvénient dans le cas présent est qu’à ma connaissance, c’est l’agent GnuPG qui ne les gère pas — donc ce n’est pas utilisable, en l’état, avec une clef d’authentification stockée sur carte OpenPGP…

          • [^] # Re: Compléments

            Posté par  . Évalué à 2. Dernière modification le 27 juillet 2015 à 16:49.

            Il faut bien voir que le démon SSH, en face, ne voit rien d’autre qu’une clef SSH tout ce qu’il y a de plus habituelle. Il n’a aucune prise en charge pour OpenPGP, et les notions de clefs primaires et de sous-clefs (qui sont propres à OpenPGP) lui sont donc totalement étrangères.

            Oui ça c'est clair et c'est pour cela que je pense que la solution viendra d'un module PAM. SSH laisse l'authentification à PAM, ce dernier interroge le module qui lui est configuré avec la correspondance clé primaire/utilisateur, et recherche la sous-clé publique d'authentification.

            Ça doit sûrement être possible, il ne reste plus qu'à voir comment.

            Une autre approche serait d’utiliser des certificats SSH : tu génères une clef SSH servant d’autorité de certification, et tu l’utilises pour signer les clefs d’authentification. Sur le serveur, tu peux dès lors ne mettre dans le fichier ~/.ssh/authorized_keys que la clef publique de l’autorité de certification, et toutes les clefs signées par celle-ci seront acceptées (supprimant ainsi la nécessité de mettre à jour le fichier ~/.ssh/authorized_keys à chaque changement de clef). Idéalement, la clef de signature sera stockée sur un support hors-ligne dont tu ne la sors qu’au moment de signer une nouvelle clef (et tu feras ça sur une machine « air-gappée »).

            Ça peut aussi être une solution intéressante que je ne connaissais pas. Je ne savais pas que les certificats SSH offraient cette possibilité. C'est à essayer.

          • [^] # Re: Compléments

            Posté par  . Évalué à 2.

            Je ne connaissais pas les certificats SSH, super intéressant, merci.
            Deux questions:
            - Dans l'article lié, il est question d'authentifier les serveurs (known_host sur le client), alors qu'ici il s'agit d'autoriser l'accès (authorized_keys sur le serveur). Les deux fonctionne pareil (en adaptant les commandes), ou bien je n'ai rien compris ?
            - Sais tu s'il y a d'autre clients à part OpenSSH qui gèrent les certificats (au hasard Putty) ?

            • [^] # Re: Compléments

              Posté par  . Évalué à 2.

              Pour la première question, la réponse est dans le premier paragraphe de l'article:

              Une note rapide sur une fonctionnalité bien utile de OpenSSH qui, bien que documentée dans les pages de manuel, ne semble pas très connue : l’utilisation de certificats, et non pas seulement de clefs publiques, pour authentifier les serveurs (ou les clients, mais je ne parlerai ici que des serveurs).

              Ma faute, j'aurais du lire moins vite…

            • [^] # Re: Compléments

              Posté par  (site web personnel) . Évalué à 3.

              Dans l'article lié, il est question d'authentifier les serveurs (known_host sur le client), alors qu'ici il s'agit d'autoriser l'accès (authorized_keys sur le serveur). Les deux fonctionne pareil (en adaptant les commandes), ou bien je n'ai rien compris ?

              Les deux fonctionnent en effet de la même façon — c’est du moins ce que dit le manuel, pour ma part je n’ai pas essayé pour l’authentification des clients.

              Sais tu s'il y a d'autre clients à part OpenSSH qui gèrent les certificats (au hasard Putty) ?

              Ça n’a pas l’air d’être le cas de Putty en tout cas, et je n’utilise pas d’autre client que celui d’OpenSSH, donc je ne sais pas.

              J’aurais pu préciser que ces certificats SSH sont une extension d’OpenSSH. Elle est documentée mais elle n’a pas fait l’objet d’une proposition de standard à ma connaissance.

              (Il y avait bien eu une proposition pour utiliser des certificats X.509 avec SSH mais il n’y a pas eu de suite. Et de toute façon je crois que les développeurs d’OpenSSH ne voulaient pas implémenter X.509, c’est justement pour ça qu’ils ont créé leur propre format de certificats.)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.