123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- package containerd
- import (
- "context"
- "crypto/tls"
- "errors"
- "net/http"
- cerrdefs "github.com/containerd/containerd/errdefs"
- "github.com/containerd/containerd/remotes"
- "github.com/containerd/containerd/remotes/docker"
- "github.com/containerd/containerd/version"
- "github.com/containerd/log"
- "github.com/distribution/reference"
- registrytypes "github.com/docker/docker/api/types/registry"
- "github.com/docker/docker/dockerversion"
- "github.com/docker/docker/pkg/useragent"
- "github.com/docker/docker/registry"
- )
- func (i *ImageService) newResolverFromAuthConfig(ctx context.Context, authConfig *registrytypes.AuthConfig, ref reference.Named) (remotes.Resolver, docker.StatusTracker) {
- tracker := docker.NewInMemoryTracker()
- hosts := hostsWrapper(i.registryHosts, authConfig, ref, i.registryService)
- headers := http.Header{}
- headers.Set("User-Agent", dockerversion.DockerUserAgent(ctx, useragent.VersionInfo{Name: "containerd-client", Version: version.Version}, useragent.VersionInfo{Name: "storage-driver", Version: i.snapshotter}))
- return docker.NewResolver(docker.ResolverOptions{
- Hosts: hosts,
- Tracker: tracker,
- Headers: headers,
- }), tracker
- }
- func hostsWrapper(hostsFn docker.RegistryHosts, optAuthConfig *registrytypes.AuthConfig, ref reference.Named, regService registryResolver) docker.RegistryHosts {
- var authorizer docker.Authorizer
- if optAuthConfig != nil {
- authorizer = authorizerFromAuthConfig(*optAuthConfig, ref)
- }
- return func(n string) ([]docker.RegistryHost, error) {
- hosts, err := hostsFn(n)
- if err != nil {
- return nil, err
- }
- for i := range hosts {
- if hosts[i].Authorizer == nil {
- hosts[i].Authorizer = authorizer
- isInsecure := regService.IsInsecureRegistry(hosts[i].Host)
- if hosts[i].Client.Transport != nil && isInsecure {
- hosts[i].Client.Transport = httpFallback{super: hosts[i].Client.Transport}
- }
- }
- }
- return hosts, nil
- }
- }
- func authorizerFromAuthConfig(authConfig registrytypes.AuthConfig, ref reference.Named) docker.Authorizer {
- cfgHost := registry.ConvertToHostname(authConfig.ServerAddress)
- if cfgHost == "" {
- cfgHost = reference.Domain(ref)
- }
- if cfgHost == registry.IndexHostname || cfgHost == registry.IndexName {
- cfgHost = registry.DefaultRegistryHost
- }
- if authConfig.RegistryToken != "" {
- return &bearerAuthorizer{
- host: cfgHost,
- bearer: authConfig.RegistryToken,
- }
- }
- return docker.NewDockerAuthorizer(docker.WithAuthCreds(func(host string) (string, string, error) {
- if cfgHost != host {
- log.G(context.TODO()).WithFields(log.Fields{
- "host": host,
- "cfgHost": cfgHost,
- }).Warn("Host doesn't match")
- return "", "", nil
- }
- if authConfig.IdentityToken != "" {
- return "", authConfig.IdentityToken, nil
- }
- return authConfig.Username, authConfig.Password, nil
- }))
- }
- type bearerAuthorizer struct {
- host string
- bearer string
- }
- func (a *bearerAuthorizer) Authorize(ctx context.Context, req *http.Request) error {
- if req.Host != a.host {
- log.G(ctx).WithFields(log.Fields{
- "host": req.Host,
- "cfgHost": a.host,
- }).Warn("Host doesn't match for bearer token")
- return nil
- }
- req.Header.Set("Authorization", "Bearer "+a.bearer)
- return nil
- }
- func (a *bearerAuthorizer) AddResponses(context.Context, []*http.Response) error {
- // Return not implemented to prevent retry of the request when bearer did not succeed
- return cerrdefs.ErrNotImplemented
- }
- type httpFallback struct {
- super http.RoundTripper
- }
- func (f httpFallback) RoundTrip(r *http.Request) (*http.Response, error) {
- resp, err := f.super.RoundTrip(r)
- var tlsErr tls.RecordHeaderError
- if errors.As(err, &tlsErr) && string(tlsErr.RecordHeader[:]) == "HTTP/" {
- // server gave HTTP response to HTTPS client
- plainHttpUrl := *r.URL
- plainHttpUrl.Scheme = "http"
- plainHttpRequest := *r
- plainHttpRequest.URL = &plainHttpUrl
- return http.DefaultTransport.RoundTrip(&plainHttpRequest)
- }
- return resp, err
- }
|