mirror of https://github.com/docker/docs.git
addressing review
Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
parent
79b05d4c0a
commit
5891805b29
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
|
|
19
tuf/tuf.go
19
tuf/tuf.go
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue