diff --git a/registry/proxy/proxyauth.go b/registry/proxy/proxyauth.go index a9cc43a6..6f4b37d5 100644 --- a/registry/proxy/proxyauth.go +++ b/registry/proxy/proxyauth.go @@ -3,11 +3,12 @@ package proxy import ( "net/http" "net/url" + "strings" + "github.com/docker/distribution/context" "github.com/docker/distribution/registry/client/auth" ) -const tokenURL = "https://auth.docker.io/token" const challengeHeader = "Docker-Distribution-Api-Version" type userpass struct { @@ -33,16 +34,43 @@ func (c credentials) SetRefreshToken(u *url.URL, service, token string) { } // configureAuth stores credentials for challenge responses -func configureAuth(username, password string) (auth.CredentialStore, error) { - creds := map[string]userpass{ - tokenURL: { +func configureAuth(username, password, remoteURL string) (auth.CredentialStore, error) { + creds := map[string]userpass{} + + authURLs, err := getAuthURLs(remoteURL) + if err != nil { + return nil, err + } + + for _, url := range authURLs { + context.GetLogger(context.Background()).Infof("Discovered token authentication URL: %s", url) + creds[url] = userpass{ username: username, password: password, - }, + } } + return credentials{creds: creds}, nil } +func getAuthURLs(remoteURL string) ([]string, error) { + authURLs := []string{} + + resp, err := http.Get(remoteURL + "/v2/") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + for _, c := range auth.ResponseChallenges(resp) { + if strings.EqualFold(c.Scheme, "bearer") { + authURLs = append(authURLs, c.Parameters["realm"]) + } + } + + return authURLs, nil +} + func ping(manager auth.ChallengeManager, endpoint, versionHeader string) error { resp, err := http.Get(endpoint) if err != nil { diff --git a/registry/proxy/proxyregistry.go b/registry/proxy/proxyregistry.go index c63bc619..9979866b 100644 --- a/registry/proxy/proxyregistry.go +++ b/registry/proxy/proxyregistry.go @@ -91,7 +91,7 @@ func NewRegistryPullThroughCache(ctx context.Context, registry distribution.Name return nil, err } - cs, err := configureAuth(config.Username, config.Password) + cs, err := configureAuth(config.Username, config.Password, config.RemoteURL) if err != nil { return nil, err }