Chapters ▾ 2nd Edition

7.14 Git Tools - Die Stoor van Aanmeldbewyse (Credential Storage)

Die Stoor van Aanmeldbewyse (Credential Storage)

As jy die SSH-vervoer gebruik om aan remotes te koppel, is dit vir jou moontlik om 'n sleutel sonder 'n wagwoordfrase (passphrase) te hê, wat jou toelaat om veilig data oor te dra sonder om jou gebruikersnaam en wagwoord in te tik. Dit is egter nie moontlik met die HTTP-protokolle nie — elke verbinding benodig 'n gebruikersnaam en wagwoord. Dit raak selfs moeiliker vir stelsels met twee-faktor-verifikasie, waar die teken (token) wat jy vir 'n wagwoord gebruik ewekansig gegenereer en onuitspreekbaar is.

Gelukkig het Git 'n aanmeldbewysstelsel (credentials system) wat hiermee kan help. Git het 'n paar opsies wat standaard ingebou is:

  • Die verstek (default) is om glad nie in die kas te stoor (cache) nie. Elke verbinding sal jou vir jou gebruikersnaam en wagwoord vra.

  • Die “cache” (kas) modus hou aanmeldbewyse in die geheue vir 'n sekere tydperk. Geen van die wagwoorde word ooit op die skyf gestoor nie, en hulle word na 15 minute uit die kas verwyder.

  • Die “store” (stoor) modus stoor die aanmeldbewyse in 'n gewone tekslêer op die skyf, en hulle verval nooit nie. Dit beteken dat totdat jy jou wagwoord vir die Git-gasheer verander, jy nooit weer jou aanmeldbewyse hoef in te tik nie. Die nadeel van hierdie benadering is dat jou wagwoorde onversleutel (cleartext) in 'n gewone lêer in jou tuisgids (home directory) gestoor word.

  • As jy macOS gebruik, kom Git met 'n “osxkeychain” modus, wat aanmeldbewyse stoor in die veilige sleutelhouer (secure keychain) wat aan jou stelselrekening gekoppel is. Hierdie metode stoor die aanmeldbewyse op die skyf, en hulle verval nooit nie, maar hulle is geënkripteer met dieselfde stelsel wat HTTPS-sertifikate en Safari se outovoltooi-data stoor.

  • As jy Windows gebruik, kan jy die Git Credential Manager kenmerk aktiveer wanneer jy Git for Windows installeer, of die nuutste GCM afsonderlik as 'n selfstandige diens installeer. Dit is soortgelyk aan die “osxkeychain” helper wat hierbo beskryf is, maar gebruik die Windows Credential Store om sensitiewe inligting te beheer. Dit kan ook aanmeldbewyse aan WSL1 of WSL2 verskaf. Sien GCM Install Instructions vir meer inligting.

Jy kan een van hierdie metodes kies deur 'n Git-konfigurasiewaarde in te stel:

$ git config --global credential.helper cache

Sommige van hierdie helpers het opsies. Die “store” helper kan 'n --file <path> argument neem, wat aanpas waar die gewone tekslêer gestoor word (die verstelling is ~/.git-credentials). Die “cache” helper aanvaar die --timeout <seconds> opsie, wat die tydsduur verander wat sy daemon aan die gang gehou word (die verstelling is “900”, of 15 minute). Hier is 'n voorbeeld van hoe jy die “store” helper met 'n pasgemaakte lêernaam sal konfigureer:

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

Git laat jou selfs toe om verskeie helpers te konfigureer. Wanneer Git na aanmeldbewyse vir 'n spesifieke gasheer soek, sal dit hulle in volgorde navraag doen (query), en stop nadat die eerste antwoord verskaf is. Wanneer aanmeldbewyse gestoor word, sal Git die gebruikersnaam en wagwoord na al die helpers in die lys stuur, en hulle kan kies wat om daarmee te doen. Hier is hoe 'n .gitconfig sou lyk as jy 'n aanmeldbewyse-lêer op 'n geheuestokkie (thumb drive) gehad het, maar die geheuekas (in-memory cache) wou gebruik om tikwerk te bespaar as die aandrywer nie ingeprop is nie:

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

Onder die Enjinkap (Under the Hood)

Hoe werk dit alles? Git se wortelopdrag (root command) vir die credential-helper-stelsel is git credential, wat 'n opdrag as 'n argument neem, en dan meer toevoer deur stdin ontvang.

Dit sal dalk makliker wees om met 'n voorbeeld te verstaan. Kom ons sê dat 'n credential helper gekonfigureer is, en die helper het aanmeldbewyse vir mygithost gestoor. Hier is 'n sessie wat die “fill” opdrag gebruik, wat geroep word wanneer Git probeer om aanmeldbewyse vir 'n gasheer te vind:

$ 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. Hierdie is die opdragreël wat die interaksie inisieer.

  2. Git-credential wag dan vir toevoer op stdin. Ons verskaf dit van die dinge wat ons weet: die protokol en gasheernaam.

  3. 'n Leë reël dui aan dat die toevoer voltooi is, en die aanmeldbewysstelsel moet antwoord met wat dit weet.

  4. Git-credential neem dan oor en skryf na stdout met die stukkies inligting wat dit gevind het.

  5. As aanmeldbewyse nie gevind word nie, vra Git die gebruiker vir die gebruikersnaam en wagwoord, en verskaf dit terug na die roepende stdout (hier is hulle aan dieselfde konsole gekoppel).

Die aanmeldbewysstelsel roep eintlik 'n program aan wat los staan van Git self; watter een en hoe hang af van die credential.helper konfigurasiewaarde. Daar is verskeie vorme wat dit kan aanneem:

Konfigurasiewaarde Gedrag

foo

Roep git-credential-foo aan

foo -a --opt=bcd

Roep git-credential-foo -a --opt=bcd aan

/absolute/path/foo -xyz

Roep /absolute/path/foo -xyz aan

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

Kode na ! word in dop (shell) geëvalueer

So die helpers wat hierbo beskryf is, word eintlik git-credential-cache, git-credential-store, ensovoorts genoem, en ons kan hulle konfigureer om opdragreël-argumente te neem. Die algemene vorm hiervoor is “git-credential-foo [args] <aksie>.” Die stdin/stdout-protokol is dieselfde as git-credential, maar hulle gebruik 'n effens ander stel aksies:

  • get is 'n versoek vir 'n gebruikersnaam/wagwoord-paar.

  • store is 'n versoek om 'n stel aanmeldbewyse in hierdie helper se geheue te stoor.

  • erase verwyder die aanmeldbewyse vir die gegewe eienskappe uit hierdie helper se geheue.

Vir die store en erase aksies is geen reaksie nodig nie (Git ignoreer dit in elk geval). Vir die get aksie stel Git egter baie daarin belang wat die helper te sê het. As die helper niks nuttigs weet nie, kan dit bloot toemaak sonder afvoer, maar as dit wel weet, moet dit die verskafde inligting aanvul met die inligting wat dit gestoor het. Die afvoer word soos 'n reeks toekenningsverklarings (assignment statements) behandel; enigiets wat verskaf word, sal dit wat Git reeds weet vervang.

Hier is dieselfde voorbeeld as hierbo, maar ons slaan git-credential oor en gaan reguit na 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. Hier sê ons vir git-credential-store om sekere aanmeldbewyse te stoor: die gebruikersnaam “bob” en die wagwoord “s3cre7” moet gebruik word wanneer https://mygithost benader word.

  2. Nou gaan ons daardie aanmeldbewyse herwin (retrieve). Ons verskaf die dele van die verbinding wat ons reeds weet (https://mygithost), en 'n leë reël.

  3. git-credential-store antwoord met die gebruikersnaam en wagwoord wat ons hierbo gestoor het.

Hier is hoe die ~/git.store lêer lyk:

https://bob:s3cre7@mygithost

Dit is net 'n reeks reëls, wat elk 'n URL bevat wat met 'n aanmeldbewys versier is. Die osxkeychain en wincred helpers gebruik die inheemse formaat van hul eie agterliggende stoorplekke (backing stores), terwyl cache sy eie geheue-formaat (in-memory format) gebruik (wat geen ander proses kan lees nie).

'n Pasgemaakte Aanmeldbewyskas (A Custom Credential Cache)

Gegewe dat git-credential-store en vriende aparte programme van Git is, is dit nie 'n groot sprong om te besef dat enige program 'n Git credential helper kan wees nie. Die helpers wat deur Git verskaf word dek baie algemene gebruiksgevalle, maar nie almal nie. Byvoorbeeld, sê nou jou span het 'n paar aanmeldbewyse wat met die hele span gedeel word, miskien vir ontplooiing (deployment). Dit word in 'n gedeelde gids gestoor, maar jy wil dit nie na jou eie aanmeldbewysstoor kopieer nie, want dit verander dikwels. Geen van die bestaande helpers dek hierdie geval nie; kom ons kyk wat dit sal verg om ons eie te skryf. Daar is verskeie sleutelkenmerke wat hierdie program moet hê:

  1. Die enigste aksie waaraan ons aandag moet gee, is get; store en erase is skryfoperasies, so ons sal net skoon toemaak wanneer dit ontvang word.

  2. Die lêerformaat van die gedeelde aanmeldbewyslêer is dieselfde as wat deur git-credential-store gebruik word.

  3. Die ligging van daardie lêer is redelik standaard, maar ons moet die gebruiker toelaat om 'n pasgemaakte pad aan te gee net vir ingeval.

Weereens sal ons hierdie uitbreiding in Ruby skryf, maar enige taal sal werk solank Git die voltooide produk kan uitvoer. Hier is die volledige bronkode van ons nuwe credential helper:

#!/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.exist? 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'] and user == known['username'] then
        puts "protocol=#{prot}"
        puts "host=#{host}"
        puts "username=#{user}"
        puts "password=#{pass}"
        exit(0)
    end
end
  1. Hier ontleed (parse) ons die opdragreël-opsies, wat die gebruiker toelaat om die toevoerlêer te spesifiseer. Die verstelling is ~/.git-credentials.

  2. Hierdie program reageer slegs as die aksie get is en die agterliggende lêer bestaan.

  3. Hierdie lus (loop) lees vanaf stdin totdat die eerste leë reël bereik word. Die toevoer word in die known hutskrabbel (hash) gestoor vir latere verwysing.

  4. Hierdie lus lees die inhoud van die stoorlêer en soek na ooreenkomste (matches). As die protokol, gasheer en gebruikersnaam in known met hierdie reël ooreenstem, druk die program die resultate na stdout en sluit af.

Ons sal ons helper as git-credential-read-only stoor, dit iewers in ons PATH plaas en dit as uitvoerbaar (executable) merk. Hier is hoe 'n interaktiewe sessie lyk:

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

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

Aangesien sy naam met “git-” begin, kan ons die eenvoudige sintaksis vir die konfigurasiewaarde gebruik:

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

Soos jy kan sien, is die uitbreiding van hierdie stelsel redelik eenvoudig, en kan dit 'n paar algemene probleme vir jou en jou span oplos.