github.com/AliyunContainerService/cli@v0.0.0-20181009023821-814ced4b30d0/e2e/image/push_test.go (about) 1 package image 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9 10 "github.com/docker/cli/e2e/internal/fixtures" 11 "github.com/docker/cli/internal/test/environment" 12 "github.com/docker/cli/internal/test/output" 13 "gotest.tools/assert" 14 "gotest.tools/fs" 15 "gotest.tools/golden" 16 "gotest.tools/icmd" 17 "gotest.tools/skip" 18 ) 19 20 const ( 21 notary = "/usr/local/bin/notary" 22 23 pubkey1 = "./testdata/notary/delgkey1.crt" 24 privkey1 = "./testdata/notary/delgkey1.key" 25 pubkey2 = "./testdata/notary/delgkey2.crt" 26 privkey2 = "./testdata/notary/delgkey2.key" 27 pubkey3 = "./testdata/notary/delgkey3.crt" 28 privkey3 = "./testdata/notary/delgkey3.key" 29 pubkey4 = "./testdata/notary/delgkey4.crt" 30 privkey4 = "./testdata/notary/delgkey4.key" 31 ) 32 33 func TestPushWithContentTrust(t *testing.T) { 34 skip.If(t, environment.RemoteDaemon()) 35 36 dir := fixtures.SetupConfigFile(t) 37 defer dir.Remove() 38 image := createImage(t, registryPrefix, "trust-push", "latest") 39 40 result := icmd.RunCmd(icmd.Command("docker", "push", image), 41 fixtures.WithConfig(dir.Path()), 42 fixtures.WithTrust, 43 fixtures.WithNotary, 44 fixtures.WithPassphrase("foo", "bar"), 45 ) 46 result.Assert(t, icmd.Success) 47 golden.Assert(t, result.Stderr(), "push-with-content-trust-err.golden") 48 output.Assert(t, result.Stdout(), map[int]func(string) error{ 49 0: output.Equals("The push refers to repository [registry:5000/trust-push]"), 50 1: output.Equals("5bef08742407: Preparing"), 51 3: output.Equals("latest: digest: sha256:641b95ddb2ea9dc2af1a0113b6b348ebc20872ba615204fbe12148e98fd6f23d size: 528"), 52 4: output.Equals("Signing and pushing trust metadata"), 53 5: output.Equals(`Finished initializing "registry:5000/trust-push"`), 54 6: output.Equals("Successfully signed registry:5000/trust-push:latest"), 55 }) 56 } 57 58 func TestPushWithContentTrustUnreachableServer(t *testing.T) { 59 skip.If(t, environment.RemoteDaemon()) 60 61 dir := fixtures.SetupConfigFile(t) 62 defer dir.Remove() 63 image := createImage(t, registryPrefix, "trust-push-unreachable", "latest") 64 65 result := icmd.RunCmd(icmd.Command("docker", "push", image), 66 fixtures.WithConfig(dir.Path()), 67 fixtures.WithTrust, 68 fixtures.WithNotaryServer("https://invalidnotaryserver"), 69 ) 70 result.Assert(t, icmd.Expected{ 71 ExitCode: 1, 72 Err: "error contacting notary server", 73 }) 74 } 75 76 func TestPushWithContentTrustExistingTag(t *testing.T) { 77 skip.If(t, environment.RemoteDaemon()) 78 79 dir := fixtures.SetupConfigFile(t) 80 defer dir.Remove() 81 image := createImage(t, registryPrefix, "trust-push-existing", "latest") 82 83 result := icmd.RunCmd(icmd.Command("docker", "push", image)) 84 result.Assert(t, icmd.Success) 85 86 result = icmd.RunCmd(icmd.Command("docker", "push", image), 87 fixtures.WithConfig(dir.Path()), 88 fixtures.WithTrust, 89 fixtures.WithNotary, 90 fixtures.WithPassphrase("foo", "bar"), 91 ) 92 result.Assert(t, icmd.Expected{ 93 Out: "Signing and pushing trust metadata", 94 }) 95 96 // Re-push 97 result = icmd.RunCmd(icmd.Command("docker", "push", image), 98 fixtures.WithConfig(dir.Path()), 99 fixtures.WithTrust, 100 fixtures.WithNotary, 101 fixtures.WithPassphrase("foo", "bar"), 102 ) 103 result.Assert(t, icmd.Expected{ 104 Out: "Signing and pushing trust metadata", 105 }) 106 } 107 108 func TestPushWithContentTrustReleasesDelegationOnly(t *testing.T) { 109 skip.If(t, environment.RemoteDaemon()) 110 111 role := "targets/releases" 112 113 dir := fixtures.SetupConfigFile(t) 114 defer dir.Remove() 115 copyPrivateKey(t, dir.Join("trust", "private"), privkey1) 116 notaryDir := setupNotaryConfig(t, dir) 117 defer notaryDir.Remove() 118 homeDir := fs.NewDir(t, "push_test_home") 119 defer notaryDir.Remove() 120 121 baseRef := fmt.Sprintf("%s/%s", registryPrefix, "trust-push-releases-delegation") 122 targetRef := fmt.Sprintf("%s:%s", baseRef, "latest") 123 124 // Init repository 125 notaryInit(t, notaryDir, homeDir, baseRef) 126 // Add delegation key (public key) 127 notaryAddDelegation(t, notaryDir, homeDir, baseRef, role, pubkey1) 128 // Publish it 129 notaryPublish(t, notaryDir, homeDir, baseRef) 130 // Import private key 131 notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, role, privkey1) 132 133 // Tag & push with content trust 134 icmd.RunCommand("docker", "pull", fixtures.AlpineImage).Assert(t, icmd.Success) 135 icmd.RunCommand("docker", "tag", fixtures.AlpineImage, targetRef).Assert(t, icmd.Success) 136 result := icmd.RunCmd(icmd.Command("docker", "push", targetRef), 137 fixtures.WithConfig(dir.Path()), 138 fixtures.WithTrust, 139 fixtures.WithNotary, 140 fixtures.WithPassphrase("foo", "foo"), 141 ) 142 result.Assert(t, icmd.Expected{ 143 Out: "Signing and pushing trust metadata", 144 }) 145 146 targetsInRole := notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, role) 147 assert.Assert(t, targetsInRole["latest"] == role, "%v", targetsInRole) 148 targetsInRole = notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets") 149 assert.Assert(t, targetsInRole["latest"] != "targets", "%v", targetsInRole) 150 151 result = icmd.RunCmd(icmd.Command("docker", "pull", targetRef), 152 fixtures.WithConfig(dir.Path()), 153 fixtures.WithTrust, 154 fixtures.WithNotary, 155 ) 156 result.Assert(t, icmd.Success) 157 } 158 159 func TestPushWithContentTrustSignsAllFirstLevelRolesWeHaveKeysFor(t *testing.T) { 160 skip.If(t, environment.RemoteDaemon()) 161 162 dir := fixtures.SetupConfigFile(t) 163 defer dir.Remove() 164 copyPrivateKey(t, dir.Join("trust", "private"), privkey1) 165 copyPrivateKey(t, dir.Join("trust", "private"), privkey2) 166 copyPrivateKey(t, dir.Join("trust", "private"), privkey3) 167 notaryDir := setupNotaryConfig(t, dir) 168 defer notaryDir.Remove() 169 homeDir := fs.NewDir(t, "push_test_home") 170 defer notaryDir.Remove() 171 172 baseRef := fmt.Sprintf("%s/%s", registryPrefix, "trust-push-releases-first-roles") 173 targetRef := fmt.Sprintf("%s:%s", baseRef, "latest") 174 175 // Init repository 176 notaryInit(t, notaryDir, homeDir, baseRef) 177 // Add delegation key (public key) 178 notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role1", pubkey1) 179 notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role2", pubkey2) 180 notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role3", pubkey3) 181 notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role1/subrole", pubkey3) 182 // Import private key 183 notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role1", privkey1) 184 notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role2", privkey2) 185 notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role1/subrole", privkey3) 186 // Publish it 187 notaryPublish(t, notaryDir, homeDir, baseRef) 188 189 // Tag & push with content trust 190 icmd.RunCommand("docker", "pull", fixtures.AlpineImage).Assert(t, icmd.Success) 191 icmd.RunCommand("docker", "tag", fixtures.AlpineImage, targetRef).Assert(t, icmd.Success) 192 result := icmd.RunCmd(icmd.Command("docker", "push", targetRef), 193 fixtures.WithConfig(dir.Path()), 194 fixtures.WithTrust, 195 fixtures.WithNotary, 196 fixtures.WithPassphrase("foo", "foo"), 197 ) 198 result.Assert(t, icmd.Expected{ 199 Out: "Signing and pushing trust metadata", 200 }) 201 202 // check to make sure that the target has been added to targets/role1 and targets/role2, and 203 // not targets (because there are delegations) or targets/role3 (due to missing key) or 204 // targets/role1/subrole (due to it being a second level delegation) 205 targetsInRole := notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets/role1") 206 assert.Assert(t, targetsInRole["latest"] == "targets/role1", "%v", targetsInRole) 207 targetsInRole = notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets/role2") 208 assert.Assert(t, targetsInRole["latest"] == "targets/role2", "%v", targetsInRole) 209 targetsInRole = notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets") 210 assert.Assert(t, targetsInRole["latest"] != "targets", "%v", targetsInRole) 211 212 assert.NilError(t, os.RemoveAll(filepath.Join(dir.Join("trust")))) 213 // Try to pull, should fail because non of these are the release role 214 // FIXME(vdemeester) should be unit test 215 result = icmd.RunCmd(icmd.Command("docker", "pull", targetRef), 216 fixtures.WithConfig(dir.Path()), 217 fixtures.WithTrust, 218 fixtures.WithNotary, 219 ) 220 result.Assert(t, icmd.Expected{ 221 ExitCode: 1, 222 }) 223 } 224 225 func TestPushWithContentTrustSignsForRolesWithKeysAndValidPaths(t *testing.T) { 226 skip.If(t, environment.RemoteDaemon()) 227 228 dir := fixtures.SetupConfigFile(t) 229 defer dir.Remove() 230 copyPrivateKey(t, dir.Join("trust", "private"), privkey1) 231 copyPrivateKey(t, dir.Join("trust", "private"), privkey2) 232 copyPrivateKey(t, dir.Join("trust", "private"), privkey3) 233 copyPrivateKey(t, dir.Join("trust", "private"), privkey4) 234 notaryDir := setupNotaryConfig(t, dir) 235 defer notaryDir.Remove() 236 homeDir := fs.NewDir(t, "push_test_home") 237 defer notaryDir.Remove() 238 239 baseRef := fmt.Sprintf("%s/%s", registryPrefix, "trust-push-releases-keys-valid-paths") 240 targetRef := fmt.Sprintf("%s:%s", baseRef, "latest") 241 242 // Init repository 243 notaryInit(t, notaryDir, homeDir, baseRef) 244 // Add delegation key (public key) 245 notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role1", pubkey1, "l", "z") 246 notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role2", pubkey2, "x", "y") 247 notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role3", pubkey3, "latest") 248 notaryAddDelegation(t, notaryDir, homeDir, baseRef, "targets/role4", pubkey4, "latest") 249 // Import private keys (except 3rd key) 250 notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role1", privkey1) 251 notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role2", privkey2) 252 notaryImportPrivateKey(t, notaryDir, homeDir, baseRef, "targets/role4", privkey4) 253 // Publish it 254 notaryPublish(t, notaryDir, homeDir, baseRef) 255 256 // Tag & push with content trust 257 icmd.RunCommand("docker", "pull", fixtures.AlpineImage).Assert(t, icmd.Success) 258 icmd.RunCommand("docker", "tag", fixtures.AlpineImage, targetRef).Assert(t, icmd.Success) 259 result := icmd.RunCmd(icmd.Command("docker", "push", targetRef), 260 fixtures.WithConfig(dir.Path()), 261 fixtures.WithTrust, 262 fixtures.WithNotary, 263 fixtures.WithPassphrase("foo", "foo"), 264 ) 265 result.Assert(t, icmd.Expected{ 266 Out: "Signing and pushing trust metadata", 267 }) 268 269 // check to make sure that the target has been added to targets/role1 and targets/role4, and 270 // not targets (because there are delegations) or targets/role2 (due to path restrictions) or 271 // targets/role3 (due to missing key) 272 targetsInRole := notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets/role1") 273 assert.Assert(t, targetsInRole["latest"] == "targets/role1", "%v", targetsInRole) 274 targetsInRole = notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets/role4") 275 assert.Assert(t, targetsInRole["latest"] == "targets/role4", "%v", targetsInRole) 276 targetsInRole = notaryListTargetsInRole(t, notaryDir, homeDir, baseRef, "targets") 277 assert.Assert(t, targetsInRole["latest"] != "targets", "%v", targetsInRole) 278 279 assert.NilError(t, os.RemoveAll(filepath.Join(dir.Join("trust")))) 280 // Try to pull, should fail because non of these are the release role 281 // FIXME(vdemeester) should be unit test 282 result = icmd.RunCmd(icmd.Command("docker", "pull", targetRef), 283 fixtures.WithConfig(dir.Path()), 284 fixtures.WithTrust, 285 fixtures.WithNotary, 286 ) 287 result.Assert(t, icmd.Expected{ 288 ExitCode: 1, 289 }) 290 } 291 292 func createImage(t *testing.T, registryPrefix, repo, tag string) string { 293 image := fmt.Sprintf("%s/%s:%s", registryPrefix, repo, tag) 294 icmd.RunCommand("docker", "pull", fixtures.AlpineImage).Assert(t, icmd.Success) 295 icmd.RunCommand("docker", "tag", fixtures.AlpineImage, image).Assert(t, icmd.Success) 296 return image 297 } 298 299 func withNotaryPassphrase(pwd string) func(*icmd.Cmd) { 300 return func(c *icmd.Cmd) { 301 c.Env = append(c.Env, []string{ 302 fmt.Sprintf("NOTARY_ROOT_PASSPHRASE=%s", pwd), 303 fmt.Sprintf("NOTARY_TARGETS_PASSPHRASE=%s", pwd), 304 fmt.Sprintf("NOTARY_SNAPSHOT_PASSPHRASE=%s", pwd), 305 fmt.Sprintf("NOTARY_DELEGATION_PASSPHRASE=%s", pwd), 306 }...) 307 } 308 } 309 310 func notaryImportPrivateKey(t *testing.T, notaryDir, homeDir *fs.Dir, baseRef, role, privkey string) { 311 icmd.RunCmd( 312 icmd.Command(notary, "-c", notaryDir.Join("client-config.json"), "key", "import", privkey, "-g", baseRef, "-r", role), 313 withNotaryPassphrase("foo"), 314 fixtures.WithHome(homeDir.Path()), 315 ).Assert(t, icmd.Success) 316 } 317 318 func notaryPublish(t *testing.T, notaryDir, homeDir *fs.Dir, baseRef string) { 319 icmd.RunCmd( 320 icmd.Command(notary, "-c", notaryDir.Join("client-config.json"), "publish", baseRef), 321 withNotaryPassphrase("foo"), 322 fixtures.WithHome(homeDir.Path()), 323 ).Assert(t, icmd.Success) 324 } 325 326 func notaryAddDelegation(t *testing.T, notaryDir, homeDir *fs.Dir, baseRef, role, pubkey string, paths ...string) { 327 pathsArg := "--all-paths" 328 if len(paths) > 0 { 329 pathsArg = "--paths=" + strings.Join(paths, ",") 330 } 331 icmd.RunCmd( 332 icmd.Command(notary, "-c", notaryDir.Join("client-config.json"), "delegation", "add", baseRef, role, pubkey, pathsArg), 333 withNotaryPassphrase("foo"), 334 fixtures.WithHome(homeDir.Path()), 335 ).Assert(t, icmd.Success) 336 } 337 338 func notaryInit(t *testing.T, notaryDir, homeDir *fs.Dir, baseRef string) { 339 icmd.RunCmd( 340 icmd.Command(notary, "-c", notaryDir.Join("client-config.json"), "init", baseRef), 341 withNotaryPassphrase("foo"), 342 fixtures.WithHome(homeDir.Path()), 343 ).Assert(t, icmd.Success) 344 } 345 346 func notaryListTargetsInRole(t *testing.T, notaryDir, homeDir *fs.Dir, baseRef, role string) map[string]string { 347 result := icmd.RunCmd( 348 icmd.Command(notary, "-c", notaryDir.Join("client-config.json"), "list", baseRef, "-r", role), 349 fixtures.WithHome(homeDir.Path()), 350 ) 351 out := result.Combined() 352 353 // should look something like: 354 // NAME DIGEST SIZE (BYTES) ROLE 355 // ------------------------------------------------------------------------------------------------------ 356 // latest 24a36bbc059b1345b7e8be0df20f1b23caa3602e85d42fff7ecd9d0bd255de56 1377 targets 357 358 targets := make(map[string]string) 359 360 // no target 361 lines := strings.Split(strings.TrimSpace(out), "\n") 362 if len(lines) == 1 && strings.Contains(out, "No targets present in this repository.") { 363 return targets 364 } 365 366 // otherwise, there is at least one target 367 assert.Assert(t, len(lines) >= 3, "output is %s", out) 368 369 for _, line := range lines[2:] { 370 tokens := strings.Fields(line) 371 assert.Assert(t, len(tokens) == 4) 372 targets[tokens[0]] = tokens[3] 373 } 374 375 return targets 376 } 377 378 func setupNotaryConfig(t *testing.T, dockerConfigDir fs.Dir) *fs.Dir { 379 return fs.NewDir(t, "notary_test", fs.WithMode(0700), 380 fs.WithFile("client-config.json", fmt.Sprintf(` 381 { 382 "trust_dir": "%s", 383 "remote_server": { 384 "url": "%s" 385 } 386 }`, dockerConfigDir.Join("trust"), fixtures.NotaryURL)), 387 ) 388 } 389 390 func copyPrivateKey(t *testing.T, dir, source string) { 391 icmd.RunCommand("/bin/cp", source, dir).Assert(t, icmd.Success) 392 }