Git 🌙
Chapters â–Ÿ 2nd Edition

7.14 Utilitaires Git - Stockage des identifiants

Stockage des identifiants

Si vous utilisez le transport SSH pour vous connecter Ă  vos dĂ©pĂŽts distants, il est possible d’avoir une clĂ© sans mot de passe qui permet de transfĂ©rer des donnĂ©es en sĂ©curitĂ© sans devoir entrer un nom d’utilisateur et un mot de passe. Cependant, ce n’est pas possible avec les protocoles HTTP ‑ toute connexion nĂ©cessite un nom d’utilisateur et un mot de passe. Cela devient mĂȘme plus difficile avec des systĂšmes Ă  authentification Ă  deux facteurs, oĂč le mot de passe utilisĂ© est gĂ©nĂ©rĂ© dynamiquement au hasard et devient imprononçable.

Heureusement, Git dispose d’un systùme de gestion d’identifiants qui peut faciliter cette gestion. Git propose de base quelques options :

  • Par dĂ©faut, rien n’est mis en cache. Toutes les connexions vous demanderont votre nom d’utilisateur et votre mot de passe.

  • Le mode « cache » conserve en mĂ©moire les identifiants pendant un certain temps. Aucun mot de passe n’est stockĂ© sur le disque et les identifiants sont oubliĂ©s aprĂšs 15 minutes.

  • Le mode « store » sauvegarde les identifiants dans un fichier texte simple sur le disque, et celui-ci n’expire jamais. Ceci signifie que tant que vous ne changerez pas votre mot de passe sur le serveur Git, vous n’aurez plus Ă  entrer votre mot de passe. Le dĂ©faut de cette approche est que vos mots de passe sont stockĂ©s en clair dans un fichier texte dans votre rĂ©pertoire personnel.

  • Si vous utilisez un Mac, Git propose un mode « osxkeychain », qui met en cache les identifiants dans un trousseau sĂ©curisĂ© attachĂ© Ă  votre compte systĂšme.

  • Si vous utilisez Windows, vous pouvez installer une application appelĂ©e « Git Credential Manager for Windows ». C’est similaire Ă  l’assistant « osxkeychain » dĂ©crit ci-dessus, mais utilise le Windows Credential Store pour sauvegarder les informations sensibles. winstore peut ĂȘtre tĂ©lĂ©chargĂ© Ă  https://github.com/Microsoft/Git-Credential-Manager-for-Windows.

Vous pouvez choisir une de ces méthodes en paramétrant une valeur de configuration Git :

$ git config --global credential.helper cache

Certains de ces assistants ont des options. L’assistant « store » accepte un argument --file <chemin> qui permet de personnaliser l’endroit oĂč le fichier texte est sauvegardĂ© (par dĂ©faut, c’est ~/.git-credentials). L’assistant cache accepte une option --timeout <secondes> qui modifie la pĂ©riode de maintien en mĂ©moire (par dĂ©faut, 900, soit 15 minutes). Voici un exemple de configuration de l’option « store » avec un nom de fichier personnalisé :

$ git config --global credential.helper 'store --file ~/.my-credentials'

Git vous permet mĂȘme de configurer plusieurs assistants. Lors de la recherche d’identifiants pour un serveur donnĂ©, Git les interrogera dans l’ordre jusqu’à la premiĂšre rĂ©ponse. Pour la sauvegarde des identifiants, Git enverra le nom d’utilisateur et le mot de passe Ă  tous les assistants et ceux-ci pourront choisir ce qu’ils en font. Voici Ă  quoi ressemblerait un .gitconfig si vous utilisiez un fichier d’identifiants sur une clĂ© USB mais souhaiteriez utiliser l’option de cache pour Ă©viter des frappes trop frĂ©quentes si la clĂ© n’est pas insĂ©rĂ©e.

[credential]
    helper = store --file /mnt/thumbdrive/.git-credentials
    helper = cache --timeout 30000

Sous le capot

Comment tout ceci fonctionne-t-il ? La commande d’origine de Git pour le systùme d’assistants d’indentification est git credential, qui accepte une commande comme argument, puis d’autres informations via stdin.

Un exemple peut aider Ă  mieux comprendre cela. Supposons qu’un assistant d’identification a Ă©tĂ© configurĂ© et que l’assistant a stockĂ© les identifiants pour mygithost. Voici une session qui utilise la commande « fill » qui est invoquĂ©e quand Git essaie de trouver les identifiants pour un hĂŽte :

$ git credential fill (1)
protocol=https (2)
host=mygithost
(3)
protocol=https (4)
host=mygithost
username=bob
password=s3cre7
$ git credential fill (5)
protocol=https
host=unknownhost

Username for 'https://unknownhost': bob
Password for 'https://bob@unknownhost':
protocol=https
host=unknownhost
username=bob
password=s3cre7
  1. C’est la ligne de commande qui dĂ©marre l’interaction.

  2. Git-credential attend la saisie d’informations sur stdin. Nous lui fournissons les informations que nous connaissons : le protocole et le nom d’hîte.

  3. Une ligne vide indique que l’entrĂ©e est complĂšte et le systĂšme d’identification devrait rĂ©pondre avec les informations qu’il connaĂźt.

  4. Git-credential prend alors la main et Ă©crit sur la sortie standard les informations qu’il a trouvĂ©es.

  5. Si aucune information d’identification n’a Ă©tĂ© trouvĂ©e, Git demande le nom d’utilisateur et le mot de passe, et les fournit sur la sortie standard d’origine (ici elles sont rattachĂ©es Ă  la mĂȘme console).

Le systĂšme d’aide Ă  l’identification invoque en fait un programme complĂštement sĂ©parĂ© de Git lui-mĂȘme. Lequel est invoquĂ© et comment il est invoquĂ© dĂ©pend de la valeur de configuration credential.helper. Cette valeur peut prendre plusieurs formes :

Valeur de configuration Comportement

foo

lance git-credential-foo

foo -a --opt=bcd

lance git-credential-foo -a --opt=bcd

/chemin/absolu/foo -xyz

lance /chemin/absolu/foo -xyz

!f() { echo "password=s3cre7"; }; f

Le code aprÚs ! est évalué dans un shell

Donc les assistants dĂ©crits ci-dessus sont en fait appelĂ©s git-credential-cache, git-credential-store, et ainsi de suite et nous pouvons les configurer pour accepter des arguments en ligne de commande. La forme gĂ©nĂ©rale pour ceci est git-credential-foo [args] <action>. Le protocole stdin/stdout est le mĂȘme que pour git-credential, mais en utilisant un ensemble d’actions lĂ©gĂšrement diffĂ©rent :

  • get est une requĂȘte pour une paire nom d’utilisateur/mot de passe.

  • store est une requĂȘte pour sauvegarder des identifiants dans la mĂ©moire de l’assistant.

  • erase purge de la mĂ©moire de l’assistant les identifiants rĂ©pondants aux critĂšres.

Pour les actions store et erase, aucune rĂ©ponse n’est exigĂ©e (Git les ignore de toute façon). Pour l’action get cependant, Git est trĂšs intĂ©ressĂ© par ce que l’assistant peut en dire. Si l’assistant n’a rien Ă  en dire d’utile, il peut simplement sortir sans rien produire, mais s’il sait quelque chose, il devrait augmenter l’information fournie avec celle qu’il a stockĂ©e. La sortie est traitĂ©e comme une sĂ©rie de dĂ©clarations d’affectation ; tout ce qui est fourni remplacera ce que Git connaĂźt dĂ©jĂ .

Voici le mĂȘme exemple que ci-dessus, mais en sautant git-credential et en s’attaquant directement Ă  git-credential-store :

$ git credential-store --file ~/git.store store (1)
protocol=https
host=mygithost
username=bob
password=s3cre7
$ git credential-store --file ~/git.store get (2)
protocol=https
host=mygithost

username=bob (3)
password=s3cre7
  1. Ici nous indiquons Ă  git-credential-store de sauvegarder des identifiants : le nom d’utilisateur (username) « bob » et le mot de passe (password) « s3cre7 » doivent ĂȘtre utilisĂ©s quand https://mygithost est accĂ©dĂ©.

  2. Maintenant, nous allons rĂ©cupĂ©rer ces identifiants. Nous fournissons les parties de l’information de connexion que nous connaissons (https://mygithost), suivi d’une ligne vide.

  3. git-credential-store rĂ©pond avec le nom d’utilisateur et le mot de passe que nous avons prĂ©cĂ©demment stockĂ©s.

Voici à quoi ressemble le fichier ~/git.store :

https://bob:s3cre7@mygithost

C’est juste une sĂ©rie de lignes, chacune contenant des URLs contenant les informations d’identification. Les assistants osxkeychain et winstore utilisent le format natif de leurs banques de stockage, tandis que cache utilise son propre format en mĂ©moire (qu’aucun autre processus ne peut lire).

Un cache d’identifiants personnalisĂ©

Étant donnĂ© que git-credential-store et consort sont des programmes sĂ©parĂ©s de Git, il y a peu Ă  penser que n’importe quel programme peut ĂȘtre un assistant d’identification Git. Les assistants fournis par Git gĂšrent de nombreux cas d’utilisation habituels, mais pas tous. Par exemple, supposons que votre Ă©quipe dispose de certains identifiants qui sont partagĂ©s par tous, pour le dĂ©ploiement. Ils sont stockĂ©s dans un rĂ©pertoire partagĂ©, mais vous ne les copiez pas dans votre propre magasin d’identifiants parce qu’ils changent souvent. Aucun assistant existant ne gĂšre ce cas ; voyons ce qu’il faudrait pour Ă©crire le nĂŽtre. Ce programme doit prĂ©senter certaines fonctionnalitĂ©s clé :

  1. La seule action Ă  laquelle nous devons rĂ©pondre est get ; store et erase sont des opĂ©rations d’écriture, donc nous sortirons directement et proprement dans ces cas.

  2. Le format du fichier d’identifiants partagĂ©s est identique Ă  celui utilisĂ© par git-credential-store.

  3. L’emplacement de ce fichier est assez standard, mais nous devrions pouvoir laisser l’utilisateur spĂ©cifier une chemin en cas de besoin.

Une fois de plus, nous Ă©crirons cette extension en Ruby, mais n’importe quel langage fonctionnera, tant que Git peut lancer un exĂ©cutable Ă  la fin. Voici le code source complet de ce nouvel assistant d’identification :

#!/usr/bin/env ruby

require 'optparse'

path = File.expand_path '~/.git-credentials' # (1)
OptionParser.new do |opts|
    opts.banner = 'USAGE: git-credential-read-only [options] <action>'
    opts.on('-f', '--file PATH', 'Specify path for backing store') do |argpath|
        path = File.expand_path argpath
    end
end.parse!

exit(0) unless ARGV[0].downcase == 'get' # (2)
exit(0) unless File.exists? path

known = {} # (3)
while line = STDIN.gets
    break if line.strip == ''
    k,v = line.strip.split '=', 2
    known[k] = v
end

File.readlines(path).each do |fileline| # (4)
    prot,user,pass,host = fileline.scan(/^(.*?):\/\/(.*?):(.*?)@(.*)$/).first
    if prot == known['protocol'] and host == known['host'] then
        puts "protocol=#{prot}"
        puts "host=#{host}"
        puts "username=#{user}"
        puts "password=#{pass}"
        exit(0)
    end
end
  1. Ici, nous analysons les options de la ligne de commande, pour permettre Ă  l’utilisateur de spĂ©cifier un fichier. Par dĂ©faut, c’est ~/.git-credentials.

  2. Ce programme ne rĂ©pondra que si l’action est get et si le fichier magasin existe.

  3. Cette boucle lit depuis stdin jusqu’à la premiĂšre ligne vide. Les entrĂ©es sont stockĂ©es dans le hash known pour rĂ©fĂ©rence ultĂ©rieure.

  4. Cette boucle lit le contenu du fichier magasin, et recherche les correspondances. Si le protocole et l’hĂŽte depuis known correspondent Ă  la ligne, le programme imprime les rĂ©sultats sur stdout et sort.

Nous allons sauvegarder notre assistant comme git-credential-read-only, le placer quelque part dans notre PATH et le marquer exécutable. Voici à quoi ressemble une session interactive :

$ git credential-read-only --file=/mnt/shared/creds get
protocol=https
host=mygithost

protocol=https
host=mygithost
username=bob
password=s3cre7

Puisque son nom commence par git-, nous pouvons utiliser une syntaxe simple pour la valeur de configuration :

$ git config --global credential.helper read-only --file /mnt/shared/creds

Comme vous pouvez le voir, étendre ce systÚme est plutÎt direct et peut résoudre des problÚmes communs pour vous et votre équipe.

scroll-to-top