Bläddra i källkod

c8d/resolver: Fallback to http for insecure registries

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Paweł Gronowski 2 år sedan
förälder
incheckning
9032e6779d
4 ändrade filer med 67 tillägg och 24 borttagningar
  1. 41 16
      daemon/containerd/resolver.go
  2. 10 7
      daemon/containerd/service.go
  3. 9 1
      daemon/daemon.go
  4. 7 0
      registry/service.go

+ 41 - 16
daemon/containerd/resolver.go

@@ -1,6 +1,9 @@
 package containerd
 
 import (
+	"net/http"
+	"strings"
+
 	"github.com/containerd/containerd/remotes"
 	"github.com/containerd/containerd/remotes/docker"
 	registrytypes "github.com/docker/docker/api/types/registry"
@@ -9,10 +12,10 @@ import (
 )
 
 func (i *ImageService) newResolverFromAuthConfig(authConfig *registrytypes.AuthConfig) (remotes.Resolver, docker.StatusTracker) {
+	tracker := docker.NewInMemoryTracker()
 	hostsFn := i.registryHosts.RegistryHosts()
-	hosts := hostsAuthorizerWrapper(hostsFn, authConfig)
 
-	tracker := docker.NewInMemoryTracker()
+	hosts := hostsWrapper(hostsFn, authConfig, i.registryService)
 
 	return docker.NewResolver(docker.ResolverOptions{
 		Hosts:   hosts,
@@ -20,24 +23,29 @@ func (i *ImageService) newResolverFromAuthConfig(authConfig *registrytypes.AuthC
 	}), tracker
 }
 
-func hostsAuthorizerWrapper(hostsFn docker.RegistryHosts, authConfig *registrytypes.AuthConfig) docker.RegistryHosts {
-	return docker.RegistryHosts(func(n string) ([]docker.RegistryHost, error) {
+func hostsWrapper(hostsFn docker.RegistryHosts, authConfig *registrytypes.AuthConfig, regService registry.Service) docker.RegistryHosts {
+	return func(n string) ([]docker.RegistryHost, error) {
 		hosts, err := hostsFn(n)
-		if err == nil {
-			for idx, host := range hosts {
-				if host.Authorizer == nil {
-					var opts []docker.AuthorizerOpt
-					if authConfig != nil {
-						opts = append(opts, authorizationCredsFromAuthConfig(*authConfig))
-					}
-					host.Authorizer = docker.NewDockerAuthorizer(opts...)
-					hosts[idx] = host
+		if err != nil {
+			return nil, err
+		}
+
+		for i := range hosts {
+			if hosts[i].Authorizer == nil {
+				var opts []docker.AuthorizerOpt
+				if authConfig != nil {
+					opts = append(opts, authorizationCredsFromAuthConfig(*authConfig))
+				}
+				hosts[i].Authorizer = docker.NewDockerAuthorizer(opts...)
+
+				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, err
-	})
+		return hosts, nil
+	}
 }
 
 func authorizationCredsFromAuthConfig(authConfig registrytypes.AuthConfig) docker.AuthorizerOpt {
@@ -57,3 +65,20 @@ func authorizationCredsFromAuthConfig(authConfig registrytypes.AuthConfig) docke
 		return authConfig.Username, authConfig.Password, nil
 	})
 }
+
+type httpFallback struct {
+	super http.RoundTripper
+}
+
+func (f httpFallback) RoundTrip(r *http.Request) (*http.Response, error) {
+	resp, err := f.super.RoundTrip(r)
+	if err != nil {
+		if strings.Contains(err.Error(), "http: server gave HTTP response to HTTPS client") {
+			plain := r.Clone(r.Context())
+			plain.URL.Scheme = "http"
+			return http.DefaultTransport.RoundTrip(plain)
+		}
+	}
+
+	return resp, err
+}

+ 10 - 7
daemon/containerd/service.go

@@ -12,14 +12,16 @@ import (
 	"github.com/docker/docker/errdefs"
 	"github.com/docker/docker/image"
 	"github.com/docker/docker/layer"
+	"github.com/docker/docker/registry"
 	"github.com/pkg/errors"
 )
 
 // ImageService implements daemon.ImageService
 type ImageService struct {
-	client        *containerd.Client
-	snapshotter   string
-	registryHosts RegistryHostsProvider
+	client          *containerd.Client
+	snapshotter     string
+	registryHosts   RegistryHostsProvider
+	registryService registry.Service
 }
 
 type RegistryHostsProvider interface {
@@ -27,11 +29,12 @@ type RegistryHostsProvider interface {
 }
 
 // NewService creates a new ImageService.
-func NewService(c *containerd.Client, snapshotter string, hostsProvider RegistryHostsProvider) *ImageService {
+func NewService(c *containerd.Client, snapshotter string, hostsProvider RegistryHostsProvider, registry registry.Service) *ImageService {
 	return &ImageService{
-		client:        c,
-		snapshotter:   snapshotter,
-		registryHosts: hostsProvider,
+		client:          c,
+		snapshotter:     snapshotter,
+		registryHosts:   hostsProvider,
+		registryService: registry,
 	}
 }
 

+ 9 - 1
daemon/daemon.go

@@ -14,6 +14,7 @@ import (
 	"path"
 	"path/filepath"
 	"runtime"
+	"strings"
 	"sync"
 	"time"
 
@@ -177,6 +178,13 @@ func (daemon *Daemon) RegistryHosts() docker.RegistryHosts {
 
 	for _, v := range daemon.configStore.InsecureRegistries {
 		u, err := url.Parse(v)
+		if err != nil && !strings.HasPrefix(v, "http://") && !strings.HasPrefix(v, "https://") {
+			originalErr := err
+			u, err = url.Parse("http://" + v)
+			if err != nil {
+				err = originalErr
+			}
+		}
 		c := resolverconfig.RegistryConfig{}
 		if err == nil {
 			v = u.Host
@@ -994,7 +1002,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
 		if err := configureKernelSecuritySupport(config, driverName); err != nil {
 			return nil, err
 		}
-		d.imageService = ctrd.NewService(d.containerdCli, driverName, d)
+		d.imageService = ctrd.NewService(d.containerdCli, driverName, d, d.registryService)
 	} else {
 		layerStore, err := layer.NewStoreFromOptions(layer.StoreOptions{
 			Root:                      config.Root,

+ 7 - 0
registry/service.go

@@ -26,6 +26,7 @@ type Service interface {
 	LoadAllowNondistributableArtifacts([]string) error
 	LoadMirrors([]string) error
 	LoadInsecureRegistries([]string) error
+	IsInsecureRegistry(string) bool
 }
 
 // defaultService is a registry service. It tracks configuration data such as a list
@@ -232,3 +233,9 @@ func (s *defaultService) LookupPushEndpoints(hostname string) (endpoints []APIEn
 	}
 	return endpoints, err
 }
+
+// IsInsecureRegistry returns true if the registry at given host is configured as
+// insecure registry.
+func (s *defaultService) IsInsecureRegistry(host string) bool {
+	return !s.config.isSecureIndex(host)
+}