docker_cli_pull_trusted_test.go 8.8 KB

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