|
@@ -10,6 +10,7 @@ import (
|
|
|
|
|
|
"github.com/docker/distribution/digest"
|
|
|
"github.com/docker/distribution/manifest/schema1"
|
|
|
+ "github.com/docker/distribution/manifest/schema2"
|
|
|
"github.com/docker/docker/pkg/integration/checker"
|
|
|
"github.com/docker/docker/pkg/stringutils"
|
|
|
"github.com/docker/engine-api/types"
|
|
@@ -56,7 +57,7 @@ func setupImageWithTag(c *check.C, tag string) (digest.Digest, error) {
|
|
|
return digest.Digest(pushDigest), nil
|
|
|
}
|
|
|
|
|
|
-func (s *DockerRegistrySuite) TestPullByTagDisplaysDigest(c *check.C) {
|
|
|
+func testPullByTagDisplaysDigest(c *check.C) {
|
|
|
testRequires(c, DaemonIsLinux)
|
|
|
pushDigest, err := setupImage(c)
|
|
|
c.Assert(err, checker.IsNil, check.Commentf("error setting up image"))
|
|
@@ -73,7 +74,15 @@ func (s *DockerRegistrySuite) TestPullByTagDisplaysDigest(c *check.C) {
|
|
|
c.Assert(pushDigest.String(), checker.Equals, pullDigest)
|
|
|
}
|
|
|
|
|
|
-func (s *DockerRegistrySuite) TestPullByDigest(c *check.C) {
|
|
|
+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)
|
|
|
c.Assert(err, checker.IsNil, check.Commentf("error setting up image"))
|
|
@@ -91,7 +100,15 @@ func (s *DockerRegistrySuite) TestPullByDigest(c *check.C) {
|
|
|
c.Assert(pushDigest.String(), checker.Equals, pullDigest)
|
|
|
}
|
|
|
|
|
|
-func (s *DockerRegistrySuite) TestPullByDigestNoFallback(c *check.C) {
|
|
|
+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 <name>@<digest> reference
|
|
|
imageReference := fmt.Sprintf("%s@sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", repoName)
|
|
@@ -100,6 +117,14 @@ func (s *DockerRegistrySuite) TestPullByDigestNoFallback(c *check.C) {
|
|
|
c.Assert(out, checker.Contains, "manifest unknown", check.Commentf("expected non-zero exit status and correct error message when pulling non-existing image"))
|
|
|
}
|
|
|
|
|
|
+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"))
|
|
@@ -372,6 +397,7 @@ func (s *DockerRegistrySuite) TestDeleteImageByIDOnlyPulledByDigest(c *check.C)
|
|
|
|
|
|
// TestPullFailsWithAlteredManifest tests that a `docker pull` fails when
|
|
|
// we have modified a manifest blob and its digest cannot be verified.
|
|
|
+// This is the schema2 version of the test.
|
|
|
func (s *DockerRegistrySuite) TestPullFailsWithAlteredManifest(c *check.C) {
|
|
|
testRequires(c, DaemonIsLinux)
|
|
|
manifestDigest, err := setupImage(c)
|
|
@@ -380,6 +406,46 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredManifest(c *check.C) {
|
|
|
// 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, check.Commentf("unable to decode image manifest from blob"))
|
|
|
+
|
|
|
+ // Change a layer in the manifest.
|
|
|
+ imgManifest.Layers[0].Digest = 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 <name>@<digest> reference.
|
|
|
+ imageReference := fmt.Sprintf("%s@%s", repoName, manifestDigest)
|
|
|
+ out, exitStatus, _ := dockerCmdWithError("pull", imageReference)
|
|
|
+ c.Assert(exitStatus, checker.Not(check.Equals), 0)
|
|
|
+
|
|
|
+ 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"))
|
|
@@ -413,6 +479,7 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredManifest(c *check.C) {
|
|
|
|
|
|
// 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)
|
|
@@ -421,6 +488,49 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredLayer(c *check.C) {
|
|
|
// 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(dockerBasePath, "image", s.d.storageDriver, "distribution")); err != nil {
|
|
|
+ c.Fatalf("error clearing distribution cache: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Pull from the registry using the <name>@<digest> 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 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)
|