Signed-off-by: cyli <cyli@twistedmatrix.com>
| ... | ... |
@@ -259,6 +259,11 @@ func (cli *DockerCli) trustedReference(ref reference.NamedTagged) (reference.Can |
| 259 | 259 |
if err != nil {
|
| 260 | 260 |
return nil, err |
| 261 | 261 |
} |
| 262 |
+ // Only list tags in the top level targets role or the releases delegation role - ignore |
|
| 263 |
+ // all other delegation roles |
|
| 264 |
+ if t.Role != releasesRole && t.Role != data.CanonicalTargetsRole {
|
|
| 265 |
+ return nil, notaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.Tag()))
|
|
| 266 |
+ } |
|
| 262 | 267 |
r, err := convertTarget(t.Target) |
| 263 | 268 |
if err != nil {
|
| 264 | 269 |
return nil, err |
| ... | ... |
@@ -332,13 +337,27 @@ func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registr |
| 332 | 332 |
fmt.Fprintf(cli.out, "Skipping target for %q\n", repoInfo.Name()) |
| 333 | 333 |
continue |
| 334 | 334 |
} |
| 335 |
+ // Only list tags in the top level targets role or the releases delegation role - ignore |
|
| 336 |
+ // all other delegation roles |
|
| 337 |
+ if tgt.Role != releasesRole && tgt.Role != data.CanonicalTargetsRole {
|
|
| 338 |
+ continue |
|
| 339 |
+ } |
|
| 335 | 340 |
refs = append(refs, t) |
| 336 | 341 |
} |
| 342 |
+ if len(refs) == 0 {
|
|
| 343 |
+ return notaryError(repoInfo.FullName(), fmt.Errorf("No trusted tags for %s", repoInfo.FullName()))
|
|
| 344 |
+ } |
|
| 337 | 345 |
} else {
|
| 338 | 346 |
t, err := notaryRepo.GetTargetByName(ref.String(), releasesRole, data.CanonicalTargetsRole) |
| 339 | 347 |
if err != nil {
|
| 340 | 348 |
return notaryError(repoInfo.FullName(), err) |
| 341 | 349 |
} |
| 350 |
+ // Only get the tag if it's in the top level targets role or the releases delegation role |
|
| 351 |
+ // ignore it if it's in any other delegation roles |
|
| 352 |
+ if t.Role != releasesRole && t.Role != data.CanonicalTargetsRole {
|
|
| 353 |
+ return notaryError(repoInfo.FullName(), fmt.Errorf("No trust data for %s", ref.String()))
|
|
| 354 |
+ } |
|
| 355 |
+ |
|
| 342 | 356 |
logrus.Debugf("retrieving target for %s role\n", t.Role)
|
| 343 | 357 |
r, err := convertTarget(t.Target) |
| 344 | 358 |
if err != nil {
|
| ... | ... |
@@ -496,9 +515,9 @@ func (cli *DockerCli) addTargetToAllSignableRoles(repo *client.NotaryRepository, |
| 496 | 496 |
var signableRoles []string |
| 497 | 497 |
|
| 498 | 498 |
// translate the full key names, which includes the GUN, into just the key IDs |
| 499 |
- allCanonicalKeyIDs := make(map[string]string) |
|
| 499 |
+ allCanonicalKeyIDs := make(map[string]struct{})
|
|
| 500 | 500 |
for fullKeyID := range repo.CryptoService.ListAllKeys() {
|
| 501 |
- allCanonicalKeyIDs[path.Base(fullKeyID)] = "" |
|
| 501 |
+ allCanonicalKeyIDs[path.Base(fullKeyID)] = struct{}{}
|
|
| 502 | 502 |
} |
| 503 | 503 |
|
| 504 | 504 |
allDelegationRoles, err := repo.GetDelegationRoles() |
| ... | ... |
@@ -506,6 +525,13 @@ func (cli *DockerCli) addTargetToAllSignableRoles(repo *client.NotaryRepository, |
| 506 | 506 |
return err |
| 507 | 507 |
} |
| 508 | 508 |
|
| 509 |
+ // if there are no delegation roles, then just try to sign it into the targets role |
|
| 510 |
+ if len(allDelegationRoles) == 0 {
|
|
| 511 |
+ return repo.AddTarget(target, data.CanonicalTargetsRole) |
|
| 512 |
+ } |
|
| 513 |
+ |
|
| 514 |
+ // there are delegation roles, find every delegation role we have a key for, and |
|
| 515 |
+ // attempt to sign into into all those roles. |
|
| 509 | 516 |
for _, delegationRole := range allDelegationRoles {
|
| 510 | 517 |
// We do not support signing any delegation role that isn't a direct child of the targets role. |
| 511 | 518 |
// 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, |
| 517 | 517 |
for _, canonicalKeyID := range delegationRole.KeyIDs {
|
| 518 | 518 |
if _, ok := allCanonicalKeyIDs[canonicalKeyID]; ok {
|
| 519 | 519 |
signableRoles = append(signableRoles, delegationRole.Name) |
| 520 |
+ break |
|
| 520 | 521 |
} |
| 521 | 522 |
} |
| 522 | 523 |
} |
| 523 | 524 |
|
| 524 |
- if len(allDelegationRoles) > 0 && len(signableRoles) == 0 {
|
|
| 525 |
+ if len(signableRoles) == 0 {
|
|
| 525 | 526 |
return fmt.Errorf("no valid signing keys for delegation roles")
|
| 526 | 527 |
} |
| 527 | 528 |
|
| ... | ... |
@@ -5799,6 +5799,83 @@ func (s *DockerTrustSuite) TestBuildContextDirIsSymlink(c *check.C) {
|
| 5799 | 5799 |
} |
| 5800 | 5800 |
} |
| 5801 | 5801 |
|
| 5802 |
+func (s *DockerTrustSuite) TestTrustedBuildTagFromReleasesRole(c *check.C) {
|
|
| 5803 |
+ testRequires(c, NotaryHosting) |
|
| 5804 |
+ |
|
| 5805 |
+ latestTag := s.setupTrustedImage(c, "trusted-build-releases-role") |
|
| 5806 |
+ repoName := strings.TrimSuffix(latestTag, ":latest") |
|
| 5807 |
+ |
|
| 5808 |
+ // Now create the releases role |
|
| 5809 |
+ s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) |
|
| 5810 |
+ s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) |
|
| 5811 |
+ s.notaryPublish(c, repoName) |
|
| 5812 |
+ |
|
| 5813 |
+ // push a different tag to the releases role |
|
| 5814 |
+ otherTag := fmt.Sprintf("%s:other", repoName)
|
|
| 5815 |
+ dockerCmd(c, "tag", "busybox", otherTag) |
|
| 5816 |
+ |
|
| 5817 |
+ pushCmd := exec.Command(dockerBinary, "push", otherTag) |
|
| 5818 |
+ s.trustedCmd(pushCmd) |
|
| 5819 |
+ out, _, err := runCommandWithOutput(pushCmd) |
|
| 5820 |
+ c.Assert(err, check.IsNil, check.Commentf("Trusted push failed: %s", out))
|
|
| 5821 |
+ s.assertTargetInRoles(c, repoName, "other", "targets/releases") |
|
| 5822 |
+ s.assertTargetNotInRoles(c, repoName, "other", "targets") |
|
| 5823 |
+ |
|
| 5824 |
+ out, status := dockerCmd(c, "rmi", otherTag) |
|
| 5825 |
+ c.Assert(status, check.Equals, 0, check.Commentf("docker rmi failed: %s", out))
|
|
| 5826 |
+ |
|
| 5827 |
+ dockerFile := fmt.Sprintf(` |
|
| 5828 |
+ FROM %s |
|
| 5829 |
+ RUN [] |
|
| 5830 |
+ `, otherTag) |
|
| 5831 |
+ |
|
| 5832 |
+ name := "testtrustedbuildreleasesrole" |
|
| 5833 |
+ |
|
| 5834 |
+ buildCmd := buildImageCmd(name, dockerFile, true) |
|
| 5835 |
+ s.trustedCmd(buildCmd) |
|
| 5836 |
+ out, _, err = runCommandWithOutput(buildCmd) |
|
| 5837 |
+ c.Assert(err, check.IsNil, check.Commentf("Trusted build failed: %s", out))
|
|
| 5838 |
+ c.Assert(out, checker.Contains, fmt.Sprintf("FROM %s@sha", repoName))
|
|
| 5839 |
+} |
|
| 5840 |
+ |
|
| 5841 |
+func (s *DockerTrustSuite) TestTrustedBuildTagIgnoresOtherDelegationRoles(c *check.C) {
|
|
| 5842 |
+ testRequires(c, NotaryHosting) |
|
| 5843 |
+ |
|
| 5844 |
+ latestTag := s.setupTrustedImage(c, "trusted-build-releases-role") |
|
| 5845 |
+ repoName := strings.TrimSuffix(latestTag, ":latest") |
|
| 5846 |
+ |
|
| 5847 |
+ // Now create a non-releases delegation role |
|
| 5848 |
+ s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[0].Public) |
|
| 5849 |
+ s.notaryImportKey(c, repoName, "targets/other", s.not.keys[0].Private) |
|
| 5850 |
+ s.notaryPublish(c, repoName) |
|
| 5851 |
+ |
|
| 5852 |
+ // push a different tag to the other role |
|
| 5853 |
+ otherTag := fmt.Sprintf("%s:other", repoName)
|
|
| 5854 |
+ dockerCmd(c, "tag", "busybox", otherTag) |
|
| 5855 |
+ |
|
| 5856 |
+ pushCmd := exec.Command(dockerBinary, "push", otherTag) |
|
| 5857 |
+ s.trustedCmd(pushCmd) |
|
| 5858 |
+ out, _, err := runCommandWithOutput(pushCmd) |
|
| 5859 |
+ c.Assert(err, check.IsNil, check.Commentf("Trusted push failed: %s", out))
|
|
| 5860 |
+ s.assertTargetInRoles(c, repoName, "other", "targets/other") |
|
| 5861 |
+ s.assertTargetNotInRoles(c, repoName, "other", "targets") |
|
| 5862 |
+ |
|
| 5863 |
+ out, status := dockerCmd(c, "rmi", otherTag) |
|
| 5864 |
+ c.Assert(status, check.Equals, 0, check.Commentf("docker rmi failed: %s", out))
|
|
| 5865 |
+ |
|
| 5866 |
+ dockerFile := fmt.Sprintf(` |
|
| 5867 |
+ FROM %s |
|
| 5868 |
+ RUN [] |
|
| 5869 |
+ `, otherTag) |
|
| 5870 |
+ |
|
| 5871 |
+ name := "testtrustedbuildotherrole" |
|
| 5872 |
+ |
|
| 5873 |
+ buildCmd := buildImageCmd(name, dockerFile, true) |
|
| 5874 |
+ s.trustedCmd(buildCmd) |
|
| 5875 |
+ out, _, err = runCommandWithOutput(buildCmd) |
|
| 5876 |
+ c.Assert(err, check.NotNil, check.Commentf("Trusted build expected to fail: %s", out))
|
|
| 5877 |
+} |
|
| 5878 |
+ |
|
| 5802 | 5879 |
// Issue #15634: COPY fails when path starts with "null" |
| 5803 | 5880 |
func (s *DockerSuite) TestBuildNullStringInAddCopyVolume(c *check.C) {
|
| 5804 | 5881 |
name := "testbuildnullstringinaddcopyvolume" |
| ... | ... |
@@ -256,16 +256,17 @@ func (s *DockerTrustSuite) TestTrustedPullDelete(c *check.C) {
|
| 256 | 256 |
} |
| 257 | 257 |
|
| 258 | 258 |
func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) {
|
| 259 |
+ testRequires(c, NotaryHosting) |
|
| 259 | 260 |
repoName := fmt.Sprintf("%v/dockerclireleasesdelegationpulling/trusted", privateRegistryURL)
|
| 260 | 261 |
targetName := fmt.Sprintf("%s:latest", repoName)
|
| 261 |
- pwd := "12345678" |
|
| 262 | 262 |
|
| 263 | 263 |
// Push with targets first, initializing the repo |
| 264 | 264 |
dockerCmd(c, "tag", "busybox", targetName) |
| 265 | 265 |
pushCmd := exec.Command(dockerBinary, "push", targetName) |
| 266 |
- s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) |
|
| 266 |
+ s.trustedCmd(pushCmd) |
|
| 267 | 267 |
out, _, err := runCommandWithOutput(pushCmd) |
| 268 | 268 |
c.Assert(err, check.IsNil, check.Commentf(out)) |
| 269 |
+ s.assertTargetInRoles(c, repoName, "latest", "targets") |
|
| 269 | 270 |
|
| 270 | 271 |
// Try pull, check we retrieve from targets role |
| 271 | 272 |
pullCmd := exec.Command(dockerBinary, "-D", "pull", repoName) |
| ... | ... |
@@ -275,15 +276,31 @@ func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) {
|
| 275 | 275 |
c.Assert(out, checker.Contains, "retrieving target for targets role") |
| 276 | 276 |
|
| 277 | 277 |
// Now we'll create the releases role, and try pushing and pulling |
| 278 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/releases", s.not.keys[0].Public) |
|
| 278 |
+ s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) |
|
| 279 | 279 |
s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) |
| 280 |
- s.notaryPublish(c, repoName, pwd) |
|
| 280 |
+ s.notaryPublish(c, repoName) |
|
| 281 |
+ |
|
| 282 |
+ // try a pull, check that we can still pull because we can still read the |
|
| 283 |
+ // old tag in the targets role |
|
| 284 |
+ pullCmd = exec.Command(dockerBinary, "-D", "pull", repoName) |
|
| 285 |
+ s.trustedCmd(pullCmd) |
|
| 286 |
+ out, _, err = runCommandWithOutput(pullCmd) |
|
| 287 |
+ c.Assert(err, check.IsNil, check.Commentf(out)) |
|
| 288 |
+ c.Assert(out, checker.Contains, "retrieving target for targets role") |
|
| 289 |
+ |
|
| 290 |
+ // try a pull -a, check that it succeeds because we can still pull from the |
|
| 291 |
+ // targets role |
|
| 292 |
+ pullCmd = exec.Command(dockerBinary, "-D", "pull", "-a", repoName) |
|
| 293 |
+ s.trustedCmd(pullCmd) |
|
| 294 |
+ out, _, err = runCommandWithOutput(pullCmd) |
|
| 295 |
+ c.Assert(err, check.IsNil, check.Commentf(out)) |
|
| 281 | 296 |
|
| 282 | 297 |
// Push, should sign with targets/releases |
| 283 | 298 |
dockerCmd(c, "tag", "busybox", targetName) |
| 284 | 299 |
pushCmd = exec.Command(dockerBinary, "push", targetName) |
| 285 |
- s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) |
|
| 300 |
+ s.trustedCmd(pushCmd) |
|
| 286 | 301 |
out, _, err = runCommandWithOutput(pushCmd) |
| 302 |
+ s.assertTargetInRoles(c, repoName, "latest", "targets", "targets/releases") |
|
| 287 | 303 |
|
| 288 | 304 |
// Try pull, check we retrieve from targets/releases role |
| 289 | 305 |
pullCmd = exec.Command(dockerBinary, "-D", "pull", repoName) |
| ... | ... |
@@ -292,14 +309,15 @@ func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) {
|
| 292 | 292 |
c.Assert(out, checker.Contains, "retrieving target for targets/releases role") |
| 293 | 293 |
|
| 294 | 294 |
// Create another delegation that we'll sign with |
| 295 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/other", s.not.keys[1].Public) |
|
| 295 |
+ s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[1].Public) |
|
| 296 | 296 |
s.notaryImportKey(c, repoName, "targets/other", s.not.keys[1].Private) |
| 297 |
- s.notaryPublish(c, repoName, pwd) |
|
| 297 |
+ s.notaryPublish(c, repoName) |
|
| 298 | 298 |
|
| 299 | 299 |
dockerCmd(c, "tag", "busybox", targetName) |
| 300 | 300 |
pushCmd = exec.Command(dockerBinary, "push", targetName) |
| 301 |
- s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) |
|
| 301 |
+ s.trustedCmd(pushCmd) |
|
| 302 | 302 |
out, _, err = runCommandWithOutput(pushCmd) |
| 303 |
+ s.assertTargetInRoles(c, repoName, "latest", "targets", "targets/releases", "targets/other") |
|
| 303 | 304 |
|
| 304 | 305 |
// Try pull, check we retrieve from targets/releases role |
| 305 | 306 |
pullCmd = exec.Command(dockerBinary, "-D", "pull", repoName) |
| ... | ... |
@@ -307,3 +325,41 @@ func (s *DockerTrustSuite) TestTrustedPullReadsFromReleasesRole(c *check.C) {
|
| 307 | 307 |
out, _, err = runCommandWithOutput(pullCmd) |
| 308 | 308 |
c.Assert(out, checker.Contains, "retrieving target for targets/releases role") |
| 309 | 309 |
} |
| 310 |
+ |
|
| 311 |
+func (s *DockerTrustSuite) TestTrustedPullIgnoresOtherDelegationRoles(c *check.C) {
|
|
| 312 |
+ testRequires(c, NotaryHosting) |
|
| 313 |
+ repoName := fmt.Sprintf("%v/dockerclipullotherdelegation/trusted", privateRegistryURL)
|
|
| 314 |
+ targetName := fmt.Sprintf("%s:latest", repoName)
|
|
| 315 |
+ |
|
| 316 |
+ // We'll create a repo first with a non-release delegation role, so that when we |
|
| 317 |
+ // push we'll sign it into the delegation role |
|
| 318 |
+ s.notaryInitRepo(c, repoName) |
|
| 319 |
+ s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[0].Public) |
|
| 320 |
+ s.notaryImportKey(c, repoName, "targets/other", s.not.keys[0].Private) |
|
| 321 |
+ s.notaryPublish(c, repoName) |
|
| 322 |
+ |
|
| 323 |
+ // Push should write to the delegation role, not targets |
|
| 324 |
+ dockerCmd(c, "tag", "busybox", targetName) |
|
| 325 |
+ pushCmd := exec.Command(dockerBinary, "push", targetName) |
|
| 326 |
+ s.trustedCmd(pushCmd) |
|
| 327 |
+ out, _, err := runCommandWithOutput(pushCmd) |
|
| 328 |
+ c.Assert(err, check.IsNil, check.Commentf(out)) |
|
| 329 |
+ s.assertTargetInRoles(c, repoName, "latest", "targets/other") |
|
| 330 |
+ s.assertTargetNotInRoles(c, repoName, "latest", "targets") |
|
| 331 |
+ |
|
| 332 |
+ // Try pull - we should fail, since pull will only pull from the targets/releases |
|
| 333 |
+ // role or the targets role |
|
| 334 |
+ pullCmd := exec.Command(dockerBinary, "-D", "pull", repoName) |
|
| 335 |
+ s.trustedCmd(pullCmd) |
|
| 336 |
+ out, _, err = runCommandWithOutput(pullCmd) |
|
| 337 |
+ c.Assert(err, check.NotNil, check.Commentf(out)) |
|
| 338 |
+ c.Assert(out, checker.Contains, "No trust data for") |
|
| 339 |
+ |
|
| 340 |
+ // try a pull -a: we should fail since pull will only pull from the targets/releases |
|
| 341 |
+ // role or the targets role |
|
| 342 |
+ pullCmd = exec.Command(dockerBinary, "-D", "pull", "-a", repoName) |
|
| 343 |
+ s.trustedCmd(pullCmd) |
|
| 344 |
+ out, _, err = runCommandWithOutput(pullCmd) |
|
| 345 |
+ c.Assert(err, check.NotNil, check.Commentf(out)) |
|
| 346 |
+ c.Assert(out, checker.Contains, "No trusted tags for") |
|
| 347 |
+} |
| ... | ... |
@@ -501,10 +501,9 @@ func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) |
| 501 | 501 |
testRequires(c, NotaryHosting) |
| 502 | 502 |
repoName := fmt.Sprintf("%v/dockerclireleasedelegationinitfirst/trusted", privateRegistryURL)
|
| 503 | 503 |
targetName := fmt.Sprintf("%s:latest", repoName)
|
| 504 |
- pwd := "12345678" |
|
| 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) |
|
| 504 |
+ s.notaryInitRepo(c, repoName) |
|
| 505 |
+ s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public) |
|
| 506 |
+ s.notaryPublish(c, repoName) |
|
| 508 | 507 |
|
| 509 | 508 |
s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private) |
| 510 | 509 |
|
| ... | ... |
@@ -512,10 +511,13 @@ func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) |
| 512 | 512 |
dockerCmd(c, "tag", "busybox", targetName) |
| 513 | 513 |
|
| 514 | 514 |
pushCmd := exec.Command(dockerBinary, "push", targetName) |
| 515 |
- s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) |
|
| 515 |
+ s.trustedCmd(pushCmd) |
|
| 516 | 516 |
out, _, err := runCommandWithOutput(pushCmd) |
| 517 | 517 |
c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
|
| 518 | 518 |
c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
|
| 519 |
+ // check to make sure that the target has been added to targets/releases and not targets |
|
| 520 |
+ s.assertTargetInRoles(c, repoName, "latest", "targets/releases") |
|
| 521 |
+ s.assertTargetNotInRoles(c, repoName, "latest", "targets") |
|
| 519 | 522 |
|
| 520 | 523 |
// Try pull after push |
| 521 | 524 |
os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) |
| ... | ... |
@@ -525,103 +527,99 @@ func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C) |
| 525 | 525 |
out, _, err = runCommandWithOutput(pullCmd) |
| 526 | 526 |
c.Assert(err, check.IsNil, check.Commentf(out)) |
| 527 | 527 |
c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) |
| 528 |
- |
|
| 529 |
- // check to make sure that the target has been added to targets/releases and not targets |
|
| 530 |
- s.assertTargetInDelegationRoles(c, repoName, "latest", "targets/releases") |
|
| 531 | 528 |
} |
| 532 | 529 |
|
| 533 | 530 |
func (s *DockerTrustSuite) TestTrustedPushSignsAllFirstLevelRolesWeHaveKeysFor(c *check.C) {
|
| 534 | 531 |
testRequires(c, NotaryHosting) |
| 535 | 532 |
repoName := fmt.Sprintf("%v/dockerclimanyroles/trusted", privateRegistryURL)
|
| 536 | 533 |
targetName := fmt.Sprintf("%s:latest", repoName)
|
| 537 |
- pwd := "12345678" |
|
| 538 |
- s.notaryInitRepo(c, repoName, pwd) |
|
| 539 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/role1", s.not.keys[0].Public) |
|
| 540 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/role2", s.not.keys[1].Public) |
|
| 541 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/role3", s.not.keys[2].Public) |
|
| 534 |
+ s.notaryInitRepo(c, repoName) |
|
| 535 |
+ s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public) |
|
| 536 |
+ s.notaryCreateDelegation(c, repoName, "targets/role2", s.not.keys[1].Public) |
|
| 537 |
+ s.notaryCreateDelegation(c, repoName, "targets/role3", s.not.keys[2].Public) |
|
| 542 | 538 |
|
| 543 | 539 |
// import everything except the third key |
| 544 | 540 |
s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private) |
| 545 | 541 |
s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private) |
| 546 | 542 |
|
| 547 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/role1/subrole", s.not.keys[3].Public) |
|
| 543 |
+ s.notaryCreateDelegation(c, repoName, "targets/role1/subrole", s.not.keys[3].Public) |
|
| 548 | 544 |
s.notaryImportKey(c, repoName, "targets/role1/subrole", s.not.keys[3].Private) |
| 549 | 545 |
|
| 550 |
- s.notaryPublish(c, repoName, pwd) |
|
| 546 |
+ s.notaryPublish(c, repoName) |
|
| 551 | 547 |
|
| 552 | 548 |
// tag the image and upload it to the private registry |
| 553 | 549 |
dockerCmd(c, "tag", "busybox", targetName) |
| 554 | 550 |
|
| 555 | 551 |
pushCmd := exec.Command(dockerBinary, "push", targetName) |
| 556 |
- s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) |
|
| 552 |
+ s.trustedCmd(pushCmd) |
|
| 557 | 553 |
out, _, err := runCommandWithOutput(pushCmd) |
| 558 | 554 |
c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
|
| 559 | 555 |
c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
|
| 560 | 556 |
|
| 557 |
+ // check to make sure that the target has been added to targets/role1 and targets/role2, and |
|
| 558 |
+ // not targets (because there are delegations) or targets/role3 (due to missing key) or |
|
| 559 |
+ // targets/role1/subrole (due to it being a second level delegation) |
|
| 560 |
+ s.assertTargetInRoles(c, repoName, "latest", "targets/role1", "targets/role2") |
|
| 561 |
+ s.assertTargetNotInRoles(c, repoName, "latest", "targets") |
|
| 562 |
+ |
|
| 561 | 563 |
// Try pull after push |
| 562 | 564 |
os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) |
| 563 | 565 |
|
| 566 |
+ // pull should fail because none of these are the releases role |
|
| 564 | 567 |
pullCmd := exec.Command(dockerBinary, "pull", targetName) |
| 565 | 568 |
s.trustedCmd(pullCmd) |
| 566 | 569 |
out, _, err = runCommandWithOutput(pullCmd) |
| 567 |
- c.Assert(err, check.IsNil, check.Commentf(out)) |
|
| 568 |
- c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) |
|
| 569 |
- |
|
| 570 |
- // check to make sure that the target has been added to targets/role1 and targets/role2, and |
|
| 571 |
- // not targets (because there are delegations) or targets/role3 (due to missing key) or |
|
| 572 |
- // targets/role1/subrole (due to it being a second level delegation) |
|
| 573 |
- s.assertTargetInDelegationRoles(c, repoName, "latest", "targets/role1", "targets/role2") |
|
| 570 |
+ c.Assert(err, check.NotNil, check.Commentf(out)) |
|
| 574 | 571 |
} |
| 575 | 572 |
|
| 576 | 573 |
func (s *DockerTrustSuite) TestTrustedPushSignsForRolesWithKeysAndValidPaths(c *check.C) {
|
| 577 | 574 |
repoName := fmt.Sprintf("%v/dockerclirolesbykeysandpaths/trusted", privateRegistryURL)
|
| 578 | 575 |
targetName := fmt.Sprintf("%s:latest", repoName)
|
| 579 |
- pwd := "12345678" |
|
| 580 |
- s.notaryInitRepo(c, repoName, pwd) |
|
| 581 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/role1", s.not.keys[0].Public, "l", "z") |
|
| 582 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/role2", s.not.keys[1].Public, "x", "y") |
|
| 583 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/role3", s.not.keys[2].Public, "latest") |
|
| 584 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/role4", s.not.keys[3].Public, "latest") |
|
| 576 |
+ s.notaryInitRepo(c, repoName) |
|
| 577 |
+ s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public, "l", "z") |
|
| 578 |
+ s.notaryCreateDelegation(c, repoName, "targets/role2", s.not.keys[1].Public, "x", "y") |
|
| 579 |
+ s.notaryCreateDelegation(c, repoName, "targets/role3", s.not.keys[2].Public, "latest") |
|
| 580 |
+ s.notaryCreateDelegation(c, repoName, "targets/role4", s.not.keys[3].Public, "latest") |
|
| 585 | 581 |
|
| 586 | 582 |
// import everything except the third key |
| 587 | 583 |
s.notaryImportKey(c, repoName, "targets/role1", s.not.keys[0].Private) |
| 588 | 584 |
s.notaryImportKey(c, repoName, "targets/role2", s.not.keys[1].Private) |
| 589 | 585 |
s.notaryImportKey(c, repoName, "targets/role4", s.not.keys[3].Private) |
| 590 | 586 |
|
| 591 |
- s.notaryPublish(c, repoName, pwd) |
|
| 587 |
+ s.notaryPublish(c, repoName) |
|
| 592 | 588 |
|
| 593 | 589 |
// tag the image and upload it to the private registry |
| 594 | 590 |
dockerCmd(c, "tag", "busybox", targetName) |
| 595 | 591 |
|
| 596 | 592 |
pushCmd := exec.Command(dockerBinary, "push", targetName) |
| 597 |
- s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) |
|
| 593 |
+ s.trustedCmd(pushCmd) |
|
| 598 | 594 |
out, _, err := runCommandWithOutput(pushCmd) |
| 599 | 595 |
c.Assert(err, check.IsNil, check.Commentf("trusted push failed: %s\n%s", err, out))
|
| 600 | 596 |
c.Assert(out, checker.Contains, "Signing and pushing trust metadata", check.Commentf("Missing expected output on trusted push with existing tag"))
|
| 601 | 597 |
|
| 598 |
+ // check to make sure that the target has been added to targets/role1 and targets/role4, and |
|
| 599 |
+ // not targets (because there are delegations) or targets/role2 (due to path restrictions) or |
|
| 600 |
+ // targets/role3 (due to missing key) |
|
| 601 |
+ s.assertTargetInRoles(c, repoName, "latest", "targets/role1", "targets/role4") |
|
| 602 |
+ s.assertTargetNotInRoles(c, repoName, "latest", "targets") |
|
| 603 |
+ |
|
| 602 | 604 |
// Try pull after push |
| 603 | 605 |
os.RemoveAll(filepath.Join(cliconfig.ConfigDir(), "trust")) |
| 604 | 606 |
|
| 607 |
+ // pull should fail because none of these are the releases role |
|
| 605 | 608 |
pullCmd := exec.Command(dockerBinary, "pull", targetName) |
| 606 | 609 |
s.trustedCmd(pullCmd) |
| 607 | 610 |
out, _, err = runCommandWithOutput(pullCmd) |
| 608 |
- c.Assert(err, check.IsNil, check.Commentf(out)) |
|
| 609 |
- c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out)) |
|
| 610 |
- |
|
| 611 |
- // check to make sure that the target has been added to targets/role1 and targets/role4, and |
|
| 612 |
- // not targets (because there are delegations) or targets/role2 (due to path restrictions) or |
|
| 613 |
- // targets/role3 (due to missing key) |
|
| 614 |
- s.assertTargetInDelegationRoles(c, repoName, "latest", "targets/role1", "targets/role4") |
|
| 611 |
+ c.Assert(err, check.NotNil, check.Commentf(out)) |
|
| 615 | 612 |
} |
| 616 | 613 |
|
| 617 | 614 |
func (s *DockerTrustSuite) TestTrustedPushDoesntSignTargetsIfDelegationsExist(c *check.C) {
|
| 618 | 615 |
testRequires(c, NotaryHosting) |
| 619 | 616 |
repoName := fmt.Sprintf("%v/dockerclireleasedelegationnotsignable/trusted", privateRegistryURL)
|
| 620 | 617 |
targetName := fmt.Sprintf("%s:latest", repoName)
|
| 621 |
- pwd := "12345678" |
|
| 622 |
- s.notaryInitRepo(c, repoName, pwd) |
|
| 623 |
- s.notaryCreateDelegation(c, repoName, pwd, "targets/role1", s.not.keys[0].Public) |
|
| 624 |
- s.notaryPublish(c, repoName, pwd) |
|
| 618 |
+ s.notaryInitRepo(c, repoName) |
|
| 619 |
+ s.notaryCreateDelegation(c, repoName, "targets/role1", s.not.keys[0].Public) |
|
| 620 |
+ s.notaryPublish(c, repoName) |
|
| 625 | 621 |
|
| 626 | 622 |
// do not import any delegations key |
| 627 | 623 |
|
| ... | ... |
@@ -629,11 +627,13 @@ func (s *DockerTrustSuite) TestTrustedPushDoesntSignTargetsIfDelegationsExist(c |
| 629 | 629 |
dockerCmd(c, "tag", "busybox", targetName) |
| 630 | 630 |
|
| 631 | 631 |
pushCmd := exec.Command(dockerBinary, "push", targetName) |
| 632 |
- s.trustedCmdWithPassphrases(pushCmd, pwd, pwd) |
|
| 632 |
+ s.trustedCmd(pushCmd) |
|
| 633 | 633 |
out, _, err := runCommandWithOutput(pushCmd) |
| 634 |
- c.Assert(err, check.Not(check.IsNil), check.Commentf("trusted push succeeded but should have failed:\n%s", out))
|
|
| 634 |
+ c.Assert(err, check.NotNil, check.Commentf("trusted push succeeded but should have failed:\n%s", out))
|
|
| 635 | 635 |
c.Assert(out, checker.Contains, "no valid signing keys", |
| 636 | 636 |
check.Commentf("Missing expected output on trusted push without keys"))
|
| 637 |
+ |
|
| 638 |
+ s.assertTargetNotInRoles(c, repoName, "latest", "targets", "targets/role1") |
|
| 637 | 639 |
} |
| 638 | 640 |
|
| 639 | 641 |
func (s *DockerRegistryAuthHtpasswdSuite) TestPushNoCredentialsNoRetry(c *check.C) {
|
| ... | ... |
@@ -211,6 +211,7 @@ func (s *DockerTrustSuite) setupTrustedImage(c *check.C, name string) string {
|
| 211 | 211 |
pushCmd := exec.Command(dockerBinary, "push", repoName) |
| 212 | 212 |
s.trustedCmd(pushCmd) |
| 213 | 213 |
out, _, err := runCommandWithOutput(pushCmd) |
| 214 |
+ |
|
| 214 | 215 |
if err != nil {
|
| 215 | 216 |
c.Fatalf("Error running trusted push: %s\n%s", err, out)
|
| 216 | 217 |
} |
| ... | ... |
@@ -225,25 +226,26 @@ func (s *DockerTrustSuite) setupTrustedImage(c *check.C, name string) string {
|
| 225 | 225 |
return repoName |
| 226 | 226 |
} |
| 227 | 227 |
|
| 228 |
-func notaryClientEnv(cmd *exec.Cmd, rootPwd, repositoryPwd string) {
|
|
| 228 |
+func notaryClientEnv(cmd *exec.Cmd) {
|
|
| 229 |
+ pwd := "12345678" |
|
| 229 | 230 |
env := []string{
|
| 230 |
- fmt.Sprintf("NOTARY_ROOT_PASSPHRASE=%s", rootPwd),
|
|
| 231 |
- fmt.Sprintf("NOTARY_TARGETS_PASSPHRASE=%s", repositoryPwd),
|
|
| 232 |
- fmt.Sprintf("NOTARY_SNAPSHOT_PASSPHRASE=%s", repositoryPwd),
|
|
| 231 |
+ fmt.Sprintf("NOTARY_ROOT_PASSPHRASE=%s", pwd),
|
|
| 232 |
+ fmt.Sprintf("NOTARY_TARGETS_PASSPHRASE=%s", pwd),
|
|
| 233 |
+ fmt.Sprintf("NOTARY_SNAPSHOT_PASSPHRASE=%s", pwd),
|
|
| 233 | 234 |
} |
| 234 | 235 |
cmd.Env = append(os.Environ(), env...) |
| 235 | 236 |
} |
| 236 | 237 |
|
| 237 |
-func (s *DockerTrustSuite) notaryInitRepo(c *check.C, repoName, pwd string) {
|
|
| 238 |
+func (s *DockerTrustSuite) notaryInitRepo(c *check.C, repoName string) {
|
|
| 238 | 239 |
initCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "init", repoName) |
| 239 |
- notaryClientEnv(initCmd, pwd, pwd) |
|
| 240 |
+ notaryClientEnv(initCmd) |
|
| 240 | 241 |
out, _, err := runCommandWithOutput(initCmd) |
| 241 | 242 |
if err != nil {
|
| 242 | 243 |
c.Fatalf("Error initializing notary repository: %s\n", out)
|
| 243 | 244 |
} |
| 244 | 245 |
} |
| 245 | 246 |
|
| 246 |
-func (s *DockerTrustSuite) notaryCreateDelegation(c *check.C, repoName, pwd, role string, pubKey string, paths ...string) {
|
|
| 247 |
+func (s *DockerTrustSuite) notaryCreateDelegation(c *check.C, repoName, role string, pubKey string, paths ...string) {
|
|
| 247 | 248 |
pathsArg := "--all-paths" |
| 248 | 249 |
if len(paths) > 0 {
|
| 249 | 250 |
pathsArg = "--paths=" + strings.Join(paths, ",") |
| ... | ... |
@@ -251,16 +253,16 @@ func (s *DockerTrustSuite) notaryCreateDelegation(c *check.C, repoName, pwd, rol |
| 251 | 251 |
|
| 252 | 252 |
delgCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), |
| 253 | 253 |
"delegation", "add", repoName, role, pubKey, pathsArg) |
| 254 |
- notaryClientEnv(delgCmd, pwd, pwd) |
|
| 254 |
+ notaryClientEnv(delgCmd) |
|
| 255 | 255 |
out, _, err := runCommandWithOutput(delgCmd) |
| 256 | 256 |
if err != nil {
|
| 257 | 257 |
c.Fatalf("Error adding %s role to notary repository: %s\n", role, out)
|
| 258 | 258 |
} |
| 259 | 259 |
} |
| 260 | 260 |
|
| 261 |
-func (s *DockerTrustSuite) notaryPublish(c *check.C, repoName, pwd string) {
|
|
| 261 |
+func (s *DockerTrustSuite) notaryPublish(c *check.C, repoName string) {
|
|
| 262 | 262 |
pubCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "publish", repoName) |
| 263 |
- notaryClientEnv(pubCmd, pwd, pwd) |
|
| 263 |
+ notaryClientEnv(pubCmd) |
|
| 264 | 264 |
out, _, err := runCommandWithOutput(pubCmd) |
| 265 | 265 |
if err != nil {
|
| 266 | 266 |
c.Fatalf("Error publishing notary repository: %s\n", out)
|
| ... | ... |
@@ -270,20 +272,20 @@ func (s *DockerTrustSuite) notaryPublish(c *check.C, repoName, pwd string) {
|
| 270 | 270 |
func (s *DockerTrustSuite) notaryImportKey(c *check.C, repoName, role string, privKey string) {
|
| 271 | 271 |
impCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "key", |
| 272 | 272 |
"import", privKey, "-g", repoName, "-r", role) |
| 273 |
- notaryClientEnv(impCmd, "", "") |
|
| 273 |
+ notaryClientEnv(impCmd) |
|
| 274 | 274 |
out, _, err := runCommandWithOutput(impCmd) |
| 275 | 275 |
if err != nil {
|
| 276 | 276 |
c.Fatalf("Error importing key to notary repository: %s\n", out)
|
| 277 | 277 |
} |
| 278 | 278 |
} |
| 279 | 279 |
|
| 280 |
-func (s *DockerTrustSuite) notaryListTargetsInRoles(c *check.C, repoName, role string) map[string]string {
|
|
| 280 |
+func (s *DockerTrustSuite) notaryListTargetsInRole(c *check.C, repoName, role string) map[string]string {
|
|
| 281 | 281 |
listCmd := exec.Command(notaryBinary, "-c", filepath.Join(s.not.dir, "client-config.json"), "list", |
| 282 | 282 |
repoName, "-r", role) |
| 283 |
- notaryClientEnv(listCmd, "", "") |
|
| 283 |
+ notaryClientEnv(listCmd) |
|
| 284 | 284 |
out, _, err := runCommandWithOutput(listCmd) |
| 285 | 285 |
if err != nil {
|
| 286 |
- c.Fatalf("Error importing key to notary repository: %s\n", out)
|
|
| 286 |
+ c.Fatalf("Error listing targets in notary repository: %s\n", out)
|
|
| 287 | 287 |
} |
| 288 | 288 |
|
| 289 | 289 |
// should look something like: |
| ... | ... |
@@ -291,9 +293,16 @@ func (s *DockerTrustSuite) notaryListTargetsInRoles(c *check.C, repoName, role s |
| 291 | 291 |
// ------------------------------------------------------------------------------------------------------ |
| 292 | 292 |
// latest 24a36bbc059b1345b7e8be0df20f1b23caa3602e85d42fff7ecd9d0bd255de56 1377 targets |
| 293 | 293 |
|
| 294 |
+ targets := make(map[string]string) |
|
| 295 |
+ |
|
| 296 |
+ // no target |
|
| 294 | 297 |
lines := strings.Split(strings.TrimSpace(out), "\n") |
| 298 |
+ if len(lines) == 1 && strings.Contains(out, "No targets present in this repository.") {
|
|
| 299 |
+ return targets |
|
| 300 |
+ } |
|
| 301 |
+ |
|
| 302 |
+ // otherwise, there is at least one target |
|
| 295 | 303 |
c.Assert(len(lines), checker.GreaterOrEqualThan, 3) |
| 296 |
- targets := make(map[string]string) |
|
| 297 | 304 |
|
| 298 | 305 |
for _, line := range lines[2:] {
|
| 299 | 306 |
tokens := strings.Fields(line) |
| ... | ... |
@@ -304,18 +313,23 @@ func (s *DockerTrustSuite) notaryListTargetsInRoles(c *check.C, repoName, role s |
| 304 | 304 |
return targets |
| 305 | 305 |
} |
| 306 | 306 |
|
| 307 |
-func (s *DockerTrustSuite) assertTargetInDelegationRoles(c *check.C, repoName, target string, roles ...string) {
|
|
| 308 |
- // assert it's not in the target role |
|
| 309 |
- targets := s.notaryListTargetsInRoles(c, repoName, "targets") |
|
| 310 |
- roleName, ok := targets[target] |
|
| 311 |
- c.Assert(ok, checker.True) |
|
| 312 |
- c.Assert(roleName, checker.Not(checker.Equals), "targets") |
|
| 313 |
- |
|
| 307 |
+func (s *DockerTrustSuite) assertTargetInRoles(c *check.C, repoName, target string, roles ...string) {
|
|
| 314 | 308 |
// check all the roles |
| 315 | 309 |
for _, role := range roles {
|
| 316 |
- targets := s.notaryListTargetsInRoles(c, repoName, role) |
|
| 310 |
+ targets := s.notaryListTargetsInRole(c, repoName, role) |
|
| 317 | 311 |
roleName, ok := targets[target] |
| 318 | 312 |
c.Assert(ok, checker.True) |
| 319 | 313 |
c.Assert(roleName, checker.Equals, role) |
| 320 | 314 |
} |
| 321 | 315 |
} |
| 316 |
+ |
|
| 317 |
+func (s *DockerTrustSuite) assertTargetNotInRoles(c *check.C, repoName, target string, roles ...string) {
|
|
| 318 |
+ targets := s.notaryListTargetsInRole(c, repoName, "targets") |
|
| 319 |
+ |
|
| 320 |
+ roleName, ok := targets[target] |
|
| 321 |
+ if ok {
|
|
| 322 |
+ for _, role := range roles {
|
|
| 323 |
+ c.Assert(roleName, checker.Not(checker.Equals), role) |
|
| 324 |
+ } |
|
| 325 |
+ } |
|
| 326 |
+} |