github.com/ssdev-go/moby@v17.12.1-ce-rc2+incompatible/integration-cli/docker_cli_pull_trusted_test.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  
     7  	"github.com/docker/docker/integration-cli/checker"
     8  	"github.com/docker/docker/integration-cli/cli"
     9  	"github.com/docker/docker/integration-cli/cli/build"
    10  	"github.com/go-check/check"
    11  	"github.com/gotestyourself/gotestyourself/icmd"
    12  )
    13  
    14  func (s *DockerTrustSuite) TestTrustedPull(c *check.C) {
    15  	repoName := s.setupTrustedImage(c, "trusted-pull")
    16  
    17  	// Try pull
    18  	cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, SuccessTagging)
    19  
    20  	cli.DockerCmd(c, "rmi", repoName)
    21  	// Try untrusted pull to ensure we pushed the tag to the registry
    22  	cli.Docker(cli.Args("pull", "--disable-content-trust=true", repoName), trustedCmd).Assert(c, SuccessDownloaded)
    23  }
    24  
    25  func (s *DockerTrustSuite) TestTrustedIsolatedPull(c *check.C) {
    26  	repoName := s.setupTrustedImage(c, "trusted-isolated-pull")
    27  
    28  	// Try pull (run from isolated directory without trust information)
    29  	cli.Docker(cli.Args("--config", "/tmp/docker-isolated", "pull", repoName), trustedCmd).Assert(c, SuccessTagging)
    30  
    31  	cli.DockerCmd(c, "rmi", repoName)
    32  }
    33  
    34  func (s *DockerTrustSuite) TestUntrustedPull(c *check.C) {
    35  	repoName := fmt.Sprintf("%v/dockercliuntrusted/pulltest:latest", privateRegistryURL)
    36  	// tag the image and upload it to the private registry
    37  	cli.DockerCmd(c, "tag", "busybox", repoName)
    38  	cli.DockerCmd(c, "push", repoName)
    39  	cli.DockerCmd(c, "rmi", repoName)
    40  
    41  	// Try trusted pull on untrusted tag
    42  	cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Expected{
    43  		ExitCode: 1,
    44  		Err:      "Error: remote trust data does not exist",
    45  	})
    46  }
    47  
    48  func (s *DockerTrustSuite) TestTrustedPullFromBadTrustServer(c *check.C) {
    49  	repoName := fmt.Sprintf("%v/dockerclievilpull/trusted:latest", privateRegistryURL)
    50  	evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir")
    51  	if err != nil {
    52  		c.Fatalf("Failed to create local temp dir")
    53  	}
    54  
    55  	// tag the image and upload it to the private registry
    56  	cli.DockerCmd(c, "tag", "busybox", repoName)
    57  
    58  	cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing)
    59  	cli.DockerCmd(c, "rmi", repoName)
    60  
    61  	// Try pull
    62  	cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, SuccessTagging)
    63  	cli.DockerCmd(c, "rmi", repoName)
    64  
    65  	// Kill the notary server, start a new "evil" one.
    66  	s.not.Close()
    67  	s.not, err = newTestNotary(c)
    68  
    69  	c.Assert(err, check.IsNil, check.Commentf("Restarting notary server failed."))
    70  
    71  	// In order to make an evil server, lets re-init a client (with a different trust dir) and push new data.
    72  	// tag an image and upload it to the private registry
    73  	cli.DockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName)
    74  
    75  	// Push up to the new server
    76  	cli.Docker(cli.Args("--config", evilLocalConfigDir, "push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing)
    77  
    78  	// Now, try pulling with the original client from this new trust server. This should fail because the new root is invalid.
    79  	cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Expected{
    80  		ExitCode: 1,
    81  		Err:      "could not rotate trust to a new trusted root",
    82  	})
    83  }
    84  
    85  func (s *DockerTrustSuite) TestTrustedOfflinePull(c *check.C) {
    86  	repoName := s.setupTrustedImage(c, "trusted-offline-pull")
    87  
    88  	cli.Docker(cli.Args("pull", repoName), trustedCmdWithServer("https://invalidnotaryserver")).Assert(c, icmd.Expected{
    89  		ExitCode: 1,
    90  		Err:      "error contacting notary server",
    91  	})
    92  	// Do valid trusted pull to warm cache
    93  	cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, SuccessTagging)
    94  	cli.DockerCmd(c, "rmi", repoName)
    95  
    96  	// Try pull again with invalid notary server, should use cache
    97  	cli.Docker(cli.Args("pull", repoName), trustedCmdWithServer("https://invalidnotaryserver")).Assert(c, SuccessTagging)
    98  }
    99  
   100  func (s *DockerTrustSuite) TestTrustedPullDelete(c *check.C) {
   101  	repoName := fmt.Sprintf("%v/dockercli/%s:latest", privateRegistryURL, "trusted-pull-delete")
   102  	// tag the image and upload it to the private registry
   103  	cli.BuildCmd(c, repoName, build.WithDockerfile(`
   104                      FROM busybox
   105                      CMD echo trustedpulldelete
   106                  `))
   107  	cli.Docker(cli.Args("push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing)
   108  
   109  	cli.DockerCmd(c, "rmi", repoName)
   110  
   111  	// Try pull
   112  	result := cli.Docker(cli.Args("pull", repoName), trustedCmd).Assert(c, icmd.Success)
   113  
   114  	matches := digestRegex.FindStringSubmatch(result.Combined())
   115  	c.Assert(matches, checker.HasLen, 2, check.Commentf("unable to parse digest from pull output: %s", result.Combined()))
   116  	pullDigest := matches[1]
   117  
   118  	imageID := inspectField(c, repoName, "Id")
   119  
   120  	imageByDigest := repoName + "@" + pullDigest
   121  	byDigestID := inspectField(c, imageByDigest, "Id")
   122  
   123  	c.Assert(byDigestID, checker.Equals, imageID)
   124  
   125  	// rmi of tag should also remove the digest reference
   126  	cli.DockerCmd(c, "rmi", repoName)
   127  
   128  	_, err := inspectFieldWithError(imageByDigest, "Id")
   129  	c.Assert(err, checker.NotNil, check.Commentf("digest reference should have been removed"))
   130  
   131  	_, err = inspectFieldWithError(imageID, "Id")
   132  	c.Assert(err, checker.NotNil, check.Commentf("image should have been deleted"))
   133  }
   134  
   135  func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) {
   136  	c.Skip("Blacklisting for Docker CE")
   137  	testRequires(c, NotaryHosting)
   138  	repoName := fmt.Sprintf("%v/dockerclireleasesdelegationpulling/trusted", privateRegistryURL)
   139  	targetName := fmt.Sprintf("%s:latest", repoName)
   140  
   141  	// Push with targets first, initializing the repo
   142  	cli.DockerCmd(c, "tag", "busybox", targetName)
   143  	cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, icmd.Success)
   144  	s.assertTargetInRoles(c, repoName, "latest", "targets")
   145  
   146  	// Try pull, check we retrieve from targets role
   147  	cli.Docker(cli.Args("-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{
   148  		Err: "retrieving target for targets role",
   149  	})
   150  
   151  	// Now we'll create the releases role, and try pushing and pulling
   152  	s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public)
   153  	s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private)
   154  	s.notaryPublish(c, repoName)
   155  
   156  	// try a pull, check that we can still pull because we can still read the
   157  	// old tag in the targets role
   158  	cli.Docker(cli.Args("-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{
   159  		Err: "retrieving target for targets role",
   160  	})
   161  
   162  	// try a pull -a, check that it succeeds because we can still pull from the
   163  	// targets role
   164  	cli.Docker(cli.Args("-D", "pull", "-a", repoName), trustedCmd).Assert(c, icmd.Success)
   165  
   166  	// Push, should sign with targets/releases
   167  	cli.DockerCmd(c, "tag", "busybox", targetName)
   168  	cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, icmd.Success)
   169  	s.assertTargetInRoles(c, repoName, "latest", "targets", "targets/releases")
   170  
   171  	// Try pull, check we retrieve from targets/releases role
   172  	cli.Docker(cli.Args("-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{
   173  		Err: "retrieving target for targets/releases role",
   174  	})
   175  
   176  	// Create another delegation that we'll sign with
   177  	s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[1].Public)
   178  	s.notaryImportKey(c, repoName, "targets/other", s.not.keys[1].Private)
   179  	s.notaryPublish(c, repoName)
   180  
   181  	cli.DockerCmd(c, "tag", "busybox", targetName)
   182  	cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, icmd.Success)
   183  	s.assertTargetInRoles(c, repoName, "latest", "targets", "targets/releases", "targets/other")
   184  
   185  	// Try pull, check we retrieve from targets/releases role
   186  	cli.Docker(cli.Args("-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{
   187  		Err: "retrieving target for targets/releases role",
   188  	})
   189  }
   190  
   191  func (s *DockerTrustSuite) TestTrustedPullIgnoresOtherDelegationRoles(c *check.C) {
   192  	c.Skip("Blacklisting for Docker CE")
   193  	testRequires(c, NotaryHosting)
   194  	repoName := fmt.Sprintf("%v/dockerclipullotherdelegation/trusted", privateRegistryURL)
   195  	targetName := fmt.Sprintf("%s:latest", repoName)
   196  
   197  	// We'll create a repo first with a non-release delegation role, so that when we
   198  	// push we'll sign it into the delegation role
   199  	s.notaryInitRepo(c, repoName)
   200  	s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[0].Public)
   201  	s.notaryImportKey(c, repoName, "targets/other", s.not.keys[0].Private)
   202  	s.notaryPublish(c, repoName)
   203  
   204  	// Push should write to the delegation role, not targets
   205  	cli.DockerCmd(c, "tag", "busybox", targetName)
   206  	cli.Docker(cli.Args("push", targetName), trustedCmd).Assert(c, icmd.Success)
   207  	s.assertTargetInRoles(c, repoName, "latest", "targets/other")
   208  	s.assertTargetNotInRoles(c, repoName, "latest", "targets")
   209  
   210  	// Try pull - we should fail, since pull will only pull from the targets/releases
   211  	// role or the targets role
   212  	cli.DockerCmd(c, "tag", "busybox", targetName)
   213  	cli.Docker(cli.Args("-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{
   214  		ExitCode: 1,
   215  		Err:      "No trust data for",
   216  	})
   217  
   218  	// try a pull -a: we should fail since pull will only pull from the targets/releases
   219  	// role or the targets role
   220  	cli.Docker(cli.Args("-D", "pull", "-a", repoName), trustedCmd).Assert(c, icmd.Expected{
   221  		ExitCode: 1,
   222  		Err:      "No trusted tags for",
   223  	})
   224  }