lfsapi: return null cred helper if cred helper isn't used for a req
This commit is contained in:
parent
c8b16f965c
commit
28ff509488
@ -21,29 +21,7 @@ var (
|
||||
)
|
||||
|
||||
func (c *Client) DoWithAuth(remote string, req *http.Request) (*http.Response, error) {
|
||||
credHelper := c.Credentials
|
||||
if credHelper == nil {
|
||||
var err error
|
||||
credHelper, err = getCredentialHelper(c.osEnv, c.gitEnv)
|
||||
if err != nil {
|
||||
tracerx.Printf("error getting credential helper: %s", err)
|
||||
}
|
||||
if credHelper == nil {
|
||||
credHelper = defaultCredentialHelper
|
||||
}
|
||||
}
|
||||
|
||||
netrcFinder := c.Netrc
|
||||
if netrcFinder == nil {
|
||||
netrcFinder = defaultNetrcFinder
|
||||
}
|
||||
|
||||
ef := c.Endpoints
|
||||
if ef == nil {
|
||||
ef = defaultEndpointFinder
|
||||
}
|
||||
|
||||
apiEndpoint, access, creds, credsURL, err := getCreds(credHelper, netrcFinder, ef, remote, req)
|
||||
apiEndpoint, access, credHelper, credsURL, creds, err := c.getCreds(remote, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -101,32 +79,48 @@ func (c *Client) doWithCreds(req *http.Request, credHelper CredentialHelper, cre
|
||||
// 3. The Git Remote URL, which should be something like "https://git.com/repo.git"
|
||||
// This URL is used for the Git Credential Helper. This way existing https
|
||||
// Git remote credentials can be re-used for LFS.
|
||||
func getCreds(credHelper CredentialHelper, netrcFinder NetrcFinder, ef EndpointFinder, remote string, req *http.Request) (Endpoint, Access, Creds, *url.URL, error) {
|
||||
func (c *Client) getCreds(remote string, req *http.Request) (Endpoint, Access, CredentialHelper, *url.URL, Creds, error) {
|
||||
ef := c.Endpoints
|
||||
if ef == nil {
|
||||
ef = defaultEndpointFinder
|
||||
}
|
||||
|
||||
netrcFinder := c.Netrc
|
||||
if netrcFinder == nil {
|
||||
netrcFinder = defaultNetrcFinder
|
||||
}
|
||||
|
||||
operation := getReqOperation(req)
|
||||
apiEndpoint := ef.Endpoint(operation, remote)
|
||||
access := ef.AccessFor(apiEndpoint.Url)
|
||||
|
||||
if access != NTLMAccess {
|
||||
if requestHasAuth(req) || setAuthFromNetrc(netrcFinder, req) || access == NoneAccess {
|
||||
return apiEndpoint, access, nil, nil, nil
|
||||
return apiEndpoint, access, nullCreds, nil, nil, nil
|
||||
}
|
||||
|
||||
credsURL, err := getCredURLForAPI(ef, operation, remote, apiEndpoint, req)
|
||||
if err != nil {
|
||||
return apiEndpoint, access, nil, nil, errors.Wrap(err, "creds")
|
||||
return apiEndpoint, access, nullCreds, nil, nil, errors.Wrap(err, "creds")
|
||||
}
|
||||
|
||||
if credsURL == nil {
|
||||
return apiEndpoint, access, nil, nil, nil
|
||||
return apiEndpoint, access, nullCreds, nil, nil, nil
|
||||
}
|
||||
|
||||
creds, err := fillGitCreds(credHelper, ef, req, credsURL)
|
||||
return apiEndpoint, access, creds, credsURL, err
|
||||
credHelper, creds, err := c.getGitCreds(ef, req, credsURL)
|
||||
if err == nil {
|
||||
tracerx.Printf("Filled credentials for %s", credsURL)
|
||||
setRequestAuth(req, creds["username"], creds["password"])
|
||||
}
|
||||
return apiEndpoint, access, credHelper, credsURL, creds, err
|
||||
}
|
||||
|
||||
// NTLM ONLY
|
||||
|
||||
credsURL, err := url.Parse(apiEndpoint.Url)
|
||||
if err != nil {
|
||||
return apiEndpoint, access, nil, nil, errors.Wrap(err, "creds")
|
||||
return apiEndpoint, access, nullCreds, nil, nil, errors.Wrap(err, "creds")
|
||||
}
|
||||
|
||||
if netrcMachine := getAuthFromNetrc(netrcFinder, req); netrcMachine != nil {
|
||||
@ -138,20 +132,16 @@ func getCreds(credHelper CredentialHelper, netrcFinder NetrcFinder, ef EndpointF
|
||||
"source": "netrc",
|
||||
}
|
||||
|
||||
return apiEndpoint, access, creds, credsURL, nil
|
||||
return apiEndpoint, access, nullCreds, credsURL, creds, nil
|
||||
}
|
||||
|
||||
creds, err := getGitCreds(credHelper, ef, req, credsURL)
|
||||
return apiEndpoint, access, creds, credsURL, err
|
||||
// NTLM uses creds to create the session
|
||||
credHelper, creds, err := c.getGitCreds(ef, req, credsURL)
|
||||
return apiEndpoint, access, credHelper, credsURL, creds, err
|
||||
}
|
||||
|
||||
func getGitCreds(credHelper CredentialHelper, ef EndpointFinder, req *http.Request, u *url.URL) (Creds, error) {
|
||||
path := strings.TrimPrefix(u.Path, "/")
|
||||
input := Creds{"protocol": u.Scheme, "host": u.Host, "path": path}
|
||||
if u.User != nil && u.User.Username() != "" {
|
||||
input["username"] = u.User.Username()
|
||||
}
|
||||
|
||||
func (c *Client) getGitCreds(ef EndpointFinder, req *http.Request, u *url.URL) (CredentialHelper, Creds, error) {
|
||||
credHelper, input := c.getCredentialHelper(u)
|
||||
creds, err := credHelper.Fill(input)
|
||||
if creds == nil || len(creds) < 1 {
|
||||
errmsg := fmt.Sprintf("Git credentials for %s not found", u)
|
||||
@ -163,17 +153,7 @@ func getGitCreds(credHelper CredentialHelper, ef EndpointFinder, req *http.Reque
|
||||
err = errors.New(errmsg)
|
||||
}
|
||||
|
||||
return creds, err
|
||||
}
|
||||
|
||||
func fillGitCreds(credHelper CredentialHelper, ef EndpointFinder, req *http.Request, u *url.URL) (Creds, error) {
|
||||
creds, err := getGitCreds(credHelper, ef, req, u)
|
||||
if err == nil {
|
||||
tracerx.Printf("Filled credentials for %s", u)
|
||||
setRequestAuth(req, creds["username"], creds["password"])
|
||||
}
|
||||
|
||||
return creds, err
|
||||
return credHelper, creds, err
|
||||
}
|
||||
|
||||
func getAuthFromNetrc(netrcFinder NetrcFinder, req *http.Request) *netrc.Machine {
|
||||
|
@ -517,8 +517,10 @@ func TestGetCreds(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
credHelper := &fakeCredentialFiller{}
|
||||
netrcFinder := &fakeNetrc{}
|
||||
client := &Client{
|
||||
Credentials: &fakeCredentialFiller{},
|
||||
Netrc: &fakeNetrc{},
|
||||
}
|
||||
for desc, test := range tests {
|
||||
t.Log(desc)
|
||||
req, err := http.NewRequest(test.Method, test.Href, nil)
|
||||
@ -531,8 +533,8 @@ func TestGetCreds(t *testing.T) {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
|
||||
ef := NewEndpointFinder(NewContext(nil, nil, test.Config))
|
||||
endpoint, access, creds, credsURL, err := getCreds(credHelper, netrcFinder, ef, test.Remote, req)
|
||||
client.Endpoints = NewEndpointFinder(NewContext(nil, nil, test.Config))
|
||||
endpoint, access, _, credsURL, creds, err := client.getCreds(test.Remote, req)
|
||||
if !assert.Nil(t, err) {
|
||||
continue
|
||||
}
|
||||
|
100
lfsapi/creds.go
100
lfsapi/creds.go
@ -8,86 +8,61 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/git-lfs/git-lfs/config"
|
||||
"github.com/git-lfs/git-lfs/errors"
|
||||
"github.com/rubyist/tracerx"
|
||||
)
|
||||
|
||||
// credsConfig supplies configuration options pertaining to the authorization
|
||||
// process in package lfsapi.
|
||||
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" os:"SSH_ASKPASS"`
|
||||
// Helper is a string defining the credential helper that Git should use.
|
||||
Helper string `git:"credential.helper"`
|
||||
// Cached is a boolean determining whether or not to enable the
|
||||
// credential cacher.
|
||||
Cached bool
|
||||
// SkipPrompt is a boolean determining whether or not to prompt the user
|
||||
// for a password.
|
||||
SkipPrompt bool `os:"GIT_TERMINAL_PROMPT"`
|
||||
}
|
||||
|
||||
// getCredentialHelper parses a 'credsConfig' from the git and OS environments,
|
||||
// returning the appropriate CredentialHelper to authenticate requests with.
|
||||
//
|
||||
// It returns an error if any configuration was invalid, or otherwise
|
||||
// un-useable.
|
||||
func getCredentialHelper(osEnv, gitEnv config.Environment) (CredentialHelper, error) {
|
||||
ccfg, err := getCredentialConfig(osEnv, gitEnv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (c *Client) getCredentialHelper(u *url.URL) (CredentialHelper, Creds) {
|
||||
path := strings.TrimPrefix(u.Path, "/")
|
||||
input := Creds{"protocol": u.Scheme, "host": u.Host, "path": path}
|
||||
if u.User != nil && u.User.Username() != "" {
|
||||
input["username"] = u.User.Username()
|
||||
}
|
||||
|
||||
if c.Credentials != nil {
|
||||
return c.Credentials, input
|
||||
}
|
||||
|
||||
askpass, ok := c.osEnv.Get("GIT_ASKPASS")
|
||||
if !ok {
|
||||
askpass, ok = c.gitEnv.Get("core.askpass")
|
||||
}
|
||||
if !ok {
|
||||
askpass, ok = c.osEnv.Get("SSH_ASKPASS")
|
||||
}
|
||||
helper, _ := c.gitEnv.Get("credential.helper")
|
||||
cached := c.gitEnv.Bool("lfs.cachecredentials", true)
|
||||
skipPrompt := c.osEnv.Bool("GIT_TERMINAL_PROMPT", false)
|
||||
|
||||
var hs []CredentialHelper
|
||||
if len(ccfg.Helper) == 0 && len(ccfg.AskPass) > 0 {
|
||||
if len(helper) == 0 && len(askpass) > 0 {
|
||||
hs = append(hs, &AskPassCredentialHelper{
|
||||
Program: ccfg.AskPass,
|
||||
Program: askpass,
|
||||
})
|
||||
}
|
||||
|
||||
var h CredentialHelper
|
||||
h = &commandCredentialHelper{
|
||||
SkipPrompt: ccfg.SkipPrompt,
|
||||
SkipPrompt: skipPrompt,
|
||||
}
|
||||
|
||||
if ccfg.Cached {
|
||||
if cached {
|
||||
h = withCredentialCache(h)
|
||||
}
|
||||
hs = append(hs, h)
|
||||
|
||||
switch len(hs) {
|
||||
case 0:
|
||||
return nil, nil
|
||||
return defaultCredentialHelper, input
|
||||
case 1:
|
||||
return hs[0], nil
|
||||
return hs[0], input
|
||||
}
|
||||
return CredentialHelpers(hs), nil
|
||||
}
|
||||
|
||||
// getCredentialConfig parses a *credsConfig given the OS and Git
|
||||
// configurations.
|
||||
func getCredentialConfig(o, g config.Environment) (*credsConfig, error) {
|
||||
askpass, ok := o.Get("GIT_ASKPASS")
|
||||
if !ok {
|
||||
askpass, ok = g.Get("core.askpass")
|
||||
}
|
||||
if !ok {
|
||||
askpass, ok = o.Get("SSH_ASKPASS")
|
||||
}
|
||||
helper, _ := g.Get("credential.helper")
|
||||
what := &credsConfig{
|
||||
AskPass: askpass,
|
||||
Helper: helper,
|
||||
Cached: g.Bool("lfs.cachecredentials", true),
|
||||
SkipPrompt: o.Bool("GIT_TERMINAL_PROMPT", false),
|
||||
}
|
||||
|
||||
return what, nil
|
||||
return CredentialHelpers(hs), input
|
||||
}
|
||||
|
||||
// CredentialHelpers is a []CredentialHelper that iterates through each
|
||||
@ -332,6 +307,8 @@ func (h *commandCredentialHelper) Reject(creds Creds) error {
|
||||
}
|
||||
|
||||
func (h *commandCredentialHelper) Approve(creds Creds) error {
|
||||
tracerx.Printf("creds: git credential approve (%q, %q, %q)",
|
||||
creds["protocol"], creds["host"], creds["path"])
|
||||
_, err := h.exec("approve", creds)
|
||||
return err
|
||||
}
|
||||
@ -383,3 +360,22 @@ func (h *commandCredentialHelper) exec(subcommand string, input Creds) (Creds, e
|
||||
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
type nullCredentialHelper struct{}
|
||||
|
||||
var (
|
||||
nullCredError = errors.New("No credential helper configured")
|
||||
nullCreds = &nullCredentialHelper{}
|
||||
)
|
||||
|
||||
func (h *nullCredentialHelper) Fill(input Creds) (Creds, error) {
|
||||
return nil, nullCredError
|
||||
}
|
||||
|
||||
func (h *nullCredentialHelper) Approve(creds Creds) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *nullCredentialHelper) Reject(creds Creds) error {
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user