Pro git - 7.14
Updated:
Pro git - Credential 저장소
1. Credential 저장소
- SSH 프로토콜을 사용하여 리모트 저장소에 접근할 때 Passphase 없이 생성한 SSH Key를 사용하면 사용자이름과 암호를 입력하지 않고도 안전하게 데이터를 주고받을 수 있다.
-
반면 HTTP 프로토콜을 사용하는 경우는 매번 사용자이름과 암호를 입력해야 한다.
- 다행히도 Git은 이렇게 매번 인증정보(Credential)를 입력하는 경우 인증정보를 저장해두고 자동으로 입력해주는 시스템을 제공한다.
-
Git Credential 기능이 제공하는 옵션은 아래와 같다.
- 일단 기본적으로 아무런 설정도 하지 않으면 어떤 암호도 저장하지 않는다.
- 이 경우 인증이 필요한 때 매번 사용자이름과 암호를 입력해야 한다.
- “cache” 모드로 설정하면 일정 시간 동안 메모리에 사용자이름과 암호 같은 인증정보를 기억한다.
- 이 정보를 Disk에 저장하지는 않으며 메모리에서도 15분 까지만 유지한다.
- “store” 모드로 설정하면 인증정보를 Disk의 텍스트 파일로 저장하며 계속 유지한다.
- 계속 유지한다는 말은 리모트의 인증정보를 변경하지 않는 한 다시 인증정보를 입력하지 않아도 접근할 수 있다는 말이다.
- “store” 모드를 사용할 때 주의할 점은 인증정보가 사용자 홈 디렉토리 아래에 일반 텍스트 파일로 저장된다는 점이다.
- Mac에서 Git을 사용하는 경우 “osxkeychain” 모드를 사용하면 Mac에서 제공하는 Keychain 시스템에 사용자이름과 암호를 현재 로그인 계정에 속하게 저장한다.
- “store” 모드하면 인증정보를 Disk에 저장하고 인증정보가 만료되지 않는 점은 같지만, Safari 브라우저가 인증정보를 저장하는 것과 같은 수준으로 암호화해서 저장한다는 점이 다르다.
- Windows 환경에서는 “Git Credential Manager for Windows.” 라는 Helper가 있다.
- “osxkeychain” Helper와 비슷하게 동작하며 Windows Credential Store를 사용하여 안전하게 인증정보를 저장한다.
-
https://github.com/Microsoft/Git-Credential-Manager-for-Windows 에서 다운로드 받을 수 있다.
- 위에서 설명한 여러 모드 중 하나를 아래와 같이 설정할 수 있다.
$ git config --global credential.helper cache
- 추가 옵션을 지정할 수 있는 Helper도 있다.
- “store” Helper는
--file <path>
옵션을 사용하여 인증정보를 저장할 텍스트 파일의 위치를 지정한다. - 기본 값은
~/.git-credentials
이다. - “cache” Helper는
--timeout <seconds>
옵션을 사용하여 언제까지 인증정보를 메모리에 유지할지 설정한다. - 기본 값은 “900” 초로 15분이다.
- 기본 경로가 아닌 다른 경로를 지정해서 인증정보를 저장하려면 아래와 같이 실행한다.
$ git config --global credential.helper 'store --file ~/.my-credentials'
- Helper를 여러개 섞어서 쓸 수도 있다.
- 인증이 필요한 리모트에 접근할 때 Git은 인증정보를 찾는데 Helper가 여러개 있으면 순서대로 찾는다.
- 반대로 인증정보를 저장할 때는 설정한 모든 모드에 저장한다.
- 아래 예제는 첫 번째 Path에 대해 인증정보를 읽거나 저장에 실패하면 두 번째 모드에 따라 메모리에서만 인증정보를 유지한다.
[credential]
helper = store --file /mnt/thumbdrive/.git-credentials
helper = cache --timeout 30000
2. 뚜껑을 열어보면
- 실제로는 어떻게 동작하는지 살펴보자.
- Git의 Credential-Helper 시스템의 기본 명령은
git credential
이다. -
이 명령이 하위 명령이나 옵션, 표준입력으로 필요한 정보를 입력받아 전달한다.
- 이 과정은 예제를 통해 이해하는 편이 쉽다.
- Credential Helper를 사용하도록 설정하고
mygithost
라는 호스트의 인증정보가 저장된 상태이다. - 아래 예제는 “fill” 명령으로 Git이 특정 호스트에 대한 인증정보를 얻으려는 과정을 보여준다.
$ 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
- 이 명령으로 인증정보를 얻어오는 과정을 시작한다.
- 이제 Git-credential 명령은 표준 입력으로 사용자의 입력을 기다린다. 인증정보가 필요한 대상의 프로토콜과 호스트이름을 입력한다.
- 빈 라인을 하나 입력하면 입력이 끝났다는 것을 의미한다. 이제 입력한 내용에 해당하는 인증정보를 응답해야 한다.
- Git-credential 명령이 전달받은 내용으로 인증정보를 찾아보고 찾으면 표준출력으로 찾은 정보를 응답한다.
- 물론 요청에 대한 인증정보가 없을 수도 있다. 이렇게 되면 Git이 사용자이름과 암호를 사용자가 입력하도록 메시지를 띄우고 값도 입력받는다. 입력받은 값을 다시 표준출력으로 응답한다.
- 이 Credential 시스템은 사실 Git과 분리된 독립적인 프로그램을 실행시켜 동작한다.
- 어떤 프로그램을 실행시킬지는
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 | ! 뒤의 코드를 쉘에서 실행 |
- 따라서 위에서 살펴본 여러 Helper는 사실
git-credential-cache
,git-credential-store
같은 명령이다. - 설정을 통해 이 명령들이 옵션이나 하위 명령을 받아서 실행하게 한다.
-
이 명령의 일반적인 형태는 “git-credential-foo [args]
” 이다. `git-credential` 명령과 마찬가지로 표준입력/표준출력을 프로토콜로 사용하지만 처리하는 액션(하위 명령)은 아래와 같이 다소 다르다. get
- 사용자이름과 암호를 요구하는 액션store
- Helper에서 인증정보를 저장하는 액션-
erase
- Helper에서 인증정보를 삭제하는 액션 store
나erase
액션은 따로 결과를 출력할 필요가 없다(Git은 결과를 무시).get
액션의 결과는 Git이 주의 깊게 관찰해서 가져다 사용하므로 매우 중요하다.- Helper는 전달받은 내용으로 인증정보를 찾고 저장된 인증정보가 없다면 아무런 결과도 출력하지 않고 종료하면 된다.
- 적당한 인증정보를 찾았을 때는 전달받은 내용에 찾은 인증정보를 추가하여 결과로 응답한다.
-
결과는 몇 라인의 할당 구문으로 구성하며, Git은 이 결과를 받아서 사용한다.
- 아래 예제는 위에서 살펴본 예제와 같은 내용으로
git-crediential
명령 대신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
git-credential-store
Helper에게 인증정보를 저장하도록 한다. 저장할 인증정보는 사용자이름이 “bob”, 암호가 “s3cre7” 이다. 프로토콜과 호스트가https://mygithost
일 때 사용한다.- 저장한 인증정보를 가져온다. 이미 아는
https://mygithost
리모트 주소를 호스트와 프로토콜로 나누어 표준입력으로 전달하고 한 라인을 비운다. git-credential-store
명령은 <1>에서 저장한 사용자이름과 암호를 표준출력으로 응답한다.
~/git.store
파일의 내용은 사실 아래와 같다.
https://bob:s3cre7@mygithost
- 단순한 텍스트파일로 인증정보가 포함된 URL 형태로 저장한다.
osxkeychain
이나wincred
Helper를 사용하면 OS에서 제공하는 좀 더 안전한 저장소에 인증정보를 저장한다.cache
Helper의 경우 나름의 형식으로 메모리에 인증정보를 저장하고 다른 프로세스에서는 (메모리의 내용을) 읽어갈 수 없다.
3. 맞춤 Credential 캐시
git-credential-store
나 다른 명령도 독립된 프로그램이다.- 아무 스크립트나 프로그램도 Git Credential Helper가 될 수 있다.
- 이미 Git이 제공하는 Helper로도 충분하지만 모든 경우를 커버하지 않는다.
- 예를 들어 어떤 인증정보는 팀 전체가 공유해야 한다.
- 배포에 사용하는 인증정보가 그렇다.
- 이 인증정보는 공유하는 디렉토리에 저장해두고 사용한다.
- 이 인증정보는 자주 변경되기 때문에 로컬 Credential 저장소에 저장하지 않고 사용하고자 한다.
- 이런 경우라면 Git이 제공하는 Helper로는 부족하며 자신만의 맞춤 Helper가 필요하다.
- 맞춤 Helper는 아래와 같은 기능을 제공해야 한다.
- 새 맞춤 Helper가 집중해야 할 액션은
get
뿐이다.store
나erase
액션은 저장하는 기능이기 때문에 이 액션을 받으면 깔끔하게 바로 종료한다. - 공유하는 Credential 파일은
git-credential-store
명령이 저장하는 형식과 같은 형식을 사용한다. - Credential 파일의 위치는 기본 값을 사용해도 되지만 파일 경로를 넘길 수 있다.
- 예제로 보여주는 맞춤 Helper도 Ruby로 작성한다.
- 하지만, 다른 어떤 언어를 사용해도 Git이 실행할 수만 있다면 상관없다.
- 작성한 저장소 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.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'] and user == known['username'] then
puts "protocol=#{prot}"
puts "host=#{host}"
puts "username=#{user}"
puts "password=#{pass}"
exit(0)
end
end
- 우선 명령 옵션을 처리한다. 옵션으로는 Credential 파일명이 들어온다. 기본 값은
~/.git-credentials
이다. - Helper 프로그램은
get
액션만 처리하며 Credential 파일이 존재하는 경우만 처리한다. - 이후에는 빈 라인이 나타날 때까지 표준입력으로부터 한 줄 한 줄 읽는다. 각 라인을 파싱하여
known
해시에 저장하고 <4>의 응답에서 사용한다. - 이 루프에서 Credential 파일을 읽어서 <3>의 해시에 해당하는 정보를 찾는다.
known
해시에서 프로토콜과 호스트 정보가 일치하는 경우 사용자이름과 암호를 포함하여 결과를 출력한다.
- 이 파일을
git-credential-read-only
로 저장하고PATH
에 등록된 디렉토리 중 하나에 위치시키고 실행 권한을 부여한다. Helper를 실행하면 아래와 같다.
$ git credential-read-only --file=/mnt/shared/creds get
protocol=https
host=mygithost
protocol=https
host=mygithost
username=bob
password=s3cre7
- 위에서 저장한 파일 이름이 “git-” 으로 시작하기 때문에 아래와 같이 간단한 이름으로 설정해서 사용할 수 있다.
$ git config --global credential.helper 'read-only --file /mnt/shared/creds'
- 이렇게 살펴본 대로 Credential 저장소를 필요에 따라 맞춤 프로그램을 작성해서 확장하는 것이 어렵지 않다.
- 스크립트를 만들어 사용자나 팀의 가려운 부분을 긁어줄 수 있다.