lfsapi/creds: use AskPassCredentialHelper with GIT_ASKPASS

This commit is contained in:
Taylor Blau 2017-08-10 16:30:42 -06:00
parent ecc9fa5810
commit 0fdc71db4e
3 changed files with 85 additions and 1 deletions

@ -51,6 +51,12 @@ be scoped inside the configuration for a remote.
Sets the maximum time, in seconds, for the HTTP client to maintain keepalive Sets the maximum time, in seconds, for the HTTP client to maintain keepalive
connections. Default: 30 minutes. connections. Default: 30 minutes.
* `core.askpass`, GIT_ASKPASS
Given as a program and its arguments, this is invoked when authentication is
needed against the LFS API. The contents of stdout are interpreted as the
password.
* `lfs.cachecredentials` * `lfs.cachecredentials`
Enables in-memory SSH and Git Credential caching for a single 'git lfs' Enables in-memory SSH and Git Credential caching for a single 'git lfs'

@ -9,12 +9,19 @@ import (
"github.com/git-lfs/git-lfs/config" "github.com/git-lfs/git-lfs/config"
"github.com/git-lfs/git-lfs/errors" "github.com/git-lfs/git-lfs/errors"
"github.com/git-lfs/git-lfs/tools"
"github.com/rubyist/tracerx" "github.com/rubyist/tracerx"
) )
// credsConfig supplies configuration options pertaining to the authorization // credsConfig supplies configuration options pertaining to the authorization
// process in package lfsapi. // process in package lfsapi.
type credsConfig struct { type credsConfig struct {
// AskPass is a string containing an executable name as well as a
// program arguments.
//
// See: https://git-scm.com/docs/gitcredentials#_requesting_credentials
// for more.
AskPass string `os:"GIT_ASKPASS" git:"core.askpass"`
// Cached is a boolean determining whether or not to enable the // Cached is a boolean determining whether or not to enable the
// credential cacher. // credential cacher.
Cached bool `git:"lfs.cachecredentials"` Cached bool `git:"lfs.cachecredentials"`
@ -34,6 +41,21 @@ func getCredentialHelper(cfg *config.Configuration) (CredentialHelper, error) {
return nil, err return nil, err
} }
var hs []CredentialHelper
if len(ccfg.AskPass) > 0 {
parts := tools.QuotedFields(ccfg.AskPass)
if len(parts) < 1 {
return nil, errors.Errorf(
"lfsapi/creds: invalid ASKPASS: %q",
ccfg.AskPass)
}
hs = append(hs, &AskPassCredentialHelper{
Program: parts[0],
Args: parts[1:],
})
}
var h CredentialHelper var h CredentialHelper
h = &commandCredentialHelper{ h = &commandCredentialHelper{
SkipPrompt: ccfg.SkipPrompt, SkipPrompt: ccfg.SkipPrompt,
@ -42,8 +64,15 @@ func getCredentialHelper(cfg *config.Configuration) (CredentialHelper, error) {
if ccfg.Cached { if ccfg.Cached {
h = withCredentialCache(h) h = withCredentialCache(h)
} }
hs = append(hs, h)
return h, nil switch len(hs) {
case 0:
return nil, nil
case 1:
return hs[0], nil
}
return CredentialHelpers(hs), nil
} }
// getCredentialConfig parses a *credsConfig given the OS and Git // getCredentialConfig parses a *credsConfig given the OS and Git

49
test/test-askpass.sh Executable file

@ -0,0 +1,49 @@
#!/usr/bin/env bash
. "test/testlib.sh"
begin_test "askpass: push with GIT_ASKPASS"
(
set -e
reponame="askpass-with-environ"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git lfs track "*.dat"
echo "hello" > a.dat
git add .gitattributes a.dat
git commit -m "initial commit"
# $password is defined from test/cmd/lfstest-gitserver.go (see: skipIfBadAuth)
password="pass"
GIT_ASKPASS="echo $password" GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push 2>&1 | tee push.log
grep "filling with GIT_ASKPASS: echo $password" push.log
)
end_test
begin_test "askpass: push with core.askpass"
(
set -e
reponame="askpass-with-config"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git lfs track "*.dat"
echo "hello" > a.dat
git add .gitattributes a.dat
git commit -m "initial commit"
# $password is defined from test/cmd/lfstest-gitserver.go (see: skipIfBadAuth)
password="pass"
git config "core.askpass" "echo $password"
cat .git/config
GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push 2>&1 | tee push.log
grep "filling with GIT_ASKPASS: echo $password" push.log
)
end_test