mirror of https://github.com/k3d-io/k3d
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.8 KiB
82 lines
2.8 KiB
package registries
|
|
|
|
import (
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/google/go-containerregistry/pkg/authn"
|
|
"github.com/google/go-containerregistry/pkg/name"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var _ authn.Keychain = &endpoint{}
|
|
var _ http.RoundTripper = &endpoint{}
|
|
|
|
type endpoint struct {
|
|
auth authn.Authenticator
|
|
keychain authn.Keychain
|
|
ref name.Reference
|
|
registry *registry
|
|
url *url.URL
|
|
}
|
|
|
|
// Resolve returns an authenticator for the authn.Keychain interface. The authenticator
|
|
// provides credentials to a registry by returning the credentials from mirror endpoints.
|
|
// If there were no credentials provided for this endpoint, the default keychain is used
|
|
// as a fallback, followed by simply anonymous access.
|
|
func (e endpoint) Resolve(target authn.Resource) (authn.Authenticator, error) {
|
|
if e.auth != nil && e.auth != authn.Anonymous {
|
|
return e.auth, nil
|
|
}
|
|
if e.keychain != nil {
|
|
return e.keychain.Resolve(target)
|
|
}
|
|
return authn.Anonymous, nil
|
|
}
|
|
|
|
// RoundTrip handles making a request to an endpoint. It is responsible for rewriting the request
|
|
// URL to reflect the scheme, host, and path specified in the endpoint config. The transport itself
|
|
// will be retrieved from the registry config, potentially using a cached entry.
|
|
func (e endpoint) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
endpointURL := e.url
|
|
originalURL := req.URL.String()
|
|
|
|
// Only rewrite the URL if the request is being made against the original registry host.
|
|
// We might have been redirected to a different URL as part of the auth
|
|
// workflow, and must not rewrite URLs if that's the case.
|
|
if e.ref.Context().RegistryStr() == req.URL.Host {
|
|
if strings.HasPrefix(req.URL.Path, "/v2") {
|
|
// The default base path is /v2; if a path is included in the endpoint,
|
|
// replace the /v2 prefix from the request path with the endpoint path.
|
|
// This behavior is cribbed from containerd.
|
|
if endpointURL.Path != "" {
|
|
req.URL.Path = endpointURL.Path + strings.TrimPrefix(req.URL.Path, "/v2")
|
|
|
|
// If either URL has RawPath set (due to the path including urlencoded
|
|
// characters), it also needs to be used to set the combined URL
|
|
if endpointURL.RawPath != "" || req.URL.RawPath != "" {
|
|
endpointPath := endpointURL.Path
|
|
if endpointURL.RawPath != "" {
|
|
endpointPath = endpointURL.RawPath
|
|
}
|
|
reqPath := req.URL.Path
|
|
if req.URL.RawPath != "" {
|
|
reqPath = req.URL.RawPath
|
|
}
|
|
req.URL.RawPath = endpointPath + strings.TrimPrefix(reqPath, "/v2")
|
|
}
|
|
}
|
|
}
|
|
|
|
// override request host and scheme
|
|
req.Host = endpointURL.Host
|
|
req.URL.Host = endpointURL.Host
|
|
req.URL.Scheme = endpointURL.Scheme
|
|
}
|
|
|
|
if newURL := req.URL.String(); originalURL != newURL {
|
|
logrus.Debugf("Registry endpoint URL modified: %s => %s", originalURL, newURL)
|
|
}
|
|
return e.registry.getTransport(req.URL).RoundTrip(req)
|
|
}
|
|
|