github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/integration-cli/docker_cli_pull_trusted_test.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os/exec" 7 "strings" 8 "time" 9 10 "github.com/docker/docker/pkg/integration/checker" 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 pullCmd := exec.Command(dockerBinary, "pull", repoName) 19 s.trustedCmd(pullCmd) 20 out, _, err := runCommandWithOutput(pullCmd) 21 22 c.Assert(err, check.IsNil, check.Commentf(out)) 23 c.Assert(string(out), checker.Contains, "Tagging", check.Commentf(out)) 24 25 dockerCmd(c, "rmi", repoName) 26 // Try untrusted pull to ensure we pushed the tag to the registry 27 pullCmd = exec.Command(dockerBinary, "pull", "--disable-content-trust=true", repoName) 28 s.trustedCmd(pullCmd) 29 out, _, err = runCommandWithOutput(pullCmd) 30 c.Assert(err, check.IsNil, check.Commentf(out)) 31 c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) 32 33 } 34 35 func (s *DockerTrustSuite) TestTrustedIsolatedPull(c *check.C) { 36 repoName := s.setupTrustedImage(c, "trusted-isolated-pull") 37 38 // Try pull (run from isolated directory without trust information) 39 pullCmd := exec.Command(dockerBinary, "--config", "/tmp/docker-isolated", "pull", repoName) 40 s.trustedCmd(pullCmd) 41 out, _, err := runCommandWithOutput(pullCmd) 42 43 c.Assert(err, check.IsNil, check.Commentf(out)) 44 c.Assert(string(out), checker.Contains, "Tagging", check.Commentf(string(out))) 45 46 dockerCmd(c, "rmi", repoName) 47 } 48 49 func (s *DockerTrustSuite) TestUntrustedPull(c *check.C) { 50 repoName := fmt.Sprintf("%v/dockercli/trusted:latest", privateRegistryURL) 51 // tag the image and upload it to the private registry 52 dockerCmd(c, "tag", "busybox", repoName) 53 dockerCmd(c, "push", repoName) 54 dockerCmd(c, "rmi", repoName) 55 56 // Try trusted pull on untrusted tag 57 pullCmd := exec.Command(dockerBinary, "pull", repoName) 58 s.trustedCmd(pullCmd) 59 out, _, err := runCommandWithOutput(pullCmd) 60 61 c.Assert(err, check.NotNil, check.Commentf(out)) 62 c.Assert(string(out), checker.Contains, "Error: remote trust data repository not initialized", check.Commentf(out)) 63 } 64 65 func (s *DockerTrustSuite) TestPullWhenCertExpired(c *check.C) { 66 c.Skip("Currently changes system time, causing instability") 67 repoName := s.setupTrustedImage(c, "trusted-cert-expired") 68 69 // Certificates have 10 years of expiration 70 elevenYearsFromNow := time.Now().Add(time.Hour * 24 * 365 * 11) 71 72 runAtDifferentDate(elevenYearsFromNow, func() { 73 // Try pull 74 pullCmd := exec.Command(dockerBinary, "pull", repoName) 75 s.trustedCmd(pullCmd) 76 out, _, err := runCommandWithOutput(pullCmd) 77 78 c.Assert(err, check.NotNil, check.Commentf(out)) 79 c.Assert(string(out), checker.Contains, "could not validate the path to a trusted root", check.Commentf(out)) 80 }) 81 82 runAtDifferentDate(elevenYearsFromNow, func() { 83 // Try pull 84 pullCmd := exec.Command(dockerBinary, "pull", "--disable-content-trust", repoName) 85 s.trustedCmd(pullCmd) 86 out, _, err := runCommandWithOutput(pullCmd) 87 88 c.Assert(err, check.IsNil, check.Commentf(out)) 89 c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) 90 }) 91 } 92 93 func (s *DockerTrustSuite) TestTrustedPullFromBadTrustServer(c *check.C) { 94 repoName := fmt.Sprintf("%v/dockerclievilpull/trusted:latest", privateRegistryURL) 95 evilLocalConfigDir, err := ioutil.TempDir("", "evil-local-config-dir") 96 if err != nil { 97 c.Fatalf("Failed to create local temp dir") 98 } 99 100 // tag the image and upload it to the private registry 101 dockerCmd(c, "tag", "busybox", repoName) 102 103 pushCmd := exec.Command(dockerBinary, "push", repoName) 104 s.trustedCmd(pushCmd) 105 out, _, err := runCommandWithOutput(pushCmd) 106 107 c.Assert(err, check.IsNil, check.Commentf(out)) 108 c.Assert(string(out), checker.Contains, "Signing and pushing trust metadata", check.Commentf(out)) 109 dockerCmd(c, "rmi", repoName) 110 111 // Try pull 112 pullCmd := exec.Command(dockerBinary, "pull", repoName) 113 s.trustedCmd(pullCmd) 114 out, _, err = runCommandWithOutput(pullCmd) 115 116 c.Assert(err, check.IsNil, check.Commentf(out)) 117 c.Assert(string(out), checker.Contains, "Tagging", check.Commentf(out)) 118 dockerCmd(c, "rmi", repoName) 119 120 // Kill the notary server, start a new "evil" one. 121 s.not.Close() 122 s.not, err = newTestNotary(c) 123 124 c.Assert(err, check.IsNil, check.Commentf("Restarting notary server failed.")) 125 126 // In order to make an evil server, lets re-init a client (with a different trust dir) and push new data. 127 // tag an image and upload it to the private registry 128 dockerCmd(c, "--config", evilLocalConfigDir, "tag", "busybox", repoName) 129 130 // Push up to the new server 131 pushCmd = exec.Command(dockerBinary, "--config", evilLocalConfigDir, "push", repoName) 132 s.trustedCmd(pushCmd) 133 out, _, err = runCommandWithOutput(pushCmd) 134 135 c.Assert(err, check.IsNil, check.Commentf(out)) 136 c.Assert(string(out), checker.Contains, "Signing and pushing trust metadata", check.Commentf(out)) 137 138 // Now, try pulling with the original client from this new trust server. This should fail. 139 pullCmd = exec.Command(dockerBinary, "pull", repoName) 140 s.trustedCmd(pullCmd) 141 out, _, err = runCommandWithOutput(pullCmd) 142 143 c.Assert(err, check.NotNil, check.Commentf(out)) 144 c.Assert(string(out), checker.Contains, "failed to validate data with current trusted certificates", check.Commentf(out)) 145 } 146 147 func (s *DockerTrustSuite) TestTrustedPullWithExpiredSnapshot(c *check.C) { 148 c.Skip("Currently changes system time, causing instability") 149 repoName := fmt.Sprintf("%v/dockercliexpiredtimestamppull/trusted:latest", privateRegistryURL) 150 // tag the image and upload it to the private registry 151 dockerCmd(c, "tag", "busybox", repoName) 152 153 // Push with default passphrases 154 pushCmd := exec.Command(dockerBinary, "push", repoName) 155 s.trustedCmd(pushCmd) 156 out, _, err := runCommandWithOutput(pushCmd) 157 158 c.Assert(err, check.IsNil, check.Commentf(out)) 159 c.Assert(string(out), checker.Contains, "Signing and pushing trust metadata", check.Commentf(out)) 160 161 dockerCmd(c, "rmi", repoName) 162 163 // Snapshots last for three years. This should be expired 164 fourYearsLater := time.Now().Add(time.Hour * 24 * 365 * 4) 165 166 runAtDifferentDate(fourYearsLater, func() { 167 // Try pull 168 pullCmd := exec.Command(dockerBinary, "pull", repoName) 169 s.trustedCmd(pullCmd) 170 out, _, err = runCommandWithOutput(pullCmd) 171 172 c.Assert(err, check.NotNil, check.Commentf("Missing expected error running trusted pull with expired snapshots")) 173 c.Assert(string(out), checker.Contains, "repository out-of-date", check.Commentf(out)) 174 }) 175 } 176 177 func (s *DockerTrustSuite) TestTrustedOfflinePull(c *check.C) { 178 repoName := s.setupTrustedImage(c, "trusted-offline-pull") 179 180 pullCmd := exec.Command(dockerBinary, "pull", repoName) 181 s.trustedCmdWithServer(pullCmd, "https://invalidnotaryserver") 182 out, _, err := runCommandWithOutput(pullCmd) 183 184 c.Assert(err, check.NotNil, check.Commentf(out)) 185 c.Assert(string(out), checker.Contains, "error contacting notary server", check.Commentf(out)) 186 // Do valid trusted pull to warm cache 187 pullCmd = exec.Command(dockerBinary, "pull", repoName) 188 s.trustedCmd(pullCmd) 189 out, _, err = runCommandWithOutput(pullCmd) 190 191 c.Assert(err, check.IsNil, check.Commentf(out)) 192 c.Assert(string(out), checker.Contains, "Tagging", check.Commentf(out)) 193 194 dockerCmd(c, "rmi", repoName) 195 196 // Try pull again with invalid notary server, should use cache 197 pullCmd = exec.Command(dockerBinary, "pull", repoName) 198 s.trustedCmdWithServer(pullCmd, "https://invalidnotaryserver") 199 out, _, err = runCommandWithOutput(pullCmd) 200 201 c.Assert(err, check.IsNil, check.Commentf(out)) 202 c.Assert(string(out), checker.Contains, "Tagging", check.Commentf(out)) 203 } 204 205 func (s *DockerTrustSuite) TestTrustedPullDelete(c *check.C) { 206 repoName := fmt.Sprintf("%v/dockercli/%s:latest", privateRegistryURL, "trusted-pull-delete") 207 // tag the image and upload it to the private registry 208 _, err := buildImage(repoName, ` 209 FROM busybox 210 CMD echo trustedpulldelete 211 `, true) 212 213 pushCmd := exec.Command(dockerBinary, "push", repoName) 214 s.trustedCmd(pushCmd) 215 out, _, err := runCommandWithOutput(pushCmd) 216 if err != nil { 217 c.Fatalf("Error running trusted push: %s\n%s", err, out) 218 } 219 if !strings.Contains(string(out), "Signing and pushing trust metadata") { 220 c.Fatalf("Missing expected output on trusted push:\n%s", out) 221 } 222 223 if out, status := dockerCmd(c, "rmi", repoName); status != 0 { 224 c.Fatalf("Error removing image %q\n%s", repoName, out) 225 } 226 227 // Try pull 228 pullCmd := exec.Command(dockerBinary, "pull", repoName) 229 s.trustedCmd(pullCmd) 230 out, _, err = runCommandWithOutput(pullCmd) 231 232 c.Assert(err, check.IsNil, check.Commentf(out)) 233 234 matches := digestRegex.FindStringSubmatch(out) 235 c.Assert(matches, checker.HasLen, 2, check.Commentf("unable to parse digest from pull output: %s", out)) 236 pullDigest := matches[1] 237 238 imageID, err := inspectField(repoName, "Id") 239 c.Assert(err, checker.IsNil, check.Commentf("error inspecting image id")) 240 241 imageByDigest := repoName + "@" + pullDigest 242 byDigestID, err := inspectField(imageByDigest, "Id") 243 c.Assert(err, checker.IsNil, check.Commentf("error inspecting image id")) 244 245 c.Assert(byDigestID, checker.Equals, imageID) 246 247 // rmi of tag should also remove the digest reference 248 dockerCmd(c, "rmi", repoName) 249 250 _, err = inspectField(imageByDigest, "Id") 251 c.Assert(err, checker.NotNil, check.Commentf("digest reference should have been removed")) 252 253 _, err = inspectField(imageID, "Id") 254 c.Assert(err, checker.NotNil, check.Commentf("image should have been deleted")) 255 }