PGP – 6e partie : Utiliser PGP avec Git

Nous poursuivons notre série de guides pratiques PGP avec un survol des tags et des commits signés qui nous aident à vérifier que notre dépôt n’a pas été saboté.

Article écrit et posté par Konstantin Ryabitsev le 21 mars 2018 sur Linux.com

Traduit par Gilles Gouget pour Librethic le 22 mai 2018

https://creativecommons.org/licenses/by-sa/4.0/

Protéger l’intégrité de votre code avec PGP – 6e partie : Utiliser PGP avec Git

Image : Creative commons zéro

Nous poursuivons notre série de guides pratiques PGP avec un survol des tags et des commits signés qui nous aident à vérifier que notre dépôt n’a pas été saboté.

Dans cette série de tutoriels, nous fournissons un guide pratique pour l’utilisation de PGP, incluant des concepts basiques, la génération et la protection de vos clés. Si vous avez manqué les articles précédents, vous pouvez rattraper avec les liens ci-dessous. Dans cet article, nous étudions l’intégration de PGP dans Git, en commençant par les tags signés, puis une introduction aux commits signés, et finalement un support aux envois (push) signés.

- 1ère partie : Concepts et outils de base
- 2e partie : Générer et protéger votre clé PGP maître
- 3e partie : Générer des sous-clés PGP
- 4e partie : Mettre votre clé maître sur un stockage hors ligne
- 5ème partie : Mettre vos sous-clés sur un matériel dédié
- 6ème partie : Utiliser PGP avec Git

Une des caractéristiques principales de Git est sa nature décentralisée – une fois qu’un dépôt est cloné sur votre système, vous avez l’historique complet du projet, avec tous ses tags, commits et branches. Toutefois, avec des centaines de dépôts clonés un peu partout, comment vérifier que le dépôt que vous avez téléchargé n’a pas été trafiqué par une tierce personne mal intentionée ? Vous pouvez l’avoir cloné de Github ou d’un autre endroit d’aspect officiel, mais qu’en est il si quelqu’un vous a trompé ?

Ou que se passe-t-il si une porte dérobée est découverte dans un des projets sur lesquels vous avez travaillé, et que la ligne “auteur” du commit dit que ça a été fait par vous, alors que vous êtes certain de n’y être pour rien ?

Pour répondre à ces deux problèmes, Git a introduit l’intégration PGP. Les tags signés prouvent l’intégrité du dépôt en assurant que son contenu est exactement le même que sur l’ordinateur de celui qui a créé le tag, tandis que les commits signés rendent impossible l’usurpation de votre identité à moins d’avoir accès à vos clés PGP.

Check-list

  • Comprendre les tags signés, les commits et les pushs (ESSENTIEL) ;
  • Configurez Git pour utiliser vos clés (ESSENTIEL) ;
  • Apprendre comment fonctionnent la signature et la vérification des tags (ESSENTIEL) ;
  • Configurez Git pour qu’il signe toujours les tags annotés (BON) ;
  • Apprendre comment fonctionnent la signature et la vérification des commits (ESSENTIEL) ;
  • Configurez Git pour qu’il signe toujours les commits (BON) ;
  • Configurer les options de gpg-agent (ESSENTIEL).

Considérations

Git implémente des niveaux d’intégration multiples avec PGP, en commençant par les tags signés, puis en introduisant les commits signés, et finalement en supportant les pushs signés.

Comprendre le hachage de Git

Git est une bestiole compliquée, mais vous aurez besoin de comprendre ce qu’est le hachage de sorte à avoir une bonne prise sur la façon dont PGP s’intègre avec. Nous allons réduire cela à deux types de hachage : le hachage d’arborescence et le hachage de commit.

Hachage d’arborescence

Chaque fois que vous commitez un changement sur un dépôt, Git enregistre des condensés des sommes de contrôle de tous les objets qu’il contient – les contenus (blobs), les répertoires (trees), les noms de fichiers et les permissions, etc. – pour chaque sous-répertoire du dépôt. Il ne fait cela que pour les répertoires et les blobs qui ont changé avec chaque commit, de sorte à ne pas recalculer la somme de contrôle de l’arborescence entière si seulement une petite partie a été touchée.

Il calcule et stocke ensuite la somme de contrôle du plus haut niveau de l’arborescence, qui sera inévitablement différente dès lors qu’une partie du dépôt aura changé.

Hachage de commits

Une fois que le hachage de l’arborescence a été créé, Git va calculer le condensé du commit, qui inclura les informations du répertoire et des modifications faites suivantes :

  • Le condensé de la somme de contrôle du répertoire ;
  • Le condensé de la somme de contrôle du répertoire avant la modification (parent) ;
  • Les informations de l’auteur (nom, email, heure de paternité) ;
  • Les informations du commiteur (nom, email, heure du commit) ;
  • Le message du commit.

Fonction de hachage

À l’heure où cet article est écrit, Git utilise encore les mécanismes de hachage SHA1 pour calculer les sommes de contrôle, bien qu’un travail soit en cours pour une transition vers un algorithme plus fort et plus résistant aux collisions. Notez que Git propose déjà des routines d’évitement des collisions, donc on peut considérer que le succès d’une attaque par collisions de Git demeure mal pratique.

Tags annotés et signatures de tag

Les tags de Git permettent aux développeurs de marquer des commits spécifiques dans l’historique de chaque dépôt Git. Les tags peuvent être “légers” – plus ou moins juste un pointeur vers un commit spécifique –, ou ils peuvent être ’annotés’, et devenir un objet propre dans l’arborescence Git. Un objet de tag annoté contient toutes les informations suivantes :

  • La somme de contrôle du commit qui est tagué ;
  • Le nom du tag ;
  • L’information du tagueur (nom, email, heure du tag) ;
  • Le message du tag.
    Un tag signé PGP est simplement un tag annoté avec toutes ces entrées enveloppées dans une signature PGP. Quand un développeur signe son tag Git, il vous assure véritablement des choses suivantes :
  • Qui il est (et pourquoi vous pouvez lui faire confiance) ;
  • Quel était l’état du dépôt au moment où il a signé ;
  • Le tag inclut le condensé du commit ;
  • Le condensé du commit inclut celui de l’arborescence...
  • ...qui inclut le condensé de tous les fichiers, contenus et sous-répertoires ;
  • Il inclut aussi toutes les informations de paternité ;
  • Y compris les moments exacts où les changements ont été effectués.
    Lorsque vous clonez un dépôt Git et vérifiez un tag signé, cela vous donne l’assurance cryptographique que tout le contenu du répertoire, incluant tout son historique, est exactement le même contenu que celui présent dans le répertoire de l’ordinateur du développeur au moment de la signature.

Commits signés

Les commits signés sont très similaires aux tags signés – le contenu de l’objet commit est signé PGP au lieu du contenu de l’objet tag. Une signature de commit vous donne aussi une information complètement vérifiable de l’état de l’arborescence du développeur au moment où la signature a été faite. Les signatures PGP de tags et de commits procurent exactement les mêmes assurances de sécurité pour le dépôt et son entier historique.

Pushs signés

Nous incluons ceci pour être tout à fait complet, sachant que cette fonctionnalité nécessite d’être activée sur le serveur recevant le push avant qu’elle ne puisse servir à quoi que ce soit. Comme nous l’avons vu plus haut, signer PGP un objet Git donne une information vérifiable sur l’arborescence Git du développeur, mais pas sur son intention quant à cette arborescence.

Par exemple, vous pouvez travailler sur une branche expérimentale de votre propre fork Git pour tester une option cool et prometteuse, mais après que vous ayez soumis votre travail pour révision, quelqu’un trouve un méchant bug dans votre code. Puisque vos commits sont correctement signés, quelqu’un pourrait prendre la branche qui contient votre méchant bug et la pousser dans le master, introduisant une vulnérabilité qui n’avait jamais été pensée pour être mise en production. Puisque le commit est correctement signé avec votre clé, tout a l’air légitime et votre réputation est remise en question lorsque le bug est découvert.

La capacité à demander une signature PGP durant un push Git a été ajoutée pour certifier l’intention du commit, et non simplement son contenu.

Configurer Git pour utiliser votre clé PGP

Si vous n’avez qu’une clé secrète dans votre porte-clés, alors vous n’avez pas besoin d’en faire plus, vu qu’elle sera votre clé par défaut.

Toutefois, si vous avez plusieurs clés secrètes, vous pouvez dire à Git quelle clé utiliser ([fpr] est l’empreinte de votre clé) :

$ git config --global user.signingKey [fpr]

NOTE : Si vous avez une commande distincte gpg2, vous devriez alors dire à Git de toujours l’utiliser à la place de la commande historique gpg de la version 1 :

$ git config --global gpg.program gpg2

Comment travailler avec des tags signés

Pour créer un tag signé, ajoutez simplement le switch -s à la commande tag :

$ git tag -s [tagname]

Nous recommandons de toujours signer les tags Git, car cela permet à d’autres développeurs de s’assurer que le dépôt Git sur lequel ils travaillent n’a pas été altéré malicieusement (par ex. pour introduire des portes dérobées).

Comment vérifier des tags signés

Pour vérifier un tag signé, utilisez simplement la commande verify-tag :

$ git verify-tag [tagname]

Si vous vérifiez le tag Git de quelqu’un d’autre, vous devrez importer sa clé PGP. Référez-vous au document ’Trusted Team Communication’ (Communication d’équipe de confiance) du dépôt pour être guidé sur ce point.

Vérifier au moment du pull

Si vous faites un pull sur un tag d’un autre fork du dépôt du projet, Git devrait automatiquement vérifier la signature de ce que vous tirez et vous montrer le résultat durant l’opération de merge :

$ git pull [url] tags/sometag

Le message de merge contiendra quelque chose comme :

Merge tag 'sometag' of [url]
[Tag message]
# gpg: Signature made [...]
# gpg: Good signature from [...]

Configurer Git pour toujours signer des tags annotés

Si vous créez un tag annoté, il y a des chances pour que vous vouliez le signer. Pour forcer Git à toujours signer des tags annotés, vous pouvez paramétrer une option de configuration globale :

$ git config --global tag.forceSignAnnotated true

Sinon, vous pouvez entraîner votre muscle de la mémoire à toujours mettre le switch -s :

$ git tag -asm 'Tag message' tagname

Comment travailler avec des commits signés

Il est facile de créer des commits signés, mais il est bien plus difficile de les intégrer dans votre processus de travail. Beaucoup de projets utilisent des commits signés comme une sorte d’équivalent à une ligne ’comitté par :’ qui enregistre la provenance du code – les signatures sont rarement vérifiées par d’autres sauf quand on recherche l’historique du projet. Dans un sens, les commits sont utilisés comme des ’preuves de modifications’, et non pour rendre ’inviolable’ le processus de travail Git.

Pour créer un commit signé, vous devez juste ajouter le drapeau -S à la commande de commit Git (c’est un -S majuscule pour éviter le conflit avec un autre drapeau) :

$ git commit -S

Nous recommandons de toujours signer les commits et de l’exiger de tous les membres du projet, indépendamment de savoir si quelqu’un les vérifiera (ça pourra toujours venir plus tard).

Comment vérifier les commits signés

Pour vérifier un seul commit, vous pouvez utiliser verify-commit :

$ git verify-commit [hash]

Vous pouvez aussi regarder les journaux du dépôt et demander que toutes les signatures de commits soient vérifiées et montrées :

$ git log --pretty=short --show-signature

Pour étendre l’expiration de votre clé d’une année de la date courante, exécutez simplement :

$ gpg --quick-set-expire [fpr] 1y

Vérifier les commits durant le merge

Si tous les membres de votre projet signent leurs commits, vous pouvez forcer la vérification des signatures au moment du merge (et signer le commit résultant lui-même en utilisant -S) :

$ git merge --verify-signatures -S merged-branch

Notez que le merge échouera s’il n’y a qu’un seul commit non signé ou qui ne passe pas la vérification. Comme c’est souvent le cas, la technologie est l’étape facile – c’est la partie humaine de l’équation qui va rendre difficile l’adoption de signature de commits stricte pour votre projet.

Si votre projet utilise des listes de diffusion pour la gestion des patchs

Si votre projet utilise des listes de diffusion pour proposer et gérer des patchs, alors il n’est pas très utile de signer les commits, car toute information de signature sera perdue lors qu’envoyée par ce moyen. C’est toujours utile de signer vos commits, juste pour que d’autres puissent se référer à votre arborescence Git publique, mais le projet en amont qui reçoit vos patchs ne sera pas en mesure de les vérifier directement avec Git.

Vous pouvez cependant toujours signer les emails contenant vos patchs.

Configurer Git pour toujours signer les commits

Vous pouvez dire à Git de toujours signer les commits :

git config --global commit.gpgSign true

Sinon, vous pouvez entraîner votre muscle de la mémoire à toujours mettre le drapeau -S à toutes les opérations de commit (ceci inclut –amend).

Configurer les options gpg-agent

Le GnuPG agent est un outil d’aide qui démarre automatiquement chaque fois que vous utilisez la commande gpg et qui tourne en tâche de fond dans le but de mettre en cache la phrase secrète de votre clé privée. De cette façon vous n’avez besoin de déverrouiller votre clé qu’une seule fois pour pouvoir l’utiliser de façon répétée (très pratique si vous devez signer un tas d’opération Git dans un script automatisé sans avoir à retaper votre phrase secrète continuellement).

Il y a deux options que vous devez connaître pour affiner vos préférences quant à l’expiration de la phrase secrète du cache :

  • default-cache-ttl (secondes) : si vous utilisez la même clé à nouveau avant d’atteindre la durée de vie, le compte à rebours redémarrera pour une nouvelle période. La valeur par défaut est de 600 (10 minutes).
  • max-cache-ttl (secondes) : indépendamment de la fréquence à laquelle vous avez utilisé la clé depuis sa première saisie, si la durée de vie maximale expire, vous devrez entrer la phrase à nouveau. Le réglage par défaut est de 30 minutes.
    Si vous trouvez l’un ou l’autre de ces réglages trop court (ou trop long), vous pouvez éditer votre fichier /.gnupg/gpg-agent.conf pour y mettre vos propres valeurs :
# set to 30 minutes for regular ttl, and 2 hours for max ttl
default-cache-ttl 1800
max-cache-ttl 7200

Bonus : Utiliser gpg-agent avec ssh

Si vous avez créé une clé [A] (Authentification) et l’avez déplacée sur une carte à puce, vous pouvez l’utiliser avec ssh pour ajouter une authentification à 2 facteurs pour vos sessions ssh. Vous devez juste dire à votre environnement d’utiliser le bon fichier de socket pour dialoguer avec l’agent.

Tout d’abord, ajoutez à votre fichier /.gnupg/gpg-agent.conf :

enable-ssh-support

Puis, ajoutez ceci à votre .bashrc :

export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)

Il vous faudra tuer le processus gpg-agent en cours et ouvrir une nouvelle session pour que les changements prennent effet :

$ killall gpg-agent
$ bash
$ ssh-add -L

La dernière commande doit lister les représentations de votre clé PGP [A] (le commentaire devrait dire cardno:XXXXXXXX à la fin pour indiquer que cela vient de la carte à puce).

Pour activer des logins basés sur des clés avec ssh, ajoutez juste la sortie ssh-add -L à /.ssh/authorized_keys sur les systèmes distants auxquels vous vous connectez. Félicitations, vous venez de rendre vos identifiants ssh très difficiles à voler.

En bonus, vous pouvez prendre les clés ssh PGP d’autres personnes sur des serveurs de clés publiques, voudriez-vous leur donner un accès ssh à quoi que ce soit :

$ gpg --export-ssh-key [keyid]

Cela peut être très pratique si vous avez besoin de donner à des développeurs un accès ssh à des dépôts Git. La prochaine fois, nous vous donnerons des conseils pour protéger vos comptes mail comme vos clés PGP.

Article écrit et posté par Konstantin Ryabitsev le21mars 2018 sur Linux.com

Traduit par Gilles Gouget pour Librethic le 22 mai 2018

https://creativecommons.org/licenses/by-sa/4.0/