Browse code

Trusted push now adds the tag to every first level delegation role for which we have keys and for which the tag conforms to path restrictions.

Signed-off-by: cyli <cyli@twistedmatrix.com>

cyli authored on 2016/03/08 04:48:11
Showing 12 changed files
... ...
@@ -442,39 +442,88 @@ func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, tag string,
442 442
 		return err
443 443
 	}
444 444
 
445
-	if err := repo.AddTarget(target, releasesRole); err != nil {
446
-		return err
445
+	// get the latest repository metadata so we can figure out which roles to sign
446
+	_, err = repo.Update(false)
447
+
448
+	switch err.(type) {
449
+	case client.ErrRepoNotInitialized, client.ErrRepositoryNotExist:
450
+		keys := repo.CryptoService.ListKeys(data.CanonicalRootRole)
451
+		var rootKeyID string
452
+		// always select the first root key
453
+		if len(keys) > 0 {
454
+			sort.Strings(keys)
455
+			rootKeyID = keys[0]
456
+		} else {
457
+			rootPublicKey, err := repo.CryptoService.Create(data.CanonicalRootRole, data.ECDSAKey)
458
+			if err != nil {
459
+				return err
460
+			}
461
+			rootKeyID = rootPublicKey.ID()
462
+		}
463
+
464
+		// Initialize the notary repository with a remotely managed snapshot key
465
+		if err := repo.Initialize(rootKeyID, data.CanonicalSnapshotRole); err != nil {
466
+			return notaryError(repoInfo.FullName(), err)
467
+		}
468
+		fmt.Fprintf(cli.out, "Finished initializing %q\n", repoInfo.FullName())
469
+		err = repo.AddTarget(target, data.CanonicalTargetsRole)
470
+	case nil:
471
+		// already initialized and we have successfully downloaded the latest metadata
472
+		err = cli.addTargetToAllSignableRoles(repo, target)
473
+	default:
474
+		return notaryError(repoInfo.FullName(), err)
447 475
 	}
448 476
 
449
-	err = repo.Publish()
450 477
 	if err == nil {
451
-		fmt.Fprintf(cli.out, "Successfully signed %q:%s\n", repoInfo.FullName(), tag)
452
-		return nil
453
-	} else if _, ok := err.(client.ErrRepoNotInitialized); !ok {
478
+		err = repo.Publish()
479
+	}
480
+
481
+	if err != nil {
454 482
 		fmt.Fprintf(cli.out, "Failed to sign %q:%s - %s\n", repoInfo.FullName(), tag, err.Error())
455 483
 		return notaryError(repoInfo.FullName(), err)
456 484
 	}
457 485
 
458
-	keys := repo.CryptoService.ListKeys(data.CanonicalRootRole)
486
+	fmt.Fprintf(cli.out, "Successfully signed %q:%s\n", repoInfo.FullName(), tag)
487
+	return nil
488
+}
459 489
 
460
-	var rootKeyID string
461
-	// always select the first root key
462
-	if len(keys) > 0 {
463
-		sort.Strings(keys)
464
-		rootKeyID = keys[0]
465
-	} else {
466
-		rootPublicKey, err := repo.CryptoService.Create(data.CanonicalRootRole, data.ECDSAKey)
467
-		if err != nil {
468
-			return err
490
+// Attempt to add the image target to all the top level delegation roles we can
491
+// (based on whether we have the signing key and whether the role's path allows
492
+// us to).
493
+// If there are no delegation roles, we add to the targets role.
494
+func (cli *DockerCli) addTargetToAllSignableRoles(repo *client.NotaryRepository, target *client.Target) error {
495
+	var signableRoles []string
496
+
497
+	// translate the full key names, which includes the GUN, into just the key IDs
498
+	allCanonicalKeyIDs := make(map[string]string)
499
+	for fullKeyID := range repo.CryptoService.ListAllKeys() {
500
+		allCanonicalKeyIDs[path.Base(fullKeyID)] = ""
501
+	}
502
+
503
+	allDelegationRoles, err := repo.GetDelegationRoles()
504
+	if err != nil {
505
+		return err
506
+	}
507
+
508
+	for _, delegationRole := range allDelegationRoles {
509
+		// We do not support signing any delegation role that isn't a direct child of the targets role.
510
+		// Also don't bother checking the keys if we can't add the target
511
+		// to this role due to path restrictions
512
+		if path.Dir(delegationRole.Name) != data.CanonicalTargetsRole || !delegationRole.CheckPaths(target.Name) {
513
+			fmt.Println("skipping", delegationRole.Name)
514
+			continue
515
+		}
516
+
517
+		for _, canonicalKeyID := range delegationRole.KeyIDs {
518
+			if _, ok := allCanonicalKeyIDs[canonicalKeyID]; ok {
519
+				signableRoles = append(signableRoles, delegationRole.Name)
520
+			}
469 521
 		}
470
-		rootKeyID = rootPublicKey.ID()
471 522
 	}
472 523
 
473
-	// Initialize the notary repository with a remotely managed snapshot key
474
-	if err := repo.Initialize(rootKeyID, data.CanonicalSnapshotRole); err != nil {
475
-		return notaryError(repoInfo.FullName(), err)
524
+	if len(allDelegationRoles) > 0 && len(signableRoles) == 0 {
525
+		return fmt.Errorf("no valid signing keys for delegation roles")
476 526
 	}
477
-	fmt.Fprintf(cli.out, "Finished initializing %q\n", repoInfo.FullName())
478 527
 
479
-	return notaryError(repoInfo.FullName(), repo.Publish())
528
+	return repo.AddTarget(target, signableRoles...)
480 529
 }
... ...
@@ -497,23 +497,29 @@ func (s *DockerTrustSuite) TestTrustedPushWithExpiredTimestamp(c *check.C) {
497 497
 	})
498 498
 }
499 499
 
500
-func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegation(c *check.C) {
500
+func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) {
501 501
 	testRequires(c, NotaryHosting)
502
-	repoName := fmt.Sprintf("%v/dockerclireleasedelegation/trusted", privateRegistryURL)
502
+	repoName := fmt.Sprintf("%v/dockerclireleasedelegationinitfirst/trusted", privateRegistryURL)
503 503
 	targetName := fmt.Sprintf("%s:latest", repoName)
504 504
 	pwd := "12345678"
505
-	s.setupDelegations(c, repoName, pwd)
505
+	s.notaryInitRepo(c, repoName, pwd)
506
+	s.notaryCreateDelegation(c, repoName, pwd, "targets/releases", s.not.keys[0].Public)
507
+	s.notaryPublish(c, repoName, pwd)
508
+
509
+	s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private)
506 510
 
507 511
 	// tag the image and upload it to the private registry
508 512
 	dockerCmd(c, "tag", "busybox", targetName)
509 513
 
510
-	pushCmd := exec.Command(dockerBinary, "-D", "push", targetName)
514
+	pushCmd := exec.Command(dockerBinary, "push", targetName)
511 515
 	s.trustedCmdWithPassphrases(pushCmd, pwd, pwd)
512 516
 	out, _, err := runCommandWithOutput(pushCmd)
513 517
 	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
514 518
 	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
515 519
 
516 520
 	// Try pull after push
521
+	os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust"))
522
+
517 523
 	pullCmd := exec.Command(dockerBinary, "pull", targetName)
518 524
 	s.trustedCmd(pullCmd)
519 525
 	out, _, err = runCommandWithOutput(pullCmd)
... ...
@@ -521,13 +527,113 @@ func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegation(c *check.C) {
521 521
 	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
522 522
 
523 523
 	// check to make sure that the target has been added to targets/releases and not targets
524
-	contents, err := ioutil.ReadFile(filepath.Join(cliconfig.ConfigDir(), "trust/tuf", repoName, "metadata/targets.json"))
525
-	c.Assert(err, check.IsNil, check.Commentf("Unable to read targets metadata"))
526
-	c.Assert(strings.Contains(string(contents), `"latest"`), checker.False, check.Commentf(string(contents)))
524
+	s.assertTargetInDelegationRoles(c, repoName, "latest", "targets/releases")
525
+}
526
+
527
+func (s *DockerTrustSuite) TestTrustedPushSignsAllFirstLevelRolesWeHaveKeysFor(c *check.C) {
528
+	testRequires(c, NotaryHosting)
529
+	repoName := fmt.Sprintf("%v/dockerclimanyroles/trusted", privateRegistryURL)
530
+	targetName := fmt.Sprintf("%s:latest", repoName)
531
+	pwd := "12345678"
532
+	s.notaryInitRepo(c, repoName, pwd)
533
+	s.notaryCreateDelegation(c, repoName, pwd, "targets/role1", s.not.keys[0].Public)
534
+	s.notaryCreateDelegation(c, repoName, pwd, "targets/role2", s.not.keys[1].Public)
535
+	s.notaryCreateDelegation(c, repoName, pwd, "targets/role3", s.not.keys[2].Public)
536
+
537
+	// import everything except the third key
538
+	s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private)
539
+	s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private)
540
+
541
+	s.notaryCreateDelegation(c, repoName, pwd, "targets/role1/subrole", s.not.keys[3].Public)
542
+	s.notaryImportKey(c, repoName, "targets/role1/subrole", s.not.keys[3].Private)
543
+
544
+	s.notaryPublish(c, repoName, pwd)
545
+
546
+	// tag the image and upload it to the private registry
547
+	dockerCmd(c, "tag", "busybox", targetName)
548
+
549
+	pushCmd := exec.Command(dockerBinary, "push", targetName)
550
+	s.trustedCmdWithPassphrases(pushCmd, pwd, pwd)
551
+	out, _, err := runCommandWithOutput(pushCmd)
552
+	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
553
+	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
554
+
555
+	// Try pull after push
556
+	os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust"))
557
+
558
+	pullCmd := exec.Command(dockerBinary, "pull", targetName)
559
+	s.trustedCmd(pullCmd)
560
+	out, _, err = runCommandWithOutput(pullCmd)
561
+	c.Assert(err, check.IsNil, check.Commentf(out))
562
+	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
563
+
564
+	// check to make sure that the target has been added to targets/role1 and targets/role2, and
565
+	// not targets (because there are delegations) or targets/role3 (due to missing key) or
566
+	// targets/role1/subrole (due to it being a second level delegation)
567
+	s.assertTargetInDelegationRoles(c, repoName, "latest", "targets/role1", "targets/role2")
568
+}
569
+
570
+func (s *DockerTrustSuite) TestTrustedPushSignsForRolesWithKeysAndValidPaths(c *check.C) {
571
+	repoName := fmt.Sprintf("%v/dockerclirolesbykeysandpaths/trusted", privateRegistryURL)
572
+	targetName := fmt.Sprintf("%s:latest", repoName)
573
+	pwd := "12345678"
574
+	s.notaryInitRepo(c, repoName, pwd)
575
+	s.notaryCreateDelegation(c, repoName, pwd, "targets/role1", s.not.keys[0].Public, "l", "z")
576
+	s.notaryCreateDelegation(c, repoName, pwd, "targets/role2", s.not.keys[1].Public, "x", "y")
577
+	s.notaryCreateDelegation(c, repoName, pwd, "targets/role3", s.not.keys[2].Public, "latest")
578
+	s.notaryCreateDelegation(c, repoName, pwd, "targets/role4", s.not.keys[3].Public, "latest")
527 579
 
528
-	contents, err = ioutil.ReadFile(filepath.Join(cliconfig.ConfigDir(), "trust/tuf", repoName, "metadata/targets/releases.json"))
529
-	c.Assert(err, check.IsNil, check.Commentf("Unable to read targets/releases metadata"))
530
-	c.Assert(string(contents), checker.Contains, `"latest"`, check.Commentf(string(contents)))
580
+	// import everything except the third key
581
+	s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private)
582
+	s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private)
583
+	s.notaryImportKey(c, repoName, "targets/role4", s.not.keys[3].Private)
584
+
585
+	s.notaryPublish(c, repoName, pwd)
586
+
587
+	// tag the image and upload it to the private registry
588
+	dockerCmd(c, "tag", "busybox", targetName)
589
+
590
+	pushCmd := exec.Command(dockerBinary, "push", targetName)
591
+	s.trustedCmdWithPassphrases(pushCmd, pwd, pwd)
592
+	out, _, err := runCommandWithOutput(pushCmd)
593
+	c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
594
+	c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
595
+
596
+	// Try pull after push
597
+	os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust"))
598
+
599
+	pullCmd := exec.Command(dockerBinary, "pull", targetName)
600
+	s.trustedCmd(pullCmd)
601
+	out, _, err = runCommandWithOutput(pullCmd)
602
+	c.Assert(err, check.IsNil, check.Commentf(out))
603
+	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
604
+
605
+	// check to make sure that the target has been added to targets/role1 and targets/role4, and
606
+	// not targets (because there are delegations) or targets/role2 (due to path restrictions) or
607
+	// targets/role3 (due to missing key)
608
+	s.assertTargetInDelegationRoles(c, repoName, "latest", "targets/role1", "targets/role4")
609
+}
610
+
611
+func (s *DockerTrustSuite) TestTrustedPushDoesntSignTargetsIfDelegationsExist(c *check.C) {
612
+	testRequires(c, NotaryHosting)
613
+	repoName := fmt.Sprintf("%v/dockerclireleasedelegationnotsignable/trusted", privateRegistryURL)
614
+	targetName := fmt.Sprintf("%s:latest", repoName)
615
+	pwd := "12345678"
616
+	s.notaryInitRepo(c, repoName, pwd)
617
+	s.notaryCreateDelegation(c, repoName, pwd, "targets/role1", s.not.keys[0].Public)
618
+	s.notaryPublish(c, repoName, pwd)
619
+
620
+	// do not import any delegations key
621
+
622
+	// tag the image and upload it to the private registry
623
+	dockerCmd(c, "tag", "busybox", targetName)
624
+
625
+	pushCmd := exec.Command(dockerBinary, "push", targetName)
626
+	s.trustedCmdWithPassphrases(pushCmd, pwd, pwd)
627
+	out, _, err := runCommandWithOutput(pushCmd)
628
+	c.Assert(err, check.Not(check.IsNil), check.Commentf("trusted push succeed but should have failed:\n%s", out))
629
+	c.Assert(out, checker.Contains, "no valid signing keys",
630
+		check.Commentf("Missing expected output on trusted push without keys"))
531 631
 }
532 632
 
533 633
 func (s *DockerRegistryAuthHtpasswdSuite) TestPushNoCredentialsNoRetry(c *check.C) {
534 634
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+-----BEGIN CERTIFICATE-----
1
+MIID8jCCAtqgAwIBAgIJAJkxr+7rAgXbMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
2
+BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G
3
+A1UEChMGRG9ja2VyMRMwEQYDVQQDEwpkZWxlZ2F0aW9uMCAXDTE2MDMwODAyNDEy
4
+MFoYDzIxMTYwMjEzMDI0MTIwWjBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
5
+FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoTBkRvY2tlcjETMBEGA1UE
6
+AxMKZGVsZWdhdGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJuz
7
+To1qoL/RY5pNxdPkP/jiO3f/RTvz20C90EweaKgRdIV/vTUUE+mMRQulpf1vpCP9
8
+uidGfEoJcq4jM1H59XTYUoUvGbAMP3Iu7Uz0rF5v+Glm82Z0WGI+PkOnwRN2bJi4
9
+LhAch6QlA/48IOFH/O9jnHYMb45lQFpm+gOvatRyGkPZCftD3ntkhVMk1OJ7EZC4
10
+LYiwzmuPEYusO/qVgcHkGtIxLWAjGmDzrV3Q5orPVwwUOxNQdRRU1L2bhfUsodcb
11
+Fgi/LCz4xnGx4YpF0O24Y7/0SPotSyaT0RYyj/j/bIKvYB20g4P7469klde1Ariz
12
+UEIf12PlaJ/H/PaIlEcCAwEAAaOBvDCBuTAdBgNVHQ4EFgQUXZK4ZGswIq54W4VZ
13
+OJY7zXvvndwwgYkGA1UdIwSBgTB/gBRdkrhkazAirnhbhVk4ljvNe++d3KFcpFow
14
+WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNp
15
+c2NvMQ8wDQYDVQQKEwZEb2NrZXIxEzARBgNVBAMTCmRlbGVnYXRpb26CCQCZMa/u
16
+6wIF2zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQA2ktnjxB2lXF+g
17
+lTc2qp9LhjofgCWKwLgWEeCwXI2nUBNE4n00hA9or2wer2viWC4IJnG0kTyMzzYT
18
+m1lBpZ8BP6S3sSkvhohaqS+gBIUVB7U65tAof/SY2UHpeVJ1YpTE4F1GAUfqSY7V
19
+6IGHZAGiLeUS5kC6pzZA4siBhyCoYKRKEb9R82jSCHeFYS3ntwY1/gqcO/uIidVE
20
+2hLHlx6vBx9BEfXv31AGLoB3YocSTZLATwlrDHUQG1+oNh5ejQU1x/z+Y62EG5Jb
21
+u0yLDdJeSgup/DzPEoNpSihtdQZytKMK+KBmh22gDA5h+a6620zTZwCvJYxH9kkM
22
+IClUWwuD
23
+-----END CERTIFICATE-----
0 24
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+-----BEGIN RSA PRIVATE KEY-----
1
+MIIEowIBAAKCAQEAm7NOjWqgv9Fjmk3F0+Q/+OI7d/9FO/PbQL3QTB5oqBF0hX+9
2
+NRQT6YxFC6Wl/W+kI/26J0Z8SglyriMzUfn1dNhShS8ZsAw/ci7tTPSsXm/4aWbz
3
+ZnRYYj4+Q6fBE3ZsmLguEByHpCUD/jwg4Uf872OcdgxvjmVAWmb6A69q1HIaQ9kJ
4
++0Pee2SFUyTU4nsRkLgtiLDOa48Ri6w7+pWBweQa0jEtYCMaYPOtXdDmis9XDBQ7
5
+E1B1FFTUvZuF9Syh1xsWCL8sLPjGcbHhikXQ7bhjv/RI+i1LJpPRFjKP+P9sgq9g
6
+HbSDg/vjr2SV17UCuLNQQh/XY+Von8f89oiURwIDAQABAoIBAB7DhfDRMaPU5n41
7
+gbIFNlKhuKhUCsT2wMqA9qgjlgAnOsOp4qObLPgHXBkaCLsTlPX7iw15ktM6HKul
8
+jt1SqxoEKAHitYugT+Tqur5q1afvLcD9s3f54wC+VaUefzquOnTOZ2ONj4tyOODB
9
+1qlMhQBzyRVWDbCv9tAl6p5RyaTh+8IULctlER6w9m3upT9NxoRi1PrPBCRiEKKo
10
+4zDRvfbT/0ucLD20GS6trPv4ihTCTU7ydFujioDkFyNzCzYNGBnImpQ9/xeT5/Ys
11
+IJQy9Tdn6V0rXMBBb1EhyBQYw5Oxy6d6tzhjvva6LaJBGo9yzX0NHt58Ymhgm1q/
12
+vscj1pECgYEAyegQFP7dkmUdXdNpdrIdCvKlvni3r/hwB/9H0sJHIJbfTusfzeLL
13
+5Q8QSZAsaR7tSgJfr9GMdOjntvefYjKLfl3SnG/wF91m05eYfkeiZXc9RGe+XXGu
14
+wv5u2m/G7a05XpW1JFX+1ORyj2x5KsvF7KDtWJyR5ryIsOwHZNGQpJ8CgYEAxWoo
15
+r2eJBc9Xj5bhhS0VxUFODXImfeQF2aG2rSeuWMY7k4vmVkJwhBZiPW/dHBu1aMPh
16
+/SY1W7cgzdVIf2RIF5MgzzkmoisEApZTiSwmP6A2bTx6miXwFCLTCHIDfiXJ0tQA
17
+Nb+Ln+exks4BfCgKHOqWTcWizKNE/8Gb6SnhB1kCgYAgM1Z9QrhrpJyuXg0v1PA0
18
+0sYEPpRtCB416Ey4HCvj0qwClhUYbNc/zMs4MDok+b22U/KWw8C21H4/+/X7XzxI
19
+BwaT1HZiF/lSPZcgbKRFsmKfCjyeAodwqctcIv+C4GGJ6C5fgSeHJHfwz8fzP1Rt
20
+jKzNuQq71c2nCb2UIqgC2QKBgEieoJDFmVYVy7P6YMNIrnV9bGTt1NMCilRgdH6F
21
+1lC5uzivge/BSPqN8V2AROoOF1GOnRcucvpmBx8wkhaqoQprCOqxr1CAWl1JRzly
22
+kC9flCXi1YbW5dXCabb1metRo0h2zAz5hTcxV9UVCt7NK8svUFMTnKuCc+NRKTVA
23
+PpMhAoGBAJ9rFgZpWHRVuzsangbGslq3fDYGENLJ2fPNjLgfgVLi+YotG9jfgQPW
24
+QCvoSA1CChxzEJEB5hzEOEv9pThnBNg1LWNj+a3N5anW2UBHMEWeCrVFZwJMVdSd
25
+srUFtap7da8iUddc+sHC5hHHFDBdqG4pDck/uTs3CNWRF/ZqzE/G
26
+-----END RSA PRIVATE KEY-----
0 27
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+-----BEGIN CERTIFICATE-----
1
+MIID8jCCAtqgAwIBAgIJAMi/AxlwFquJMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
2
+BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G
3
+A1UEChMGRG9ja2VyMRMwEQYDVQQDEwpkZWxlZ2F0aW9uMCAXDTE2MDMwODAyNDEy
4
+MloYDzIxMTYwMjEzMDI0MTIyWjBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
5
+FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoTBkRvY2tlcjETMBEGA1UE
6
+AxMKZGVsZWdhdGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL/a
7
+1GO+02jt1p0sME+YGaK4+uZ9jezrpkCXKMsMfItgqCKRTX7YVuR7tnRt/Y1DNVqR
8
+nMeGc77soDag6eW4xrYrv9LwylUsOLanvK1d/8hDxZhzJjqlJBmz6BvLWDZUF9uu
9
+OjULL8yuP2cmRogjn0bqmdeKztrZtDQqQiwsG02nVjfuvVi3rP4G4DhL5fUoHB0R
10
+E6L9Su3/2OWGpdxZqkT7GAbjgLl4/4CXs00493m8xZIHXQ9559PiVlLfk6p6FjEV
11
+7irZp7XXSe1My/0HGebFXkYqEL9+My2od4w+qJmBT23aTduGTo8IZC7g9lwKEykA
12
+hWrYhR5tjkLvOsQIE7ECAwEAAaOBvDCBuTAdBgNVHQ4EFgQUHtEAVcwI3k7W5B6c
13
+L3w+eKQRsIYwgYkGA1UdIwSBgTB/gBQe0QBVzAjeTtbkHpwvfD54pBGwhqFcpFow
14
+WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNp
15
+c2NvMQ8wDQYDVQQKEwZEb2NrZXIxEzARBgNVBAMTCmRlbGVnYXRpb26CCQDIvwMZ
16
+cBariTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAfjsMtZ+nJ7y5t
17
+rH9xPwWMLmtC5MwzDRvTUAGbNbFwwm8AncfvsDmmERqsr8L2qhY8CZ9vsN4NjjBn
18
+QRmM/ynYA8JTbf/5ZNDnD4D6qTXLgGFqyHcBaorcB9uQ8eiMOFAbhxLYfPrKaYdV
19
+qj+MejcFa3HmzmYCSqsvxRhSje5b4sORe9/3jNheXsX8VZUpWtCHc3k4GiCU6KyS
20
+gpnXkShU4sG92cK72L8pxmGTz8ynNMj/9WKkLxpNIv5u0/D01a3z4wx5k1zfRZiz
21
+IQS+xqxV/ztY844MDknxENlYzcqGj0Fd6hE5OKZxnGaH83A5adldMLlnhG1rscGP
22
+as9uwPYP
23
+-----END CERTIFICATE-----
0 24
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+-----BEGIN RSA PRIVATE KEY-----
1
+MIIEpAIBAAKCAQEAv9rUY77TaO3WnSwwT5gZorj65n2N7OumQJcoywx8i2CoIpFN
2
+fthW5Hu2dG39jUM1WpGcx4ZzvuygNqDp5bjGtiu/0vDKVSw4tqe8rV3/yEPFmHMm
3
+OqUkGbPoG8tYNlQX2646NQsvzK4/ZyZGiCOfRuqZ14rO2tm0NCpCLCwbTadWN+69
4
+WLes/gbgOEvl9SgcHRETov1K7f/Y5Yal3FmqRPsYBuOAuXj/gJezTTj3ebzFkgdd
5
+D3nn0+JWUt+TqnoWMRXuKtmntddJ7UzL/QcZ5sVeRioQv34zLah3jD6omYFPbdpN
6
+24ZOjwhkLuD2XAoTKQCFatiFHm2OQu86xAgTsQIDAQABAoIBAQCDdASic1WXR58N
7
+AgH4B1dJT0VaOBzOgIfhKbEhruSG+ys4xCY9Cy4+TyWskNBxweMEs1CgxVb5Mlh0
8
+Fb0tUXWVzFQazDFWOn6BaFy2zPk81nLFCeDfvdcGZWZb5PAECYpvUuk+/vM5Ywq+
9
+OlOJZB72EDhonwssmI4IUAwXCAGNKjLfC4L+3ZgA3+I1xgxisJ2XWNYSLwHzIDRh
10
+U3zO2NpJi1edTNPltDBTb4iFhajX0SFgbARc+XVTpA3pgQujWo6CNB5YKCPuzIqr
11
+GFsvGSZDVzOUnfOlitaYNW+QIWAQf8VLWULwyFrS5Cb2WR/k7AmojZVuDHvzWrtg
12
+ZMG6b1mBAoGBAOV+3SiX8+khKBpxnOJLq0XlGjFNDWNNB34UIMVkFehRxpUr2261
13
+HDp4YiC9n7l47sjeFBk4IQf2vG/5MPpuqIixsk2W3siCASdMQypVZMG+zj6xDFfH
14
+8rwQSeZhwjmk2a+A7qgnhqvd/qa7EYOnsn1tLf2iBB2EaHV9lWBJFX0lAoGBANYD
15
+GbAPEiwh4Fns8pf59T3Lp0Q9XvAN3uh4DUU0mFrQ1HQHeXIw1IDCJ9JiRjLX7aHu
16
+79EtDssVPQ9dv0MN5rRULtrutCfRLsomm385PLLBIgBdVApnVvJJIWhQkFFMrhFt
17
+UP+483utiDOcCVXMxAy+1jx23EiWvl2H0xGIwsSdAoGBAMIcM+OJ4vxk1w7G2fNu
18
+HUfZJ/ZbPd+n35Z8X9uVdBI0WMsDdW6GMYIjIJygxuCRsSak8EsEdqvNvkTXeN3Z
19
+iyNTaYTG/1iI3YDnuEeuQrK9OKU+CzqUHHOFM3xxY15uWNFhNHt2MypbcnCD+aRp
20
+y0bbefL1fpWY0OHPfvEZ39shAoGAPbVdJc/irIkEGMni1YGEflIHo/ySMGO/f4aG
21
+RQs6Vw1aBS7WjN+ZlprlQpuFpElwwr2TttvoJRS1q4WbjakneZ3AeO5VUhnWBQIG
22
+2jNV1jEsLbC7d9h+UJRXpq18P4T9uBauQV5CDspluIPoiS3m5cntGjgnomKc93kf
23
+mjG1/10CgYA7kgOOva64sjWakL/IgDRiwr0YrJkAfPUZYwxYLHuiW9izUgngpqWd
24
+1wtq+YCsc4l7t8u9Tahb8OE0KSN5RC6QM6b8yW9qFDZ68QAX00+sN6di4qyAZlm+
25
+rK05W/3JmyvQbvO+JVRQtegZ1ExCj7LGuGOQ5KIpWsBEM3ic9ZP9gw==
26
+-----END RSA PRIVATE KEY-----
0 27
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+-----BEGIN CERTIFICATE-----
1
+MIID8jCCAtqgAwIBAgIJAI3uONxeFQJtMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
2
+BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G
3
+A1UEChMGRG9ja2VyMRMwEQYDVQQDEwpkZWxlZ2F0aW9uMCAXDTE2MDMwODAyNDEy
4
+NFoYDzIxMTYwMjEzMDI0MTI0WjBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
5
+FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoTBkRvY2tlcjETMBEGA1UE
6
+AxMKZGVsZWdhdGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOii
7
+Ij01MkSExgurs5owUNxNgRvrZFxNSNGfnscYZiaT/wNcocrOz40vvY29SOBEbCSW
8
+oBlCi0rYu/7LZBqvsP3YItmifpJHGfRiZ6xEQ4rKznY8+8E3FHVChlmVv9x6QPhA
9
+9OpATlSLvcdiXHbohdc+kQsl9qM93+QadRQLmtZ6H5Sv90d1MHNViX+8d/k2WyT0
10
+8u6fNv0ZHeltnZFYruF82YKJCOPdAJnCLUOXWRSG6xDhhvSewjxz6gFla5n8m+D9
11
+jvmIUUjoMEhjORUIVeA/lXT0AT3Lx0xE8uyhJQbp+hGtcPCcwYFZdz3yLcrxKO47
12
+nh6qOygf7I2fiR1ogqECAwEAAaOBvDCBuTAdBgNVHQ4EFgQUUqsFJdVoos2aewDh
13
+m1r66zyXeI4wgYkGA1UdIwSBgTB/gBRSqwUl1WiizZp7AOGbWvrrPJd4jqFcpFow
14
+WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNp
15
+c2NvMQ8wDQYDVQQKEwZEb2NrZXIxEzARBgNVBAMTCmRlbGVnYXRpb26CCQCN7jjc
16
+XhUCbTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQADcyno8/AwNatf
17
+pjgILCZl1DVrqaKEVbp6ciNgVRCF4cM0bE5W4mjd5tO8d3/yTilry2FPicqxiMps
18
+oGroMFR+X1cZbOf0U32FyEW4EyWm2jjbiuEpnM5J/EeB/QfckqP6whS/QAM7PxDV
19
+Sxd8sKDb9SOGZiickFU4QpG1fdmY/knrrtbzRl7Nk/3tBgRaq+Brg7YNZZKlpUNB
20
+Hp3q0E+MFgVAojpcL7w1oSgoNev+cUNaBdPEmWIEi7F5rosCzmAIhuIY+ghmo9Qg
21
+zy+byAcxLpujl8vZvE1nZKMKZ7oJayOOgjB2Ztk6bO1r+GPtK5VfqEPhKTRDbBlo
22
+xS3tSCDJ
23
+-----END CERTIFICATE-----
0 24
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+-----BEGIN RSA PRIVATE KEY-----
1
+MIIEpAIBAAKCAQEA6KIiPTUyRITGC6uzmjBQ3E2BG+tkXE1I0Z+exxhmJpP/A1yh
2
+ys7PjS+9jb1I4ERsJJagGUKLSti7/stkGq+w/dgi2aJ+kkcZ9GJnrERDisrOdjz7
3
+wTcUdUKGWZW/3HpA+ED06kBOVIu9x2JcduiF1z6RCyX2oz3f5Bp1FAua1noflK/3
4
+R3Uwc1WJf7x3+TZbJPTy7p82/Rkd6W2dkViu4XzZgokI490AmcItQ5dZFIbrEOGG
5
+9J7CPHPqAWVrmfyb4P2O+YhRSOgwSGM5FQhV4D+VdPQBPcvHTETy7KElBun6Ea1w
6
+8JzBgVl3PfItyvEo7jueHqo7KB/sjZ+JHWiCoQIDAQABAoIBADvh8HpdBTGKFAjR
7
+DAx2v3nWIZP0RgNUiZgcRJzvdOwdUJmm8KbqEZdAYMTpoqbINiY8971I2d5MaCgw
8
+ZvZPn3nYdzAamgZBczbrVdCMSe6iQf9Bt3SHHycIFtlcqOSyO6Mr5V+fagptZk66
9
+zR52wG0l1+RMw25F8SogfV7JlfP7Qh5Bob0lEN2xpbhwLiNaaB+IHNe0FelmRvmJ
10
+VUonoD0xaos25EXUES7J/9coiBqgRlDVHdUM0oaa/94UnxNPJnoNfte0yd+mC4LZ
11
+JVHo0Zti3x/8SiCYMbLQs5L8AL8VtPu9OPfur/J8+9Rv0Rh+L1Ben+JWzCzUw1Cj
12
+abH1zvkCgYEA9Q06Lu69ZLD31fTv46CphN+dGS/VgvMELkob6VQOhbV3RPhe6vqL
13
+p7D67J53iq4rZY5KX3zuXZ+A5s48atc8gz+hTsrE022QVXmO2ZrE22bEpL+mwpsB
14
+8//ul1UG51XTw6YR9CmLLD3Y4BgMjhSllx4Wwr9e9+PKl+DuSreqhxMCgYEA8wbf
15
+P3zh85jPN92gBG8+VIbVlXYOTK0OllYUoLt4URmLRllmrB6LyRlpODCyb9+JymMg
16
+WvAq5Bc0h8gMbSQEkYaAUq2CfSbyExASUHA+/nZglsTZhPkg5PJImntK6S58KAM7
17
+RJzyz20gxYA5H4KXFSiF+ONOE9X/cFUPxzF1AfsCgYBfgUY54GYEBkyxIIMWDhnD
18
+ZXtOw6vNG3V3rP5v04jNZ8oSIVKs9fTT6FADREeGzxauv+QQjxo/dtjAG4TEhxpY
19
+dMYjdTd8x2jHR1b7TCyI7eaZ5u/RTKRYOlj8tfC43GRqDiFVLZPGLFyIChdqkHVx
20
+DhME15zls+vTgaCdkjNt7QKBgQCfwDywNx8wSZqtVnoBcD7AwYFUpi3wKTIVkLAu
21
+mA0XAnuS2uGq8slgf9uynBAvifnBmDeEj6siFD7roozIkYyPPKLNtlC4hAlMjpv7
22
+VE2UZ6xGb0+tITaGSN2A7trnPS9P/g/PonvZ7hpEuWzTUbyOo/ytBn4ke99VsBSX
23
+E+OeUQKBgQCgmcwCj2/IH+GOpe9qAG6MTMKK7k22O8fBCrcDybL1pMWIesJEbzpv
24
+T5Atcx9L5ff6Q4Ysghb8ebXsErv4oZ72xyAwWJmbIaPllWn2ffUikzL3grSriWZy
25
+0bz6P9sRqYpbdmX3oVvTfBP5kbv+mtDXOB3h5rGfczKWNMyuZmxDOg==
26
+-----END RSA PRIVATE KEY-----
0 27
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+-----BEGIN CERTIFICATE-----
1
+MIID8jCCAtqgAwIBAgIJAKKDRMrryBRKMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
2
+BAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEPMA0G
3
+A1UEChMGRG9ja2VyMRMwEQYDVQQDEwpkZWxlZ2F0aW9uMCAXDTE2MDMwODAyNDEy
4
+N1oYDzIxMTYwMjEzMDI0MTI3WjBYMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
5
+FjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xDzANBgNVBAoTBkRvY2tlcjETMBEGA1UE
6
+AxMKZGVsZWdhdGlvbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOCf
7
+Wfff5mX/ko/Y790O04eR7h8/4YtZU3LFItcjhkphMf2V2BRlhWwwW6v96gTN1xsZ
8
+1il6/YXjviWiLjhrtOVLQBE2yK0A7Wwdh9KJg3QgNqwtFrR1MA1LgWto1F7NyEMC
9
+9H6Hc95+bgWx1jN0IflfPh1C1m/sA5xGqHDl+8YzJJUOoa5bh04Yk3aIeecatso/
10
+z7P5c6KicPcZIjhgjxHYB95It/oj8ZuY0hQZb7B5HEGNyBbT2F0vuElWtp+mXexr
11
+6mzgzvHgaKG36bNCTLxr8BxGA/sbVn01LyI3wpk2uqWzyUFk21M4g2X46OPgKrh7
12
+2h5b+C0X8DUPi45djHcCAwEAAaOBvDCBuTAdBgNVHQ4EFgQUKcrfRFg+6o2l4xbt
13
+Ll6hV9pjJh8wgYkGA1UdIwSBgTB/gBQpyt9EWD7qjaXjFu0uXqFX2mMmH6FcpFow
14
+WDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNp
15
+c2NvMQ8wDQYDVQQKEwZEb2NrZXIxEzARBgNVBAMTCmRlbGVnYXRpb26CCQCig0TK
16
+68gUSjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAhdKgYUQ36JSPS
17
+f3Dws09pM5hzSsSae4+nG9XckX6dVQ7sLKmjeeeLrXuzjfygir/+h9cHyShgXFH4
18
+ZbGpdzf6APG1KRag3/njqEWi+kKZZduxZKvI2EHJhj1xBtf8Qru0TgS7bHPlp9bl
19
+1/61+aIrtj05LQhqzWzehuJFrmSdWP9cnNbvlPdOdgfgkKakAiLGwwGNvMQbqxaO
20
+FIB4UPuPdQgm5bpimd5/CThKbpK9/0nr9K4po/m519nvEKxZzsDw5tefGp9Xqly3
21
+4pk9uyAxO/E2cL0cVA/WHTVTsHPbO7lXxBi6/EjiTUi0Nj1X+btO8+jCLkJyNY0m
22
+qaiL5k9h
23
+-----END CERTIFICATE-----
0 24
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+-----BEGIN RSA PRIVATE KEY-----
1
+MIIEpAIBAAKCAQEA4J9Z99/mZf+Sj9jv3Q7Th5HuHz/hi1lTcsUi1yOGSmEx/ZXY
2
+FGWFbDBbq/3qBM3XGxnWKXr9heO+JaIuOGu05UtAETbIrQDtbB2H0omDdCA2rC0W
3
+tHUwDUuBa2jUXs3IQwL0fodz3n5uBbHWM3Qh+V8+HULWb+wDnEaocOX7xjMklQ6h
4
+rluHThiTdoh55xq2yj/Ps/lzoqJw9xkiOGCPEdgH3ki3+iPxm5jSFBlvsHkcQY3I
5
+FtPYXS+4SVa2n6Zd7GvqbODO8eBoobfps0JMvGvwHEYD+xtWfTUvIjfCmTa6pbPJ
6
+QWTbUziDZfjo4+AquHvaHlv4LRfwNQ+Ljl2MdwIDAQABAoIBAQCrN2wZsFZr2zK5
7
+aS/0/Y8poIe01Dm0wWMFcdULzm1XltzHIgfyDCx2ein2YPaXsNtNMhV3yuMiwqU3
8
+BHdc1GSv/vsX4/11Oea/6YaVafKEeuWRulC7PzRgffRpjh+LICqNQdxh8hfVOePd
9
+fV/8GoKnFf0/yqmv6GQcJBPS8stGmFmjo4rkBGvBBMoiUtMYllQqdfH0DtpI24Jh
10
+nR3lZKAPECkAciV7/Lx6+CUEaNOML2XPbLv6EyRh+J/r80jwE8myzpO7R6I+KCzo
11
+R/xuBb/hrUh5Sd5YmuBMa6WfF9yqawTgmVvkpD9fkRusSPSQCq3oe+AugYWu6Fht
12
+XBiZlvjJAoGBAPPBuUaagaUgHyjIzjbRPBHDhSYJpgYR4l/jcypfrl+m0OFC5acA
13
+QG7Hr8AbStIPGtaJRn2pm8dNVPtFecPoi5jVWux2n5RqYlOnwY0tziuxbhU9GQ/W
14
+oCp+99TJSMHFep0E7IoDk8YSxyA/86qk/Tx7KkUUlXv4sjJts17ZHxstAoGBAOvn
15
+mF9rm8Y+Og17WlUQyf5j7g4soWG/4zMnoGpjocDfHVms/pASKbIBp5aFtDgWCmM5
16
+H7InptvBUInROHlooK6paJRDLbDgzVa/m+NLHoct7N25J4NiG8xV6Wv7hlrRp+XK
17
+zyWL8iL95GnB21HJKvEiVBWvOuZnqfVcnzhbmzyzAoGAYT46jMkcyWRMKfgaFFJa
18
+lXebybX1rtw5pClYC2KKbQxerk8C0SHPkqJFIe2BZtWxzj6LiZw9UkAuk+N+lUJT
19
+VpBfKpCUTyA1w8vb8leAtXueQAjU07W6xdlLQ29dgDgpFzUcrF6K+G0LVXlN2xjh
20
+EdzM2yxACmoHpQiQk1kpCK0CgYAz640Fs1FdmGR+gx+miUNr0eKbDAeY0/rVT2tm
21
+/vai1HhJPGHqo5S5sNOJtXOsxG0U2YW4WDHJPArVyk57qiNzTaXOu9pai5+l8BYH
22
+OIlHhzwSsKWZrQYhOudc9MblRi+Fy9U7lkl8mhSjkh8LKRNibwPCogZ8n2QwtGn2
23
+pXLNMQKBgQDxvs46CA0M9lGvpl0ggnC7bIYYUEvIlszlBh+o2CgF3IOFlGVcvCia
24
+r18i7hTM5wbcct9OWDzZG4ejBIhtE+gMQ333ofQ64PPJOcfuHxT3Z/fMWfv/yDEj
25
+4e4ZPK44ktcTvuusxAoSe5C5dbcNX2ymAhlRg/F0LyMkhw+qGh4xOQ==
26
+-----END RSA PRIVATE KEY-----
... ...
@@ -92,10 +92,10 @@ var (
92 92
 			// for now notary binary is built only if we're running inside
93 93
 			// container through `make test`. Figure that out by testing if
94 94
 			// notary-server binary is in PATH.
95
-			_, err := exec.LookPath(notaryBinary)
95
+			_, err := exec.LookPath(notaryServerBinary)
96 96
 			return err == nil
97 97
 		},
98
-		fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryBinary),
98
+		fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryServerBinary),
99 99
 	}
100 100
 	NotaryServerHosting = testRequirement{
101 101
 		func() bool {
... ...
@@ -12,19 +12,23 @@ import (
12 12
 	"time"
13 13
 
14 14
 	"github.com/docker/docker/cliconfig"
15
+	"github.com/docker/docker/pkg/integration/checker"
15 16
 	"github.com/docker/docker/pkg/tlsconfig"
16
-	"github.com/docker/notary/client"
17
-	"github.com/docker/notary/passphrase"
18
-	"github.com/docker/notary/tuf/data"
19 17
 	"github.com/go-check/check"
20 18
 )
21 19
 
22 20
 var notaryBinary = "notary"
23 21
 var notaryServerBinary = "notary-server"
24 22
 
23
+type keyPair struct {
24
+	Public  string
25
+	Private string
26
+}
27
+
25 28
 type testNotary struct {
26
-	cmd *exec.Cmd
27
-	dir string
29
+	cmd  *exec.Cmd
30
+	dir  string
31
+	keys []keyPair
28 32
 }
29 33
 
30 34
 const notaryHost = "localhost:4443"
... ...
@@ -90,6 +94,15 @@ func newTestNotary(c *check.C) (*testNotary, error) {
90 90
 		return nil, err
91 91
 	}
92 92
 
93
+	// load key fixture filenames
94
+	var keys []keyPair
95
+	for i := 1; i < 5; i++ {
96
+		keys = append(keys, keyPair{
97
+			Public:  filepath.Join(workingDir, fmt.Sprintf("fixtures/notary/delgkey%v.crt", i)),
98
+			Private: filepath.Join(workingDir, fmt.Sprintf("fixtures/notary/delgkey%v.key", i)),
99
+		})
100
+	}
101
+
93 102
 	// run notary-server
94 103
 	cmd := exec.Command(notaryServerBinary, "-config", confPath)
95 104
 	if err := cmd.Start(); err != nil {
... ...
@@ -101,8 +114,9 @@ func newTestNotary(c *check.C) (*testNotary, error) {
101 101
 	}
102 102
 
103 103
 	testNotary := &testNotary{
104
-		cmd: cmd,
105
-		dir: tmp,
104
+		cmd:  cmd,
105
+		dir:  tmp,
106
+		keys: keys,
106 107
 	}
107 108
 
108 109
 	// Wait for notary to be ready to serve requests.
... ...
@@ -220,33 +234,88 @@ func notaryClientEnv(cmd *exec.Cmd, rootPwd, repositoryPwd string) {
220 220
 	cmd.Env = append(os.Environ(), env...)
221 221
 }
222 222
 
223
-func (s *DockerTrustSuite) setupDelegations(c *check.C, repoName, pwd string) {
223
+func (s *DockerTrustSuite) notaryInitRepo(c *check.C, repoName, pwd string) {
224 224
 	initCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "init", repoName)
225 225
 	notaryClientEnv(initCmd, pwd, pwd)
226 226
 	out, _, err := runCommandWithOutput(initCmd)
227 227
 	if err != nil {
228 228
 		c.Fatalf("Error initializing notary repository: %s\n", out)
229 229
 	}
230
+}
230 231
 
231
-	// no command line for this, so build by hand
232
-	nRepo, err := client.NewNotaryRepository(filepath.Join(cliconfig.ConfigDir(), "trust"), repoName, notaryURL, nil, passphrase.ConstantRetriever(pwd))
233
-	if err != nil {
234
-		c.Fatalf("Error creating notary repository: %s\n", err)
235
-	}
236
-	delgKey, err := nRepo.CryptoService.Create("targets/releases", data.ECDSAKey)
237
-	if err != nil {
238
-		c.Fatalf("Error creating delegation key: %s\n", err)
232
+func (s *DockerTrustSuite) notaryCreateDelegation(c *check.C, repoName, pwd, role string, pubKey string, paths ...string) {
233
+	pathsArg := "--all-paths"
234
+	if len(paths) > 0 {
235
+		pathsArg = "--paths=" + strings.Join(paths, ",")
239 236
 	}
240
-	err = nRepo.AddDelegation("targets/releases", []data.PublicKey{delgKey}, []string{""})
237
+
238
+	delgCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"),
239
+		"delegation", "add", repoName, role, pubKey, pathsArg)
240
+	notaryClientEnv(delgCmd, pwd, pwd)
241
+	out, _, err := runCommandWithOutput(delgCmd)
241 242
 	if err != nil {
242
-		c.Fatalf("Error creating delegation: %s\n", err)
243
+		c.Fatalf("Error adding %s role to notary repository: %s\n", role, out)
243 244
 	}
245
+}
244 246
 
245
-	// publishing first simulates the client pushing to a repo that they have been given delegated access to
247
+func (s *DockerTrustSuite) notaryPublish(c *check.C, repoName, pwd string) {
246 248
 	pubCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "publish", repoName)
247 249
 	notaryClientEnv(pubCmd, pwd, pwd)
248
-	out, _, err = runCommandWithOutput(pubCmd)
250
+	out, _, err := runCommandWithOutput(pubCmd)
249 251
 	if err != nil {
250 252
 		c.Fatalf("Error publishing notary repository: %s\n", out)
251 253
 	}
252 254
 }
255
+
256
+func (s *DockerTrustSuite) notaryImportKey(c *check.C, repoName, role string, privKey string) {
257
+	impCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "key",
258
+		"import", privKey, "-g", repoName, "-r", role)
259
+	notaryClientEnv(impCmd, "", "")
260
+	out, _, err := runCommandWithOutput(impCmd)
261
+	if err != nil {
262
+		c.Fatalf("Error importing key to notary repository: %s\n", out)
263
+	}
264
+}
265
+
266
+func (s *DockerTrustSuite) notaryListTargetsInRoles(c *check.C, repoName, role string) map[string]string {
267
+	listCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "list",
268
+		repoName, "-r", role)
269
+	notaryClientEnv(listCmd, "", "")
270
+	out, _, err := runCommandWithOutput(listCmd)
271
+	if err != nil {
272
+		c.Fatalf("Error importing key to notary repository: %s\n", out)
273
+	}
274
+
275
+	// should look something like:
276
+	//    NAME                                 DIGEST                                SIZE (BYTES)    ROLE
277
+	// ------------------------------------------------------------------------------------------------------
278
+	//   latest   24a36bbc059b1345b7e8be0df20f1b23caa3602e85d42fff7ecd9d0bd255de56   1377           targets
279
+
280
+	lines := strings.Split(strings.TrimSpace(out), "\n")
281
+	c.Assert(len(lines), checker.GreaterOrEqualThan, 3)
282
+	targets := make(map[string]string)
283
+
284
+	for _, line := range lines[2:] {
285
+		tokens := strings.Fields(line)
286
+		c.Assert(tokens, checker.HasLen, 4)
287
+		targets[tokens[0]] = tokens[3]
288
+	}
289
+
290
+	return targets
291
+}
292
+
293
+func (s *DockerTrustSuite) assertTargetInDelegationRoles(c *check.C, repoName, target string, roles ...string) {
294
+	// assert it's not in the target role
295
+	targets := s.notaryListTargetsInRoles(c, repoName, "targets")
296
+	roleName, ok := targets[target]
297
+	c.Assert(ok, checker.True)
298
+	c.Assert(roleName, checker.Not(checker.Equals), "targets")
299
+
300
+	// check all the roles
301
+	for _, role := range roles {
302
+		targets := s.notaryListTargetsInRoles(c, repoName, role)
303
+		roleName, ok := targets[target]
304
+		c.Assert(ok, checker.True)
305
+		c.Assert(roleName, checker.Equals, role)
306
+	}
307
+}