diff options
author | Galen Guyer <galen@galenguyer.com> | 2022-08-31 13:26:38 -0400 |
---|---|---|
committer | Galen Guyer <galen@galenguyer.com> | 2022-08-31 13:26:38 -0400 |
commit | b8f0569e23d12dac26831249c05d872cf80b1e55 (patch) | |
tree | c9eca59ea965ff99da5cf5bac364b4ae948c18bf | |
parent | 0db50996b76fa009b4e905dff35be3a1d308f698 (diff) |
Add a PostV2Registry method for push authorization
This commit adds a method nearly identical to PingV2Registry,
except it uses a POST request instead of a GET request. This is
so that registries that use a proxy that perform authentication on
POST requests but not GET requests (to allow for anonymous pulls)
are able to provide this functionality. Previously, using a GET request
meant there was no way to differentiate if the action being taken was
a push or pull and handle it differently, this allows that.
-rw-r--r-- | distribution/push.go | 2 | ||||
-rw-r--r-- | distribution/registry.go | 2 | ||||
-rw-r--r-- | registry/auth.go | 30 |
3 files changed, 32 insertions, 2 deletions
diff --git a/distribution/push.go b/distribution/push.go index 808c5ec316..c703e1f80c 100644 --- a/distribution/push.go +++ b/distribution/push.go @@ -30,7 +30,7 @@ func Push(ctx context.Context, ref reference.Named, config *ImagePushConfig) err return err } - progress.Messagef(config.ProgressOutput, "", "The push refers to repository [%s]", repoInfo.Name.Name()) + progress.Messagef(config.ProgressOutput, "", "The push refers to repository [%s] (using modified push)", repoInfo.Name.Name()) associations := config.ReferenceStore.ReferencesByName(repoInfo.Name) if len(associations) == 0 { diff --git a/distribution/registry.go b/distribution/registry.go index 36d3a42ca0..677730c04c 100644 --- a/distribution/registry.go +++ b/distribution/registry.go @@ -84,7 +84,7 @@ func newRepository( modifiers := registry.Headers(dockerversion.DockerUserAgent(ctx), metaHeaders) authTransport := transport.NewTransport(base, modifiers...) - challengeManager, err := registry.PingV2Registry(endpoint.URL, authTransport) + challengeManager, err := registry.PostV2Registry(endpoint.URL, authTransport) if err != nil { transportOK := false if responseErr, ok := err.(registry.PingResponseError); ok { diff --git a/registry/auth.go b/registry/auth.go index dd75a49f38..c0e50e1f42 100644 --- a/registry/auth.go +++ b/registry/auth.go @@ -194,3 +194,33 @@ func PingV2Registry(endpoint *url.URL, transport http.RoundTripper) (challenge.M return challengeManager, nil } + +// PostV2Registry attempts to ping a v2 registry and on success return a +// challenge manager for the supported authentication types. +// If a response is received but cannot be interpreted, a PingResponseError will be returned. +// A POST request is used for registries that have a proxy that restricts pushing but not pulling +func PostV2Registry(endpoint *url.URL, transport http.RoundTripper) (challenge.Manager, error) { + pingClient := &http.Client{ + Transport: transport, + Timeout: 15 * time.Second, + } + endpointStr := strings.TrimRight(endpoint.String(), "/") + "/v2/" + req, err := http.NewRequest(http.MethodPost, endpointStr, nil) + if err != nil { + return nil, err + } + resp, err := pingClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + challengeManager := challenge.NewSimpleManager() + if err := challengeManager.AddResponse(resp); err != nil { + return nil, PingResponseError{ + Err: err, + } + } + + return challengeManager, nil +} |