@@ -3,9 +3,12 @@ package main
33import (
44 "encoding/json"
55 "fmt"
6+ "os"
7+ "path/filepath"
68 "regexp"
79 "strings"
810
11+ "github.com/docker/distribution/manifest/schema1"
912 "github.com/docker/distribution/manifest/schema2"
1013 "github.com/docker/docker/api/types"
1114 "github.com/docker/docker/integration-cli/checker"
@@ -77,6 +80,10 @@ func (s *DockerRegistrySuite) TestPullByTagDisplaysDigest(c *check.C) {
7780 testPullByTagDisplaysDigest (c )
7881}
7982
83+ func (s * DockerSchema1RegistrySuite ) TestPullByTagDisplaysDigest (c * check.C ) {
84+ testPullByTagDisplaysDigest (c )
85+ }
86+
8087func testPullByDigest (c * check.C ) {
8188 testRequires (c , DaemonIsLinux )
8289 pushDigest , err := setupImage (c )
@@ -99,6 +106,10 @@ func (s *DockerRegistrySuite) TestPullByDigest(c *check.C) {
99106 testPullByDigest (c )
100107}
101108
109+ func (s * DockerSchema1RegistrySuite ) TestPullByDigest (c * check.C ) {
110+ testPullByDigest (c )
111+ }
112+
102113func testPullByDigestNoFallback (c * check.C ) {
103114 testRequires (c , DaemonIsLinux )
104115 // pull from the registry using the <name>@<digest> reference
@@ -112,6 +123,10 @@ func (s *DockerRegistrySuite) TestPullByDigestNoFallback(c *check.C) {
112123 testPullByDigestNoFallback (c )
113124}
114125
126+ func (s * DockerSchema1RegistrySuite ) TestPullByDigestNoFallback (c * check.C ) {
127+ testPullByDigestNoFallback (c )
128+ }
129+
115130func (s * DockerRegistrySuite ) TestCreateByDigest (c * check.C ) {
116131 pushDigest , err := setupImage (c )
117132 assert .NilError (c , err , "error setting up image" )
@@ -546,3 +561,131 @@ func (s *DockerRegistrySuite) TestPullFailsWithAlteredManifest(c *check.C) {
546561 expectedErrorMsg := fmt .Sprintf ("manifest verification failed for digest %s" , manifestDigest )
547562 assert .Assert (c , is .Contains (out , expectedErrorMsg ))
548563}
564+
565+ // TestPullFailsWithAlteredManifest tests that a `docker pull` fails when
566+ // we have modified a manifest blob and its digest cannot be verified.
567+ // This is the schema1 version of the test.
568+ func (s * DockerSchema1RegistrySuite ) TestPullFailsWithAlteredManifest (c * check.C ) {
569+ testRequires (c , DaemonIsLinux )
570+ manifestDigest , err := setupImage (c )
571+ c .Assert (err , checker .IsNil , check .Commentf ("error setting up image" ))
572+
573+ // Load the target manifest blob.
574+ manifestBlob := s .reg .ReadBlobContents (c , manifestDigest )
575+
576+ var imgManifest schema1.Manifest
577+ err = json .Unmarshal (manifestBlob , & imgManifest )
578+ c .Assert (err , checker .IsNil , check .Commentf ("unable to decode image manifest from blob" ))
579+
580+ // Change a layer in the manifest.
581+ imgManifest .FSLayers [0 ] = schema1.FSLayer {
582+ BlobSum : digest .Digest ("sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" ),
583+ }
584+
585+ // Move the existing data file aside, so that we can replace it with a
586+ // malicious blob of data. NOTE: we defer the returned undo func.
587+ undo := s .reg .TempMoveBlobData (c , manifestDigest )
588+ defer undo ()
589+
590+ alteredManifestBlob , err := json .MarshalIndent (imgManifest , "" , " " )
591+ c .Assert (err , checker .IsNil , check .Commentf ("unable to encode altered image manifest to JSON" ))
592+
593+ s .reg .WriteBlobContents (c , manifestDigest , alteredManifestBlob )
594+
595+ // Now try pulling that image by digest. We should get an error about
596+ // digest verification for the manifest digest.
597+
598+ // Pull from the registry using the <name>@<digest> reference.
599+ imageReference := fmt .Sprintf ("%s@%s" , repoName , manifestDigest )
600+ out , exitStatus , _ := dockerCmdWithError ("pull" , imageReference )
601+ c .Assert (exitStatus , checker .Not (check .Equals ), 0 )
602+
603+ expectedErrorMsg := fmt .Sprintf ("image verification failed for digest %s" , manifestDigest )
604+ c .Assert (out , checker .Contains , expectedErrorMsg )
605+ }
606+
607+ // TestPullFailsWithAlteredLayer tests that a `docker pull` fails when
608+ // we have modified a layer blob and its digest cannot be verified.
609+ // This is the schema2 version of the test.
610+ func (s * DockerRegistrySuite ) TestPullFailsWithAlteredLayer (c * check.C ) {
611+ testRequires (c , DaemonIsLinux )
612+ manifestDigest , err := setupImage (c )
613+ c .Assert (err , checker .IsNil )
614+
615+ // Load the target manifest blob.
616+ manifestBlob := s .reg .ReadBlobContents (c , manifestDigest )
617+
618+ var imgManifest schema2.Manifest
619+ err = json .Unmarshal (manifestBlob , & imgManifest )
620+ c .Assert (err , checker .IsNil )
621+
622+ // Next, get the digest of one of the layers from the manifest.
623+ targetLayerDigest := imgManifest .Layers [0 ].Digest
624+
625+ // Move the existing data file aside, so that we can replace it with a
626+ // malicious blob of data. NOTE: we defer the returned undo func.
627+ undo := s .reg .TempMoveBlobData (c , targetLayerDigest )
628+ defer undo ()
629+
630+ // Now make a fake data blob in this directory.
631+ s .reg .WriteBlobContents (c , targetLayerDigest , []byte ("This is not the data you are looking for." ))
632+
633+ // Now try pulling that image by digest. We should get an error about
634+ // digest verification for the target layer digest.
635+
636+ // Remove distribution cache to force a re-pull of the blobs
637+ if err := os .RemoveAll (filepath .Join (testEnv .DaemonInfo .DockerRootDir , "image" , s .d .StorageDriver (), "distribution" )); err != nil {
638+ c .Fatalf ("error clearing distribution cache: %v" , err )
639+ }
640+
641+ // Pull from the registry using the <name>@<digest> reference.
642+ imageReference := fmt .Sprintf ("%s@%s" , repoName , manifestDigest )
643+ out , exitStatus , _ := dockerCmdWithError ("pull" , imageReference )
644+ c .Assert (exitStatus , checker .Not (check .Equals ), 0 , check .Commentf ("expected a non-zero exit status" ))
645+
646+ expectedErrorMsg := fmt .Sprintf ("filesystem layer verification failed for digest %s" , targetLayerDigest )
647+ c .Assert (out , checker .Contains , expectedErrorMsg , check .Commentf ("expected error message in output: %s" , out ))
648+ }
649+
650+ // TestPullFailsWithAlteredLayer tests that a `docker pull` fails when
651+ // we have modified a layer blob and its digest cannot be verified.
652+ // This is the schema1 version of the test.
653+ func (s * DockerSchema1RegistrySuite ) TestPullFailsWithAlteredLayer (c * check.C ) {
654+ testRequires (c , DaemonIsLinux )
655+ manifestDigest , err := setupImage (c )
656+ c .Assert (err , checker .IsNil )
657+
658+ // Load the target manifest blob.
659+ manifestBlob := s .reg .ReadBlobContents (c , manifestDigest )
660+
661+ var imgManifest schema1.Manifest
662+ err = json .Unmarshal (manifestBlob , & imgManifest )
663+ c .Assert (err , checker .IsNil )
664+
665+ // Next, get the digest of one of the layers from the manifest.
666+ targetLayerDigest := imgManifest .FSLayers [0 ].BlobSum
667+
668+ // Move the existing data file aside, so that we can replace it with a
669+ // malicious blob of data. NOTE: we defer the returned undo func.
670+ undo := s .reg .TempMoveBlobData (c , targetLayerDigest )
671+ defer undo ()
672+
673+ // Now make a fake data blob in this directory.
674+ s .reg .WriteBlobContents (c , targetLayerDigest , []byte ("This is not the data you are looking for." ))
675+
676+ // Now try pulling that image by digest. We should get an error about
677+ // digest verification for the target layer digest.
678+
679+ // Remove distribution cache to force a re-pull of the blobs
680+ if err := os .RemoveAll (filepath .Join (testEnv .DaemonInfo .DockerRootDir , "image" , s .d .StorageDriver (), "distribution" )); err != nil {
681+ c .Fatalf ("error clearing distribution cache: %v" , err )
682+ }
683+
684+ // Pull from the registry using the <name>@<digest> reference.
685+ imageReference := fmt .Sprintf ("%s@%s" , repoName , manifestDigest )
686+ out , exitStatus , _ := dockerCmdWithError ("pull" , imageReference )
687+ c .Assert (exitStatus , checker .Not (check .Equals ), 0 , check .Commentf ("expected a non-zero exit status" ))
688+
689+ expectedErrorMsg := fmt .Sprintf ("filesystem layer verification failed for digest %s" , targetLayerDigest )
690+ c .Assert (out , checker .Contains , expectedErrorMsg , check .Commentf ("expected error message in output: %s" , out ))
691+ }
0 commit comments