зеркало из https://github.com/microsoft/docker.git
Merge pull request #16385 from RichardScothern/v1-deprecation
Add a daemon flag to prevent contact with v1 registries.
This commit is contained in:
Коммит
85244f80e3
|
@ -100,3 +100,9 @@ docker was automatically creating the `/host/path` if it didn't already exist.
|
|||
|
||||
This auto-creation of the host path is deprecated and docker will error out if
|
||||
the path does not exist.
|
||||
|
||||
### Interacting with V1 registries
|
||||
|
||||
Version 1.9 adds a flag (`--no-legacy-registry=false`) which prevents the docker daemon from `pull`, `push`, and `login` operations against v1 registries. Though disabled by default, this signals the intent to deprecate the v1 protocol.
|
||||
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ weight=1
|
|||
--log-driver="json-file" Default driver for container logs
|
||||
--log-opt=[] Log driver specific options
|
||||
--mtu=0 Set the containers network MTU
|
||||
--no-legacy-registry=false Do not contact legacy registries
|
||||
-p, --pidfile="/var/run/docker.pid" Path to use for daemon PID file
|
||||
--registry-mirror=[] Preferred Docker registry mirror
|
||||
-s, --storage-driver="" Storage driver to use
|
||||
|
@ -457,6 +458,10 @@ because its use creates security vulnerabilities it should ONLY be enabled for
|
|||
testing purposes. For increased security, users should add their CA to their
|
||||
system's list of trusted CAs instead of enabling `--insecure-registry`.
|
||||
|
||||
## Legacy Registries
|
||||
|
||||
Enabling `--no-legacy-registry` forces a docker daemon to only interact with registries which support the V2 protocol. Specifically, the daemon will not attempt `push`, `pull` and `login` to v1 registries. The exception to this is `search` which can still be performed on v1 registries.
|
||||
|
||||
## Running a Docker daemon behind a HTTPS_PROXY
|
||||
|
||||
When running inside a LAN that uses a `HTTPS` proxy, the Docker Hub
|
||||
|
|
|
@ -60,6 +60,9 @@ func (p *v1Puller) Pull(tag string) (fallback bool, err error) {
|
|||
// TODO(dmcgowan): Check if should fallback
|
||||
return false, err
|
||||
}
|
||||
out := p.config.OutStream
|
||||
out.Write(p.sf.FormatStatus("", "%s: this image was pulled from a legacy registry. Important: This registry version will not be supported in future versions of docker.", p.repoInfo.CanonicalName))
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -32,10 +32,13 @@ func init() {
|
|||
type DockerRegistrySuite struct {
|
||||
ds *DockerSuite
|
||||
reg *testRegistryV2
|
||||
d *Daemon
|
||||
}
|
||||
|
||||
func (s *DockerRegistrySuite) SetUpTest(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
s.reg = setupRegistry(c)
|
||||
s.d = NewDaemon(c)
|
||||
}
|
||||
|
||||
func (s *DockerRegistrySuite) TearDownTest(c *check.C) {
|
||||
|
@ -45,6 +48,7 @@ func (s *DockerRegistrySuite) TearDownTest(c *check.C) {
|
|||
if s.ds != nil {
|
||||
s.ds.TearDownTest(c)
|
||||
}
|
||||
s.d.Stop()
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-check/check"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
func makefile(contents string) (string, func(), error) {
|
||||
cleanup := func() {
|
||||
|
||||
}
|
||||
|
||||
f, err := ioutil.TempFile(".", "tmp")
|
||||
if err != nil {
|
||||
return "", cleanup, err
|
||||
}
|
||||
err = ioutil.WriteFile(f.Name(), []byte(contents), os.ModePerm)
|
||||
if err != nil {
|
||||
return "", cleanup, err
|
||||
}
|
||||
|
||||
cleanup = func() {
|
||||
err := os.Remove(f.Name())
|
||||
if err != nil {
|
||||
fmt.Println("Error removing tmpfile")
|
||||
}
|
||||
}
|
||||
return f.Name(), cleanup, nil
|
||||
|
||||
}
|
||||
|
||||
// TestV2Only ensures that a daemon in v2-only mode does not
|
||||
// attempt to contact any v1 registry endpoints.
|
||||
func (s *DockerRegistrySuite) TestV2Only(c *check.C) {
|
||||
reg, err := newTestRegistry(c)
|
||||
if err != nil {
|
||||
c.Fatal(err.Error())
|
||||
}
|
||||
|
||||
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(404)
|
||||
})
|
||||
|
||||
reg.registerHandler("/v1/.*", func(w http.ResponseWriter, r *http.Request) {
|
||||
c.Fatal("V1 registry contacted")
|
||||
})
|
||||
|
||||
repoName := fmt.Sprintf("%s/busybox", reg.hostport)
|
||||
|
||||
err = s.d.Start("--insecure-registry", reg.hostport, "--no-legacy-registry=true")
|
||||
if err != nil {
|
||||
c.Fatalf("Error starting daemon: %s", err.Error())
|
||||
}
|
||||
|
||||
dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.hostport))
|
||||
if err != nil {
|
||||
c.Fatalf("Unable to create test dockerfile")
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
s.d.Cmd("build", "--file", dockerfileName, ".")
|
||||
|
||||
s.d.Cmd("run", repoName)
|
||||
s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "testuser@testdomain.com", reg.hostport)
|
||||
s.d.Cmd("tag", "busybox", repoName)
|
||||
s.d.Cmd("push", repoName)
|
||||
s.d.Cmd("pull", repoName)
|
||||
}
|
||||
|
||||
// TestV1 starts a daemon in 'normal' mode
|
||||
// and ensure v1 endpoints are hit for the following operations:
|
||||
// login, push, pull, build & run
|
||||
func (s *DockerRegistrySuite) TestV1(c *check.C) {
|
||||
reg, err := newTestRegistry(c)
|
||||
if err != nil {
|
||||
c.Fatal(err.Error())
|
||||
}
|
||||
|
||||
v2Pings := 0
|
||||
reg.registerHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
|
||||
v2Pings++
|
||||
// V2 ping 404 causes fallback to v1
|
||||
w.WriteHeader(404)
|
||||
})
|
||||
|
||||
v1Pings := 0
|
||||
reg.registerHandler("/v1/_ping", func(w http.ResponseWriter, r *http.Request) {
|
||||
v1Pings++
|
||||
})
|
||||
|
||||
v1Logins := 0
|
||||
reg.registerHandler("/v1/users/", func(w http.ResponseWriter, r *http.Request) {
|
||||
v1Logins++
|
||||
})
|
||||
|
||||
v1Repo := 0
|
||||
reg.registerHandler("/v1/repositories/busybox/", func(w http.ResponseWriter, r *http.Request) {
|
||||
v1Repo++
|
||||
})
|
||||
|
||||
reg.registerHandler("/v1/repositories/busybox/images", func(w http.ResponseWriter, r *http.Request) {
|
||||
v1Repo++
|
||||
})
|
||||
|
||||
err = s.d.Start("--insecure-registry", reg.hostport, "--no-legacy-registry=false")
|
||||
if err != nil {
|
||||
c.Fatalf("Error starting daemon: %s", err.Error())
|
||||
}
|
||||
|
||||
dockerfileName, cleanup, err := makefile(fmt.Sprintf("FROM %s/busybox", reg.hostport))
|
||||
if err != nil {
|
||||
c.Fatalf("Unable to create test dockerfile")
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
s.d.Cmd("build", "--file", dockerfileName, ".")
|
||||
if v1Repo == 0 {
|
||||
c.Errorf("Expected v1 repository access after build")
|
||||
}
|
||||
|
||||
repoName := fmt.Sprintf("%s/busybox", reg.hostport)
|
||||
s.d.Cmd("run", repoName)
|
||||
if v1Repo == 1 {
|
||||
c.Errorf("Expected v1 repository access after run")
|
||||
}
|
||||
|
||||
s.d.Cmd("login", "-u", "richard", "-p", "testtest", "-e", "testuser@testdomain.com", reg.hostport)
|
||||
if v1Logins == 0 {
|
||||
c.Errorf("Expected v1 login attempt")
|
||||
}
|
||||
|
||||
s.d.Cmd("tag", "busybox", repoName)
|
||||
s.d.Cmd("push", repoName)
|
||||
|
||||
if v1Repo != 2 || v1Pings != 1 {
|
||||
c.Error("Not all endpoints contacted after push", v1Repo, v1Pings)
|
||||
}
|
||||
|
||||
s.d.Cmd("pull", repoName)
|
||||
if v1Repo != 3 {
|
||||
c.Errorf("Expected v1 repository access after pull")
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
type handlerFunc func(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
type testRegistry struct {
|
||||
server *httptest.Server
|
||||
hostport string
|
||||
handlers map[string]handlerFunc
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (tr *testRegistry) registerHandler(path string, h handlerFunc) {
|
||||
tr.mu.Lock()
|
||||
defer tr.mu.Unlock()
|
||||
tr.handlers[path] = h
|
||||
}
|
||||
|
||||
func newTestRegistry(c *check.C) (*testRegistry, error) {
|
||||
testReg := &testRegistry{handlers: make(map[string]handlerFunc)}
|
||||
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
url := r.URL.String()
|
||||
|
||||
var matched bool
|
||||
var err error
|
||||
for re, function := range testReg.handlers {
|
||||
matched, err = regexp.MatchString(re, url)
|
||||
if err != nil {
|
||||
c.Fatalf("Error with handler regexp")
|
||||
return
|
||||
}
|
||||
if matched {
|
||||
function(w, r)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !matched {
|
||||
c.Fatal("Unable to match", url, "with regexp")
|
||||
}
|
||||
}))
|
||||
|
||||
testReg.server = ts
|
||||
testReg.hostport = strings.Replace(ts.URL, "http://", "", 1)
|
||||
return testReg, nil
|
||||
}
|
|
@ -40,6 +40,7 @@ docker-daemon - Enable daemon mode
|
|||
[**--log-driver**[=*json-file*]]
|
||||
[**--log-opt**[=*map[]*]]
|
||||
[**--mtu**[=*0*]]
|
||||
[**--no-legacy-registry**[=*false*]]
|
||||
[**-p**|**--pidfile**[=*/var/run/docker.pid*]]
|
||||
[**--registry-mirror**[=*[]*]]
|
||||
[**-s**|**--storage-driver**[=*STORAGE-DRIVER*]]
|
||||
|
@ -170,6 +171,9 @@ unix://[/path/to/socket] to use.
|
|||
**--mtu**=VALUE
|
||||
Set the containers network mtu. Default is `0`.
|
||||
|
||||
**--no-legacy-registry**=*true*|*false*
|
||||
Do not contact legacy registries
|
||||
|
||||
**-p**, **--pidfile**=""
|
||||
Path to use for daemon PID file. Default is `/var/run/docker.pid`
|
||||
|
||||
|
|
|
@ -44,6 +44,10 @@ var (
|
|||
ErrInvalidRepositoryName = errors.New("Invalid repository name (ex: \"registry.domain.tld/myrepos\")")
|
||||
|
||||
emptyServiceConfig = NewServiceConfig(nil)
|
||||
|
||||
// V2Only controls access to legacy registries. If it is set to true via the
|
||||
// command line flag the daemon will not attempt to contact v1 legacy registries
|
||||
V2Only = false
|
||||
)
|
||||
|
||||
// InstallFlags adds command-line options to the top-level flag parser for
|
||||
|
@ -53,6 +57,7 @@ func (options *Options) InstallFlags(cmd *flag.FlagSet, usageFn func(string) str
|
|||
cmd.Var(&options.Mirrors, []string{"-registry-mirror"}, usageFn("Preferred Docker registry mirror"))
|
||||
options.InsecureRegistries = opts.NewListOpts(ValidateIndexName)
|
||||
cmd.Var(&options.InsecureRegistries, []string{"-insecure-registry"}, usageFn("Enable insecure registry communication"))
|
||||
cmd.BoolVar(&V2Only, []string{"-no-legacy-registry"}, false, "Do not contact legacy registries")
|
||||
}
|
||||
|
||||
type netIPNet net.IPNet
|
||||
|
|
|
@ -42,8 +42,9 @@ func scanForAPIVersion(address string) (string, APIVersion) {
|
|||
return address, APIVersionUnknown
|
||||
}
|
||||
|
||||
// NewEndpoint parses the given address to return a registry endpoint.
|
||||
func NewEndpoint(index *IndexInfo, metaHeaders http.Header) (*Endpoint, error) {
|
||||
// NewEndpoint parses the given address to return a registry endpoint. v can be used to
|
||||
// specify a specific endpoint version
|
||||
func NewEndpoint(index *IndexInfo, metaHeaders http.Header, v APIVersion) (*Endpoint, error) {
|
||||
tlsConfig, err := newTLSConfig(index.Name, index.Secure)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -52,6 +53,9 @@ func NewEndpoint(index *IndexInfo, metaHeaders http.Header) (*Endpoint, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if v != APIVersionUnknown {
|
||||
endpoint.Version = v
|
||||
}
|
||||
if err := validateEndpoint(endpoint); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -111,11 +115,6 @@ func newEndpoint(address string, tlsConfig *tls.Config, metaHeaders http.Header)
|
|||
return endpoint, nil
|
||||
}
|
||||
|
||||
// GetEndpoint returns a new endpoint with the specified headers
|
||||
func (repoInfo *RepositoryInfo) GetEndpoint(metaHeaders http.Header) (*Endpoint, error) {
|
||||
return NewEndpoint(repoInfo.Index, metaHeaders)
|
||||
}
|
||||
|
||||
// Endpoint stores basic information about a registry endpoint.
|
||||
type Endpoint struct {
|
||||
client *http.Client
|
||||
|
|
|
@ -49,6 +49,10 @@ func init() {
|
|||
httpVersion = append(httpVersion, useragent.VersionInfo{"arch", runtime.GOARCH})
|
||||
|
||||
dockerUserAgent = useragent.AppendVersions("", httpVersion...)
|
||||
|
||||
if runtime.GOOS != "linux" {
|
||||
V2Only = true
|
||||
}
|
||||
}
|
||||
|
||||
func newTLSConfig(hostname string, isSecure bool) (*tls.Config, error) {
|
||||
|
|
|
@ -23,7 +23,7 @@ const (
|
|||
|
||||
func spawnTestRegistrySession(t *testing.T) *Session {
|
||||
authConfig := &cliconfig.AuthConfig{}
|
||||
endpoint, err := NewEndpoint(makeIndex("/v1/"), nil)
|
||||
endpoint, err := NewEndpoint(makeIndex("/v1/"), nil, APIVersionUnknown)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ func spawnTestRegistrySession(t *testing.T) *Session {
|
|||
|
||||
func TestPingRegistryEndpoint(t *testing.T) {
|
||||
testPing := func(index *IndexInfo, expectedStandalone bool, assertMessage string) {
|
||||
ep, err := NewEndpoint(index, nil)
|
||||
ep, err := NewEndpoint(index, nil, APIVersionUnknown)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ func TestPingRegistryEndpoint(t *testing.T) {
|
|||
func TestEndpoint(t *testing.T) {
|
||||
// Simple wrapper to fail test if err != nil
|
||||
expandEndpoint := func(index *IndexInfo) *Endpoint {
|
||||
endpoint, err := NewEndpoint(index, nil)
|
||||
endpoint, err := NewEndpoint(index, nil, APIVersionUnknown)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ func TestEndpoint(t *testing.T) {
|
|||
|
||||
assertInsecureIndex := func(index *IndexInfo) {
|
||||
index.Secure = true
|
||||
_, err := NewEndpoint(index, nil)
|
||||
_, err := NewEndpoint(index, nil, APIVersionUnknown)
|
||||
assertNotEqual(t, err, nil, index.Name+": Expected error for insecure index")
|
||||
assertEqual(t, strings.Contains(err.Error(), "insecure-registry"), true, index.Name+": Expected insecure-registry error for insecure index")
|
||||
index.Secure = false
|
||||
|
@ -87,7 +87,7 @@ func TestEndpoint(t *testing.T) {
|
|||
|
||||
assertSecureIndex := func(index *IndexInfo) {
|
||||
index.Secure = true
|
||||
_, err := NewEndpoint(index, nil)
|
||||
_, err := NewEndpoint(index, nil, APIVersionUnknown)
|
||||
assertNotEqual(t, err, nil, index.Name+": Expected cert error for secure index")
|
||||
assertEqual(t, strings.Contains(err.Error(), "certificate signed by unknown authority"), true, index.Name+": Expected cert error for secure index")
|
||||
index.Secure = false
|
||||
|
@ -153,7 +153,7 @@ func TestEndpoint(t *testing.T) {
|
|||
}
|
||||
for _, address := range badEndpoints {
|
||||
index.Name = address
|
||||
_, err := NewEndpoint(index, nil)
|
||||
_, err := NewEndpoint(index, nil, APIVersionUnknown)
|
||||
checkNotEqual(t, err, nil, "Expected error while expanding bad endpoint")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,11 @@ package registry
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/distribution/registry/client/auth"
|
||||
"github.com/docker/docker/cliconfig"
|
||||
"github.com/docker/docker/pkg/tlsconfig"
|
||||
)
|
||||
|
||||
// Service is a registry service. It tracks configuration data such as a list
|
||||
|
@ -40,7 +36,14 @@ func (s *Service) Auth(authConfig *cliconfig.AuthConfig) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
endpoint, err := NewEndpoint(index, nil)
|
||||
|
||||
endpointVersion := APIVersion(APIVersionUnknown)
|
||||
if V2Only {
|
||||
// Override the endpoint to only attempt a v2 ping
|
||||
endpointVersion = APIVersion2
|
||||
}
|
||||
|
||||
endpoint, err := NewEndpoint(index, nil, endpointVersion)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -57,10 +60,11 @@ func (s *Service) Search(term string, authConfig *cliconfig.AuthConfig, headers
|
|||
}
|
||||
|
||||
// *TODO: Search multiple indexes.
|
||||
endpoint, err := repoInfo.GetEndpoint(http.Header(headers))
|
||||
endpoint, err := NewEndpoint(repoInfo.Index, http.Header(headers), APIVersionUnknown)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r, err := NewSession(endpoint.client, authConfig, endpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -132,97 +136,20 @@ func (s *Service) LookupPushEndpoints(repoName string) (endpoints []APIEndpoint,
|
|||
}
|
||||
|
||||
func (s *Service) lookupEndpoints(repoName string) (endpoints []APIEndpoint, err error) {
|
||||
var cfg = tlsconfig.ServerDefault
|
||||
tlsConfig := &cfg
|
||||
if strings.HasPrefix(repoName, DefaultNamespace+"/") {
|
||||
// v2 mirrors
|
||||
for _, mirror := range s.Config.Mirrors {
|
||||
mirrorTLSConfig, err := s.tlsConfigForMirror(mirror)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
endpoints = append(endpoints, APIEndpoint{
|
||||
URL: mirror,
|
||||
// guess mirrors are v2
|
||||
Version: APIVersion2,
|
||||
Mirror: true,
|
||||
TrimHostname: true,
|
||||
TLSConfig: mirrorTLSConfig,
|
||||
})
|
||||
}
|
||||
// v2 registry
|
||||
endpoints = append(endpoints, APIEndpoint{
|
||||
URL: DefaultV2Registry,
|
||||
Version: APIVersion2,
|
||||
Official: true,
|
||||
TrimHostname: true,
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
if runtime.GOOS == "linux" { // do not inherit legacy API for OSes supported in the future
|
||||
// v1 registry
|
||||
endpoints = append(endpoints, APIEndpoint{
|
||||
URL: DefaultV1Registry,
|
||||
Version: APIVersion1,
|
||||
Official: true,
|
||||
TrimHostname: true,
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
}
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
slashIndex := strings.IndexRune(repoName, '/')
|
||||
if slashIndex <= 0 {
|
||||
return nil, fmt.Errorf("invalid repo name: missing '/': %s", repoName)
|
||||
}
|
||||
hostname := repoName[:slashIndex]
|
||||
|
||||
tlsConfig, err = s.TLSConfig(hostname)
|
||||
endpoints, err = s.lookupV2Endpoints(repoName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
isSecure := !tlsConfig.InsecureSkipVerify
|
||||
|
||||
v2Versions := []auth.APIVersion{
|
||||
{
|
||||
Type: "registry",
|
||||
Version: "2.0",
|
||||
},
|
||||
}
|
||||
endpoints = []APIEndpoint{
|
||||
{
|
||||
URL: "https://" + hostname,
|
||||
Version: APIVersion2,
|
||||
TrimHostname: true,
|
||||
TLSConfig: tlsConfig,
|
||||
VersionHeader: DefaultRegistryVersionHeader,
|
||||
Versions: v2Versions,
|
||||
},
|
||||
{
|
||||
URL: "https://" + hostname,
|
||||
Version: APIVersion1,
|
||||
TrimHostname: true,
|
||||
TLSConfig: tlsConfig,
|
||||
},
|
||||
if V2Only {
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
if !isSecure {
|
||||
endpoints = append(endpoints, APIEndpoint{
|
||||
URL: "http://" + hostname,
|
||||
Version: APIVersion2,
|
||||
TrimHostname: true,
|
||||
// used to check if supposed to be secure via InsecureSkipVerify
|
||||
TLSConfig: tlsConfig,
|
||||
VersionHeader: DefaultRegistryVersionHeader,
|
||||
Versions: v2Versions,
|
||||
}, APIEndpoint{
|
||||
URL: "http://" + hostname,
|
||||
Version: APIVersion1,
|
||||
TrimHostname: true,
|
||||
// used to check if supposed to be secure via InsecureSkipVerify
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
legacyEndpoints, err := s.lookupV1Endpoints(repoName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
endpoints = append(endpoints, legacyEndpoints...)
|
||||
|
||||
return endpoints, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/pkg/tlsconfig"
|
||||
)
|
||||
|
||||
func (s *Service) lookupV1Endpoints(repoName string) (endpoints []APIEndpoint, err error) {
|
||||
var cfg = tlsconfig.ServerDefault
|
||||
tlsConfig := &cfg
|
||||
if strings.HasPrefix(repoName, DefaultNamespace+"/") {
|
||||
endpoints = append(endpoints, APIEndpoint{
|
||||
URL: DefaultV1Registry,
|
||||
Version: APIVersion1,
|
||||
Official: true,
|
||||
TrimHostname: true,
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
slashIndex := strings.IndexRune(repoName, '/')
|
||||
if slashIndex <= 0 {
|
||||
return nil, fmt.Errorf("invalid repo name: missing '/': %s", repoName)
|
||||
}
|
||||
hostname := repoName[:slashIndex]
|
||||
|
||||
tlsConfig, err = s.TLSConfig(hostname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
endpoints = []APIEndpoint{
|
||||
{
|
||||
URL: "https://" + hostname,
|
||||
Version: APIVersion1,
|
||||
TrimHostname: true,
|
||||
TLSConfig: tlsConfig,
|
||||
},
|
||||
}
|
||||
|
||||
if tlsConfig.InsecureSkipVerify {
|
||||
endpoints = append(endpoints, APIEndpoint{ // or this
|
||||
URL: "http://" + hostname,
|
||||
Version: APIVersion1,
|
||||
TrimHostname: true,
|
||||
// used to check if supposed to be secure via InsecureSkipVerify
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
}
|
||||
return endpoints, nil
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package registry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/distribution/registry/client/auth"
|
||||
"github.com/docker/docker/pkg/tlsconfig"
|
||||
)
|
||||
|
||||
func (s *Service) lookupV2Endpoints(repoName string) (endpoints []APIEndpoint, err error) {
|
||||
var cfg = tlsconfig.ServerDefault
|
||||
tlsConfig := &cfg
|
||||
if strings.HasPrefix(repoName, DefaultNamespace+"/") {
|
||||
// v2 mirrors
|
||||
for _, mirror := range s.Config.Mirrors {
|
||||
mirrorTLSConfig, err := s.tlsConfigForMirror(mirror)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
endpoints = append(endpoints, APIEndpoint{
|
||||
URL: mirror,
|
||||
// guess mirrors are v2
|
||||
Version: APIVersion2,
|
||||
Mirror: true,
|
||||
TrimHostname: true,
|
||||
TLSConfig: mirrorTLSConfig,
|
||||
})
|
||||
}
|
||||
// v2 registry
|
||||
endpoints = append(endpoints, APIEndpoint{
|
||||
URL: DefaultV2Registry,
|
||||
Version: APIVersion2,
|
||||
Official: true,
|
||||
TrimHostname: true,
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
slashIndex := strings.IndexRune(repoName, '/')
|
||||
if slashIndex <= 0 {
|
||||
return nil, fmt.Errorf("invalid repo name: missing '/': %s", repoName)
|
||||
}
|
||||
hostname := repoName[:slashIndex]
|
||||
|
||||
tlsConfig, err = s.TLSConfig(hostname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v2Versions := []auth.APIVersion{
|
||||
{
|
||||
Type: "registry",
|
||||
Version: "2.0",
|
||||
},
|
||||
}
|
||||
endpoints = []APIEndpoint{
|
||||
{
|
||||
URL: "https://" + hostname,
|
||||
Version: APIVersion2,
|
||||
TrimHostname: true,
|
||||
TLSConfig: tlsConfig,
|
||||
VersionHeader: DefaultRegistryVersionHeader,
|
||||
Versions: v2Versions,
|
||||
},
|
||||
}
|
||||
|
||||
if tlsConfig.InsecureSkipVerify {
|
||||
endpoints = append(endpoints, APIEndpoint{
|
||||
URL: "http://" + hostname,
|
||||
Version: APIVersion2,
|
||||
TrimHostname: true,
|
||||
// used to check if supposed to be secure via InsecureSkipVerify
|
||||
TLSConfig: tlsConfig,
|
||||
VersionHeader: DefaultRegistryVersionHeader,
|
||||
Versions: v2Versions,
|
||||
})
|
||||
}
|
||||
|
||||
return endpoints, nil
|
||||
}
|
Загрузка…
Ссылка в новой задаче