aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalen Guyer <galen@galenguyer.com>2022-08-31 13:26:38 -0400
committerGalen Guyer <galen@galenguyer.com>2022-08-31 13:26:38 -0400
commitb8f0569e23d12dac26831249c05d872cf80b1e55 (patch)
treec9eca59ea965ff99da5cf5bac364b4ae948c18bf
parent0db50996b76fa009b4e905dff35be3a1d308f698 (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.go2
-rw-r--r--distribution/registry.go2
-rw-r--r--registry/auth.go30
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
+}