resolver.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package containerd
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "errors"
  6. "net/http"
  7. "github.com/containerd/containerd/log"
  8. "github.com/containerd/containerd/remotes"
  9. "github.com/containerd/containerd/remotes/docker"
  10. "github.com/containerd/containerd/version"
  11. registrytypes "github.com/docker/docker/api/types/registry"
  12. "github.com/docker/docker/dockerversion"
  13. "github.com/docker/docker/pkg/useragent"
  14. "github.com/docker/docker/registry"
  15. "github.com/sirupsen/logrus"
  16. )
  17. func (i *ImageService) newResolverFromAuthConfig(ctx context.Context, authConfig *registrytypes.AuthConfig) (remotes.Resolver, docker.StatusTracker) {
  18. tracker := docker.NewInMemoryTracker()
  19. hosts := hostsWrapper(i.registryHosts, authConfig, i.registryService)
  20. headers := http.Header{}
  21. headers.Set("User-Agent", dockerversion.DockerUserAgent(ctx, useragent.VersionInfo{Name: "containerd-client", Version: version.Version}, useragent.VersionInfo{Name: "storage-driver", Version: i.snapshotter}))
  22. return docker.NewResolver(docker.ResolverOptions{
  23. Hosts: hosts,
  24. Tracker: tracker,
  25. Headers: headers,
  26. }), tracker
  27. }
  28. func hostsWrapper(hostsFn docker.RegistryHosts, optAuthConfig *registrytypes.AuthConfig, regService RegistryConfigProvider) docker.RegistryHosts {
  29. var authorizer docker.Authorizer
  30. if optAuthConfig != nil {
  31. authorizer = docker.NewDockerAuthorizer(authorizationCredsFromAuthConfig(*optAuthConfig))
  32. }
  33. return func(n string) ([]docker.RegistryHost, error) {
  34. hosts, err := hostsFn(n)
  35. if err != nil {
  36. return nil, err
  37. }
  38. for i := range hosts {
  39. if hosts[i].Authorizer == nil {
  40. hosts[i].Authorizer = authorizer
  41. isInsecure := regService.IsInsecureRegistry(hosts[i].Host)
  42. if hosts[i].Client.Transport != nil && isInsecure {
  43. hosts[i].Client.Transport = httpFallback{super: hosts[i].Client.Transport}
  44. }
  45. }
  46. }
  47. return hosts, nil
  48. }
  49. }
  50. func authorizationCredsFromAuthConfig(authConfig registrytypes.AuthConfig) docker.AuthorizerOpt {
  51. cfgHost := registry.ConvertToHostname(authConfig.ServerAddress)
  52. if cfgHost == "" || cfgHost == registry.IndexHostname {
  53. cfgHost = registry.DefaultRegistryHost
  54. }
  55. return docker.WithAuthCreds(func(host string) (string, string, error) {
  56. if cfgHost != host {
  57. log.G(context.TODO()).WithFields(logrus.Fields{
  58. "host": host,
  59. "cfgHost": cfgHost,
  60. }).Warn("Host doesn't match")
  61. return "", "", nil
  62. }
  63. if authConfig.IdentityToken != "" {
  64. return "", authConfig.IdentityToken, nil
  65. }
  66. return authConfig.Username, authConfig.Password, nil
  67. })
  68. }
  69. type httpFallback struct {
  70. super http.RoundTripper
  71. }
  72. func (f httpFallback) RoundTrip(r *http.Request) (*http.Response, error) {
  73. resp, err := f.super.RoundTrip(r)
  74. var tlsErr tls.RecordHeaderError
  75. if errors.As(err, &tlsErr) && string(tlsErr.RecordHeader[:]) == "HTTP/" {
  76. // server gave HTTP response to HTTPS client
  77. plainHttpUrl := *r.URL
  78. plainHttpUrl.Scheme = "http"
  79. plainHttpRequest := *r
  80. plainHttpRequest.URL = &plainHttpUrl
  81. return http.DefaultTransport.RoundTrip(&plainHttpRequest)
  82. }
  83. return resp, err
  84. }