func TestGetDelegationRolesInvalidPaths(t *testing.T) { ed25519 := signed.NewEd25519() repo := initRepo(t, ed25519) testKey1, err := ed25519.Create("targets/test", data.ED25519Key) assert.NoError(t, err) role, err := data.NewRole("targets/test", 1, []string{testKey1.ID()}, []string{"path", "anotherpath"}) assert.NoError(t, err) err = repo.UpdateDelegations(role, data.KeyList{testKey1}) assert.NoError(t, err) testKey2, err := ed25519.Create("targets/test/b", data.ED25519Key) assert.NoError(t, err) // Now we add a delegation with a path that is not prefixed by its parent delegation role, err = data.NewRole("targets/test/b", 1, []string{testKey2.ID()}, []string{"invalidpath"}) assert.NoError(t, err) err = repo.UpdateDelegations(role, data.KeyList{testKey2}) assert.NoError(t, err) // Getting this delegation does not actually restrict paths, unless we use the RestrictChild method delgRole, err := repo.GetDelegationRole("targets/test/b") assert.NoError(t, err) assert.Contains(t, delgRole.Paths, "invalidpath") delgRole, err = repo.GetDelegationRole("targets/test") assert.NoError(t, err) assert.Contains(t, delgRole.Paths, "path") assert.Contains(t, delgRole.Paths, "anotherpath") }
func TestUpdateDelegations(t *testing.T) { ed25519 := signed.NewEd25519() keyDB := keys.NewDB() repo := initRepo(t, ed25519, keyDB) testKey, err := ed25519.Create("targets/test", data.ED25519Key) if err != nil { t.Fatal(err) } role, err := data.NewRole("targets/test", 1, []string{testKey.ID()}, []string{"test"}, []string{}) if err != nil { t.Fatal(err) } err = repo.UpdateDelegations(role, data.KeyList{testKey}, "") if err != nil { t.Fatal(err) } testDeepKey, err := ed25519.Create("targets/test/deep", data.ED25519Key) if err != nil { t.Fatal(err) } roleDeep, err := data.NewRole("targets/test/deep", 1, []string{testDeepKey.ID()}, []string{"test/deep"}, []string{}) if err != nil { t.Fatal(err) } err = repo.UpdateDelegations(roleDeep, data.KeyList{testDeepKey}, "") if err != nil { t.Fatal(err) } writeRepo(t, "/tmp/tufdelegation", repo) }
func TestDeleteDelegationsRoleNotExistBecauseNoParentMeta(t *testing.T) { ed25519 := signed.NewEd25519() keyDB := keys.NewDB() repo := initRepo(t, ed25519, keyDB) testKey, err := ed25519.Create("targets/test", data.ED25519Key) assert.NoError(t, err) role, err := data.NewRole("targets/test", 1, []string{testKey.ID()}, []string{"test"}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(role, data.KeyList{testKey}) assert.NoError(t, err) // no empty delegation metadata created for new delegation _, ok := repo.Targets["targets/test"] assert.False(t, ok, "no targets file should be created for empty delegation") delRole, err := data.NewRole( "targets/test/a", 1, []string{testKey.ID()}, []string{"test"}, []string{}) err = repo.DeleteDelegation(*delRole) assert.NoError(t, err) // still no metadata _, ok = repo.Targets["targets/test"] assert.False(t, ok) }
func TestDeleteDelegationsMidSliceRole(t *testing.T) { ed25519 := signed.NewEd25519() keyDB := keys.NewDB() repo := initRepo(t, ed25519, keyDB) testKey, err := ed25519.Create("targets/test", data.ED25519Key) assert.NoError(t, err) role, err := data.NewRole("targets/test", 1, []string{}, []string{""}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(role, data.KeyList{testKey}) assert.NoError(t, err) role2, err := data.NewRole("targets/test2", 1, []string{}, []string{""}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(role2, data.KeyList{testKey}) assert.NoError(t, err) role3, err := data.NewRole("targets/test3", 1, []string{}, []string{""}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(role3, data.KeyList{testKey}) assert.NoError(t, err) err = repo.DeleteDelegation(*role2) assert.NoError(t, err) r, ok := repo.Targets[data.CanonicalTargetsRole] assert.True(t, ok) assert.Len(t, r.Signed.Delegations.Roles, 2) assert.Len(t, r.Signed.Delegations.Keys, 1) assert.True(t, r.Dirty) }
func TestRotationNewSigMissing(t *testing.T) { logrus.SetLevel(logrus.DebugLevel) kdb := keys.NewDB() signer := signed.NewEd25519() repo := tuf.NewRepo(kdb, signer) remote := store.NewMemoryStore(nil, nil) cache := store.NewMemoryStore(nil, nil) // Generate initial root key and role and add to key DB rootKey, err := signer.Create("root", data.ED25519Key) assert.NoError(t, err, "Error creating root key") rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil, nil) assert.NoError(t, err, "Error creating root role") kdb.AddKey(rootKey) err = kdb.AddRole(rootRole) assert.NoError(t, err, "Error adding root role to db") // Generate new key and role. These will appear in the root.json // but will not be added to the keyDB. replacementKey, err := signer.Create("root", data.ED25519Key) assert.NoError(t, err, "Error creating replacement root key") replacementRole, err := data.NewRole("root", 1, []string{replacementKey.ID()}, nil, nil) assert.NoError(t, err, "Error creating replacement root role") assert.NotEqual(t, rootKey.ID(), replacementKey.ID(), "Key IDs are the same") // Generate a new root with the replacement key and role testRoot, err := data.NewRoot( map[string]data.PublicKey{replacementKey.ID(): replacementKey}, map[string]*data.RootRole{"root": &replacementRole.RootRole}, false, ) assert.NoError(t, err, "Failed to create new root") _, ok := testRoot.Signed.Keys[rootKey.ID()] assert.False(t, ok, "Old root key appeared in test root") // Sign testRoot with both old and new keys signedRoot, err := testRoot.ToSigned() err = signed.Sign(signer, signedRoot, rootKey) assert.NoError(t, err, "Failed to sign root") var origKeySig bool var replKeySig bool for _, sig := range signedRoot.Signatures { if sig.KeyID == rootKey.ID() { origKeySig = true } else if sig.KeyID == replacementKey.ID() { replKeySig = true } } assert.True(t, origKeySig, "Original root key signature not present") assert.False(t, replKeySig, "Replacement root key signature was present and shouldn't be") client := NewClient(repo, remote, kdb, cache) err = client.verifyRoot("root", signedRoot, 0) assert.Error(t, err, "Should have errored on verify as replacement signature was missing.") }
func TestRotation(t *testing.T) { signer := signed.NewEd25519() repo := tuf.NewRepo(signer) remote := store.NewMemoryStore(nil) cache := store.NewMemoryStore(nil) // Generate initial root key and role and add to key DB rootKey, err := signer.Create("root", data.ED25519Key) assert.NoError(t, err, "Error creating root key") rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil) assert.NoError(t, err, "Error creating root role") originalRoot, err := data.NewRoot( map[string]data.PublicKey{rootKey.ID(): rootKey}, map[string]*data.RootRole{"root": &rootRole.RootRole}, false, ) repo.Root = originalRoot // Generate new key and role. replacementKey, err := signer.Create("root", data.ED25519Key) assert.NoError(t, err, "Error creating replacement root key") replacementRole, err := data.NewRole("root", 1, []string{replacementKey.ID()}, nil) assert.NoError(t, err, "Error creating replacement root role") // Generate a new root with the replacement key and role testRoot, err := data.NewRoot( map[string]data.PublicKey{replacementKey.ID(): replacementKey}, map[string]*data.RootRole{ data.CanonicalRootRole: &replacementRole.RootRole, data.CanonicalSnapshotRole: &replacementRole.RootRole, data.CanonicalTargetsRole: &replacementRole.RootRole, data.CanonicalTimestampRole: &replacementRole.RootRole, }, false, ) assert.NoError(t, err, "Failed to create new root") // Sign testRoot with both old and new keys signedRoot, err := testRoot.ToSigned() err = signed.Sign(signer, signedRoot, rootKey, replacementKey) assert.NoError(t, err, "Failed to sign root") var origKeySig bool var replKeySig bool for _, sig := range signedRoot.Signatures { if sig.KeyID == rootKey.ID() { origKeySig = true } else if sig.KeyID == replacementKey.ID() { replKeySig = true } } assert.True(t, origKeySig, "Original root key signature not present") assert.True(t, replKeySig, "Replacement root key signature not present") client := NewClient(repo, remote, cache) err = client.verifyRoot("root", signedRoot, 0) assert.NoError(t, err, "Failed to verify key rotated root") }
func initRoles(kdb *keys.KeyDB, rootKey, targetsKey, snapshotKey, timestampKey data.PublicKey) error { rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil, nil) if err != nil { return err } targetsRole, err := data.NewRole("targets", 1, []string{targetsKey.ID()}, nil, nil) if err != nil { return err } snapshotRole, err := data.NewRole("snapshot", 1, []string{snapshotKey.ID()}, nil, nil) if err != nil { return err } timestampRole, err := data.NewRole("timestamp", 1, []string{timestampKey.ID()}, nil, nil) if err != nil { return err } if err := kdb.AddRole(rootRole); err != nil { return err } if err := kdb.AddRole(targetsRole); err != nil { return err } if err := kdb.AddRole(snapshotRole); err != nil { return err } if err := kdb.AddRole(timestampRole); err != nil { return err } return nil }
func TestUpdateDelegationsReplaceRole(t *testing.T) { ed25519 := signed.NewEd25519() keyDB := keys.NewDB() repo := initRepo(t, ed25519, keyDB) testKey, err := ed25519.Create("targets/test", data.ED25519Key) assert.NoError(t, err) role, err := data.NewRole("targets/test", 1, []string{testKey.ID()}, []string{"test"}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(role, data.KeyList{testKey}) assert.NoError(t, err) r, ok := repo.Targets[data.CanonicalTargetsRole] assert.True(t, ok) assert.Len(t, r.Signed.Delegations.Roles, 1) assert.Len(t, r.Signed.Delegations.Keys, 1) keyIDs := r.Signed.Delegations.Roles[0].KeyIDs assert.Len(t, keyIDs, 1) assert.Equal(t, testKey.ID(), keyIDs[0]) // no empty delegation metadata created for new delegation _, ok = repo.Targets["targets/test"] assert.False(t, ok, "no targets file should be created for empty delegation") // create one now to assert that replacing the delegation doesn't delete the // metadata repo.InitTargets("targets/test") // create another role with the same name and ensure it replaces the // previous role testKey2, err := ed25519.Create("targets/test", data.ED25519Key) assert.NoError(t, err) role2, err := data.NewRole("targets/test", 1, []string{testKey2.ID()}, []string{"test"}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(role2, data.KeyList{testKey2}) assert.NoError(t, err) r, ok = repo.Targets["targets"] assert.True(t, ok) assert.Len(t, r.Signed.Delegations.Roles, 1) assert.Len(t, r.Signed.Delegations.Keys, 1) keyIDs = r.Signed.Delegations.Roles[0].KeyIDs assert.Len(t, keyIDs, 1) assert.Equal(t, testKey2.ID(), keyIDs[0]) assert.True(t, r.Dirty) // delegation was not deleted _, ok = repo.Targets["targets/test"] assert.True(t, ok, "targets file should still be here") }
func TestUpdateDelegations(t *testing.T) { ed25519 := signed.NewEd25519() keyDB := keys.NewDB() repo := initRepo(t, ed25519, keyDB) testKey, err := ed25519.Create("targets/test", data.ED25519Key) assert.NoError(t, err) role, err := data.NewRole("targets/test", 1, []string{testKey.ID()}, []string{"test"}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(role, data.KeyList{testKey}) assert.NoError(t, err) // no empty metadata is created for this role _, ok := repo.Targets["targets/test"] assert.False(t, ok, "no empty targets file should be created for deepest delegation") r, ok := repo.Targets[data.CanonicalTargetsRole] assert.True(t, ok) assert.Len(t, r.Signed.Delegations.Roles, 1) assert.Len(t, r.Signed.Delegations.Keys, 1) keyIDs := r.Signed.Delegations.Roles[0].KeyIDs assert.Len(t, keyIDs, 1) assert.Equal(t, testKey.ID(), keyIDs[0]) testDeepKey, err := ed25519.Create("targets/test/deep", data.ED25519Key) assert.NoError(t, err) roleDeep, err := data.NewRole("targets/test/deep", 1, []string{testDeepKey.ID()}, []string{"test/deep"}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(roleDeep, data.KeyList{testDeepKey}) assert.NoError(t, err) // this metadata didn't exist before, but creating targets/test/deep created // the targets/test metadata r, ok = repo.Targets["targets/test"] assert.True(t, ok) assert.Len(t, r.Signed.Delegations.Roles, 1) assert.Len(t, r.Signed.Delegations.Keys, 1) keyIDs = r.Signed.Delegations.Roles[0].KeyIDs assert.Len(t, keyIDs, 1) assert.Equal(t, testDeepKey.ID(), keyIDs[0]) assert.True(t, r.Dirty) // no empty delegation metadata is created for targets/test/deep _, ok = repo.Targets["targets/test/deep"] assert.False(t, ok, "no empty targets file should be created for deepest delegation") }
// AddBaseKeys is used to add keys to the role in root.json func (tr *Repo) AddBaseKeys(role string, keys ...data.PublicKey) error { if tr.Root == nil { return ErrNotLoaded{role: "root"} } ids := []string{} for _, k := range keys { // Store only the public portion tr.Root.Signed.Keys[k.ID()] = k tr.keysDB.AddKey(k) tr.Root.Signed.Roles[role].KeyIDs = append(tr.Root.Signed.Roles[role].KeyIDs, k.ID()) ids = append(ids, k.ID()) } r, err := data.NewRole( role, tr.Root.Signed.Roles[role].Threshold, ids, nil, nil, ) if err != nil { return err } tr.keysDB.AddRole(r) tr.Root.Dirty = true return nil }
func TestDuplicateSigs(t *testing.T) { cs := NewEd25519() k, err := cs.Create("root", data.ED25519Key) assert.NoError(t, err) r, err := data.NewRole( "root", 2, []string{k.ID()}, nil, nil, ) assert.NoError(t, err) db := keys.NewDB() assert.NoError(t, err) db.AddKey(k) err = db.AddRole(r) assert.NoError(t, err) meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) assert.NoError(t, err) s := &data.Signed{Signed: b} Sign(cs, s, k) s.Signatures = append(s.Signatures, s.Signatures[0]) err = Verify(s, "root", 1, db) assert.IsType(t, ErrRoleThreshold{}, err) }
func TestMoreThanEnoughSigs(t *testing.T) { cs := NewEd25519() k1, err := cs.Create("root", data.ED25519Key) assert.NoError(t, err) k2, err := cs.Create("root", data.ED25519Key) assert.NoError(t, err) r, err := data.NewRole( "root", 1, []string{k1.ID(), k2.ID()}, nil, nil, ) assert.NoError(t, err) db := keys.NewDB() assert.NoError(t, err) db.AddKey(k1) db.AddKey(k2) err = db.AddRole(r) assert.NoError(t, err) meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) assert.NoError(t, err) s := &data.Signed{Signed: b} Sign(cs, s, k1, k2) assert.Equal(t, 2, len(s.Signatures)) err = Verify(s, "root", 1, db) assert.NoError(t, err) }
// Adding targets to a role that exists and has not metadata first creates the // metadata and then correctly adds the target func TestAddTargetsRoleExistsAndMetadataDoesntExist(t *testing.T) { hash := sha256.Sum256([]byte{}) f := data.FileMeta{ Length: 1, Hashes: map[string][]byte{ "sha256": hash[:], }, } ed25519 := signed.NewEd25519() repo := initRepo(t, ed25519) testKey, err := ed25519.Create("targets/test", data.ED25519Key) assert.NoError(t, err) role, err := data.NewRole("targets/test", 1, []string{testKey.ID()}, []string{""}) assert.NoError(t, err) err = repo.UpdateDelegations(role, data.KeyList{testKey}) assert.NoError(t, err) // no empty metadata is created for this role _, ok := repo.Targets["targets/test"] assert.False(t, ok, "no empty targets file should be created") // adding the targets to the role should create the metadata though _, err = repo.AddTargets("targets/test", data.Files{"f": f}) assert.NoError(t, err) r, ok := repo.Targets["targets/test"] assert.True(t, ok) targetsF, ok := r.Signed.Targets["f"] assert.True(t, ok) assert.Equal(t, f, targetsF) }
// ToNewRole creates a fresh role object from the TUFDelegation data func (td TUFDelegation) ToNewRole(scope string) (*data.Role, error) { name := scope if td.NewName != "" { name = td.NewName } return data.NewRole(name, td.NewThreshold, td.AddKeys.IDs(), td.AddPaths) }
// If applying a change fails due to a prefix error, it does not fall back // on the parent. func TestChangeTargetMetaDoesntFallbackIfPrefixError(t *testing.T) { repo, cs, err := testutils.EmptyRepo("docker.com/notary") assert.NoError(t, err) newKey, err := cs.Create("targets/level1", data.ED25519Key) assert.NoError(t, err) r, err := data.NewRole("targets/level1", 1, []string{newKey.ID()}, []string{"pathprefix"}) assert.NoError(t, err) repo.UpdateDelegations(r, []data.PublicKey{newKey}) hash := sha256.Sum256([]byte{}) f := &data.FileMeta{ Length: 1, Hashes: map[string][]byte{ "sha256": hash[:], }, } fjson, err := json.Marshal(f) assert.NoError(t, err) err = changeTargetMeta(repo, &changelist.TufChange{ Actn: changelist.ActionCreate, Role: "targets/level1", ChangeType: "target", ChangePath: "notPathPrefix", Data: fjson, }) assert.Error(t, err) // no target in targets or targets/latest assert.Empty(t, repo.Targets[data.CanonicalTargetsRole].Signed.Targets) assert.Empty(t, repo.Targets["targets/level1"].Signed.Targets) }
// Adding targets to a role that we don't have signing keys for fails func TestAddTargetsNoSigningKeys(t *testing.T) { hash := sha256.Sum256([]byte{}) f := data.FileMeta{ Length: 1, Hashes: map[string][]byte{ "sha256": hash[:], }, } ed25519 := signed.NewEd25519() keyDB := keys.NewDB() repo := initRepo(t, ed25519, keyDB) testKey, err := ed25519.Create("targets/test", data.ED25519Key) assert.NoError(t, err) role, err := data.NewRole( "targets/test", 1, []string{testKey.ID()}, []string{"test"}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(role, data.KeyList{testKey}) assert.NoError(t, err) // now delete the signing key (all keys) repo.cryptoService = signed.NewEd25519() // adding the targets to the role should create the metadata though _, err = repo.AddTargets("targets/test", data.Files{"f": f}) assert.Error(t, err) assert.IsType(t, signed.ErrNoKeys{}, err) }
// Removing targets from a role that exists, has targets, and is signable // should succeed, even if we also want to remove targets that don't exist. func TestRemoveExistingAndNonexistingTargets(t *testing.T) { ed25519 := signed.NewEd25519() keyDB := keys.NewDB() repo := initRepo(t, ed25519, keyDB) testKey, err := ed25519.Create("targets/test", data.ED25519Key) assert.NoError(t, err) role, err := data.NewRole( "targets/test", 1, []string{testKey.ID()}, []string{"test"}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(role, data.KeyList{testKey}) assert.NoError(t, err) // no empty metadata is created for this role _, ok := repo.Targets["targets/test"] assert.False(t, ok, "no empty targets file should be created") // now remove a target assert.NoError(t, repo.RemoveTargets("targets/test", "f")) // still no metadata _, ok = repo.Targets["targets/test"] assert.False(t, ok) }
// A delegation can be created with a role that is missing a signing key, so // long as UpdateDelegations is called with the key func TestUpdateDelegationsRoleThatIsMissingDelegationKey(t *testing.T) { ed25519 := signed.NewEd25519() keyDB := keys.NewDB() repo := initRepo(t, ed25519, keyDB) roleKey, err := ed25519.Create("Invalid Role", data.ED25519Key) assert.NoError(t, err) role, err := data.NewRole("targets/role", 1, []string{}, []string{""}, []string{}) assert.NoError(t, err) // key should get added to role as part of updating the delegation err = repo.UpdateDelegations(role, data.KeyList{roleKey}) assert.NoError(t, err) r, ok := repo.Targets[data.CanonicalTargetsRole] assert.True(t, ok) assert.Len(t, r.Signed.Delegations.Roles, 1) assert.Len(t, r.Signed.Delegations.Keys, 1) keyIDs := r.Signed.Delegations.Roles[0].KeyIDs assert.Len(t, keyIDs, 1) assert.Equal(t, roleKey.ID(), keyIDs[0]) assert.True(t, r.Dirty) // no empty delegation metadata created for new delegation _, ok = repo.Targets["targets/role"] assert.False(t, ok, "no targets file should be created for empty delegation") }
func TestUpdateDelegationsInvalidRole(t *testing.T) { ed25519 := signed.NewEd25519() keyDB := keys.NewDB() repo := initRepo(t, ed25519, keyDB) roleKey, err := ed25519.Create("Invalid Role", data.ED25519Key) assert.NoError(t, err) // data.NewRole errors if the role isn't a valid TUF role so use one of the non-delegation // valid roles invalidRole, err := data.NewRole("root", 1, []string{roleKey.ID()}, []string{}, []string{}) assert.NoError(t, err) err = repo.UpdateDelegations(invalidRole, data.KeyList{roleKey}) assert.Error(t, err) assert.IsType(t, data.ErrInvalidRole{}, err) r, ok := repo.Targets[data.CanonicalTargetsRole] assert.True(t, ok) assert.Len(t, r.Signed.Delegations.Roles, 0) // no delegation metadata created for invalid delgation _, ok = repo.Targets["root"] assert.False(t, ok, "no targets file should be created since delegation failed") }
// SetRoot parses the Signed object into a SignedRoot object, sets // the keys and roles in the KeyDB, and sets the Repo.Root field // to the SignedRoot object. func (tr *Repo) SetRoot(s *data.SignedRoot) error { for _, key := range s.Signed.Keys { logrus.Debug("Adding key ", key.ID()) tr.keysDB.AddKey(key) } for roleName, role := range s.Signed.Roles { logrus.Debugf("Adding role %s with keys %s", roleName, strings.Join(role.KeyIDs, ",")) baseRole, err := data.NewRole( roleName, role.Threshold, role.KeyIDs, nil, nil, ) if err != nil { return err } err = tr.keysDB.AddRole(baseRole) if err != nil { return err } } tr.Root = s return nil }
// Each change applies only to the role specified func TestApplyChangelistTargetsToMultipleRoles(t *testing.T) { repo, cs, err := testutils.EmptyRepo("docker.com/notary") assert.NoError(t, err) newKey, err := cs.Create("targets/level1", data.ED25519Key) assert.NoError(t, err) r, err := data.NewRole("targets/level1", 1, []string{newKey.ID()}, []string{""}) assert.NoError(t, err) repo.UpdateDelegations(r, []data.PublicKey{newKey}) r, err = data.NewRole("targets/level2", 1, []string{newKey.ID()}, []string{""}) assert.NoError(t, err) repo.UpdateDelegations(r, []data.PublicKey{newKey}) hash := sha256.Sum256([]byte{}) f := &data.FileMeta{ Length: 1, Hashes: map[string][]byte{ "sha256": hash[:], }, } fjson, err := json.Marshal(f) assert.NoError(t, err) cl := changelist.NewMemChangelist() assert.NoError(t, cl.Add(&changelist.TufChange{ Actn: changelist.ActionCreate, Role: "targets/level1", ChangeType: "target", ChangePath: "latest", Data: fjson, })) assert.NoError(t, cl.Add(&changelist.TufChange{ Actn: changelist.ActionDelete, Role: "targets/level2", ChangeType: "target", ChangePath: "latest", Data: nil, })) assert.NoError(t, applyChangelist(repo, cl)) _, ok := repo.Targets["targets/level1"].Signed.Targets["latest"] assert.True(t, ok) _, ok = repo.Targets["targets/level2"] assert.False(t, ok, "no change to targets/level2, so metadata not created") }
func TestValidateTargetsRoleNotInParent(t *testing.T) { baseRepo, cs, err := testutils.EmptyRepo("docker.com/notary") assert.NoError(t, err) store := storage.NewMemStorage() level1Key, err := cs.Create("targets/level1", data.ED25519Key) assert.NoError(t, err) r, err := data.NewRole("targets/level1", 1, []string{level1Key.ID()}, []string{""}) baseRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Roles = []*data.Role{r} baseRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Keys = data.Keys{ level1Key.ID(): level1Key, } baseRepo.InitTargets("targets/level1") del, err := baseRepo.SignTargets("targets/level1", data.DefaultExpires(data.CanonicalTargetsRole)) assert.NoError(t, err) delJSON, err := json.Marshal(del) assert.NoError(t, err) delUpdate := storage.MetaUpdate{ Role: "targets/level1", Version: 1, Data: delJSON, } // set back to empty so stored targets doesn't have reference to level1 baseRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Roles = nil baseRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Keys = nil targets, err := baseRepo.SignTargets(data.CanonicalTargetsRole, data.DefaultExpires(data.CanonicalTargetsRole)) tgtsJSON, err := json.Marshal(targets) assert.NoError(t, err) update := storage.MetaUpdate{ Role: data.CanonicalTargetsRole, Version: 1, Data: tgtsJSON, } store.UpdateCurrent("gun", update) roles := map[string]storage.MetaUpdate{ "targets/level1": delUpdate, data.CanonicalTargetsRole: update, } valRepo := tuf.NewRepo(nil) valRepo.SetRoot(baseRepo.Root) // because we sort the roles, the list of returned updates // will contain shallower roles first, in this case "targets", // and then "targets/level1" updates, err := loadAndValidateTargets("gun", valRepo, roles, store) assert.NoError(t, err) assert.Len(t, updates, 1) assert.Equal(t, data.CanonicalTargetsRole, updates[0].Role) assert.Equal(t, tgtsJSON, updates[0].Data) }
func TestValidateTargetsParentInUpdate(t *testing.T) { _, baseRepo, cs, err := testutils.EmptyRepo("docker.com/notary") assert.NoError(t, err) store := storage.NewMemStorage() k, err := cs.Create("targets/level1", data.ED25519Key) assert.NoError(t, err) r, err := data.NewRole("targets/level1", 1, []string{k.ID()}, []string{""}, nil) assert.NoError(t, err) baseRepo.UpdateDelegations(r, []data.PublicKey{k}) // no targets file is created for the new delegations, so force one baseRepo.InitTargets("targets/level1") targets, err := baseRepo.SignTargets("targets", data.DefaultExpires(data.CanonicalTargetsRole)) tgtsJSON, err := json.Marshal(targets) assert.NoError(t, err) update := storage.MetaUpdate{ Role: data.CanonicalTargetsRole, Version: 1, Data: tgtsJSON, } store.UpdateCurrent("gun", update) del, err := baseRepo.SignTargets("targets/level1", data.DefaultExpires(data.CanonicalTargetsRole)) assert.NoError(t, err) delJSON, err := json.Marshal(del) assert.NoError(t, err) delUpdate := storage.MetaUpdate{ Role: "targets/level1", Version: 1, Data: delJSON, } roles := map[string]storage.MetaUpdate{ "targets/level1": delUpdate, "targets": update, } kdb := keys.NewDB() valRepo := tuf.NewRepo(kdb, nil) valRepo.SetRoot(baseRepo.Root) // because we sort the roles, the list of returned updates // will contain shallower roles first, in this case "targets", // and then "targets/level1" updates, err := loadAndValidateTargets("gun", valRepo, roles, kdb, store) assert.NoError(t, err) assert.Len(t, updates, 2) assert.Equal(t, "targets", updates[0].Role) assert.Equal(t, tgtsJSON, updates[0].Data) assert.Equal(t, "targets/level1", updates[1].Role) assert.Equal(t, delJSON, updates[1].Data) }
func TestFindRoleIndexNotFound(t *testing.T) { role, err := data.NewRole("targets/test", 1, []string{}, []string{""}) require.NoError(t, err) require.Equal( t, -1, FindRoleIndex(nil, role.Name), ) }
func TestFindRoleIndexFound(t *testing.T) { role, err := data.NewRole("targets/test", 1, []string{}, []string{""}) assert.NoError(t, err) assert.Equal( t, 0, FindRoleIndex([]*data.Role{role}, role.Name), ) }
func TestValidateTargetsRoleNotInParent(t *testing.T) { kdb, baseRepo, cs := testutils.EmptyRepo() store := storage.NewMemStorage() k, err := cs.Create("targets/level1", data.ED25519Key) assert.NoError(t, err) r, err := data.NewRole("targets/level1", 1, []string{k.ID()}, []string{""}, nil) assert.NoError(t, err) kdb.AddKey(k) err = kdb.AddRole(r) assert.NoError(t, err) baseRepo.InitTargets("targets/level1") targets, err := baseRepo.SignTargets("targets", data.DefaultExpires(data.CanonicalTargetsRole)) tgtsJSON, err := json.MarshalCanonical(targets) assert.NoError(t, err) update := storage.MetaUpdate{ Role: data.CanonicalTargetsRole, Version: 1, Data: tgtsJSON, } store.UpdateCurrent("gun", update) del, err := baseRepo.SignTargets("targets/level1", data.DefaultExpires(data.CanonicalTargetsRole)) assert.NoError(t, err) delJSON, err := json.MarshalCanonical(del) assert.NoError(t, err) delUpdate := storage.MetaUpdate{ Role: "targets/level1", Version: 1, Data: delJSON, } roles := map[string]storage.MetaUpdate{ "targets/level1": delUpdate, "targets": update, } kdb = keys.NewDB() valRepo := tuf.NewRepo(kdb, nil) valRepo.SetRoot(baseRepo.Root) // because we sort the roles, the list of returned updates // will contain shallower roles first, in this case "targets", // and then "targets/level1" updates, err := loadAndValidateTargets("gun", valRepo, roles, kdb, store) assert.NoError(t, err) assert.Len(t, updates, 1) assert.Equal(t, "targets", updates[0].Role) assert.Equal(t, tgtsJSON, updates[0].Data) }
// add a key to a KeyDB, and create a role for the key and add it. func addKeyForRole(kdb *keys.KeyDB, role string, key data.PublicKey) error { theRole, err := data.NewRole(role, 1, []string{key.ID()}, nil, nil) if err != nil { return err } kdb.AddKey(key) if err := kdb.AddRole(theRole); err != nil { return err } return nil }
func testValidateSuccessfulRootRotation(t *testing.T, keyAlg, rootKeyType string) { // The gun to test gun := "docker.com/notary" tempBaseDir, keyStoreManager, certs := filestoreWithTwoCerts(t, gun, keyAlg) defer os.RemoveAll(tempBaseDir) origRootCert := certs[0] replRootCert := certs[1] // Add the old root cert part of trustedCertificates keyStoreManager.AddTrustedCert(origRootCert) // We need the PEM representation of the replacement key to put it into the TUF data origRootPEMCert := trustmanager.CertToPEM(origRootCert) replRootPEMCert := trustmanager.CertToPEM(replRootCert) // Tuf key with PEM-encoded x509 certificate origRootKey := data.NewPublicKey(rootKeyType, origRootPEMCert) replRootKey := data.NewPublicKey(rootKeyType, replRootPEMCert) rootRole, err := data.NewRole("root", 1, []string{replRootKey.ID()}, nil, nil) assert.NoError(t, err) testRoot, err := data.NewRoot( map[string]data.PublicKey{replRootKey.ID(): replRootKey}, map[string]*data.RootRole{"root": &rootRole.RootRole}, false, ) assert.NoError(t, err, "Failed to create new root") signedTestRoot, err := testRoot.ToSigned() assert.NoError(t, err) cs := cryptoservice.NewCryptoService(gun, keyStoreManager.KeyStore) err = signed.Sign(cs, signedTestRoot, replRootKey) assert.NoError(t, err) err = signed.Sign(cs, signedTestRoot, origRootKey) assert.NoError(t, err) // // This call to ValidateRoot will succeed since we are using a valid PEM // encoded certificate, and have no other certificates for this CN // err = keyStoreManager.ValidateRoot(signedTestRoot, gun) assert.NoError(t, err) // Finally, validate the only trusted certificate that exists is the new one certs = keyStoreManager.trustedCertificateStore.GetCertificates() assert.Len(t, certs, 1) assert.Equal(t, certs[0], replRootCert) }
// If the parent exists, the metadata exists, and the delegation is in it, // returns the role that was found func TestGetDelegationRoleAndMetadataExistDelegationExists(t *testing.T) { ed25519 := signed.NewEd25519() repo := initRepo(t, ed25519) testKey, err := ed25519.Create("meh", data.ED25519Key) assert.NoError(t, err) role, err := data.NewRole("targets/level1", 1, []string{testKey.ID()}, []string{""}) assert.NoError(t, err) assert.NoError(t, repo.UpdateDelegations(role, data.KeyList{testKey})) role, err = data.NewRole("targets/level1/level2", 1, []string{testKey.ID()}, []string{""}) assert.NoError(t, err) assert.NoError(t, repo.UpdateDelegations(role, data.KeyList{testKey})) gottenRole, gottenKeys, err := repo.GetDelegation("targets/level1/level2") assert.NoError(t, err) assert.Equal(t, role, gottenRole) _, ok := gottenKeys[testKey.ID()] assert.True(t, ok) }
// TargetMeta returns the file metadata for a file path in the role subtree, // if it exists. It also returns the role in that subtree in which the target // was found. If the path doesn't exist in that role subtree, returns // nil and an empty string. func TestTargetMeta(t *testing.T) { kdb, repo, cs, err := testutils.EmptyRepo("docker.com/notary") assert.NoError(t, err) localStorage := store.NewMemoryStore(nil) client := NewClient(repo, nil, kdb, localStorage) delegations := []string{ "targets/level1", "targets/level1/a", "targets/level1/a/i", } k, err := cs.Create("", data.ED25519Key) assert.NoError(t, err) hash := sha256.Sum256([]byte{}) f := data.FileMeta{ Length: 1, Hashes: map[string][]byte{ "sha256": hash[:], }, } for i, r := range delegations { // create role role, err := data.NewRole(r, 1, []string{k.ID()}, []string{""}, nil) assert.NoError(t, err) // add role to repo repo.UpdateDelegations(role, []data.PublicKey{k}) repo.InitTargets(r) // add a target to the role _, err = repo.AddTargets(r, data.Files{strconv.Itoa(i): f}) assert.NoError(t, err) } // returns the right level fileMeta, role := client.TargetMeta("targets", "1") assert.Equal(t, &f, fileMeta) assert.Equal(t, "targets/level1/a", role) // looks only in subtree fileMeta, role = client.TargetMeta("targets/level1/a", "0") assert.Nil(t, fileMeta) assert.Equal(t, "", role) fileMeta, role = client.TargetMeta("targets/level1/a", "2") assert.Equal(t, &f, fileMeta) assert.Equal(t, "targets/level1/a/i", role) }