mirror of https://github.com/docker/docs.git
				
				
				
			Add checks to TUFRepo to fail on updating a target if there are no signing keys.
So UpdateDelegation, DeleteDelegation, AddTargets, RemoveTargets now all check for the role existence, not metadata existence. And they also check the role's signing keys - there's no point in adding if we can't sign. Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
		
							parent
							
								
									a1cbe5d43c
								
							
						
					
					
						commit
						0892ebb13f
					
				|  | @ -245,7 +245,7 @@ func (r *NotaryRepository) Initialize(rootKeyID string, serverManagedRoles ...st | |||
| 		logrus.Debug("Error on InitRoot: ", err.Error()) | ||||
| 		return err | ||||
| 	} | ||||
| 	err = r.tufRepo.InitTargets(data.CanonicalTargetsRole) | ||||
| 	_, err = r.tufRepo.InitTargets(data.CanonicalTargetsRole) | ||||
| 	if err != nil { | ||||
| 		logrus.Debug("Error on InitTargets: ", err.Error()) | ||||
| 		return err | ||||
|  |  | |||
|  | @ -6,21 +6,14 @@ import ( | |||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/docker/notary/client/changelist" | ||||
| 	tuf "github.com/docker/notary/tuf" | ||||
| 	"github.com/docker/notary/tuf/data" | ||||
| 	"github.com/docker/notary/tuf/keys" | ||||
| 	"github.com/docker/notary/tuf/testutils" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
| 
 | ||||
| func TestApplyTargetsChange(t *testing.T) { | ||||
| 	kdb := keys.NewDB() | ||||
| 	role, err := data.NewRole("targets", 1, nil, nil, nil) | ||||
| 	assert.NoError(t, err) | ||||
| 	kdb.AddRole(role) | ||||
| 
 | ||||
| 	repo := tuf.NewRepo(kdb, nil) | ||||
| 	err = repo.InitTargets(data.CanonicalTargetsRole) | ||||
| 	_, repo, _ := testutils.EmptyRepo() | ||||
| 	_, err := repo.InitTargets(data.CanonicalTargetsRole) | ||||
| 	assert.NoError(t, err) | ||||
| 	hash := sha256.Sum256([]byte{}) | ||||
| 	f := &data.FileMeta{ | ||||
|  | @ -57,13 +50,8 @@ func TestApplyTargetsChange(t *testing.T) { | |||
| } | ||||
| 
 | ||||
| func TestApplyChangelist(t *testing.T) { | ||||
| 	kdb := keys.NewDB() | ||||
| 	role, err := data.NewRole("targets", 1, nil, nil, nil) | ||||
| 	assert.NoError(t, err) | ||||
| 	kdb.AddRole(role) | ||||
| 
 | ||||
| 	repo := tuf.NewRepo(kdb, nil) | ||||
| 	err = repo.InitTargets(data.CanonicalTargetsRole) | ||||
| 	_, repo, _ := testutils.EmptyRepo() | ||||
| 	_, err := repo.InitTargets(data.CanonicalTargetsRole) | ||||
| 	assert.NoError(t, err) | ||||
| 	hash := sha256.Sum256([]byte{}) | ||||
| 	f := &data.FileMeta{ | ||||
|  | @ -105,13 +93,8 @@ func TestApplyChangelist(t *testing.T) { | |||
| } | ||||
| 
 | ||||
| func TestApplyChangelistMulti(t *testing.T) { | ||||
| 	kdb := keys.NewDB() | ||||
| 	role, err := data.NewRole("targets", 1, nil, nil, nil) | ||||
| 	assert.NoError(t, err) | ||||
| 	kdb.AddRole(role) | ||||
| 
 | ||||
| 	repo := tuf.NewRepo(kdb, nil) | ||||
| 	err = repo.InitTargets(data.CanonicalTargetsRole) | ||||
| 	_, repo, _ := testutils.EmptyRepo() | ||||
| 	_, err := repo.InitTargets(data.CanonicalTargetsRole) | ||||
| 	assert.NoError(t, err) | ||||
| 	hash := sha256.Sum256([]byte{}) | ||||
| 	f := &data.FileMeta{ | ||||
|  |  | |||
							
								
								
									
										93
									
								
								tuf/tuf.go
								
								
								
								
							
							
						
						
									
										93
									
								
								tuf/tuf.go
								
								
								
								
							|  | @ -212,16 +212,18 @@ func (tr *Repo) UpdateDelegations(role *data.Role, keys []data.PublicKey) error | |||
| 	} | ||||
| 	parent := filepath.Dir(role.Name) | ||||
| 
 | ||||
| 	// check the parent role
 | ||||
| 	if parentRole := tr.keysDB.GetRole(parent); parentRole == nil { | ||||
| 		return data.ErrInvalidRole{Role: role.Name, Reason: "parent role not found"} | ||||
| 	if err := tr.VerifyCanSign(parent); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// check the parent role's metadata
 | ||||
| 	p, ok := tr.Targets[parent] | ||||
| 	if !ok { // the parent targetfile may not exist yet - if not, then create it
 | ||||
| 		p = data.NewTargets() | ||||
| 		tr.Targets[parent] = p | ||||
| 		var err error | ||||
| 		p, err = tr.InitTargets(parent) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for _, k := range keys { | ||||
|  | @ -270,9 +272,20 @@ func (tr *Repo) DeleteDelegation(role data.Role) error { | |||
| 	name := role.Name | ||||
| 
 | ||||
| 	parent := filepath.Dir(name) | ||||
| 	if err := tr.VerifyCanSign(parent); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// delete delegated data from Targets map and Snapshot - if they don't
 | ||||
| 	// exist, these are no-op
 | ||||
| 	delete(tr.Targets, name) | ||||
| 	tr.Snapshot.DeleteMeta(name) | ||||
| 
 | ||||
| 	p, ok := tr.Targets[parent] | ||||
| 	if !ok { | ||||
| 		return data.ErrInvalidRole{Role: name, Reason: "parent role not found"} | ||||
| 		// if there is no parent metadata (the role exists though), then this
 | ||||
| 		// is as good as done.
 | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	foundAt := utils.FindRoleIndex(p.Signed.Delegations.Roles, name) | ||||
|  | @ -289,10 +302,6 @@ func (tr *Repo) DeleteDelegation(role data.Role) error { | |||
| 		utils.RemoveUnusedKeys(p) | ||||
| 
 | ||||
| 		p.Dirty = true | ||||
| 
 | ||||
| 		// delete delegated data from Targets map and Snapshot
 | ||||
| 		delete(tr.Targets, name) | ||||
| 		tr.Snapshot.DeleteMeta(name) | ||||
| 	} // if the role wasn't found, it's a good as deleted
 | ||||
| 
 | ||||
| 	return nil | ||||
|  | @ -306,7 +315,7 @@ func (tr *Repo) InitRepo(consistent bool) error { | |||
| 	if err := tr.InitRoot(consistent); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := tr.InitTargets(data.CanonicalTargetsRole); err != nil { | ||||
| 	if _, err := tr.InitTargets(data.CanonicalTargetsRole); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := tr.InitSnapshot(); err != nil { | ||||
|  | @ -341,18 +350,18 @@ func (tr *Repo) InitRoot(consistent bool) error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // InitTargets initializes an empty targets
 | ||||
| func (tr *Repo) InitTargets(role string) error { | ||||
| // InitTargets initializes an empty targets, and returns the new empty target
 | ||||
| func (tr *Repo) InitTargets(role string) (*data.SignedTargets, error) { | ||||
| 	r := data.Role{Name: role} | ||||
| 	if !r.IsDelegation() && !(data.CanonicalRole(role) == data.CanonicalTargetsRole) { | ||||
| 		return data.ErrInvalidRole{ | ||||
| 		return nil, data.ErrInvalidRole{ | ||||
| 			Role:   role, | ||||
| 			Reason: fmt.Sprintf("role is not a valid targets role name: %s", role), | ||||
| 		} | ||||
| 	} | ||||
| 	targets := data.NewTargets() | ||||
| 	tr.Targets[data.RoleName(role)] = targets | ||||
| 	return nil | ||||
| 	return targets, nil | ||||
| } | ||||
| 
 | ||||
| // InitSnapshot initializes a snapshot based on the current root and targets
 | ||||
|  | @ -510,23 +519,49 @@ func (tr Repo) FindTarget(path string) *data.FileMeta { | |||
| 	return walkTargets("targets") | ||||
| } | ||||
| 
 | ||||
| // VerifyCanSign returns nil if the role exists and we have at least one
 | ||||
| // signing key for the role, false otherwise.  This does not check that we have
 | ||||
| // enough signing keys to meet the threshold, since we want to support the use
 | ||||
| // case of multiple signers for a role.  It returns an error if the role doesn't
 | ||||
| // exist or if there are no signing keys.
 | ||||
| func (tr *Repo) VerifyCanSign(roleName string) error { | ||||
| 	role := tr.keysDB.GetRole(roleName) | ||||
| 	if role == nil { | ||||
| 		return data.ErrInvalidRole{Role: roleName, Reason: "does not exist"} | ||||
| 	} | ||||
| 
 | ||||
| 	for _, keyID := range role.KeyIDs { | ||||
| 		p, _, err := tr.cryptoService.GetPrivateKey(keyID) | ||||
| 		if err == nil && p != nil { | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| 	return signed.ErrNoKeys{KeyIDs: role.KeyIDs} | ||||
| } | ||||
| 
 | ||||
| // AddTargets will attempt to add the given targets specifically to
 | ||||
| // the directed role. If the metadata for the role doesn't exist yet,
 | ||||
| // AddTargets will create one.
 | ||||
| func (tr *Repo) AddTargets(role string, targets data.Files) (data.Files, error) { | ||||
| 	// check the role exists
 | ||||
| 	r := tr.keysDB.GetRole(role) | ||||
| 	if r == nil { | ||||
| 		return nil, data.ErrInvalidRole{Role: role, Reason: "does not exist"} | ||||
| 
 | ||||
| 	err := tr.VerifyCanSign(role) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// check the role's metadata
 | ||||
| 	t, ok := tr.Targets[role] | ||||
| 	if !ok { // the targetfile may not exist yet - if not, then create it
 | ||||
| 		t = data.NewTargets() | ||||
| 		tr.Targets[role] = t | ||||
| 		var err error | ||||
| 		t, err = tr.InitTargets(role) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// VerifyCanSign already makes sure this is not nil
 | ||||
| 	r := tr.keysDB.GetRole(role) | ||||
| 
 | ||||
| 	invalid := make(data.Files) | ||||
| 	for path, target := range targets { | ||||
| 		pathDigest := sha256.Sum256([]byte(path)) | ||||
|  | @ -546,15 +581,19 @@ func (tr *Repo) AddTargets(role string, targets data.Files) (data.Files, error) | |||
| 
 | ||||
| // RemoveTargets removes the given target (paths) from the given target role (delegation)
 | ||||
| func (tr *Repo) RemoveTargets(role string, targets ...string) error { | ||||
| 	t, ok := tr.Targets[role] | ||||
| 	if !ok { | ||||
| 		return data.ErrInvalidRole{Role: role, Reason: "does not exist"} | ||||
| 	if err := tr.VerifyCanSign(role); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	for _, path := range targets { | ||||
| 		delete(t.Signed.Targets, path) | ||||
| 	// if the role exists but metadata does not yet, then our work is done
 | ||||
| 	t, ok := tr.Targets[role] | ||||
| 	if ok { | ||||
| 		for _, path := range targets { | ||||
| 			delete(t.Signed.Targets, path) | ||||
| 		} | ||||
| 		t.Dirty = true | ||||
| 	} | ||||
| 	t.Dirty = true | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										240
									
								
								tuf/tuf_test.go
								
								
								
								
							
							
						
						
									
										240
									
								
								tuf/tuf_test.go
								
								
								
								
							|  | @ -215,6 +215,31 @@ func TestUpdateDelegationsParentMissing(t *testing.T) { | |||
| 	assert.False(t, ok, "no targets file should be created for nonexistent parent delegation") | ||||
| } | ||||
| 
 | ||||
| // Updating delegations needs to modify the parent of the role being updated.
 | ||||
| // If there is no signing key for that parent, the delegation cannot be added.
 | ||||
| func TestUpdateDelegationsMissingParentKey(t *testing.T) { | ||||
| 	ed25519 := signed.NewEd25519() | ||||
| 	keyDB := keys.NewDB() | ||||
| 	repo := initRepo(t, ed25519, keyDB) | ||||
| 
 | ||||
| 	// remove the target key (all keys)
 | ||||
| 	repo.cryptoService = signed.NewEd25519() | ||||
| 
 | ||||
| 	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) | ||||
| 
 | ||||
| 	err = repo.UpdateDelegations(role, data.KeyList{roleKey}) | ||||
| 	assert.Error(t, err) | ||||
| 	assert.IsType(t, signed.ErrNoKeys{}, err) | ||||
| 
 | ||||
| 	// 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() | ||||
|  | @ -241,7 +266,9 @@ func TestUpdateDelegationsInvalidRole(t *testing.T) { | |||
| 	assert.False(t, ok, "no targets file should be created since delegation failed") | ||||
| } | ||||
| 
 | ||||
| func TestUpdateDelegationsRoleMissingKey(t *testing.T) { | ||||
| // 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) | ||||
|  | @ -403,10 +430,16 @@ func TestDeleteDelegations(t *testing.T) { | |||
| 	assert.Len(t, keyIDs, 1) | ||||
| 	assert.Equal(t, testKey.ID(), keyIDs[0]) | ||||
| 
 | ||||
| 	// ensure that the metadata is there
 | ||||
| 	repo.InitTargets("targets/test") | ||||
| 	// ensure that the metadata is there and snapshot is there
 | ||||
| 	targets, err := repo.InitTargets("targets/test") | ||||
| 	assert.NoError(t, err) | ||||
| 	targetsSigned, err := targets.ToSigned() | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.NoError(t, repo.UpdateSnapshot("targets/test", targetsSigned)) | ||||
| 	_, ok = repo.Snapshot.Signed.Meta["targets/test"] | ||||
| 	assert.True(t, ok) | ||||
| 
 | ||||
| 	err = repo.DeleteDelegation(*role) | ||||
| 	assert.NoError(t, repo.DeleteDelegation(*role)) | ||||
| 	assert.Len(t, r.Signed.Delegations.Roles, 0) | ||||
| 	assert.Len(t, r.Signed.Delegations.Keys, 0) | ||||
| 	assert.True(t, r.Dirty) | ||||
|  | @ -414,7 +447,35 @@ func TestDeleteDelegations(t *testing.T) { | |||
| 	// metadata should be deleted
 | ||||
| 	_, ok = repo.Targets["targets/test"] | ||||
| 	assert.False(t, ok) | ||||
| 	_, ok = repo.Snapshot.Signed.Meta["targets/test"] | ||||
| 	assert.False(t, ok) | ||||
| } | ||||
| 
 | ||||
| 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 TestDeleteDelegationsRoleNotExist(t *testing.T) { | ||||
|  | @ -475,6 +536,54 @@ func TestDeleteDelegationsParentMissing(t *testing.T) { | |||
| 	assert.Len(t, r.Signed.Delegations.Roles, 0) | ||||
| } | ||||
| 
 | ||||
| // Can't delete a delegation if we don't have the parent's signing key
 | ||||
| func TestDeleteDelegationsMissingParentSigningKey(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]) | ||||
| 
 | ||||
| 	// ensure that the metadata is there and snapshot is there
 | ||||
| 	targets, err := repo.InitTargets("targets/test") | ||||
| 	assert.NoError(t, err) | ||||
| 	targetsSigned, err := targets.ToSigned() | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.NoError(t, repo.UpdateSnapshot("targets/test", targetsSigned)) | ||||
| 	_, ok = repo.Snapshot.Signed.Meta["targets/test"] | ||||
| 	assert.True(t, ok) | ||||
| 
 | ||||
| 	// delete all signing keys
 | ||||
| 	repo.cryptoService = signed.NewEd25519() | ||||
| 	err = repo.DeleteDelegation(*role) | ||||
| 	assert.Error(t, err) | ||||
| 	assert.IsType(t, signed.ErrNoKeys{}, err) | ||||
| 
 | ||||
| 	assert.Len(t, r.Signed.Delegations.Roles, 1) | ||||
| 	assert.Len(t, r.Signed.Delegations.Keys, 1) | ||||
| 	assert.True(t, r.Dirty) | ||||
| 
 | ||||
| 	// metadata should be here still
 | ||||
| 	_, ok = repo.Targets["targets/test"] | ||||
| 	assert.True(t, ok) | ||||
| 	_, ok = repo.Snapshot.Signed.Meta["targets/test"] | ||||
| 	assert.True(t, ok) | ||||
| } | ||||
| 
 | ||||
| func TestDeleteDelegationsMidSliceRole(t *testing.T) { | ||||
| 	ed25519 := signed.NewEd25519() | ||||
| 	keyDB := keys.NewDB() | ||||
|  | @ -675,6 +784,129 @@ func TestAddTargetsRoleDoesntExist(t *testing.T) { | |||
| 	assert.IsType(t, data.ErrInvalidRole{}, err) | ||||
| } | ||||
| 
 | ||||
| // 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) | ||||
| } | ||||
| 
 | ||||
| // Removing targets from a role that exists but without metadata succeeds.
 | ||||
| func TestRemoveTargetsNonexistentMetadata(t *testing.T) { | ||||
| 	ed25519 := signed.NewEd25519() | ||||
| 	keyDB := keys.NewDB() | ||||
| 	repo := initRepo(t, ed25519, keyDB) | ||||
| 
 | ||||
| 	err := repo.RemoveTargets("targets/test", "f") | ||||
| 	assert.Error(t, err) | ||||
| 	assert.IsType(t, data.ErrInvalidRole{}, err) | ||||
| } | ||||
| 
 | ||||
| // Removing targets from a role that doesn't exist fails
 | ||||
| func TestRemoveTargetsRoleDoesntExist(t *testing.T) { | ||||
| 	ed25519 := signed.NewEd25519() | ||||
| 	keyDB := keys.NewDB() | ||||
| 	repo := initRepo(t, ed25519, keyDB) | ||||
| 
 | ||||
| 	err := repo.RemoveTargets("targets/test", "f") | ||||
| 	assert.Error(t, err) | ||||
| 	assert.IsType(t, data.ErrInvalidRole{}, err) | ||||
| } | ||||
| 
 | ||||
| // Removing targets from a role that we don't have signing keys for fails
 | ||||
| func TestRemoveTargetsNoSigningKeys(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) | ||||
| 
 | ||||
| 	// 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) | ||||
| 	_, ok = r.Signed.Targets["f"] | ||||
| 	assert.True(t, ok) | ||||
| 
 | ||||
| 	// now delete the signing key (all keys)
 | ||||
| 	repo.cryptoService = signed.NewEd25519() | ||||
| 
 | ||||
| 	// now remove the target - it should fail
 | ||||
| 	err = repo.RemoveTargets("targets/test", "f") | ||||
| 	assert.Error(t, err) | ||||
| 	assert.IsType(t, signed.ErrNoKeys{}, err) | ||||
| } | ||||
| 
 | ||||
| // adding a key to a role marks root as dirty as well as the role
 | ||||
| func TestAddBaseKeysToRoot(t *testing.T) { | ||||
| 	for role := range data.ValidRoles { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue