diff --git a/Dockerfile b/Dockerfile index b0e304d200..f5f32c4ed3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,11 +49,6 @@ RUN apt-get update && apt-get install -y \ && make PREFIX=/build/ install-criu FROM base AS registry -# Install two versions of the registry. The first is an older version that -# only supports schema1 manifests. The second is a newer version that supports -# both. This allows integration-cli tests to cover push/pull with both schema1 -# and schema2 manifests. -ENV REGISTRY_COMMIT_SCHEMA1 ec87e9b6971d831f0eff752ddb54fb64693e51cd ENV REGISTRY_COMMIT 47a064d4195a9b56133891bbb13620c3ac83a827 RUN set -x \ && export GOPATH="$(mktemp -d)" \ @@ -61,13 +56,6 @@ RUN set -x \ && (cd "$GOPATH/src/github.com/docker/distribution" && git checkout -q "$REGISTRY_COMMIT") \ && GOPATH="$GOPATH/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH" \ go build -buildmode=pie -o /build/registry-v2 github.com/docker/distribution/cmd/registry \ - && case $(dpkg --print-architecture) in \ - amd64|ppc64*|s390x) \ - (cd "$GOPATH/src/github.com/docker/distribution" && git checkout -q "$REGISTRY_COMMIT_SCHEMA1"); \ - GOPATH="$GOPATH/src/github.com/docker/distribution/Godeps/_workspace:$GOPATH"; \ - go build -buildmode=pie -o /build/registry-v2-schema1 github.com/docker/distribution/cmd/registry; \ - ;; \ - esac \ && rm -rf "$GOPATH" diff --git a/cmd/dockerd/config.go b/cmd/dockerd/config.go index bf64108ef4..317315414f 100644 --- a/cmd/dockerd/config.go +++ b/cmd/dockerd/config.go @@ -12,8 +12,6 @@ import ( const ( // defaultShutdownTimeout is the default shutdown timeout for the daemon defaultShutdownTimeout = 15 - // defaultTrustKeyFile is the default filename for the trust key - defaultTrustKeyFile = "key.json" ) // installCommonConfigFlags adds flags to the pflag.FlagSet to configure the daemon @@ -83,13 +81,6 @@ func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) error { flags.IntVar(&conf.NetworkControlPlaneMTU, "network-control-plane-mtu", config.DefaultNetworkMtu, "Network Control plane MTU") - // "--deprecated-key-path" is to allow configuration of the key used - // for the daemon ID and the deprecated image signing. It was never - // exposed as a command line option but is added here to allow - // overriding the default path in configuration. - flags.Var(opts.NewQuotedString(&conf.TrustKeyPath), "deprecated-key-path", "Path to key file for ID and image signing") - flags.MarkHidden("deprecated-key-path") - conf.MaxConcurrentDownloads = &maxConcurrentDownloads conf.MaxConcurrentUploads = &maxConcurrentUploads return nil @@ -103,10 +94,4 @@ func installRegistryServiceFlags(options *registry.ServiceOptions, flags *pflag. flags.Var(ana, "allow-nondistributable-artifacts", "Allow push of nondistributable artifacts to registry") flags.Var(mirrors, "registry-mirror", "Preferred Docker registry mirror") flags.Var(insecureRegistries, "insecure-registry", "Enable insecure registry communication") - - if runtime.GOOS != "windows" { - // TODO: Remove this flag after 3 release cycles (18.03) - flags.BoolVar(&options.V2Only, "disable-legacy-registry", true, "Disable contacting legacy registries") - flags.MarkHidden("disable-legacy-registry") - } } diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index 6f99207ca1..cdb0c2ac95 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -432,14 +432,6 @@ func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) { conf.CommonTLSOptions.KeyFile = opts.TLSOptions.KeyFile } - if conf.TrustKeyPath == "" { - daemonConfDir, err := getDaemonConfDir(conf.Root) - if err != nil { - return nil, err - } - conf.TrustKeyPath = filepath.Join(daemonConfDir, defaultTrustKeyFile) - } - if flags.Changed("graph") && flags.Changed("data-root") { return nil, errors.New(`cannot specify both "--graph" and "--data-root" option`) } @@ -462,17 +454,6 @@ func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) { return nil, err } - if runtime.GOOS != "windows" { - if flags.Changed("disable-legacy-registry") { - // TODO: Remove this error after 3 release cycles (18.03) - return nil, errors.New("ERROR: The '--disable-legacy-registry' flag has been removed. Interacting with legacy (v1) registries is no longer supported") - } - if !conf.V2Only { - // TODO: Remove this error after 3 release cycles (18.03) - return nil, errors.New("ERROR: The 'disable-legacy-registry' configuration option has been removed. Interacting with legacy (v1) registries is no longer supported") - } - } - if flags.Changed("graph") { logrus.Warnf(`The "-g / --graph" flag is deprecated. Please use "--data-root" instead`) } diff --git a/cmd/dockerd/daemon_unix.go b/cmd/dockerd/daemon_unix.go index f6ada580aa..5626477e74 100644 --- a/cmd/dockerd/daemon_unix.go +++ b/cmd/dockerd/daemon_unix.go @@ -55,10 +55,6 @@ func setDefaultUmask() error { return nil } -func getDaemonConfDir(_ string) (string, error) { - return getDefaultDaemonConfigDir() -} - func (cli *DaemonCli) getPlatformContainerdDaemonOpts() ([]supervisor.DaemonOpt, error) { opts := []supervisor.DaemonOpt{ supervisor.WithOOMScore(cli.Config.OOMScoreAdjust), diff --git a/cmd/dockerd/daemon_windows.go b/cmd/dockerd/daemon_windows.go index f4d213da96..7cd96c356e 100644 --- a/cmd/dockerd/daemon_windows.go +++ b/cmd/dockerd/daemon_windows.go @@ -4,7 +4,6 @@ import ( "fmt" "net" "os" - "path/filepath" "github.com/docker/docker/daemon/config" "github.com/docker/docker/libcontainerd/supervisor" @@ -21,10 +20,6 @@ func setDefaultUmask() error { return nil } -func getDaemonConfDir(root string) (string, error) { - return filepath.Join(root, `\config`), nil -} - // preNotifySystem sends a message to the host when the API is active, but before the daemon is func preNotifySystem() { // start the service now to prevent timeouts waiting for daemon to start diff --git a/daemon/config/config.go b/daemon/config/config.go index 1b1dc9ca16..75430ed4b8 100644 --- a/daemon/config/config.go +++ b/daemon/config/config.go @@ -8,7 +8,6 @@ import ( "io/ioutil" "os" "reflect" - "runtime" "strings" "sync" @@ -135,12 +134,6 @@ type CommonConfig struct { SocketGroup string `json:"group,omitempty"` CorsHeaders string `json:"api-cors-header,omitempty"` - // TrustKeyPath is used to generate the daemon ID and for signing schema 1 manifests - // when pushing to a registry which does not support schema 2. This field is marked as - // deprecated because schema 1 manifests are deprecated in favor of schema 2 and the - // daemon ID will use a dedicated identifier not shared with exported signatures. - TrustKeyPath string `json:"deprecated-key-path,omitempty"` - // LiveRestoreEnabled determines whether we should keep containers // alive upon daemon shutdown/start LiveRestoreEnabled bool `json:"live-restore,omitempty"` @@ -247,9 +240,6 @@ func New() *Config { config.LogConfig.Config = make(map[string]string) config.ClusterOpts = make(map[string]string) - if runtime.GOOS != "linux" { - config.V2Only = true - } return &config } diff --git a/daemon/daemon.go b/daemon/daemon.go index d0e2f8578e..a41c2a8e4d 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -953,7 +953,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S return nil, err } - trustKey, err := loadOrCreateTrustKey(config.TrustKeyPath) + uuid, err := loadOrCreateUUID(filepath.Join(config.Root, "engine_uuid")) if err != nil { return nil, err } @@ -998,7 +998,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S return nil, errors.New("Devices cgroup isn't mounted") } - d.ID = trustKey.PublicKey().KeyID() + d.ID = uuid d.repository = daemonRepo d.containers = container.NewMemoryStore() if d.containersReplica, err = container.NewViewDB(); err != nil { @@ -1029,7 +1029,6 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S MaxConcurrentUploads: *config.MaxConcurrentUploads, ReferenceStore: rs, RegistryService: registryService, - TrustKey: trustKey, }) go d.execCommandGC() diff --git a/daemon/images/image_push.go b/daemon/images/image_push.go index 4c7be8d2e9..c397b1cd52 100644 --- a/daemon/images/image_push.go +++ b/daemon/images/image_push.go @@ -54,7 +54,6 @@ func (i *ImageService) PushImage(ctx context.Context, image, tag string, metaHea }, ConfigMediaType: schema2.MediaTypeImageConfig, LayerStores: distribution.NewLayerProvidersFromStores(i.layerStores), - TrustKey: i.trustKey, UploadManager: i.uploadManager, } diff --git a/daemon/images/service.go b/daemon/images/service.go index e8df5cb649..9034e5f37c 100644 --- a/daemon/images/service.go +++ b/daemon/images/service.go @@ -14,7 +14,6 @@ import ( "github.com/docker/docker/layer" dockerreference "github.com/docker/docker/reference" "github.com/docker/docker/registry" - "github.com/docker/libtrust" "github.com/opencontainers/go-digest" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -40,7 +39,6 @@ type ImageServiceConfig struct { MaxConcurrentUploads int ReferenceStore dockerreference.Store RegistryService registry.Service - TrustKey libtrust.PrivateKey } // NewImageService returns a new ImageService from a configuration @@ -56,7 +54,6 @@ func NewImageService(config ImageServiceConfig) *ImageService { layerStores: config.LayerStores, referenceStore: config.ReferenceStore, registryService: config.RegistryService, - trustKey: config.TrustKey, uploadManager: xfer.NewLayerUploadManager(config.MaxConcurrentUploads), } } @@ -72,7 +69,6 @@ type ImageService struct { pruneRunning int32 referenceStore dockerreference.Store registryService registry.Service - trustKey libtrust.PrivateKey uploadManager *xfer.LayerUploadManager } diff --git a/daemon/trustkey.go b/daemon/trustkey.go deleted file mode 100644 index 4d72c932f1..0000000000 --- a/daemon/trustkey.go +++ /dev/null @@ -1,57 +0,0 @@ -package daemon // import "github.com/docker/docker/daemon" - -import ( - "encoding/json" - "encoding/pem" - "fmt" - "os" - "path/filepath" - - "github.com/docker/docker/pkg/ioutils" - "github.com/docker/docker/pkg/system" - "github.com/docker/libtrust" -) - -// LoadOrCreateTrustKey attempts to load the libtrust key at the given path, -// otherwise generates a new one -// TODO: this should use more of libtrust.LoadOrCreateTrustKey which may need -// a refactor or this function to be moved into libtrust -func loadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) { - err := system.MkdirAll(filepath.Dir(trustKeyPath), 0755, "") - if err != nil { - return nil, err - } - trustKey, err := libtrust.LoadKeyFile(trustKeyPath) - if err == libtrust.ErrKeyFileDoesNotExist { - trustKey, err = libtrust.GenerateECP256PrivateKey() - if err != nil { - return nil, fmt.Errorf("Error generating key: %s", err) - } - encodedKey, err := serializePrivateKey(trustKey, filepath.Ext(trustKeyPath)) - if err != nil { - return nil, fmt.Errorf("Error serializing key: %s", err) - } - if err := ioutils.AtomicWriteFile(trustKeyPath, encodedKey, os.FileMode(0600)); err != nil { - return nil, fmt.Errorf("Error saving key file: %s", err) - } - } else if err != nil { - return nil, fmt.Errorf("Error loading key file %s: %s", trustKeyPath, err) - } - return trustKey, nil -} - -func serializePrivateKey(key libtrust.PrivateKey, ext string) (encoded []byte, err error) { - if ext == ".json" || ext == ".jwk" { - encoded, err = json.Marshal(key) - if err != nil { - return nil, fmt.Errorf("unable to encode private key JWK: %s", err) - } - } else { - pemBlock, err := key.PEMBlock() - if err != nil { - return nil, fmt.Errorf("unable to encode private key PEM: %s", err) - } - encoded = pem.EncodeToMemory(pemBlock) - } - return -} diff --git a/daemon/trustkey_test.go b/daemon/trustkey_test.go deleted file mode 100644 index e49e76aa3e..0000000000 --- a/daemon/trustkey_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package daemon // import "github.com/docker/docker/daemon" - -import ( - "io/ioutil" - "os" - "path/filepath" - "testing" - - "gotest.tools/assert" - is "gotest.tools/assert/cmp" - "gotest.tools/fs" -) - -// LoadOrCreateTrustKey -func TestLoadOrCreateTrustKeyInvalidKeyFile(t *testing.T) { - tmpKeyFolderPath, err := ioutil.TempDir("", "api-trustkey-test") - assert.NilError(t, err) - defer os.RemoveAll(tmpKeyFolderPath) - - tmpKeyFile, err := ioutil.TempFile(tmpKeyFolderPath, "keyfile") - assert.NilError(t, err) - - _, err = loadOrCreateTrustKey(tmpKeyFile.Name()) - assert.Check(t, is.ErrorContains(err, "Error loading key file")) -} - -func TestLoadOrCreateTrustKeyCreateKeyWhenFileDoesNotExist(t *testing.T) { - tmpKeyFolderPath := fs.NewDir(t, "api-trustkey-test") - defer tmpKeyFolderPath.Remove() - - // Without the need to create the folder hierarchy - tmpKeyFile := tmpKeyFolderPath.Join("keyfile") - - key, err := loadOrCreateTrustKey(tmpKeyFile) - assert.NilError(t, err) - assert.Check(t, key != nil) - - _, err = os.Stat(tmpKeyFile) - assert.NilError(t, err, "key file doesn't exist") -} - -func TestLoadOrCreateTrustKeyCreateKeyWhenDirectoryDoesNotExist(t *testing.T) { - tmpKeyFolderPath := fs.NewDir(t, "api-trustkey-test") - defer tmpKeyFolderPath.Remove() - tmpKeyFile := tmpKeyFolderPath.Join("folder/hierarchy/keyfile") - - key, err := loadOrCreateTrustKey(tmpKeyFile) - assert.NilError(t, err) - assert.Check(t, key != nil) - - _, err = os.Stat(tmpKeyFile) - assert.NilError(t, err, "key file doesn't exist") -} - -func TestLoadOrCreateTrustKeyCreateKeyNoPath(t *testing.T) { - defer os.Remove("keyfile") - key, err := loadOrCreateTrustKey("keyfile") - assert.NilError(t, err) - assert.Check(t, key != nil) - - _, err = os.Stat("keyfile") - assert.NilError(t, err, "key file doesn't exist") -} - -func TestLoadOrCreateTrustKeyLoadValidKey(t *testing.T) { - tmpKeyFile := filepath.Join("testdata", "keyfile") - key, err := loadOrCreateTrustKey(tmpKeyFile) - assert.NilError(t, err) - expected := "AWX2:I27X:WQFX:IOMK:CNAK:O7PW:VYNB:ZLKC:CVAE:YJP2:SI4A:XXAY" - assert.Check(t, is.Contains(key.String(), expected)) -} diff --git a/daemon/uuid.go b/daemon/uuid.go new file mode 100644 index 0000000000..fc68981095 --- /dev/null +++ b/daemon/uuid.go @@ -0,0 +1,28 @@ +package daemon // import "github.com/docker/docker/daemon" + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "github.com/docker/docker/pkg/ioutils" + "github.com/pborman/uuid" +) + +func loadOrCreateUUID(path string) (string, error) { + err := os.MkdirAll(filepath.Dir(path), 0755) + if err != nil { + return "", err + } + id, err := ioutil.ReadFile(path) + if os.IsNotExist(err) { + id = []byte(uuid.New()) + if err := ioutils.AtomicWriteFile(path, id, os.FileMode(0600)); err != nil { + return "", fmt.Errorf("Error saving uuid file: %s", err) + } + } else if err != nil { + return "", fmt.Errorf("Error loading uuid file %s: %s", path, err) + } + return string(id), nil +} diff --git a/distribution/config.go b/distribution/config.go index 438051c296..e9631d1b8c 100644 --- a/distribution/config.go +++ b/distribution/config.go @@ -18,7 +18,6 @@ import ( "github.com/docker/docker/pkg/system" refstore "github.com/docker/docker/reference" "github.com/docker/docker/registry" - "github.com/docker/libtrust" "github.com/opencontainers/go-digest" specs "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -73,9 +72,6 @@ type ImagePushConfig struct { ConfigMediaType string // LayerStores (indexed by operating system) manages layers. LayerStores map[string]PushLayerProvider - // TrustKey is the private key for legacy signatures. This is typically - // an ephemeral key, since these signatures are no longer verified. - TrustKey libtrust.PrivateKey // UploadManager dispatches uploads. UploadManager *xfer.LayerUploadManager } diff --git a/distribution/push_v2.go b/distribution/push_v2.go index 9dc3e7a2a6..5281677734 100644 --- a/distribution/push_v2.go +++ b/distribution/push_v2.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "io" - "runtime" "sort" "strings" "sync" @@ -181,26 +180,8 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, id putOptions := []distribution.ManifestServiceOption{distribution.WithTag(ref.Tag())} if _, err = manSvc.Put(ctx, manifest, putOptions...); err != nil { - if runtime.GOOS == "windows" || p.config.TrustKey == nil || p.config.RequireSchema2 { - logrus.Warnf("failed to upload schema2 manifest: %v", err) - return err - } - - logrus.Warnf("failed to upload schema2 manifest: %v - falling back to schema1", err) - - manifestRef, err := reference.WithTag(p.repo.Named(), ref.Tag()) - if err != nil { - return err - } - builder = schema1.NewConfigManifestBuilder(p.repo.Blobs(ctx), p.config.TrustKey, manifestRef, imgConfig) - manifest, err = manifestFromBuilder(ctx, builder, descriptors) - if err != nil { - return err - } - - if _, err = manSvc.Put(ctx, manifest, putOptions...); err != nil { - return err - } + logrus.Warnf("failed to upload schema2 manifest: %v", err) + return err } var canonicalManifest []byte diff --git a/integration-cli/check_test.go b/integration-cli/check_test.go index 0abf18154a..21945a331d 100644 --- a/integration-cli/check_test.go +++ b/integration-cli/check_test.go @@ -141,39 +141,6 @@ func (s *DockerRegistrySuite) TearDownTest(c *check.C) { s.ds.TearDownTest(c) } -func init() { - check.Suite(&DockerSchema1RegistrySuite{ - ds: &DockerSuite{}, - }) -} - -type DockerSchema1RegistrySuite struct { - ds *DockerSuite - reg *registry.V2 - d *daemon.Daemon -} - -func (s *DockerSchema1RegistrySuite) OnTimeout(c *check.C) { - s.d.DumpStackAndQuit() -} - -func (s *DockerSchema1RegistrySuite) SetUpTest(c *check.C) { - testRequires(c, DaemonIsLinux, RegistryHosting, NotArm64, testEnv.IsLocalDaemon) - s.reg = registry.NewV2(c, registry.Schema1) - s.reg.WaitReady(c) - s.d = daemon.New(c, dockerBinary, dockerdBinary, testdaemon.WithEnvironment(testEnv.Execution)) -} - -func (s *DockerSchema1RegistrySuite) TearDownTest(c *check.C) { - if s.reg != nil { - s.reg.Close() - } - if s.d != nil { - s.d.Stop(c) - } - s.ds.TearDownTest(c) -} - func init() { check.Suite(&DockerRegistryAuthHtpasswdSuite{ ds: &DockerSuite{}, diff --git a/integration-cli/docker_cli_by_digest_test.go b/integration-cli/docker_cli_by_digest_test.go index 006cf11e1a..8db9f871bd 100644 --- a/integration-cli/docker_cli_by_digest_test.go +++ b/integration-cli/docker_cli_by_digest_test.go @@ -3,12 +3,9 @@ package main import ( "encoding/json" "fmt" - "os" - "path/filepath" "regexp" "strings" - "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" "github.com/docker/docker/api/types" "github.com/docker/docker/integration-cli/checker" @@ -80,10 +77,6 @@ func (s *DockerRegistrySuite) TestPullByTagDisplaysDigest(c *check.C) { testPullByTagDisplaysDigest(c) } -func (s *DockerSchema1RegistrySuite) TestPullByTagDisplaysDigest(c *check.C) { - testPullByTagDisplaysDigest(c) -} - func testPullByDigest(c *check.C) { testRequires(c, DaemonIsLinux) pushDigest, err := setupImage(c) @@ -106,10 +99,6 @@ func (s *DockerRegistrySuite) TestPullByDigest(c *check.C) { testPullByDigest(c) } -func (s *DockerSchema1RegistrySuite) TestPullByDigest(c *check.C) { - testPullByDigest(c) -} - func testPullByDigestNoFallback(c *check.C) { testRequires(c, DaemonIsLinux) // pull from the registry using the @ reference @@ -123,10 +112,6 @@ func (s *DockerRegistrySuite) TestPullByDigestNoFallback(c *check.C) { testPullByDigestNoFallback(c) } -func (s *DockerSchema1RegistrySuite) TestPullByDigestNoFallback(c *check.C) { - testPullByDigestNoFallback(c) -} - func (s *DockerRegistrySuite) TestCreateByDigest(c *check.C) { pushDigest, err := setupImage(c) c.Assert(err, checker.IsNil, check.Commentf("error setting up image")) @@ -563,131 +548,3 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredManifest(c *check.C) { expectedErrorMsg := fmt.Sprintf("manifest verification failed for digest %s", manifestDigest) c.Assert(out, checker.Contains, expectedErrorMsg) } - -// TestPullFailsWithAlteredManifest tests that a `docker pull` fails when -// we have modified a manifest blob and its digest cannot be verified. -// This is the schema1 version of the test. -func (s *DockerSchema1RegistrySuite) TestPullFailsWithAlteredManifest(c *check.C) { - testRequires(c, DaemonIsLinux) - manifestDigest, err := setupImage(c) - c.Assert(err, checker.IsNil, check.Commentf("error setting up image")) - - // Load the target manifest blob. - manifestBlob := s.reg.ReadBlobContents(c, manifestDigest) - - var imgManifest schema1.Manifest - err = json.Unmarshal(manifestBlob, &imgManifest) - c.Assert(err, checker.IsNil, check.Commentf("unable to decode image manifest from blob")) - - // Change a layer in the manifest. - imgManifest.FSLayers[0] = schema1.FSLayer{ - BlobSum: digest.Digest("sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"), - } - - // Move the existing data file aside, so that we can replace it with a - // malicious blob of data. NOTE: we defer the returned undo func. - undo := s.reg.TempMoveBlobData(c, manifestDigest) - defer undo() - - alteredManifestBlob, err := json.MarshalIndent(imgManifest, "", " ") - c.Assert(err, checker.IsNil, check.Commentf("unable to encode altered image manifest to JSON")) - - s.reg.WriteBlobContents(c, manifestDigest, alteredManifestBlob) - - // Now try pulling that image by digest. We should get an error about - // digest verification for the manifest digest. - - // Pull from the registry using the @ reference. - imageReference := fmt.Sprintf("%s@%s", repoName, manifestDigest) - out, exitStatus, _ := dockerCmdWithError("pull", imageReference) - c.Assert(exitStatus, checker.Not(check.Equals), 0) - - expectedErrorMsg := fmt.Sprintf("image verification failed for digest %s", manifestDigest) - c.Assert(out, checker.Contains, expectedErrorMsg) -} - -// TestPullFailsWithAlteredLayer tests that a `docker pull` fails when -// we have modified a layer blob and its digest cannot be verified. -// This is the schema2 version of the test. -func (s *DockerRegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) { - testRequires(c, DaemonIsLinux) - manifestDigest, err := setupImage(c) - c.Assert(err, checker.IsNil) - - // Load the target manifest blob. - manifestBlob := s.reg.ReadBlobContents(c, manifestDigest) - - var imgManifest schema2.Manifest - err = json.Unmarshal(manifestBlob, &imgManifest) - c.Assert(err, checker.IsNil) - - // Next, get the digest of one of the layers from the manifest. - targetLayerDigest := imgManifest.Layers[0].Digest - - // Move the existing data file aside, so that we can replace it with a - // malicious blob of data. NOTE: we defer the returned undo func. - undo := s.reg.TempMoveBlobData(c, targetLayerDigest) - defer undo() - - // Now make a fake data blob in this directory. - s.reg.WriteBlobContents(c, targetLayerDigest, []byte("This is not the data you are looking for.")) - - // Now try pulling that image by digest. We should get an error about - // digest verification for the target layer digest. - - // Remove distribution cache to force a re-pull of the blobs - if err := os.RemoveAll(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "image", s.d.StorageDriver(), "distribution")); err != nil { - c.Fatalf("error clearing distribution cache: %v", err) - } - - // Pull from the registry using the @ reference. - imageReference := fmt.Sprintf("%s@%s", repoName, manifestDigest) - out, exitStatus, _ := dockerCmdWithError("pull", imageReference) - c.Assert(exitStatus, checker.Not(check.Equals), 0, check.Commentf("expected a non-zero exit status")) - - expectedErrorMsg := fmt.Sprintf("filesystem layer verification failed for digest %s", targetLayerDigest) - c.Assert(out, checker.Contains, expectedErrorMsg, check.Commentf("expected error message in output: %s", out)) -} - -// TestPullFailsWithAlteredLayer tests that a `docker pull` fails when -// we have modified a layer blob and its digest cannot be verified. -// This is the schema1 version of the test. -func (s *DockerSchema1RegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) { - testRequires(c, DaemonIsLinux) - manifestDigest, err := setupImage(c) - c.Assert(err, checker.IsNil) - - // Load the target manifest blob. - manifestBlob := s.reg.ReadBlobContents(c, manifestDigest) - - var imgManifest schema1.Manifest - err = json.Unmarshal(manifestBlob, &imgManifest) - c.Assert(err, checker.IsNil) - - // Next, get the digest of one of the layers from the manifest. - targetLayerDigest := imgManifest.FSLayers[0].BlobSum - - // Move the existing data file aside, so that we can replace it with a - // malicious blob of data. NOTE: we defer the returned undo func. - undo := s.reg.TempMoveBlobData(c, targetLayerDigest) - defer undo() - - // Now make a fake data blob in this directory. - s.reg.WriteBlobContents(c, targetLayerDigest, []byte("This is not the data you are looking for.")) - - // Now try pulling that image by digest. We should get an error about - // digest verification for the target layer digest. - - // Remove distribution cache to force a re-pull of the blobs - if err := os.RemoveAll(filepath.Join(testEnv.DaemonInfo.DockerRootDir, "image", s.d.StorageDriver(), "distribution")); err != nil { - c.Fatalf("error clearing distribution cache: %v", err) - } - - // Pull from the registry using the @ reference. - imageReference := fmt.Sprintf("%s@%s", repoName, manifestDigest) - out, exitStatus, _ := dockerCmdWithError("pull", imageReference) - c.Assert(exitStatus, checker.Not(check.Equals), 0, check.Commentf("expected a non-zero exit status")) - - expectedErrorMsg := fmt.Sprintf("filesystem layer verification failed for digest %s", targetLayerDigest) - c.Assert(out, checker.Contains, expectedErrorMsg, check.Commentf("expected error message in output: %s", out)) -} diff --git a/integration-cli/docker_cli_daemon_test.go b/integration-cli/docker_cli_daemon_test.go index c9f79aa3ad..a3d38b1c09 100644 --- a/integration-cli/docker_cli_daemon_test.go +++ b/integration-cli/docker_cli_daemon_test.go @@ -35,7 +35,6 @@ import ( "github.com/docker/docker/pkg/mount" "github.com/docker/go-units" "github.com/docker/libnetwork/iptables" - "github.com/docker/libtrust" "github.com/go-check/check" "github.com/kr/pty" "golang.org/x/sys/unix" @@ -551,23 +550,6 @@ func (s *DockerDaemonSuite) TestDaemonAllocatesListeningPort(c *check.C) { } } -func (s *DockerDaemonSuite) TestDaemonKeyGeneration(c *check.C) { - // TODO: skip or update for Windows daemon - os.Remove("/etc/docker/key.json") - s.d.Start(c) - s.d.Stop(c) - - k, err := libtrust.LoadKeyFile("/etc/docker/key.json") - if err != nil { - c.Fatalf("Error opening key file") - } - kid := k.KeyID() - // Test Key ID is a valid fingerprint (e.g. QQXN:JY5W:TBXI:MK3X:GX6P:PD5D:F56N:NHCS:LVRZ:JA46:R24J:XEFF) - if len(kid) != 59 { - c.Fatalf("Bad key ID: %s", kid) - } -} - // GH#11320 - verify that the daemon exits on failure properly // Note that this explicitly tests the conflict of {-b,--bridge} and {--bip} options as the means // to get a daemon init failure; no other tests for -b/--bip conflict are therefore required @@ -1195,59 +1177,6 @@ func (s *DockerDaemonSuite) TestDaemonUnixSockCleanedUp(c *check.C) { } } -func (s *DockerDaemonSuite) TestDaemonWithWrongkey(c *check.C) { - type Config struct { - Crv string `json:"crv"` - D string `json:"d"` - Kid string `json:"kid"` - Kty string `json:"kty"` - X string `json:"x"` - Y string `json:"y"` - } - - os.Remove("/etc/docker/key.json") - s.d.Start(c) - s.d.Stop(c) - - config := &Config{} - bytes, err := ioutil.ReadFile("/etc/docker/key.json") - if err != nil { - c.Fatalf("Error reading key.json file: %s", err) - } - - // byte[] to Data-Struct - if err := json.Unmarshal(bytes, &config); err != nil { - c.Fatalf("Error Unmarshal: %s", err) - } - - //replace config.Kid with the fake value - config.Kid = "VSAJ:FUYR:X3H2:B2VZ:KZ6U:CJD5:K7BX:ZXHY:UZXT:P4FT:MJWG:HRJ4" - - // NEW Data-Struct to byte[] - newBytes, err := json.Marshal(&config) - if err != nil { - c.Fatalf("Error Marshal: %s", err) - } - - // write back - if err := ioutil.WriteFile("/etc/docker/key.json", newBytes, 0400); err != nil { - c.Fatalf("Error ioutil.WriteFile: %s", err) - } - - defer os.Remove("/etc/docker/key.json") - - if err := s.d.StartWithError(); err == nil { - c.Fatalf("It should not be successful to start daemon with wrong key: %v", err) - } - - content, err := s.d.ReadLogFile() - c.Assert(err, checker.IsNil) - - if !strings.Contains(string(content), "Public Key ID does not match") { - c.Fatalf("Missing KeyID message from daemon logs: %s", string(content)) - } -} - func (s *DockerDaemonSuite) TestDaemonRestartKillWait(c *check.C) { s.d.StartWithBusybox(c) diff --git a/integration-cli/docker_cli_pull_local_test.go b/integration-cli/docker_cli_pull_local_test.go index 33d4ae5e7c..f2260dc3ac 100644 --- a/integration-cli/docker_cli_pull_local_test.go +++ b/integration-cli/docker_cli_pull_local_test.go @@ -55,10 +55,6 @@ func (s *DockerRegistrySuite) TestPullImageWithAliases(c *check.C) { testPullImageWithAliases(c) } -func (s *DockerSchema1RegistrySuite) TestPullImageWithAliases(c *check.C) { - testPullImageWithAliases(c) -} - // testConcurrentPullWholeRepo pulls the same repo concurrently. func testConcurrentPullWholeRepo(c *check.C) { repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) @@ -111,10 +107,6 @@ func (s *DockerRegistrySuite) testConcurrentPullWholeRepo(c *check.C) { testConcurrentPullWholeRepo(c) } -func (s *DockerSchema1RegistrySuite) testConcurrentPullWholeRepo(c *check.C) { - testConcurrentPullWholeRepo(c) -} - // testConcurrentFailingPull tries a concurrent pull that doesn't succeed. func testConcurrentFailingPull(c *check.C) { repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) @@ -142,10 +134,6 @@ func (s *DockerRegistrySuite) testConcurrentFailingPull(c *check.C) { testConcurrentFailingPull(c) } -func (s *DockerSchema1RegistrySuite) testConcurrentFailingPull(c *check.C) { - testConcurrentFailingPull(c) -} - // testConcurrentPullMultipleTags pulls multiple tags from the same repo // concurrently. func testConcurrentPullMultipleTags(c *check.C) { @@ -198,10 +186,6 @@ func (s *DockerRegistrySuite) TestConcurrentPullMultipleTags(c *check.C) { testConcurrentPullMultipleTags(c) } -func (s *DockerSchema1RegistrySuite) TestConcurrentPullMultipleTags(c *check.C) { - testConcurrentPullMultipleTags(c) -} - // testPullIDStability verifies that pushing an image and pulling it back // preserves the image ID. func testPullIDStability(c *check.C) { @@ -259,10 +243,6 @@ func (s *DockerRegistrySuite) TestPullIDStability(c *check.C) { testPullIDStability(c) } -func (s *DockerSchema1RegistrySuite) TestPullIDStability(c *check.C) { - testPullIDStability(c) -} - // #21213 func testPullNoLayers(c *check.C) { repoName := fmt.Sprintf("%v/dockercli/scratch", privateRegistryURL) @@ -279,10 +259,6 @@ func (s *DockerRegistrySuite) TestPullNoLayers(c *check.C) { testPullNoLayers(c) } -func (s *DockerSchema1RegistrySuite) TestPullNoLayers(c *check.C) { - testPullNoLayers(c) -} - func (s *DockerRegistrySuite) TestPullManifestList(c *check.C) { testRequires(c, NotArm) pushDigest, err := setupImage(c) diff --git a/integration-cli/docker_cli_push_test.go b/integration-cli/docker_cli_push_test.go index 0f0df1ab24..2ca205c831 100644 --- a/integration-cli/docker_cli_push_test.go +++ b/integration-cli/docker_cli_push_test.go @@ -30,10 +30,6 @@ func (s *DockerRegistrySuite) TestPushBusyboxImage(c *check.C) { testPushBusyboxImage(c) } -func (s *DockerSchema1RegistrySuite) TestPushBusyboxImage(c *check.C) { - testPushBusyboxImage(c) -} - // pushing an image without a prefix should throw an error func (s *DockerSuite) TestPushUnprefixedRepo(c *check.C) { out, _, err := dockerCmdWithError("push", "busybox") @@ -53,10 +49,6 @@ func (s *DockerRegistrySuite) TestPushUntagged(c *check.C) { testPushUntagged(c) } -func (s *DockerSchema1RegistrySuite) TestPushUntagged(c *check.C) { - testPushUntagged(c) -} - func testPushBadTag(c *check.C) { repoName := fmt.Sprintf("%v/dockercli/busybox:latest", privateRegistryURL) expected := "does not exist" @@ -70,10 +62,6 @@ func (s *DockerRegistrySuite) TestPushBadTag(c *check.C) { testPushBadTag(c) } -func (s *DockerSchema1RegistrySuite) TestPushBadTag(c *check.C) { - testPushBadTag(c) -} - func testPushMultipleTags(c *check.C) { repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) repoTag1 := fmt.Sprintf("%v/dockercli/busybox:t1", privateRegistryURL) @@ -115,10 +103,6 @@ func (s *DockerRegistrySuite) TestPushMultipleTags(c *check.C) { testPushMultipleTags(c) } -func (s *DockerSchema1RegistrySuite) TestPushMultipleTags(c *check.C) { - testPushMultipleTags(c) -} - func testPushEmptyLayer(c *check.C) { repoName := fmt.Sprintf("%v/dockercli/emptylayer", privateRegistryURL) emptyTarball, err := ioutil.TempFile("", "empty_tarball") @@ -146,10 +130,6 @@ func (s *DockerRegistrySuite) TestPushEmptyLayer(c *check.C) { testPushEmptyLayer(c) } -func (s *DockerSchema1RegistrySuite) TestPushEmptyLayer(c *check.C) { - testPushEmptyLayer(c) -} - // testConcurrentPush pushes multiple tags to the same repo // concurrently. func testConcurrentPush(c *check.C) { @@ -200,10 +180,6 @@ func (s *DockerRegistrySuite) TestConcurrentPush(c *check.C) { testConcurrentPush(c) } -func (s *DockerSchema1RegistrySuite) TestConcurrentPush(c *check.C) { - testConcurrentPush(c) -} - func (s *DockerRegistrySuite) TestCrossRepositoryLayerPush(c *check.C) { sourceRepoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) // tag the image to upload it to the private registry @@ -245,39 +221,6 @@ func (s *DockerRegistrySuite) TestCrossRepositoryLayerPush(c *check.C) { c.Assert(out4, check.Equals, "hello world") } -func (s *DockerSchema1RegistrySuite) TestCrossRepositoryLayerPushNotSupported(c *check.C) { - sourceRepoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL) - // tag the image to upload it to the private registry - dockerCmd(c, "tag", "busybox", sourceRepoName) - // push the image to the registry - out1, _, err := dockerCmdWithError("push", sourceRepoName) - c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out1)) - // ensure that none of the layers were mounted from another repository during push - c.Assert(strings.Contains(out1, "Mounted from"), check.Equals, false) - - digest1 := reference.DigestRegexp.FindString(out1) - c.Assert(len(digest1), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest")) - - destRepoName := fmt.Sprintf("%v/dockercli/crossrepopush", privateRegistryURL) - // retag the image to upload the same layers to another repo in the same registry - dockerCmd(c, "tag", "busybox", destRepoName) - // push the image to the registry - out2, _, err := dockerCmdWithError("push", destRepoName) - c.Assert(err, check.IsNil, check.Commentf("pushing the image to the private registry has failed: %s", out2)) - // schema1 registry should not support cross-repo layer mounts, so ensure that this does not happen - c.Assert(strings.Contains(out2, "Mounted from"), check.Equals, false) - - digest2 := reference.DigestRegexp.FindString(out2) - c.Assert(len(digest2), checker.GreaterThan, 0, check.Commentf("no digest found for pushed manifest")) - c.Assert(digest1, check.Not(check.Equals), digest2) - - // ensure that we can pull and run the second pushed repository - dockerCmd(c, "rmi", destRepoName) - dockerCmd(c, "pull", destRepoName) - out3, _ := dockerCmd(c, "run", destRepoName, "echo", "-n", "hello world") - c.Assert(out3, check.Equals, "hello world") -} - func (s *DockerRegistryAuthHtpasswdSuite) TestPushNoCredentialsNoRetry(c *check.C) { repoName := fmt.Sprintf("%s/busybox", privateRegistryURL) dockerCmd(c, "tag", "busybox", repoName) diff --git a/integration/system/uuid_test.go b/integration/system/uuid_test.go new file mode 100644 index 0000000000..b93b335ca0 --- /dev/null +++ b/integration/system/uuid_test.go @@ -0,0 +1,20 @@ +package system + +import ( + "context" + "testing" + + "github.com/pborman/uuid" + "gotest.tools/assert" +) + +func TestUUIDGeneration(t *testing.T) { + defer setupTest(t)() + + c := testEnv.APIClient() + info, err := c.Info(context.Background()) + assert.NilError(t, err) + + id := uuid.Parse(info.ID) + assert.Equal(t, id != nil, true) +} diff --git a/internal/test/fixtures/plugin/plugin.go b/internal/test/fixtures/plugin/plugin.go index 1af6584269..93f5f99fed 100644 --- a/internal/test/fixtures/plugin/plugin.go +++ b/internal/test/fixtures/plugin/plugin.go @@ -92,7 +92,7 @@ func CreateInRegistry(ctx context.Context, repo string, auth *types.AuthConfig, return nil, nil } - regService, err := registry.NewService(registry.ServiceOptions{V2Only: true}) + regService, err := registry.NewService(registry.ServiceOptions{}) if err != nil { return err } diff --git a/registry/config.go b/registry/config.go index de5a526b69..6bb9258c9b 100644 --- a/registry/config.go +++ b/registry/config.go @@ -19,16 +19,11 @@ type ServiceOptions struct { AllowNondistributableArtifacts []string `json:"allow-nondistributable-artifacts,omitempty"` Mirrors []string `json:"registry-mirrors,omitempty"` InsecureRegistries []string `json:"insecure-registries,omitempty"` - - // 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 bool `json:"disable-legacy-registry,omitempty"` } // serviceConfig holds daemon configuration for the registry service. type serviceConfig struct { registrytypes.ServiceConfig - V2Only bool } var ( @@ -76,7 +71,6 @@ func newServiceConfig(options ServiceOptions) (*serviceConfig, error) { // Hack: Bypass setting the mirrors to IndexConfigs since they are going away // and Mirrors are only for the official registry anyways. }, - V2Only: options.V2Only, } if err := config.LoadAllowNondistributableArtifacts(options.AllowNondistributableArtifacts); err != nil { return nil, err diff --git a/registry/service.go b/registry/service.go index b441970ff1..08f5c7a4e1 100644 --- a/registry/service.go +++ b/registry/service.go @@ -309,20 +309,5 @@ func (s *DefaultService) LookupPushEndpoints(hostname string) (endpoints []APIEn } func (s *DefaultService) lookupEndpoints(hostname string) (endpoints []APIEndpoint, err error) { - endpoints, err = s.lookupV2Endpoints(hostname) - if err != nil { - return nil, err - } - - if s.config.V2Only { - return endpoints, nil - } - - legacyEndpoints, err := s.lookupV1Endpoints(hostname) - if err != nil { - return nil, err - } - endpoints = append(endpoints, legacyEndpoints...) - - return endpoints, nil + return s.lookupV2Endpoints(hostname) }