diff --git a/client/client.go b/client/client.go index 9ceb0325ad..24b4f40a71 100644 --- a/client/client.go +++ b/client/client.go @@ -454,8 +454,7 @@ func (r *NotaryRepository) listSubtree(targets map[string]*Target, role string, } for name, meta := range tgts.Signed.Targets { if _, ok := targets[name]; !ok { - target := &Target{Name: name, Hashes: meta.Hashes, Length: meta.Length} - targets[name] = target + targets[name] = &Target{Name: name, Hashes: meta.Hashes, Length: meta.Length} } } for _, d := range tgts.Signed.Delegations.Roles { diff --git a/client/client_test.go b/client/client_test.go index 31c579b3a3..d59d8cce24 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -806,6 +806,14 @@ func fakeServerData(t *testing.T, repo *NotaryRepository, mux *http.ServeMux, assert.NoError(t, err) } + signedLevel2, err := savedTUFRepo.SignTargets( + "targets/level2", + data.DefaultExpires(data.CanonicalTargetsRole), + ) + if _, ok := savedTUFRepo.Targets["targets/level2"]; ok { + assert.NoError(t, err) + } + signedSnapshot, err := savedTUFRepo.SignSnapshot( data.DefaultExpires("snapshot")) assert.NoError(t, err) @@ -844,6 +852,13 @@ func fakeServerData(t *testing.T, repo *NotaryRepository, mux *http.ServeMux, assert.NoError(t, err) fmt.Fprint(w, string(level1JSON)) }) + + mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/targets/level2.json", + func(w http.ResponseWriter, r *http.Request) { + level1JSON, err := json.Marshal(signedLevel2) + assert.NoError(t, err) + fmt.Fprint(w, string(level1JSON)) + }) } // We want to sort by name, so we can guarantee ordering. @@ -939,6 +954,17 @@ func testListTargetWithDelegates(t *testing.T, rootType string) { delegatedTarget := addTarget(t, repo, "current", "../fixtures/root-ca.crt", "targets/level1") otherTarget := addTarget(t, repo, "other", "../fixtures/root-ca.crt", "targets/level1") + // setup delegated targets/level2 role + k, err = repo.CryptoService.Create("targets/level2", rootType) + assert.NoError(t, err) + r, err = data.NewRole("targets/level2", 1, []string{k.ID()}, nil, nil) + assert.NoError(t, err) + repo.tufRepo.UpdateDelegations(r, []data.PublicKey{k}) + // this target should not show up as the one in targets/level1 takes higher priority + _ = addTarget(t, repo, "current", "../fixtures/notary-server.crt", "targets/level2") + // this target should show up as the name doesn't exist elsewhere + level2Target := addTarget(t, repo, "level2", "../fixtures/notary-server.crt", "targets/level2") + // Apply the changelist. Normally, this would be done by Publish // load the changelist for this repo @@ -954,6 +980,8 @@ func testListTargetWithDelegates(t *testing.T, rootType string) { assert.True(t, ok) _, ok = repo.tufRepo.Targets["targets/level1"].Signed.Targets["other"] assert.True(t, ok) + _, ok = repo.tufRepo.Targets["targets/level2"].Signed.Targets["level2"] + assert.True(t, ok) fakeServerData(t, repo, mux, keys) @@ -961,14 +989,15 @@ func testListTargetWithDelegates(t *testing.T, rootType string) { assert.NoError(t, err) // Should be two targets - assert.Len(t, targets, 3, "unexpected number of targets returned by ListTargets") + assert.Len(t, targets, 4, "unexpected number of targets returned by ListTargets") sort.Stable(targetSorter(targets)) // current should be first assert.Equal(t, delegatedTarget, targets[0], "current target does not match") assert.Equal(t, latestTarget, targets[1], "latest target does not match") - assert.Equal(t, otherTarget, targets[2], "other target does not match") + assert.Equal(t, level2Target, targets[2], "level2 target does not match") + assert.Equal(t, otherTarget, targets[3], "other target does not match") // Also test GetTargetByName newLatestTarget, err := repo.GetTargetByName("latest") @@ -982,6 +1011,10 @@ func testListTargetWithDelegates(t *testing.T, rootType string) { newOtherTarget, err := repo.GetTargetByName("other") assert.NoError(t, err) assert.True(t, reflect.DeepEqual(otherTarget, newOtherTarget), "other target does not match") + + newLevel2Target, err := repo.GetTargetByName("level2") + assert.NoError(t, err) + assert.True(t, reflect.DeepEqual(level2Target, newLevel2Target), "level2 target does not match") } // TestValidateRootKey verifies that the public data in root.json for the root