diff --git a/lfsapi/auth.go b/lfsapi/auth.go index 4027dc16..f6c4ad1a 100644 --- a/lfsapi/auth.go +++ b/lfsapi/auth.go @@ -9,6 +9,7 @@ import ( "os" "strings" + "github.com/bgentry/go-netrc/netrc" "github.com/git-lfs/git-lfs/errors" "github.com/rubyist/tracerx" ) @@ -108,24 +109,47 @@ func getCreds(credHelper CredentialHelper, netrcFinder NetrcFinder, ef EndpointF operation := getReqOperation(req) apiEndpoint := ef.Endpoint(operation, remote) access := ef.AccessFor(apiEndpoint.Url) - if access == NTLMAccess || requestHasAuth(req) || setAuthFromNetrc(netrcFinder, req) || access == NoneAccess { - return apiEndpoint, access, nil, nil, nil + + if access != NTLMAccess { + if requestHasAuth(req) || setAuthFromNetrc(netrcFinder, req) || access == NoneAccess { + return apiEndpoint, access, nil, nil, nil + } + + credsURL, err := getCredURLForAPI(ef, operation, remote, apiEndpoint, req) + if err != nil { + return apiEndpoint, access, nil, nil, errors.Wrap(err, "creds") + } + + if credsURL == nil { + return apiEndpoint, access, nil, nil, nil + } + + creds, err := fillGitCreds(credHelper, ef, req, credsURL) + return apiEndpoint, access, creds, credsURL, err } - credsURL, err := getCredURLForAPI(ef, operation, remote, apiEndpoint, req) + credsURL, err := url.Parse(apiEndpoint.Url) if err != nil { return apiEndpoint, access, nil, nil, errors.Wrap(err, "creds") } - if credsURL == nil { - return apiEndpoint, access, nil, nil, nil + if netrcMachine := getAuthFromNetrc(netrcFinder, req); netrcMachine != nil { + creds := Creds{ + "protocol": credsURL.Scheme, + "host": credsURL.Host, + "username": netrcMachine.Login, + "password": netrcMachine.Password, + "source": "netrc", + } + + return apiEndpoint, access, creds, credsURL, nil } - creds, err := fillCredentials(credHelper, ef, req, credsURL) + creds, err := getGitCreds(credHelper, ef, req, credsURL) return apiEndpoint, access, creds, credsURL, err } -func fillCredentials(credHelper CredentialHelper, ef EndpointFinder, req *http.Request, u *url.URL) (Creds, error) { +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() != "" { @@ -143,17 +167,20 @@ func fillCredentials(credHelper CredentialHelper, ef EndpointFinder, req *http.R err = errors.New(errmsg) } - if err != nil { - return nil, err - } + return creds, err +} - tracerx.Printf("Filled credentials for %s", u) - setRequestAuth(req, creds["username"], creds["password"]) +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 } -func setAuthFromNetrc(netrcFinder NetrcFinder, req *http.Request) bool { +func getAuthFromNetrc(netrcFinder NetrcFinder, req *http.Request) *netrc.Machine { hostname := req.URL.Host var host string @@ -162,13 +189,17 @@ func setAuthFromNetrc(netrcFinder NetrcFinder, req *http.Request) bool { host, _, err = net.SplitHostPort(hostname) if err != nil { tracerx.Printf("netrc: error parsing %q: %s", hostname, err) - return false + return nil } } else { host = hostname } - if machine := netrcFinder.FindMachine(host); machine != nil { + return netrcFinder.FindMachine(host) +} + +func setAuthFromNetrc(netrcFinder NetrcFinder, req *http.Request) bool { + if machine := getAuthFromNetrc(netrcFinder, req); machine != nil { setRequestAuth(req, machine.Login, machine.Password) return true } diff --git a/lfsapi/auth_test.go b/lfsapi/auth_test.go index a32db43a..8d64ec02 100644 --- a/lfsapi/auth_test.go +++ b/lfsapi/auth_test.go @@ -280,6 +280,48 @@ func TestGetCreds(t *testing.T) { }, }, }, + "ntlm": getCredsTest{ + Remote: "origin", + Method: "GET", + Href: "https://git-server.com/repo/lfs/locks", + Config: map[string]string{ + "lfs.url": "https://git-server.com/repo/lfs", + "lfs.https://git-server.com/repo/lfs.access": "ntlm", + }, + Expected: getCredsExpected{ + Access: NTLMAccess, + Endpoint: "https://git-server.com/repo/lfs", + CredsURL: "https://git-server.com/repo/lfs", + Creds: map[string]string{ + "protocol": "https", + "host": "git-server.com", + "username": "git-server.com", + "password": "monkey", + "path": "repo/lfs", + }, + }, + }, + "ntlm with netrc": getCredsTest{ + Remote: "origin", + Method: "GET", + Href: "https://netrc-host.com/repo/lfs/locks", + Config: map[string]string{ + "lfs.url": "https://netrc-host.com/repo/lfs", + "lfs.https://netrc-host.com/repo/lfs.access": "ntlm", + }, + Expected: getCredsExpected{ + Access: NTLMAccess, + Endpoint: "https://netrc-host.com/repo/lfs", + CredsURL: "https://netrc-host.com/repo/lfs", + Creds: map[string]string{ + "protocol": "https", + "host": "netrc-host.com", + "username": "abc", + "password": "def", + "source": "netrc", + }, + }, + }, "custom auth": getCredsTest{ Remote: "origin", Method: "GET",