github.com/flavio/docker@v0.1.3-0.20170117145210-f63d1a6eec47/integration-cli/docker_cli_pull_trusted_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "time" 7 8 "github.com/docker/docker/integration-cli/checker" 9 "github.com/docker/docker/pkg/testutil" 10 icmd "github.com/docker/docker/pkg/testutil/cmd" 11 "github.com/go-check/check" 12 ) 13 14 func (s *DockerTrustSuite) TestTrustedPull(c *check.C) { 15 repoName := s.setupTrustedImage(c, "trusted-pull") 16 17 // Try pull 18 icmd.RunCmd(icmd.Command(dockerBinary, "pull", repoName), trustedCmd).Assert(c, SuccessTagging) 19 20 dockerCmd(c, "rmi", repoName) 21 // Try untrusted pull to ensure we pushed the tag to the registry 22 icmd.RunCmd(icmd.Command(dockerBinary, "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 icmd.RunCmd(icmd.Command(dockerBinary, "--config", "/tmp/docker-isolated", "pull", repoName), trustedCmd).Assert(c, SuccessTagging) 30 31 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 dockerCmd(c, "tag", "busybox", repoName) 38 dockerCmd(c, "push", repoName) 39 dockerCmd(c, "rmi", repoName) 40 41 // Try trusted pull on untrusted tag 42 icmd.RunCmd(icmd.Command(dockerBinary, "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) TestPullWhenCertExpired(c *check.C) { 49 c.Skip("Currently changes system time, causing instability") 50 repoName := s.setupTrustedImage(c, "trusted-cert-expired") 51 52 // Certificates have 10 years of expiration 53 elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11) 54 55 testutil.RunAtDifferentDate(elevenYearsFromNow, func() { 56 // Try pull 57 icmd.RunCmd(icmd.Cmd{ 58 Command: []string{dockerBinary, "pull", repoName}, 59 }, trustedCmd).Assert(c, icmd.Expected{ 60 ExitCode: 1, 61 Err: "could not validate the path to a trusted root", 62 }) 63 }) 64 65 testutil.RunAtDifferentDate(elevenYearsFromNow, func() { 66 // Try pull 67 icmd.RunCmd(icmd.Cmd{ 68 Command: []string{dockerBinary, "pull", "--disable-content-trust", repoName}, 69 }, trustedCmd).Assert(c, SuccessDownloaded) 70 }) 71 } 72 73 func (s *DockerTrustSuite) TestTrustedPullFromBadTrustServer(c *check.C) { 74 repoName := fmt.Sprintf("%v/dockerclievilpull/trusted:latest", privateRegistryURL) 75 evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir") 76 if err != nil { 77 c.Fatalf("Failed to create local temp dir") 78 } 79 80 // tag the image and upload it to the private registry 81 dockerCmd(c, "tag", "busybox", repoName) 82 83 icmd.RunCmd(icmd.Command(dockerBinary, "push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) 84 dockerCmd(c, "rmi", repoName) 85 86 // Try pull 87 icmd.RunCmd(icmd.Command(dockerBinary, "pull", repoName), trustedCmd).Assert(c, SuccessTagging) 88 dockerCmd(c, "rmi", repoName) 89 90 // Kill the notary server, start a new "evil" one. 91 s.not.Close() 92 s.not, err = newTestNotary(c) 93 94 c.Assert(err, check.IsNil, check.Commentf("Restarting notary server failed.")) 95 96 // In order to make an evil server, lets re-init a client (with a different trust dir) and push new data. 97 // tag an image and upload it to the private registry 98 dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName) 99 100 // Push up to the new server 101 icmd.RunCmd(icmd.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) 102 103 // Now, try pulling with the original client from this new trust server. This should fail because the new root is invalid. 104 icmd.RunCmd(icmd.Command(dockerBinary, "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ 105 ExitCode: 1, 106 Err: "could not rotate trust to a new trusted root", 107 }) 108 } 109 110 func (s *DockerTrustSuite) TestTrustedPullWithExpiredSnapshot(c *check.C) { 111 c.Skip("Currently changes system time, causing instability") 112 repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppull/trusted:latest", privateRegistryURL) 113 // tag the image and upload it to the private registry 114 dockerCmd(c, "tag", "busybox", repoName) 115 116 // Push with default passphrases 117 icmd.RunCmd(icmd.Command(dockerBinary, "push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) 118 dockerCmd(c, "rmi", repoName) 119 120 // Snapshots last for three years. This should be expired 121 fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4) 122 123 testutil.RunAtDifferentDate(fourYearsLater, func() { 124 // Try pull 125 icmd.RunCmd(icmd.Cmd{ 126 Command: []string{dockerBinary, "pull", repoName}, 127 }, trustedCmd).Assert(c, icmd.Expected{ 128 ExitCode: 1, 129 Err: "repository out-of-date", 130 }) 131 }) 132 } 133 134 func (s *DockerTrustSuite) TestTrustedOfflinePull(c *check.C) { 135 repoName := s.setupTrustedImage(c, "trusted-offline-pull") 136 137 icmd.RunCmd(icmd.Command(dockerBinary, "pull", repoName), trustedCmdWithServer("https://invalidnotaryserver")).Assert(c, icmd.Expected{ 138 ExitCode: 1, 139 Err: "error contacting notary server", 140 }) 141 // Do valid trusted pull to warm cache 142 icmd.RunCmd(icmd.Command(dockerBinary, "pull", repoName), trustedCmd).Assert(c, SuccessTagging) 143 dockerCmd(c, "rmi", repoName) 144 145 // Try pull again with invalid notary server, should use cache 146 icmd.RunCmd(icmd.Command(dockerBinary, "pull", repoName), trustedCmdWithServer("https://invalidnotaryserver")).Assert(c, SuccessTagging) 147 } 148 149 func (s *DockerTrustSuite) TestTrustedPullDelete(c *check.C) { 150 repoName := fmt.Sprintf("%v/dockercli/%s:latest", privateRegistryURL, "trusted-pull-delete") 151 // tag the image and upload it to the private registry 152 _, err := buildImage(repoName, ` 153 FROM busybox 154 CMD echo trustedpulldelete 155 `, true) 156 157 icmd.RunCmd(icmd.Command(dockerBinary, "push", repoName), trustedCmd).Assert(c, SuccessSigningAndPushing) 158 159 dockerCmd(c, "rmi", repoName) 160 161 // Try pull 162 result := icmd.RunCmd(icmd.Command(dockerBinary, "pull", repoName), trustedCmd) 163 result.Assert(c, icmd.Success) 164 165 matches := digestRegex.FindStringSubmatch(result.Combined()) 166 c.Assert(matches, checker.HasLen, 2, check.Commentf("unable to parse digest from pull output: %s", result.Combined())) 167 pullDigest := matches[1] 168 169 imageID := inspectField(c, repoName, "Id") 170 171 imageByDigest := repoName + "@" + pullDigest 172 byDigestID := inspectField(c, imageByDigest, "Id") 173 174 c.Assert(byDigestID, checker.Equals, imageID) 175 176 // rmi of tag should also remove the digest reference 177 dockerCmd(c, "rmi", repoName) 178 179 _, err = inspectFieldWithError(imageByDigest, "Id") 180 c.Assert(err, checker.NotNil, check.Commentf("digest reference should have been removed")) 181 182 _, err = inspectFieldWithError(imageID, "Id") 183 c.Assert(err, checker.NotNil, check.Commentf("image should have been deleted")) 184 } 185 186 func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) { 187 testRequires(c, NotaryHosting) 188 repoName := fmt.Sprintf("%v/dockerclireleasesdelegationpulling/trusted", privateRegistryURL) 189 targetName := fmt.Sprintf("%s:latest", repoName) 190 191 // Push with targets first, initializing the repo 192 dockerCmd(c, "tag", "busybox", targetName) 193 icmd.RunCmd(icmd.Command(dockerBinary, "push", targetName), trustedCmd).Assert(c, icmd.Success) 194 s.assertTargetInRoles(c, repoName, "latest", "targets") 195 196 // Try pull, check we retrieve from targets role 197 icmd.RunCmd(icmd.Command(dockerBinary, "-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ 198 Err: "retrieving target for targets role", 199 }) 200 201 // Now we'll create the releases role, and try pushing and pulling 202 s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) 203 s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) 204 s.notaryPublish(c, repoName) 205 206 // try a pull, check that we can still pull because we can still read the 207 // old tag in the targets role 208 icmd.RunCmd(icmd.Command(dockerBinary, "-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ 209 Err: "retrieving target for targets role", 210 }) 211 212 // try a pull -a, check that it succeeds because we can still pull from the 213 // targets role 214 icmd.RunCmd(icmd.Command(dockerBinary, "-D", "pull", "-a", repoName), trustedCmd).Assert(c, icmd.Success) 215 216 // Push, should sign with targets/releases 217 dockerCmd(c, "tag", "busybox", targetName) 218 icmd.RunCmd(icmd.Command(dockerBinary, "push", targetName), trustedCmd).Assert(c, icmd.Success) 219 s.assertTargetInRoles(c, repoName, "latest", "targets", "targets/releases") 220 221 // Try pull, check we retrieve from targets/releases role 222 icmd.RunCmd(icmd.Command(dockerBinary, "-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ 223 Err: "retrieving target for targets/releases role", 224 }) 225 226 // Create another delegation that we'll sign with 227 s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[1].Public) 228 s.notaryImportKey(c, repoName, "targets/other", s.not.keys[1].Private) 229 s.notaryPublish(c, repoName) 230 231 dockerCmd(c, "tag", "busybox", targetName) 232 icmd.RunCmd(icmd.Command(dockerBinary, "push", targetName), trustedCmd).Assert(c, icmd.Success) 233 s.assertTargetInRoles(c, repoName, "latest", "targets", "targets/releases", "targets/other") 234 235 // Try pull, check we retrieve from targets/releases role 236 icmd.RunCmd(icmd.Command(dockerBinary, "-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ 237 Err: "retrieving target for targets/releases role", 238 }) 239 } 240 241 func (s *DockerTrustSuite) TestTrustedPullIgnoresOtherDelegationRoles(c *check.C) { 242 testRequires(c, NotaryHosting) 243 repoName := fmt.Sprintf("%v/dockerclipullotherdelegation/trusted", privateRegistryURL) 244 targetName := fmt.Sprintf("%s:latest", repoName) 245 246 // We'll create a repo first with a non-release delegation role, so that when we 247 // push we'll sign it into the delegation role 248 s.notaryInitRepo(c, repoName) 249 s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[0].Public) 250 s.notaryImportKey(c, repoName, "targets/other", s.not.keys[0].Private) 251 s.notaryPublish(c, repoName) 252 253 // Push should write to the delegation role, not targets 254 dockerCmd(c, "tag", "busybox", targetName) 255 icmd.RunCmd(icmd.Command(dockerBinary, "push", targetName), trustedCmd).Assert(c, icmd.Success) 256 s.assertTargetInRoles(c, repoName, "latest", "targets/other") 257 s.assertTargetNotInRoles(c, repoName, "latest", "targets") 258 259 // Try pull - we should fail, since pull will only pull from the targets/releases 260 // role or the targets role 261 dockerCmd(c, "tag", "busybox", targetName) 262 icmd.RunCmd(icmd.Command(dockerBinary, "-D", "pull", repoName), trustedCmd).Assert(c, icmd.Expected{ 263 ExitCode: 1, 264 Err: "No trust data for", 265 }) 266 267 // try a pull -a: we should fail since pull will only pull from the targets/releases 268 // role or the targets role 269 icmd.RunCmd(icmd.Command(dockerBinary, "-D", "pull", "-a", repoName), trustedCmd).Assert(c, icmd.Expected{ 270 ExitCode: 1, 271 Err: "No trusted tags for", 272 }) 273 }