diff --git a/api/client/trust.go b/api/client/trust.go index 32cfabee6f..39afe526d4 100644 --- a/api/client/trust.go +++ b/api/client/trust.go @@ -259,6 +259,11 @@ func (cli *DockerCli) trustedReference(ref reference.NamedTagged) (reference.Can if err != nil { return nil, err } + // Only list tags in the top level targets role or the releases delegation role - ignore + // all other delegation roles + if t.Role != releasesRole && t.Role != data.CanonicalTargetsRole { + return nil, notaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.Tag())) + } r, err := convertTarget(t.Target) if err != nil { return nil, err @@ -332,13 +337,27 @@ func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registr fmt.Fprintf(cli.out, "Skipping target for %q\n", repoInfo.Name()) continue } + // Only list tags in the top level targets role or the releases delegation role - ignore + // all other delegation roles + if tgt.Role != releasesRole && tgt.Role != data.CanonicalTargetsRole { + continue + } refs = append(refs, t) } + if len(refs) == 0 { + return notaryError(repoInfo.FullName(), fmt.Errorf("No trusted tags for %s", repoInfo.FullName())) + } } else { t, err := notaryRepo.GetTargetByName(ref.String(), releasesRole, data.CanonicalTargetsRole) if err != nil { return notaryError(repoInfo.FullName(), err) } + // Only get the tag if it's in the top level targets role or the releases delegation role + // ignore it if it's in any other delegation roles + if t.Role != releasesRole && t.Role != data.CanonicalTargetsRole { + return notaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.String())) + } + logrus.Debugf("retrieving target for %s role\n", t.Role) r, err := convertTarget(t.Target) if err != nil { @@ -496,9 +515,9 @@ func (cli *DockerCli) addTargetToAllSignableRoles(repo *client.NotaryRepository, var signableRoles []string // translate the full key names, which includes the GUN, into just the key IDs - allCanonicalKeyIDs := make(map[string]string) + allCanonicalKeyIDs := make(map[string]struct{}) for fullKeyID := range repo.CryptoService.ListAllKeys() { - allCanonicalKeyIDs[path.Base(fullKeyID)] = "" + allCanonicalKeyIDs[path.Base(fullKeyID)] = struct{}{} } allDelegationRoles, err := repo.GetDelegationRoles() @@ -506,6 +525,13 @@ func (cli *DockerCli) addTargetToAllSignableRoles(repo *client.NotaryRepository, return err } + // if there are no delegation roles, then just try to sign it into the targets role + if len(allDelegationRoles) == 0 { + return repo.AddTarget(target, data.CanonicalTargetsRole) + } + + // there are delegation roles, find every delegation role we have a key for, and + // attempt to sign into into all those roles. for _, delegationRole := range allDelegationRoles { // We do not support signing any delegation role that isn't a direct child of the targets role. // Also don't bother checking the keys if we can't add the target @@ -517,11 +543,12 @@ func (cli *DockerCli) addTargetToAllSignableRoles(repo *client.NotaryRepository, for _, canonicalKeyID := range delegationRole.KeyIDs { if _, ok := allCanonicalKeyIDs[canonicalKeyID]; ok { signableRoles = append(signableRoles, delegationRole.Name) + break } } } - if len(allDelegationRoles) > 0 && len(signableRoles) == 0 { + if len(signableRoles) == 0 { return fmt.Errorf("no valid signing keys for delegation roles") } diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index ad52222628..b11bfc1c78 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -5799,6 +5799,83 @@ func (s *DockerTrustSuite) TestBuildContextDirIsSymlink(c *check.C) { } } +func (s *DockerTrustSuite) TestTrustedBuildTagFromReleasesRole(c *check.C) { + testRequires(c, NotaryHosting) + + latestTag := s.setupTrustedImage(c, "trusted-build-releases-role") + repoName := strings.TrimSuffix(latestTag, ":latest") + + // Now create the releases role + s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) + s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) + s.notaryPublish(c, repoName) + + // push a different tag to the releases role + otherTag := fmt.Sprintf("%s:other", repoName) + dockerCmd(c, "tag", "busybox", otherTag) + + pushCmd := exec.Command(dockerBinary, "push", otherTag) + s.trustedCmd(pushCmd) + out, _, err := runCommandWithOutput(pushCmd) + c.Assert(err, check.IsNil, check.Commentf("Trusted push failed: %s", out)) + s.assertTargetInRoles(c, repoName, "other", "targets/releases") + s.assertTargetNotInRoles(c, repoName, "other", "targets") + + out, status := dockerCmd(c, "rmi", otherTag) + c.Assert(status, check.Equals, 0, check.Commentf("docker rmi failed: %s", out)) + + dockerFile := fmt.Sprintf(` + FROM %s + RUN [] + `, otherTag) + + name := "testtrustedbuildreleasesrole" + + buildCmd := buildImageCmd(name, dockerFile, true) + s.trustedCmd(buildCmd) + out, _, err = runCommandWithOutput(buildCmd) + c.Assert(err, check.IsNil, check.Commentf("Trusted build failed: %s", out)) + c.Assert(out, checker.Contains, fmt.Sprintf("FROM %s@sha", repoName)) +} + +func (s *DockerTrustSuite) TestTrustedBuildTagIgnoresOtherDelegationRoles(c *check.C) { + testRequires(c, NotaryHosting) + + latestTag := s.setupTrustedImage(c, "trusted-build-releases-role") + repoName := strings.TrimSuffix(latestTag, ":latest") + + // Now create a non-releases delegation role + s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[0].Public) + s.notaryImportKey(c, repoName, "targets/other", s.not.keys[0].Private) + s.notaryPublish(c, repoName) + + // push a different tag to the other role + otherTag := fmt.Sprintf("%s:other", repoName) + dockerCmd(c, "tag", "busybox", otherTag) + + pushCmd := exec.Command(dockerBinary, "push", otherTag) + s.trustedCmd(pushCmd) + out, _, err := runCommandWithOutput(pushCmd) + c.Assert(err, check.IsNil, check.Commentf("Trusted push failed: %s", out)) + s.assertTargetInRoles(c, repoName, "other", "targets/other") + s.assertTargetNotInRoles(c, repoName, "other", "targets") + + out, status := dockerCmd(c, "rmi", otherTag) + c.Assert(status, check.Equals, 0, check.Commentf("docker rmi failed: %s", out)) + + dockerFile := fmt.Sprintf(` + FROM %s + RUN [] + `, otherTag) + + name := "testtrustedbuildotherrole" + + buildCmd := buildImageCmd(name, dockerFile, true) + s.trustedCmd(buildCmd) + out, _, err = runCommandWithOutput(buildCmd) + c.Assert(err, check.NotNil, check.Commentf("Trusted build expected to fail: %s", out)) +} + // Issue #15634: COPY fails when path starts with "null" func (s *DockerSuite) TestBuildNullStringInAddCopyVolume(c *check.C) { name := "testbuildnullstringinaddcopyvolume" diff --git a/integration-cli/docker_cli_pull_trusted_test.go b/integration-cli/docker_cli_pull_trusted_test.go index 34261ff432..6bc38e699f 100644 --- a/integration-cli/docker_cli_pull_trusted_test.go +++ b/integration-cli/docker_cli_pull_trusted_test.go @@ -256,16 +256,17 @@ func (s *DockerTrustSuite) TestTrustedPullDelete(c *check.C) { } func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) { + testRequires(c, NotaryHosting) repoName := fmt.Sprintf("%v/dockerclireleasesdelegationpulling/trusted", privateRegistryURL) targetName := fmt.Sprintf("%s:latest", repoName) - pwd := "12345678" // Push with targets first, initializing the repo dockerCmd(c, "tag", "busybox", targetName) pushCmd := exec.Command(dockerBinary, "push", targetName) - s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) + s.trustedCmd(pushCmd) out, _, err := runCommandWithOutput(pushCmd) c.Assert(err, check.IsNil, check.Commentf(out)) + s.assertTargetInRoles(c, repoName, "latest", "targets") // Try pull, check we retrieve from targets role pullCmd := exec.Command(dockerBinary, "-D", "pull", repoName) @@ -275,15 +276,31 @@ func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) { c.Assert(out, checker.Contains, "retrieving target for targets role") // Now we'll create the releases role, and try pushing and pulling - s.notaryCreateDelegation(c, repoName, pwd, "targets/releases", s.not.keys[0].Public) + s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) - s.notaryPublish(c, repoName, pwd) + s.notaryPublish(c, repoName) + + // try a pull, check that we can still pull because we can still read the + // old tag in the targets role + pullCmd = exec.Command(dockerBinary, "-D", "pull", repoName) + s.trustedCmd(pullCmd) + out, _, err = runCommandWithOutput(pullCmd) + c.Assert(err, check.IsNil, check.Commentf(out)) + c.Assert(out, checker.Contains, "retrieving target for targets role") + + // try a pull -a, check that it succeeds because we can still pull from the + // targets role + pullCmd = exec.Command(dockerBinary, "-D", "pull", "-a", repoName) + s.trustedCmd(pullCmd) + out, _, err = runCommandWithOutput(pullCmd) + c.Assert(err, check.IsNil, check.Commentf(out)) // Push, should sign with targets/releases dockerCmd(c, "tag", "busybox", targetName) pushCmd = exec.Command(dockerBinary, "push", targetName) - s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) + s.trustedCmd(pushCmd) out, _, err = runCommandWithOutput(pushCmd) + s.assertTargetInRoles(c, repoName, "latest", "targets", "targets/releases") // Try pull, check we retrieve from targets/releases role pullCmd = exec.Command(dockerBinary, "-D", "pull", repoName) @@ -292,14 +309,15 @@ func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) { c.Assert(out, checker.Contains, "retrieving target for targets/releases role") // Create another delegation that we'll sign with - s.notaryCreateDelegation(c, repoName, pwd, "targets/other", s.not.keys[1].Public) + s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[1].Public) s.notaryImportKey(c, repoName, "targets/other", s.not.keys[1].Private) - s.notaryPublish(c, repoName, pwd) + s.notaryPublish(c, repoName) dockerCmd(c, "tag", "busybox", targetName) pushCmd = exec.Command(dockerBinary, "push", targetName) - s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) + s.trustedCmd(pushCmd) out, _, err = runCommandWithOutput(pushCmd) + s.assertTargetInRoles(c, repoName, "latest", "targets", "targets/releases", "targets/other") // Try pull, check we retrieve from targets/releases role pullCmd = exec.Command(dockerBinary, "-D", "pull", repoName) @@ -307,3 +325,41 @@ func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) { out, _, err = runCommandWithOutput(pullCmd) c.Assert(out, checker.Contains, "retrieving target for targets/releases role") } + +func (s *DockerTrustSuite) TestTrustedPullIgnoresOtherDelegationRoles(c *check.C) { + testRequires(c, NotaryHosting) + repoName := fmt.Sprintf("%v/dockerclipullotherdelegation/trusted", privateRegistryURL) + targetName := fmt.Sprintf("%s:latest", repoName) + + // We'll create a repo first with a non-release delegation role, so that when we + // push we'll sign it into the delegation role + s.notaryInitRepo(c, repoName) + s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[0].Public) + s.notaryImportKey(c, repoName, "targets/other", s.not.keys[0].Private) + s.notaryPublish(c, repoName) + + // Push should write to the delegation role, not targets + dockerCmd(c, "tag", "busybox", targetName) + pushCmd := exec.Command(dockerBinary, "push", targetName) + s.trustedCmd(pushCmd) + out, _, err := runCommandWithOutput(pushCmd) + c.Assert(err, check.IsNil, check.Commentf(out)) + s.assertTargetInRoles(c, repoName, "latest", "targets/other") + s.assertTargetNotInRoles(c, repoName, "latest", "targets") + + // Try pull - we should fail, since pull will only pull from the targets/releases + // role or the targets role + pullCmd := exec.Command(dockerBinary, "-D", "pull", repoName) + s.trustedCmd(pullCmd) + out, _, err = runCommandWithOutput(pullCmd) + c.Assert(err, check.NotNil, check.Commentf(out)) + c.Assert(out, checker.Contains, "No trust data for") + + // try a pull -a: we should fail since pull will only pull from the targets/releases + // role or the targets role + pullCmd = exec.Command(dockerBinary, "-D", "pull", "-a", repoName) + s.trustedCmd(pullCmd) + out, _, err = runCommandWithOutput(pullCmd) + c.Assert(err, check.NotNil, check.Commentf(out)) + c.Assert(out, checker.Contains, "No trusted tags for") +} diff --git a/integration-cli/docker_cli_push_test.go b/integration-cli/docker_cli_push_test.go index 73ed7fdd88..6459cc031a 100644 --- a/integration-cli/docker_cli_push_test.go +++ b/integration-cli/docker_cli_push_test.go @@ -501,10 +501,9 @@ func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) testRequires(c, NotaryHosting) repoName := fmt.Sprintf("%v/dockerclireleasedelegationinitfirst/trusted", privateRegistryURL) targetName := fmt.Sprintf("%s:latest", repoName) - pwd := "12345678" - s.notaryInitRepo(c, repoName, pwd) - s.notaryCreateDelegation(c, repoName, pwd, "targets/releases", s.not.keys[0].Public) - s.notaryPublish(c, repoName, pwd) + s.notaryInitRepo(c, repoName) + s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) + s.notaryPublish(c, repoName) s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) @@ -512,10 +511,13 @@ func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) dockerCmd(c, "tag", "busybox", targetName) pushCmd := exec.Command(dockerBinary, "push", targetName) - s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) + s.trustedCmd(pushCmd) out, _, err := runCommandWithOutput(pushCmd) c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out)) c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag")) + // check to make sure that the target has been added to targets/releases and not targets + s.assertTargetInRoles(c, repoName, "latest", "targets/releases") + s.assertTargetNotInRoles(c, repoName, "latest", "targets") // Try pull after push os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) @@ -525,103 +527,99 @@ func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) out, _, err = runCommandWithOutput(pullCmd) c.Assert(err, check.IsNil, check.Commentf(out)) c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) - - // check to make sure that the target has been added to targets/releases and not targets - s.assertTargetInDelegationRoles(c, repoName, "latest", "targets/releases") } func (s *DockerTrustSuite) TestTrustedPushSignsAllFirstLevelRolesWeHaveKeysFor(c *check.C) { testRequires(c, NotaryHosting) repoName := fmt.Sprintf("%v/dockerclimanyroles/trusted", privateRegistryURL) targetName := fmt.Sprintf("%s:latest", repoName) - pwd := "12345678" - s.notaryInitRepo(c, repoName, pwd) - s.notaryCreateDelegation(c, repoName, pwd, "targets/role1", s.not.keys[0].Public) - s.notaryCreateDelegation(c, repoName, pwd, "targets/role2", s.not.keys[1].Public) - s.notaryCreateDelegation(c, repoName, pwd, "targets/role3", s.not.keys[2].Public) + s.notaryInitRepo(c, repoName) + s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public) + s.notaryCreateDelegation(c, repoName, "targets/role2", s.not.keys[1].Public) + s.notaryCreateDelegation(c, repoName, "targets/role3", s.not.keys[2].Public) // import everything except the third key s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private) s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private) - s.notaryCreateDelegation(c, repoName, pwd, "targets/role1/subrole", s.not.keys[3].Public) + s.notaryCreateDelegation(c, repoName, "targets/role1/subrole", s.not.keys[3].Public) s.notaryImportKey(c, repoName, "targets/role1/subrole", s.not.keys[3].Private) - s.notaryPublish(c, repoName, pwd) + s.notaryPublish(c, repoName) // tag the image and upload it to the private registry dockerCmd(c, "tag", "busybox", targetName) pushCmd := exec.Command(dockerBinary, "push", targetName) - s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) + s.trustedCmd(pushCmd) out, _, err := runCommandWithOutput(pushCmd) c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out)) c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag")) - // Try pull after push - os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) - - pullCmd := exec.Command(dockerBinary, "pull", targetName) - s.trustedCmd(pullCmd) - out, _, err = runCommandWithOutput(pullCmd) - c.Assert(err, check.IsNil, check.Commentf(out)) - c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) - // check to make sure that the target has been added to targets/role1 and targets/role2, and // not targets (because there are delegations) or targets/role3 (due to missing key) or // targets/role1/subrole (due to it being a second level delegation) - s.assertTargetInDelegationRoles(c, repoName, "latest", "targets/role1", "targets/role2") + s.assertTargetInRoles(c, repoName, "latest", "targets/role1", "targets/role2") + s.assertTargetNotInRoles(c, repoName, "latest", "targets") + + // Try pull after push + os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) + + // pull should fail because none of these are the releases role + pullCmd := exec.Command(dockerBinary, "pull", targetName) + s.trustedCmd(pullCmd) + out, _, err = runCommandWithOutput(pullCmd) + c.Assert(err, check.NotNil, check.Commentf(out)) } func (s *DockerTrustSuite) TestTrustedPushSignsForRolesWithKeysAndValidPaths(c *check.C) { repoName := fmt.Sprintf("%v/dockerclirolesbykeysandpaths/trusted", privateRegistryURL) targetName := fmt.Sprintf("%s:latest", repoName) - pwd := "12345678" - s.notaryInitRepo(c, repoName, pwd) - s.notaryCreateDelegation(c, repoName, pwd, "targets/role1", s.not.keys[0].Public, "l", "z") - s.notaryCreateDelegation(c, repoName, pwd, "targets/role2", s.not.keys[1].Public, "x", "y") - s.notaryCreateDelegation(c, repoName, pwd, "targets/role3", s.not.keys[2].Public, "latest") - s.notaryCreateDelegation(c, repoName, pwd, "targets/role4", s.not.keys[3].Public, "latest") + s.notaryInitRepo(c, repoName) + s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public, "l", "z") + s.notaryCreateDelegation(c, repoName, "targets/role2", s.not.keys[1].Public, "x", "y") + s.notaryCreateDelegation(c, repoName, "targets/role3", s.not.keys[2].Public, "latest") + s.notaryCreateDelegation(c, repoName, "targets/role4", s.not.keys[3].Public, "latest") // import everything except the third key s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private) s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private) s.notaryImportKey(c, repoName, "targets/role4", s.not.keys[3].Private) - s.notaryPublish(c, repoName, pwd) + s.notaryPublish(c, repoName) // tag the image and upload it to the private registry dockerCmd(c, "tag", "busybox", targetName) pushCmd := exec.Command(dockerBinary, "push", targetName) - s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) + s.trustedCmd(pushCmd) out, _, err := runCommandWithOutput(pushCmd) c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out)) c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag")) - // Try pull after push - os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) - - pullCmd := exec.Command(dockerBinary, "pull", targetName) - s.trustedCmd(pullCmd) - out, _, err = runCommandWithOutput(pullCmd) - c.Assert(err, check.IsNil, check.Commentf(out)) - c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) - // check to make sure that the target has been added to targets/role1 and targets/role4, and // not targets (because there are delegations) or targets/role2 (due to path restrictions) or // targets/role3 (due to missing key) - s.assertTargetInDelegationRoles(c, repoName, "latest", "targets/role1", "targets/role4") + s.assertTargetInRoles(c, repoName, "latest", "targets/role1", "targets/role4") + s.assertTargetNotInRoles(c, repoName, "latest", "targets") + + // Try pull after push + os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) + + // pull should fail because none of these are the releases role + pullCmd := exec.Command(dockerBinary, "pull", targetName) + s.trustedCmd(pullCmd) + out, _, err = runCommandWithOutput(pullCmd) + c.Assert(err, check.NotNil, check.Commentf(out)) } func (s *DockerTrustSuite) TestTrustedPushDoesntSignTargetsIfDelegationsExist(c *check.C) { testRequires(c, NotaryHosting) repoName := fmt.Sprintf("%v/dockerclireleasedelegationnotsignable/trusted", privateRegistryURL) targetName := fmt.Sprintf("%s:latest", repoName) - pwd := "12345678" - s.notaryInitRepo(c, repoName, pwd) - s.notaryCreateDelegation(c, repoName, pwd, "targets/role1", s.not.keys[0].Public) - s.notaryPublish(c, repoName, pwd) + s.notaryInitRepo(c, repoName) + s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public) + s.notaryPublish(c, repoName) // do not import any delegations key @@ -629,11 +627,13 @@ func (s *DockerTrustSuite) TestTrustedPushDoesntSignTargetsIfDelegationsExist(c dockerCmd(c, "tag", "busybox", targetName) pushCmd := exec.Command(dockerBinary, "push", targetName) - s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) + s.trustedCmd(pushCmd) out, _, err := runCommandWithOutput(pushCmd) - c.Assert(err, check.Not(check.IsNil), check.Commentf("trusted push succeeded but should have failed:\n%s", out)) + c.Assert(err, check.NotNil, check.Commentf("trusted push succeeded but should have failed:\n%s", out)) c.Assert(out, checker.Contains, "no valid signing keys", check.Commentf("Missing expected output on trusted push without keys")) + + s.assertTargetNotInRoles(c, repoName, "latest", "targets", "targets/role1") } func (s *DockerRegistryAuthHtpasswdSuite) TestPushNoCredentialsNoRetry(c *check.C) { diff --git a/integration-cli/trust_server.go b/integration-cli/trust_server.go index 2c974959ce..308f624a23 100644 --- a/integration-cli/trust_server.go +++ b/integration-cli/trust_server.go @@ -211,6 +211,7 @@ func (s *DockerTrustSuite) setupTrustedImage(c *check.C, name string) string { pushCmd := exec.Command(dockerBinary, "push", repoName) s.trustedCmd(pushCmd) out, _, err := runCommandWithOutput(pushCmd) + if err != nil { c.Fatalf("Error running trusted push: %s\n%s", err, out) } @@ -225,25 +226,26 @@ func (s *DockerTrustSuite) setupTrustedImage(c *check.C, name string) string { return repoName } -func notaryClientEnv(cmd *exec.Cmd, rootPwd, repositoryPwd string) { +func notaryClientEnv(cmd *exec.Cmd) { + pwd := "12345678" env := []string{ - fmt.Sprintf("NOTARY_ROOT_PASSPHRASE=%s", rootPwd), - fmt.Sprintf("NOTARY_TARGETS_PASSPHRASE=%s", repositoryPwd), - fmt.Sprintf("NOTARY_SNAPSHOT_PASSPHRASE=%s", repositoryPwd), + fmt.Sprintf("NOTARY_ROOT_PASSPHRASE=%s", pwd), + fmt.Sprintf("NOTARY_TARGETS_PASSPHRASE=%s", pwd), + fmt.Sprintf("NOTARY_SNAPSHOT_PASSPHRASE=%s", pwd), } cmd.Env = append(os.Environ(), env...) } -func (s *DockerTrustSuite) notaryInitRepo(c *check.C, repoName, pwd string) { +func (s *DockerTrustSuite) notaryInitRepo(c *check.C, repoName string) { initCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "init", repoName) - notaryClientEnv(initCmd, pwd, pwd) + notaryClientEnv(initCmd) out, _, err := runCommandWithOutput(initCmd) if err != nil { c.Fatalf("Error initializing notary repository: %s\n", out) } } -func (s *DockerTrustSuite) notaryCreateDelegation(c *check.C, repoName, pwd, role string, pubKey string, paths ...string) { +func (s *DockerTrustSuite) notaryCreateDelegation(c *check.C, repoName, role string, pubKey string, paths ...string) { pathsArg := "--all-paths" if len(paths) > 0 { pathsArg = "--paths=" + strings.Join(paths, ",") @@ -251,16 +253,16 @@ func (s *DockerTrustSuite) notaryCreateDelegation(c *check.C, repoName, pwd, rol delgCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "delegation", "add", repoName, role, pubKey, pathsArg) - notaryClientEnv(delgCmd, pwd, pwd) + notaryClientEnv(delgCmd) out, _, err := runCommandWithOutput(delgCmd) if err != nil { c.Fatalf("Error adding %s role to notary repository: %s\n", role, out) } } -func (s *DockerTrustSuite) notaryPublish(c *check.C, repoName, pwd string) { +func (s *DockerTrustSuite) notaryPublish(c *check.C, repoName string) { pubCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "publish", repoName) - notaryClientEnv(pubCmd, pwd, pwd) + notaryClientEnv(pubCmd) out, _, err := runCommandWithOutput(pubCmd) if err != nil { c.Fatalf("Error publishing notary repository: %s\n", out) @@ -270,20 +272,20 @@ func (s *DockerTrustSuite) notaryPublish(c *check.C, repoName, pwd string) { func (s *DockerTrustSuite) notaryImportKey(c *check.C, repoName, role string, privKey string) { impCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "key", "import", privKey, "-g", repoName, "-r", role) - notaryClientEnv(impCmd, "", "") + notaryClientEnv(impCmd) out, _, err := runCommandWithOutput(impCmd) if err != nil { c.Fatalf("Error importing key to notary repository: %s\n", out) } } -func (s *DockerTrustSuite) notaryListTargetsInRoles(c *check.C, repoName, role string) map[string]string { +func (s *DockerTrustSuite) notaryListTargetsInRole(c *check.C, repoName, role string) map[string]string { listCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "list", repoName, "-r", role) - notaryClientEnv(listCmd, "", "") + notaryClientEnv(listCmd) out, _, err := runCommandWithOutput(listCmd) if err != nil { - c.Fatalf("Error importing key to notary repository: %s\n", out) + c.Fatalf("Error listing targets in notary repository: %s\n", out) } // should look something like: @@ -291,10 +293,17 @@ func (s *DockerTrustSuite) notaryListTargetsInRoles(c *check.C, repoName, role s // ------------------------------------------------------------------------------------------------------ // latest 24a36bbc059b1345b7e8be0df20f1b23caa3602e85d42fff7ecd9d0bd255de56 1377 targets - lines := strings.Split(strings.TrimSpace(out), "\n") - c.Assert(len(lines), checker.GreaterOrEqualThan, 3) targets := make(map[string]string) + // no target + lines := strings.Split(strings.TrimSpace(out), "\n") + if len(lines) == 1 && strings.Contains(out, "No targets present in this repository.") { + return targets + } + + // otherwise, there is at least one target + c.Assert(len(lines), checker.GreaterOrEqualThan, 3) + for _, line := range lines[2:] { tokens := strings.Fields(line) c.Assert(tokens, checker.HasLen, 4) @@ -304,18 +313,23 @@ func (s *DockerTrustSuite) notaryListTargetsInRoles(c *check.C, repoName, role s return targets } -func (s *DockerTrustSuite) assertTargetInDelegationRoles(c *check.C, repoName, target string, roles ...string) { - // assert it's not in the target role - targets := s.notaryListTargetsInRoles(c, repoName, "targets") - roleName, ok := targets[target] - c.Assert(ok, checker.True) - c.Assert(roleName, checker.Not(checker.Equals), "targets") - +func (s *DockerTrustSuite) assertTargetInRoles(c *check.C, repoName, target string, roles ...string) { // check all the roles for _, role := range roles { - targets := s.notaryListTargetsInRoles(c, repoName, role) + targets := s.notaryListTargetsInRole(c, repoName, role) roleName, ok := targets[target] c.Assert(ok, checker.True) c.Assert(roleName, checker.Equals, role) } } + +func (s *DockerTrustSuite) assertTargetNotInRoles(c *check.C, repoName, target string, roles ...string) { + targets := s.notaryListTargetsInRole(c, repoName, "targets") + + roleName, ok := targets[target] + if ok { + for _, role := range roles { + c.Assert(roleName, checker.Not(checker.Equals), role) + } + } +}