c8d/resolver: Fallback to http for insecure registries
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
parent
c83fce86d4
commit
9032e6779d
4 changed files with 68 additions and 25 deletions
|
@ -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) {
|
||||
hostsFn := i.registryHosts.RegistryHosts()
|
||||
hosts := hostsAuthorizerWrapper(hostsFn, authConfig)
|
||||
|
||||
tracker := docker.NewInMemoryTracker()
|
||||
hostsFn := i.registryHosts.RegistryHosts()
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue