Git
Chapters ▾ 2nd Edition

7.14 Гит алати - Складиште акредитива

Складиште акредитива

Ако за повезивање на удаљене репозиторијуме користите SSH транспорт, могуће је да имате кључ без вишеделне лозинке који вам омогућава да безбедно преносите податке без потребе уноса корисничког имена и лозинке. Међутим, ово није могуће са HTTP протоколима – за сваку везу је неопходно корисничко име и лозинка. Ово постаје још теже за системе са двофакторском аутентификацијом код којих се токен коришћен за лозинку генерише насумично и не може да се изговори.

На срећу, програм Гит поседује систем акредитива који вам помаже у оваквим ситуацијама. Програм Гит нуди неколико уграђених опција:

  • Акредитиви се подразумевано не кеширају. Приликом сваког повезивања бићете упитани за своје корисничко име и лозинку.

  • „cache” режим чува акредитиве у меморији на одређени период. Ниједна лозинка се никада не чува на диск и уклањају се из кеша након 15 минута.

  • „store” режим чува акредитиве у фајлу на диск као чисти текст и никада не истичу. Ово значи да докле год не промените своју лозинку за Гит хост, више нећете морати поново да уносите своје акредитиве. Мана овог приступа је што се нешифриране лозинке чувају у чистом фајлу који се налази у вашем почетном директоријуму.

  • Ако користите Мек, програм Гит долази са „osxkeychain” режимом који акредититве кешира у сигурном привеску за кључеве (keychain) који је везан са ваш системски налог. Ова метода чува акредитиве на диск и они никада не истичу, али су шифровани истим системом који чува HTTPS сертификате и аутоматска попуњавања за програм Сафари.

  • Ако користите Виндоуз, можете да инсталирате помоћник под називом Git Credential Manager for Windows”. Ово је слично са „osxkeychain” помоћником описаним изнад, само што за контролу осетљивих информација користи Windows Credential Store. Можете га пронаћи на адреси https://github.com/Microsoft/Git-Credential-Manager-for-Windows.

Неку од ових метода можете изабрати тако што поставите Гит конфигурациону вредност:

$ git config --global credential.helper cache

Неки од ових помоћника имају опције. „store” помоћник може да прихвати --file <путања> аргумент који прилагођава место чувања фајла са чистим текстом (подразумевана вредност је ~/.git-credentials). „cache” помоћник прихвата опцију --timeout <секунди> која мења време током којег даемон наставља са извршавањем (подразумевана вредност је „900”, или 15 минута). Ево примера како да за „store” помоћник подсетите жељено име фајла:

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

Програм Гит вам чак дозвољава да подесите и неколико помоћника. Када тражи акредитиве за одређени хост, програм Гит ће питати помоћнике редом и зауставиће се када прими први одговор. Када чува акредитиве, програм Гит ће послати корисничко име и лозинку свим помоћницима са листе, па они могу одлучити шта да раде са тим подацима. Ево како би изгледао .gitconfig ако имате фајл са акредитивима на флеш драјву, али желите да користите кеш у меморији како не бисте морали да куцате када драјв није у порту:

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

Испод хаубе

Како све ово функционише? Основна команда програма Гит за систем помоћника за акредитиве је git credential која узима команду као аргумент, па затим још улазних података кроз stdin.

Ово се вероватно лакше схвата кроз пример. Рецимо да је помоћник за акредитиве конфигурисан и да је помоћник сачувао акредитиве за mygithost. Следи сесија која користи команду „fill”, која се позива када програм Гит покушава да пронађе акредитиве за неки хост:

$ 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. Ово је команда која започиње интеракцију.

  2. Git-credential затим чека на улаз са stdin. Прослеђујемо му ствари које знамо: протокол и име хоста.

  3. Празна линија означава да је унос завршен и да би систем акредитива требало да одговори оним што зна.

  4. Затим git-credential преузима и исписује на stdout делиће информације коју је пронашао.

  5. Ако се акредитиви не пронађу, програм Гит тражи од корисника да унесе корисничко име и лозинку, па иг доставља назад позивајућем stdout (овде су они прикачени на исту конзолу).

Систем акредитива уствари позива програм који није део самог програма Гит; који је то програм, зависи од вредности конфигурационе променљиве credential.helper. Она може узети неколико облика:

Вредност конф. променљиве Понашање

foo

Покреће git-credential-foo

foo -a --opt=bcd

Покреће git-credential-foo -a --opt=bcd

/absolute/path/foo -xyz

Покреће /absolute/path/foo -xyz

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

Кôд након ! се израчунава у љуски

Тако да се помоћници описани изнад уствари називају git-credential-cache, git-credential-store и тако даље, па можемо да их конфигуришемо тако да узимају аргументе из команде. Општи облик за ово је git-credential-foo [арг] <акција>. stdin/stdout протокол је исти као за git-credential, само што користе донекле измењени скуп акција:

  • get је захтев за пар корисничко_име/лозинка.

  • store је захтев за чување скупа акредитива у меморији помоћника.

  • erase чисти акредитиве за дате особине из меморије помоћника.

Одговор није обавезан за store и erase акције (програм Гит га ионако игнорише). Међутим, у случају get акције, програм Гит је веома заинтересован да чује шта помоћник има да каже. Ако помоћник не зна било шта корисно, он једноставно може да заврши извршавање без икаквог излаза, али ако зна, требало би да достављену информацију допуни са сачуваним подацима. Излаз се третира као низ наредби доделе; све што се достави ће заменити оно што програм Гит већ зна.

Ево ситог примера као малопре, само што прескачемо git-credential и прелазимо право на 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. Овим кажемо помоћнику git-credential-store за сачува неке акредитиве: корисничко име „bob” и лозинка „s3cre7” би требало да се употребе када се приступа https://mygithost.

  2. Сада ћемо преузети те акредитиве. Достављамо делове везе које већ познајемо (https://mygithost), и празну линију.

  3. git-credential-store одговара са корисничким именом и лозинком коју смо сачували изнад.

Ево како изгледа фајл ~/git.store:

https://bob:s3cre7@mygithost

Он је само низ линија од којих свака садржи URL украшен акредитивима. Помоћници osxkeychain и winstore користе нативни формат својих складишта, док cache користи свој сопствени формат у меморији (који ниједан други процес не може да прочита).

Прилагођени кеш акредитива

Како су git-credential-store и пријатељи програми одвојени од програма Гит, не треба пуно вештине да се схвати како било који програм може бити Гит помоћник за акредитиве. Помоћници које обезбеђује програм Гит покривају многе уобичајене случајеве употребе, али не све. На пример, рецимо да ваш тима има неке акредитиве које дели цео тим, вероватно за постављање. Они се чувају у дељеном директоријуму, али не желите да их копирате у своје складиште акредитива јер се често мењају. Овај случај употребе не покрива ниједан од постојећих помоћника; па хајде да видимо шта је потребно да напишете сопствени. Постоји неколико кључних могућности које овај програм мора да поседује:

  1. Једина акција на коју треба да обратимо пажњу је get; store и erase су операције уписа, па када их примимо просто ћемо на чист начин да завршимо извршавање.

  2. Формат дељеног фајла акредитива је исти као онај који користи git-credential-store.

  3. Локација тог фајла је прилично стандардна, али би кориснику за сваки случај ипак требало да омогућимо прослеђивање прилагођене путање.

И овога пута ћемо проширење написати у језику Руби, мада функционише било који језик све док програм Гит буде у стању да изврши завршени производ. Ево комплетног изворног кода нашег новог помоћника за акредитиве:

#!/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. Овде парсирамо опције из командне линије чиме кориснику омогућавамо да достави улазни фајл. Подразумевана вредност је ~/.git-credentials.

  2. Овај програм враћа одговор само у случају да је акција get и да постоји фајл позадински фајл за чување акредитива.

  3. Ова петља чита са stdin све док се не наиђе на празну линију. Улази се чувају у хешу known за каснију употребу.

  4. Ова петља чита садржај фајл који чува акредитиве и тражи подударања. Ако се протокол и хост из known подударају са овом линијом, програм исписује резултате на stdout и прекида извршавање.

Наш помоћник ћемо сачувати као git-credential-read-only негде унутар PATH и обележити га тако да се може извршавати. Ево како изгледа интерактивна сесија:

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

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

Пошто име почиње на „git-”, за вредност конфигурационе променљиве можемо употребити једноставну синтаксу:

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

Као што видите, проширивање овог система је прилично једноставно и вама и вашем тиму може решити неке честе проблеме.