addressing review

Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
David Lawrence 2015-12-15 14:31:12 -08:00
parent 79b05d4c0a
commit 5891805b29
5 changed files with 219 additions and 50 deletions

View File

@ -244,7 +244,7 @@ func (r *NotaryRepository) Initialize(rootKeyID string, serverManagedRoles ...st
logrus.Debug("Error on InitRoot: ", err.Error())
return err
}
err = r.tufRepo.InitTargets()
err = r.tufRepo.InitTargets(data.CanonicalTargetsRole)
if err != nil {
logrus.Debug("Error on InitTargets: ", err.Error())
return err

View File

@ -67,37 +67,51 @@ func applyTargetsChange(repo *tuf.Repo, c changelist.Change) error {
func changeTargetsDelegation(repo *tuf.Repo, c changelist.Change) error {
switch c.Action() {
case changelist.ActionCreate, changelist.ActionUpdate:
case changelist.ActionCreate:
td := changelist.TufDelegation{}
err := json.Unmarshal(c.Content(), &td)
if err != nil {
return err
}
r, err := repo.GetDelegation(c.Scope())
if err == nil {
// role exists, merge
if err := r.AddPaths(td.AddPaths); err != nil {
return err
}
if err := r.AddPathHashPrefixes(td.AddPathHashPrefixes); err != nil {
return err
}
r.RemoveKeys(td.RemoveKeys)
r.RemovePaths(td.RemovePaths)
r.RemovePathHashPrefixes(td.RemovePathHashPrefixes)
return repo.UpdateDelegations(r, td.AddKeys, "")
} else if _, ok := err.(data.ErrNoSuchRole); ok {
// role doesn't exist, create brand new
r, err = td.ToNewRole(c.Scope())
if err != nil {
return err
}
return repo.UpdateDelegations(r, td.AddKeys, "")
} else {
// any error other than ErrNoSuchRole indicates
// bad data
return fmt.Errorf("could not apply delegations change because: \"%v\"", err)
if _, ok := err.(data.ErrNoSuchRole); err != nil && !ok {
// error that wasn't ErrNoSuchRole
return err
}
if err == nil {
// role existed
return data.ErrInvalidRole{
Role: c.Scope(),
Reason: "cannot create a role that already exists",
}
}
// role doesn't exist, create brand new
r, err = td.ToNewRole(c.Scope())
if err != nil {
return err
}
return repo.UpdateDelegations(r, td.AddKeys)
case changelist.ActionUpdate:
td := changelist.TufDelegation{}
err := json.Unmarshal(c.Content(), &td)
if err != nil {
return err
}
r, err := repo.GetDelegation(c.Scope())
if err != nil {
return err
}
// role exists, merge
if err := r.AddPaths(td.AddPaths); err != nil {
return err
}
if err := r.AddPathHashPrefixes(td.AddPathHashPrefixes); err != nil {
return err
}
r.RemoveKeys(td.RemoveKeys)
r.RemovePaths(td.RemovePaths)
r.RemovePathHashPrefixes(td.RemovePathHashPrefixes)
return repo.UpdateDelegations(r, td.AddKeys)
case changelist.ActionDelete:
r := data.Role{Name: c.Scope()}
return repo.DeleteDelegation(r)

View File

@ -20,7 +20,7 @@ func TestApplyTargetsChange(t *testing.T) {
kdb.AddRole(role)
repo := tuf.NewRepo(kdb, nil)
err = repo.InitTargets()
err = repo.InitTargets(data.CanonicalTargetsRole)
assert.NoError(t, err)
hash := sha256.Sum256([]byte{})
f := &data.FileMeta{
@ -63,7 +63,7 @@ func TestApplyChangelist(t *testing.T) {
kdb.AddRole(role)
repo := tuf.NewRepo(kdb, nil)
err = repo.InitTargets()
err = repo.InitTargets(data.CanonicalTargetsRole)
assert.NoError(t, err)
hash := sha256.Sum256([]byte{})
f := &data.FileMeta{
@ -111,7 +111,7 @@ func TestApplyChangelistMulti(t *testing.T) {
kdb.AddRole(role)
repo := tuf.NewRepo(kdb, nil)
err = repo.InitTargets()
err = repo.InitTargets(data.CanonicalTargetsRole)
assert.NoError(t, err)
hash := sha256.Sum256([]byte{})
f := &data.FileMeta{
@ -185,6 +185,7 @@ func TestApplyTargetsDelegationCreateDelete(t *testing.T) {
assert.True(t, ok)
role := tgts.Signed.Delegations.Roles[0]
assert.Len(t, role.KeyIDs, 1)
assert.Equal(t, newKey.ID(), role.KeyIDs[0])
assert.Equal(t, "targets/level1", role.Name)
assert.Equal(t, "level1", role.Paths[0])
@ -260,11 +261,13 @@ func TestApplyTargetsDelegationCreate2SharedKey(t *testing.T) {
assert.Len(t, tgts.Signed.Delegations.Keys, 1)
role1 := tgts.Signed.Delegations.Roles[0]
assert.Len(t, role1.KeyIDs, 1)
assert.Equal(t, newKey.ID(), role1.KeyIDs[0])
assert.Equal(t, "targets/level1", role1.Name)
assert.Equal(t, "level1", role1.Paths[0])
role2 := tgts.Signed.Delegations.Roles[1]
assert.Len(t, role2.KeyIDs, 1)
assert.Equal(t, newKey.ID(), role2.KeyIDs[0])
assert.Equal(t, "targets/level2", role2.Name)
assert.Equal(t, "level2", role2.Paths[0])
@ -367,6 +370,73 @@ func TestApplyTargetsDelegationCreateEdit(t *testing.T) {
assert.Equal(t, "level1", role.Paths[0])
}
func TestApplyTargetsDelegationEditNonExisting(t *testing.T) {
_, repo, cs := testutils.EmptyRepo()
newKey, err := cs.Create("targets/level1", data.ED25519Key)
assert.NoError(t, err)
// create delegation
kl := data.KeyList{newKey}
td := &changelist.TufDelegation{
NewThreshold: 1,
AddKeys: kl,
AddPaths: []string{"level1"},
}
tdJSON, err := json.Marshal(td)
assert.NoError(t, err)
ch := changelist.NewTufChange(
changelist.ActionUpdate,
"targets/level1",
changelist.TypeTargetsDelegation,
"",
tdJSON,
)
err = applyTargetsChange(repo, ch)
assert.Error(t, err)
assert.IsType(t, data.ErrNoSuchRole{}, err)
}
func TestApplyTargetsDelegationCreateAlreadyExisting(t *testing.T) {
_, repo, cs := testutils.EmptyRepo()
newKey, err := cs.Create("targets/level1", data.ED25519Key)
assert.NoError(t, err)
// create delegation
kl := data.KeyList{newKey}
td := &changelist.TufDelegation{
NewThreshold: 1,
AddKeys: kl,
AddPaths: []string{"level1"},
}
tdJSON, err := json.Marshal(td)
assert.NoError(t, err)
ch := changelist.NewTufChange(
changelist.ActionCreate,
"targets/level1",
changelist.TypeTargetsDelegation,
"",
tdJSON,
)
err = applyTargetsChange(repo, ch)
assert.NoError(t, err)
// we have sufficient checks elsewhere we don't need to confirm that
// creating fresh works here via more asserts.
// when attempting to create the same role again, assert we receive
// an ErrInvalidRole because an existing role can't be "created"
err = applyTargetsChange(repo, ch)
assert.Error(t, err)
assert.IsType(t, data.ErrInvalidRole{}, err)
}
func TestApplyTargetsDelegationInvalidRole(t *testing.T) {
_, repo, cs := testutils.EmptyRepo()
@ -455,6 +525,9 @@ func TestApplyTargetsChangeInvalidType(t *testing.T) {
assert.Error(t, err)
}
// A delegated role MUST NOT have both Paths and PathHashPrefixes defined.
// These next 2 tests check that attempting to edit an existing role to
// create an invalid role errors in both possible combinations.
func TestApplyTargetsDelegationConflictPathsPrefixes(t *testing.T) {
_, repo, cs := testutils.EmptyRepo()
@ -576,3 +649,82 @@ func TestApplyTargetsDelegationCreateInvalid(t *testing.T) {
err = applyTargetsChange(repo, ch)
assert.Error(t, err)
}
func TestApplyTargetsDelegationCreate2Deep(t *testing.T) {
_, repo, cs := testutils.EmptyRepo()
newKey, err := cs.Create("targets/level1", data.ED25519Key)
assert.NoError(t, err)
// create delegation
kl := data.KeyList{newKey}
td := &changelist.TufDelegation{
NewThreshold: 1,
AddKeys: kl,
AddPaths: []string{"level1"},
}
tdJSON, err := json.Marshal(td)
assert.NoError(t, err)
ch := changelist.NewTufChange(
changelist.ActionCreate,
"targets/level1",
changelist.TypeTargetsDelegation,
"",
tdJSON,
)
err = applyTargetsChange(repo, ch)
assert.NoError(t, err)
tgts := repo.Targets[data.CanonicalTargetsRole]
assert.Len(t, tgts.Signed.Delegations.Roles, 1)
assert.Len(t, tgts.Signed.Delegations.Keys, 1)
_, ok := tgts.Signed.Delegations.Keys[newKey.ID()]
assert.True(t, ok)
role := tgts.Signed.Delegations.Roles[0]
assert.Len(t, role.KeyIDs, 1)
assert.Equal(t, newKey.ID(), role.KeyIDs[0])
assert.Equal(t, "targets/level1", role.Name)
assert.Equal(t, "level1", role.Paths[0])
// init delegations targets file. This would be done as part of a publish
// operation
repo.InitTargets("targets/level1")
td = &changelist.TufDelegation{
NewThreshold: 1,
AddKeys: kl,
AddPaths: []string{"level1/level2"},
}
tdJSON, err = json.Marshal(td)
assert.NoError(t, err)
ch = changelist.NewTufChange(
changelist.ActionCreate,
"targets/level1/level2",
changelist.TypeTargetsDelegation,
"",
tdJSON,
)
err = applyTargetsChange(repo, ch)
assert.NoError(t, err)
tgts = repo.Targets["targets/level1"]
assert.Len(t, tgts.Signed.Delegations.Roles, 1)
assert.Len(t, tgts.Signed.Delegations.Keys, 1)
_, ok = tgts.Signed.Delegations.Keys[newKey.ID()]
assert.True(t, ok)
role = tgts.Signed.Delegations.Roles[0]
assert.Len(t, role.KeyIDs, 1)
assert.Equal(t, newKey.ID(), role.KeyIDs[0])
assert.Equal(t, "targets/level1/level2", role.Name)
assert.Equal(t, "level1/level2", role.Paths[0])
}

View File

@ -180,11 +180,7 @@ func (tr *Repo) GetDelegation(role string) (*data.Role, error) {
// a new delegation or updating an existing one. If keys are
// provided, the IDs will be added to the role (if they do not exist
// there already), and the keys will be added to the targets file.
// The "before" argument specifies another role which this new role
// will be added in front of (i.e. higher priority) in the delegation list.
// An empty before string indicates to add the role to the end of the
// delegation list.
func (tr *Repo) UpdateDelegations(role *data.Role, keys []data.PublicKey, before string) error {
func (tr *Repo) UpdateDelegations(role *data.Role, keys []data.PublicKey) error {
if !role.IsDelegation() || !role.IsValid() {
return data.ErrInvalidRole{Role: role.Name, Reason: "not a valid delegated role"}
}
@ -275,7 +271,7 @@ func (tr *Repo) InitRepo(consistent bool) error {
if err := tr.InitRoot(consistent); err != nil {
return err
}
if err := tr.InitTargets(); err != nil {
if err := tr.InitTargets(data.CanonicalTargetsRole); err != nil {
return err
}
if err := tr.InitSnapshot(); err != nil {
@ -311,9 +307,16 @@ func (tr *Repo) InitRoot(consistent bool) error {
}
// InitTargets initializes an empty targets
func (tr *Repo) InitTargets() error {
func (tr *Repo) InitTargets(role string) error {
r := data.Role{Name: role}
if !r.IsDelegation() && !(data.CanonicalRole(role) == data.CanonicalTargetsRole) {
return data.ErrInvalidRole{
Role: role,
Reason: fmt.Sprintf("role is not a valid targets role name: %s", role),
}
}
targets := data.NewTargets()
tr.Targets[data.ValidRoles["targets"]] = targets
tr.Targets[data.RoleName(role)] = targets
return nil
}

View File

@ -143,7 +143,7 @@ func TestUpdateDelegations(t *testing.T) {
t.Fatal(err)
}
err = repo.UpdateDelegations(role, data.KeyList{testKey}, "")
err = repo.UpdateDelegations(role, data.KeyList{testKey})
if err != nil {
t.Fatal(err)
}
@ -164,7 +164,7 @@ func TestUpdateDelegations(t *testing.T) {
t.Fatal(err)
}
err = repo.UpdateDelegations(roleDeep, data.KeyList{testDeepKey}, "")
err = repo.UpdateDelegations(roleDeep, data.KeyList{testDeepKey})
if err != nil {
t.Fatal(err)
}
@ -188,7 +188,7 @@ func TestUpdateDelegationsParentMissing(t *testing.T) {
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}, "")
err = repo.UpdateDelegations(roleDeep, data.KeyList{testDeepKey})
assert.Error(t, err)
assert.IsType(t, data.ErrInvalidRole{}, err)
@ -209,7 +209,7 @@ func TestUpdateDelegationsInvalidRole(t *testing.T) {
invalidRole, err := data.NewRole("root", 1, []string{roleKey.ID()}, []string{}, []string{})
assert.NoError(t, err)
err = repo.UpdateDelegations(invalidRole, data.KeyList{roleKey}, "")
err = repo.UpdateDelegations(invalidRole, data.KeyList{roleKey})
assert.Error(t, err)
assert.IsType(t, data.ErrInvalidRole{}, err)
@ -229,7 +229,7 @@ func TestUpdateDelegationsRoleMissingKey(t *testing.T) {
assert.NoError(t, err)
// key should get added to role as part of updating the delegation
err = repo.UpdateDelegations(role, data.KeyList{roleKey}, "")
err = repo.UpdateDelegations(role, data.KeyList{roleKey})
assert.NoError(t, err)
r := repo.Targets[data.CanonicalTargetsRole]
@ -253,7 +253,7 @@ func TestUpdateDelegationsNotEnoughKeys(t *testing.T) {
assert.NoError(t, err)
// key should get added to role as part of updating the delegation
err = repo.UpdateDelegations(role, data.KeyList{roleKey}, "")
err = repo.UpdateDelegations(role, data.KeyList{roleKey})
assert.Error(t, err)
assert.IsType(t, data.ErrInvalidRole{}, err)
}
@ -268,7 +268,7 @@ func TestUpdateDelegationsReplaceRole(t *testing.T) {
role, err := data.NewRole("targets/test", 1, []string{testKey.ID()}, []string{"test"}, []string{})
assert.NoError(t, err)
err = repo.UpdateDelegations(role, data.KeyList{testKey}, "")
err = repo.UpdateDelegations(role, data.KeyList{testKey})
assert.NoError(t, err)
r := repo.Targets[data.CanonicalTargetsRole]
@ -285,7 +285,7 @@ func TestUpdateDelegationsReplaceRole(t *testing.T) {
role2, err := data.NewRole("targets/test", 1, []string{testKey2.ID()}, []string{"test"}, []string{})
assert.NoError(t, err)
err = repo.UpdateDelegations(role2, data.KeyList{testKey2}, "")
err = repo.UpdateDelegations(role2, data.KeyList{testKey2})
assert.NoError(t, err)
r = repo.Targets["targets"]
@ -307,7 +307,7 @@ func TestUpdateDelegationsAddKeyToRole(t *testing.T) {
role, err := data.NewRole("targets/test", 1, []string{testKey.ID()}, []string{"test"}, []string{})
assert.NoError(t, err)
err = repo.UpdateDelegations(role, data.KeyList{testKey}, "")
err = repo.UpdateDelegations(role, data.KeyList{testKey})
assert.NoError(t, err)
r := repo.Targets[data.CanonicalTargetsRole]
@ -320,7 +320,7 @@ func TestUpdateDelegationsAddKeyToRole(t *testing.T) {
testKey2, err := ed25519.Create("targets/test", data.ED25519Key)
assert.NoError(t, err)
err = repo.UpdateDelegations(role, data.KeyList{testKey2}, "")
err = repo.UpdateDelegations(role, data.KeyList{testKey2})
assert.NoError(t, err)
r = repo.Targets["targets"]
@ -344,7 +344,7 @@ func TestDeleteDelegations(t *testing.T) {
role, err := data.NewRole("targets/test", 1, []string{testKey.ID()}, []string{"test"}, []string{})
assert.NoError(t, err)
err = repo.UpdateDelegations(role, data.KeyList{testKey}, "")
err = repo.UpdateDelegations(role, data.KeyList{testKey})
assert.NoError(t, err)
r := repo.Targets[data.CanonicalTargetsRole]
@ -425,19 +425,19 @@ func TestDeleteDelegationsMidSliceRole(t *testing.T) {
role, err := data.NewRole("targets/test", 1, []string{}, []string{}, []string{})
assert.NoError(t, err)
err = repo.UpdateDelegations(role, data.KeyList{testKey}, "")
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}, "")
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}, "")
err = repo.UpdateDelegations(role3, data.KeyList{testKey})
assert.NoError(t, err)
err = repo.DeleteDelegation(*role2)