PoC broken down client api for delegations

Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
This commit is contained in:
Riyaz Faizullabhoy 2016-01-29 15:57:14 -08:00
parent 2fac65df71
commit 70ee4f8670
6 changed files with 269 additions and 94 deletions

View File

@ -88,6 +88,7 @@ type TufDelegation struct {
RemoveKeys []string `json:"remove_keys,omitempty"`
AddPaths []string `json:"add_paths,omitempty"`
RemovePaths []string `json:"remove_paths,omitempty"`
ClearAllPaths bool `json:"clear_paths,omitempty"`
AddPathHashPrefixes []string `json:"add_prefixes,omitempty"`
RemovePathHashPrefixes []string `json:"remove_prefixes,omitempty"`
}

View File

@ -302,12 +302,28 @@ func addChange(cl *changelist.FileChangelist, c changelist.Change, roles ...stri
return nil
}
// AddDelegation creates a new changelist entry to add a delegation to the repository
// when the changelist gets applied at publish time. This does not do any validation
// other than checking the name of the delegation to add - all that will happen
// at publish time.
func (r *NotaryRepository) AddDelegation(name string, threshold int,
delegationKeys []data.PublicKey, paths []string) error {
// AddDelegation creates changelist entries to add provided delegation public keys and paths.
// This method composes AddDelegationRoleAndKeys and AddDelegationPaths (each creates one changelist if called).
func (r *NotaryRepository) AddDelegation(name string, delegationKeys []data.PublicKey, paths []string) error {
if len(delegationKeys) > 0 {
err := r.AddDelegationRoleAndKeys(name, delegationKeys)
if err != nil {
return err
}
}
if len(paths) > 0 {
err := r.AddDelegationPaths(name, paths)
if err != nil {
return err
}
}
return nil
}
// AddDelegationRoleAndKeys creates a changelist entry to add provided delegation public keys.
// This method is the simplest way to create a new delegation, because the delegation must have at least
// one key upon creation to be valid since we will reject the changelist while validating the threshold.
func (r *NotaryRepository) AddDelegationRoleAndKeys(name string, delegationKeys []data.PublicKey) error {
if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
@ -320,33 +336,68 @@ func (r *NotaryRepository) AddDelegation(name string, threshold int,
defer cl.Close()
logrus.Debugf(`Adding delegation "%s" with threshold %d, and %d keys\n`,
name, threshold, len(delegationKeys))
name, notary.MinThreshold, len(delegationKeys))
// Defaulting to threshold of 1, since we don't allow for larger thresholds at the moment.
tdJSON, err := json.Marshal(&changelist.TufDelegation{
NewThreshold: threshold,
NewThreshold: notary.MinThreshold,
AddKeys: data.KeyList(delegationKeys),
AddPaths: paths,
})
if err != nil {
return err
}
template := changelist.NewTufChange(
changelist.ActionCreate,
name,
changelist.TypeTargetsDelegation,
"", // no path
tdJSON,
)
template := newCreateDelegationChange(name, tdJSON)
return addChange(cl, template, name)
}
// RemoveDelegation creates a new changelist entry to remove a delegation from
// the repository when the changelist gets applied at publish time.
// This does not validate that the delegation exists, since one might exist
// after applying all changes.
func (r *NotaryRepository) RemoveDelegation(name string, keyIDs, paths []string, removeAll bool) error {
// AddDelegationPaths creates a changelist entry to add provided paths to an existing delegation.
// This method cannot create a new delegation itself because the role must meet the key threshold upon creation.
func (r *NotaryRepository) AddDelegationPaths(name string, paths []string) error {
if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
}
cl, err := changelist.NewFileChangelist(filepath.Join(r.tufRepoPath, "changelist"))
if err != nil {
return err
}
defer cl.Close()
logrus.Debugf(`Adding delegation "%s" with threshold %d, and %s paths\n`, name, paths)
tdJSON, err := json.Marshal(&changelist.TufDelegation{
AddPaths: paths,
})
if err != nil {
return err
}
template := newCreateDelegationChange(name, tdJSON)
return addChange(cl, template, name)
}
// RemoveDelegationKeysAndPaths creates changelist entries to remove provided delegation key IDs and paths.
// This method composes RemoveDelegationPaths and RemoveDelegationKeys (each creates one changelist if called).
func (r *NotaryRepository) RemoveDelegationKeysAndPaths(name string, keyIDs, paths []string) error {
if len(paths) > 0 {
err := r.RemoveDelegationPaths(name, paths)
if err != nil {
return err
}
}
if len(keyIDs) > 0 {
err := r.RemoveDelegationKeys(name, keyIDs)
if err != nil {
return err
}
}
return nil
}
// RemoveDelegationRole creates a changelist to remove all paths and keys from a role, and delete the role in its entirety.
func (r *NotaryRepository) RemoveDelegationRole(name string) error {
if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
@ -359,39 +410,121 @@ func (r *NotaryRepository) RemoveDelegation(name string, keyIDs, paths []string,
defer cl.Close()
logrus.Debugf(`Removing delegation "%s"\n`, name)
var template *changelist.TufChange
// We use the Delete action only for force removal, Update is used for removing individual keys and paths
if removeAll {
template = changelist.NewTufChange(
changelist.ActionDelete,
name,
changelist.TypeTargetsDelegation,
"", // no path
nil, // deleting role, no data needed
)
template := newDeleteDelegationChange(name, nil)
return addChange(cl, template, name)
}
} else {
tdJSON, err := json.Marshal(&changelist.TufDelegation{
RemoveKeys: keyIDs,
RemovePaths: paths,
})
if err != nil {
return err
}
// RemoveDelegationPaths creates a changelist entry to remove provided paths from an existing delegation.
func (r *NotaryRepository) RemoveDelegationPaths(name string, paths []string) error {
template = changelist.NewTufChange(
changelist.ActionUpdate,
name,
changelist.TypeTargetsDelegation,
"", // no path
tdJSON,
)
if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
}
cl, err := changelist.NewFileChangelist(filepath.Join(r.tufRepoPath, "changelist"))
if err != nil {
return err
}
defer cl.Close()
logrus.Debugf(`Removing %s paths from delegation "%s"\n`, paths, name)
tdJSON, err := json.Marshal(&changelist.TufDelegation{
RemovePaths: paths,
})
if err != nil {
return err
}
template := newUpdateDelegationChange(name, tdJSON)
return addChange(cl, template, name)
}
// RemoveDelegationKeys creates a changelist entry to remove provided keys from an existing delegation.
// When this changelist is applied, if the specified keys are the only keys left in the role,
// the role itself will be deleted in its entirety.
func (r *NotaryRepository) RemoveDelegationKeys(name string, keyIDs []string) error {
if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
}
cl, err := changelist.NewFileChangelist(filepath.Join(r.tufRepoPath, "changelist"))
if err != nil {
return err
}
defer cl.Close()
logrus.Debugf(`Removing %s keys from delegation "%s"\n`, keyIDs, name)
tdJSON, err := json.Marshal(&changelist.TufDelegation{
RemoveKeys: keyIDs,
})
if err != nil {
return err
}
template := newUpdateDelegationChange(name, tdJSON)
return addChange(cl, template, name)
}
// ClearDelegationPaths creates a changelist entry to remove all paths from an existing delegation.
func (r *NotaryRepository) ClearDelegationPaths(name string) error {
if !data.IsDelegation(name) {
return data.ErrInvalidRole{Role: name, Reason: "invalid delegation role name"}
}
cl, err := changelist.NewFileChangelist(filepath.Join(r.tufRepoPath, "changelist"))
if err != nil {
return err
}
defer cl.Close()
logrus.Debugf(`Removing all paths from delegation "%s"\n`, name)
tdJSON, err := json.Marshal(&changelist.TufDelegation{
ClearAllPaths: true,
})
if err != nil {
return err
}
template := newUpdateDelegationChange(name, tdJSON)
return addChange(cl, template, name)
}
func newUpdateDelegationChange(name string, content []byte) *changelist.TufChange {
return changelist.NewTufChange(
changelist.ActionUpdate,
name,
changelist.TypeTargetsDelegation,
"", // no path for delegations
content,
)
}
func newCreateDelegationChange(name string, content []byte) *changelist.TufChange {
return changelist.NewTufChange(
changelist.ActionCreate,
name,
changelist.TypeTargetsDelegation,
"", // no path for delegations
content,
)
}
func newDeleteDelegationChange(name string, content []byte) *changelist.TufChange {
return changelist.NewTufChange(
changelist.ActionDelete,
name,
changelist.TypeTargetsDelegation,
"", // no path for delegations
content,
)
}
// AddTarget creates new changelist entries to add a target to the given roles
// in the repository when the changelist gets applied at publish time.
// If roles are unspecified, the default role is "targets".

View File

@ -1910,10 +1910,10 @@ func testPublishDelegations(t *testing.T, clearCache, x509Keys bool) {
// targets/a, because these should execute in order
for _, delgName := range []string{"targets/a", "targets/a/b", "targets/c"} {
assert.NoError(t,
repo1.AddDelegation(delgName, 1, []data.PublicKey{delgKey}, []string{""}),
repo1.AddDelegation(delgName, []data.PublicKey{delgKey}, []string{""}),
"error creating delegation")
}
assert.Len(t, getChanges(t, repo1), 3, "wrong number of changelist files found")
assert.Len(t, getChanges(t, repo1), 6, "wrong number of changelist files found")
var rec *passRoleRecorder
if clearCache {
@ -1932,11 +1932,11 @@ func testPublishDelegations(t *testing.T, clearCache, x509Keys bool) {
// this should not publish, because targets/z doesn't exist
assert.NoError(t,
repo1.AddDelegation("targets/z/y", 1, []data.PublicKey{delgKey}, []string{""}),
repo1.AddDelegation("targets/z/y", []data.PublicKey{delgKey}, []string{""}),
"error creating delegation")
assert.Len(t, getChanges(t, repo1), 1, "wrong number of changelist files found")
assert.Len(t, getChanges(t, repo1), 2, "wrong number of changelist files found")
assert.Error(t, repo1.Publish())
assert.Len(t, getChanges(t, repo1), 1, "wrong number of changelist files found")
assert.Len(t, getChanges(t, repo1), 2, "wrong number of changelist files found")
if clearCache {
rec.assertAsked(t, nil)
@ -2035,7 +2035,7 @@ func testPublishTargetsDelgationScopeNoFallbackIfNoKeys(t *testing.T, clearCache
}
// ensure that the role exists
assert.NoError(t, repo.AddDelegation("targets/a", 1, []data.PublicKey{aPubKey}, []string{""}))
assert.NoError(t, repo.AddDelegation("targets/a", []data.PublicKey{aPubKey}, []string{""}))
assert.NoError(t, repo.Publish())
if clearCache {
@ -2076,7 +2076,7 @@ func TestPublishTargetsDelgationSuccessLocallyHasRoles(t *testing.T) {
for _, delgName := range []string{"targets/a", "targets/a/b"} {
delgKey := createKey(t, repo, delgName, false)
assert.NoError(t,
repo.AddDelegation(delgName, 1, []data.PublicKey{delgKey}, []string{""}),
repo.AddDelegation(delgName, []data.PublicKey{delgKey}, []string{""}),
"error creating delegation")
}
@ -2106,7 +2106,7 @@ func TestPublishTargetsDelgationNoTargetsKeyNeeded(t *testing.T) {
for _, delgName := range []string{"targets/a", "targets/a/b"} {
delgKey := createKey(t, repo, delgName, false)
assert.NoError(t,
repo.AddDelegation(delgName, 1, []data.PublicKey{delgKey}, []string{""}),
repo.AddDelegation(delgName, []data.PublicKey{delgKey}, []string{""}),
"error creating delegation")
}
@ -2170,10 +2170,10 @@ func TestPublishTargetsDelgationSuccessNeedsToDownloadRoles(t *testing.T) {
// owner creates delegations, adds the delegated key to them, and publishes them
assert.NoError(t,
ownerRepo.AddDelegation("targets/a", 1, []data.PublicKey{aKey}, []string{""}),
ownerRepo.AddDelegation("targets/a", []data.PublicKey{aKey}, []string{""}),
"error creating delegation")
assert.NoError(t,
ownerRepo.AddDelegation("targets/a/b", 1, []data.PublicKey{bKey}, []string{""}),
ownerRepo.AddDelegation("targets/a/b", []data.PublicKey{bKey}, []string{""}),
"error creating delegation")
assert.NoError(t, ownerRepo.Publish())
@ -2212,7 +2212,7 @@ func TestPublishTargetsDelgationFromTwoRepos(t *testing.T) {
// delegation includes both keys
assert.NoError(t,
repo1.AddDelegation("targets/a", 1, []data.PublicKey{key1, key2}, []string{""}),
repo1.AddDelegation("targets/a", []data.PublicKey{key1, key2}, []string{""}),
"error creating delegation")
assert.NoError(t, repo1.Publish())
@ -2282,7 +2282,7 @@ func TestPublishRemoveDelgationKeyFromDelegationRole(t *testing.T) {
// owner creates delegation, adds the delegated key to it, and publishes it
assert.NoError(t,
ownerRepo.AddDelegation("targets/a", 1, []data.PublicKey{aKey}, []string{""}),
ownerRepo.AddDelegation("targets/a", []data.PublicKey{aKey}, []string{""}),
"error creating delegation")
assert.NoError(t, ownerRepo.Publish())
@ -2340,7 +2340,7 @@ func TestPublishRemoveDelgation(t *testing.T) {
// owner creates delegation, adds the delegated key to it, and publishes it
assert.NoError(t,
ownerRepo.AddDelegation("targets/a", 1, []data.PublicKey{aKey}, []string{""}),
ownerRepo.AddDelegation("targets/a", []data.PublicKey{aKey}, []string{""}),
"error creating delegation")
assert.NoError(t, ownerRepo.Publish())
@ -2351,7 +2351,7 @@ func TestPublishRemoveDelgation(t *testing.T) {
// owner removes delegation
aKeyCanonicalID, err := utils.CanonicalKeyID(aKey)
assert.NoError(t, err)
assert.NoError(t, ownerRepo.RemoveDelegation("targets/a", []string{aKeyCanonicalID}, []string{}, false))
assert.NoError(t, ownerRepo.RemoveDelegationKeys("targets/a", []string{aKeyCanonicalID}))
assert.NoError(t, ownerRepo.Publish())
// delegated repo can now no longer publish to delegated role
@ -2374,7 +2374,7 @@ func TestPublishSucceedsDespiteDelegationCorrupt(t *testing.T) {
assert.NoError(t, err, "error creating delegation key")
assert.NoError(t,
repo.AddDelegation("targets/a", 1, []data.PublicKey{delgKey}, []string{""}),
repo.AddDelegation("targets/a", []data.PublicKey{delgKey}, []string{""}),
"error creating delegation")
testPublishBadMetadata(t, "targets/a", repo, false, true)
@ -2609,22 +2609,25 @@ func TestAddDelegationChangefileValid(t *testing.T) {
targetPubKey := repo.CryptoService.GetKey(targetKeyIds[0])
assert.NotNil(t, targetPubKey)
err := repo.AddDelegation("root", 1, []data.PublicKey{targetPubKey}, []string{""})
err := repo.AddDelegation("root", []data.PublicKey{targetPubKey}, []string{""})
assert.Error(t, err)
assert.IsType(t, data.ErrInvalidRole{}, err)
assert.Empty(t, getChanges(t, repo))
// to show that adding does not care about the hierarchy
err = repo.AddDelegation("targets/a/b/c", 1, []data.PublicKey{targetPubKey}, []string{""})
err = repo.AddDelegation("targets/a/b/c", []data.PublicKey{targetPubKey}, []string{""})
assert.NoError(t, err)
// ensure that the changefiles is correct
changes := getChanges(t, repo)
assert.Len(t, changes, 1)
assert.Len(t, changes, 2)
assert.Equal(t, changelist.ActionCreate, changes[0].Action())
assert.Equal(t, "targets/a/b/c", changes[0].Scope())
assert.Equal(t, changelist.TypeTargetsDelegation, changes[0].Type())
assert.Equal(t, "", changes[0].Path())
assert.Equal(t, changelist.ActionCreate, changes[1].Action())
assert.Equal(t, "targets/a/b/c", changes[1].Scope())
assert.Equal(t, changelist.TypeTargetsDelegation, changes[1].Type())
assert.Equal(t, "", changes[1].Path())
assert.NotEmpty(t, changes[0].Content())
}
@ -2645,10 +2648,10 @@ func TestAddDelegationChangefileApplicable(t *testing.T) {
assert.NotNil(t, targetPubKey)
// this hierarchy has to be right to be applied
err := repo.AddDelegation("targets/a", 1, []data.PublicKey{targetPubKey}, []string{""})
err := repo.AddDelegation("targets/a", []data.PublicKey{targetPubKey}, []string{""})
assert.NoError(t, err)
changes := getChanges(t, repo)
assert.Len(t, changes, 1)
assert.Len(t, changes, 2)
// ensure that it can be applied correctly
err = applyTargetsChange(repo.tufRepo, changes[0])
@ -2676,7 +2679,7 @@ func TestAddDelegationErrorWritingChanges(t *testing.T) {
targetPubKey := repo.CryptoService.GetKey(targetKeyIds[0])
assert.NotNil(t, targetPubKey)
return repo.AddDelegation("targets/a", 1, []data.PublicKey{targetPubKey}, []string{""})
return repo.AddDelegation("targets/a", []data.PublicKey{targetPubKey}, []string{""})
})
}
@ -2693,14 +2696,14 @@ func TestRemoveDelegationChangefileValid(t *testing.T) {
rootPubKey := repo.CryptoService.GetKey(rootKeyID)
assert.NotNil(t, rootPubKey)
err := repo.RemoveDelegation("root", []string{rootKeyID}, []string{}, false)
err := repo.RemoveDelegationKeys("root", []string{rootKeyID})
assert.Error(t, err)
assert.IsType(t, data.ErrInvalidRole{}, err)
assert.Empty(t, getChanges(t, repo))
// to demonstrate that so long as the delegation name is valid, the
// existence of the delegation doesn't matter
assert.NoError(t, repo.RemoveDelegation("targets/a/b/c", []string{rootKeyID}, []string{}, false))
assert.NoError(t, repo.RemoveDelegationKeys("targets/a/b/c", []string{rootKeyID}))
// ensure that the changefile is correct
changes := getChanges(t, repo)
@ -2711,7 +2714,7 @@ func TestRemoveDelegationChangefileValid(t *testing.T) {
assert.Equal(t, "", changes[0].Path())
}
// The changefile produced by RemoveDelegation, when applied, actually removes
// The changefile produced by RemoveDelegationKeys, when applied, actually removes
// the delegation from the repo (assuming the repo exists - tests for
// change application validation are in helpers_test.go)
func TestRemoveDelegationChangefileApplicable(t *testing.T) {
@ -2725,10 +2728,11 @@ func TestRemoveDelegationChangefileApplicable(t *testing.T) {
assert.NotNil(t, rootPubKey)
// add a delegation first so it can be removed
assert.NoError(t, repo.AddDelegation("targets/a", 1, []data.PublicKey{rootPubKey}, []string{""}))
assert.NoError(t, repo.AddDelegation("targets/a", []data.PublicKey{rootPubKey}, []string{""}))
changes := getChanges(t, repo)
assert.Len(t, changes, 1)
assert.Len(t, changes, 2)
assert.NoError(t, applyTargetsChange(repo.tufRepo, changes[0]))
assert.NoError(t, applyTargetsChange(repo.tufRepo, changes[1]))
targetRole := repo.tufRepo.Targets[data.CanonicalTargetsRole]
assert.Len(t, targetRole.Signed.Delegations.Roles, 1)
@ -2737,21 +2741,51 @@ func TestRemoveDelegationChangefileApplicable(t *testing.T) {
// now remove it
rootKeyCanonicalID, err := utils.CanonicalKeyID(rootPubKey)
assert.NoError(t, err)
assert.NoError(t, repo.RemoveDelegation("targets/a", []string{rootKeyCanonicalID}, []string{}, false))
assert.NoError(t, repo.RemoveDelegationKeys("targets/a", []string{rootKeyCanonicalID}))
changes = getChanges(t, repo)
assert.Len(t, changes, 2)
assert.NoError(t, applyTargetsChange(repo.tufRepo, changes[1]))
assert.Len(t, changes, 3)
assert.NoError(t, applyTargetsChange(repo.tufRepo, changes[2]))
targetRole = repo.tufRepo.Targets[data.CanonicalTargetsRole]
assert.Empty(t, targetRole.Signed.Delegations.Roles)
assert.Empty(t, targetRole.Signed.Delegations.Keys)
}
// The changefile with the ClearAllPaths key, when applied, actually removes
// all paths from the specified delegation in the repo (assuming the repo and delegation exist)
func TestClearAllPathsDelegationChangefileApplicable(t *testing.T) {
gun := "docker.com/notary"
ts, _, _ := simpleTestServer(t)
defer ts.Close()
repo, rootKeyID := initializeRepo(t, data.ECDSAKey, gun, ts.URL, false)
defer os.RemoveAll(repo.baseDir)
rootPubKey := repo.CryptoService.GetKey(rootKeyID)
assert.NotNil(t, rootPubKey)
// add a delegation first so it can be removed
assert.NoError(t, repo.AddDelegation("targets/a", []data.PublicKey{rootPubKey}, []string{"abc,123,xyz,path"}))
changes := getChanges(t, repo)
assert.Len(t, changes, 2)
assert.NoError(t, applyTargetsChange(repo.tufRepo, changes[0]))
assert.NoError(t, applyTargetsChange(repo.tufRepo, changes[1]))
// now clear paths it
assert.NoError(t, repo.ClearDelegationPaths("targets/a"))
changes = getChanges(t, repo)
assert.Len(t, changes, 3)
assert.NoError(t, applyTargetsChange(repo.tufRepo, changes[2]))
delgRoles := repo.tufRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Roles
assert.Len(t, delgRoles, 1)
assert.Len(t, delgRoles[0].Paths, 0)
}
// TestRemoveDelegationErrorWritingChanges expects errors writing a change to
// file to be propagated.
func TestRemoveDelegationErrorWritingChanges(t *testing.T) {
testErrorWritingChangefiles(t, func(repo *NotaryRepository) error {
return repo.RemoveDelegation("targets/a", []string{""}, []string{}, false)
return repo.RemoveDelegationKeysAndPaths("targets/a", []string{""}, []string{})
})
}
@ -2859,10 +2893,10 @@ func testPublishTargetsDelgationCanUseUserKeyWithArbitraryRole(t *testing.T, x50
// owner creates delegations, adds the delegated key to them, and publishes them
assert.NoError(t,
ownerRepo.AddDelegation("targets/a", 1, []data.PublicKey{aKey}, []string{""}),
ownerRepo.AddDelegation("targets/a", []data.PublicKey{aKey}, []string{""}),
"error creating delegation")
assert.NoError(t,
ownerRepo.AddDelegation("targets/a/b", 1, []data.PublicKey{bKey}, []string{""}),
ownerRepo.AddDelegation("targets/a/b", []data.PublicKey{bKey}, []string{""}),
"error creating delegation")
assert.NoError(t, ownerRepo.Publish())
@ -3016,7 +3050,7 @@ func TestListRoles(t *testing.T) {
// Create a delegation on the top level
aKey := createKey(t, repo, "user", true)
assert.NoError(t,
repo.AddDelegation("targets/a", 1, []data.PublicKey{aKey}, []string{""}),
repo.AddDelegation("targets/a", []data.PublicKey{aKey}, []string{""}),
"error creating delegation")
assert.NoError(t, repo.Publish())
@ -3053,7 +3087,7 @@ func TestListRoles(t *testing.T) {
// Create another delegation, one level further
bKey := createKey(t, repo, "user", true)
assert.NoError(t,
repo.AddDelegation("targets/a/b", 1, []data.PublicKey{bKey}, []string{""}),
repo.AddDelegation("targets/a/b", []data.PublicKey{bKey}, []string{""}),
"error creating delegation")
assert.NoError(t, repo.Publish())

View File

@ -136,8 +136,13 @@ func changeTargetsDelegation(repo *tuf.Repo, c changelist.Change) error {
if err := r.AddPathHashPrefixes(td.AddPathHashPrefixes); err != nil {
return err
}
r.RemoveKeys(removeTUFKeyIDs)
r.RemovePaths(td.RemovePaths)
// Clear all paths if we're given the flag, else remove specified paths
if td.ClearAllPaths {
r.RemovePaths(r.Paths)
} else {
r.RemovePaths(td.RemovePaths)
}
r.RemovePathHashPrefixes(td.RemovePathHashPrefixes)
return repo.UpdateDelegations(r, td.AddKeys)
case changelist.ActionDelete:

View File

@ -4,7 +4,6 @@ import (
"fmt"
"io/ioutil"
"github.com/docker/notary"
notaryclient "github.com/docker/notary/client"
"github.com/docker/notary/passphrase"
"github.com/docker/notary/trustmanager"
@ -139,13 +138,19 @@ func (d *delegationCommander) delegationRemove(cmd *cobra.Command, args []string
} else {
cmd.Println("Confirmed `yes` from flag")
}
// Delete the entire delegation
err = nRepo.RemoveDelegationRole(role)
if err != nil {
return fmt.Errorf("failed to remove delegation: %v", err)
}
} else {
// Remove any keys or paths that we passed in
err = nRepo.RemoveDelegationKeysAndPaths(role, keyIDs, paths)
if err != nil {
return fmt.Errorf("failed to remove delegation: %v", err)
}
}
// Remove the delegation from the repository
err = nRepo.RemoveDelegation(role, keyIDs, paths, removeAll)
if err != nil {
return fmt.Errorf("failed to remove delegation: %v", err)
}
cmd.Println("")
if removeAll {
cmd.Printf("Forced removal (including all keys and paths) of delegation role %s to repository \"%s\" staged for next publish.\n", role, gun)
@ -197,9 +202,7 @@ func (d *delegationCommander) delegationAdd(cmd *cobra.Command, args []string) e
}
// Add the delegation to the repository
// Sets threshold to 1 since we only added one key - thresholds are not currently fully supported, though
// one can use additional client-side validation to check for signatures from a quorum of varying delegation roles
err = nRepo.AddDelegation(role, notary.MinThreshold, pubKeys, paths)
err = nRepo.AddDelegation(role, pubKeys, paths)
if err != nil {
return fmt.Errorf("failed to create delegation: %v", err)
}

View File

@ -242,7 +242,6 @@ func (tr *Repo) UpdateDelegations(role *data.Role, keys []data.PublicKey) error
p.Signed.Delegations.Keys[k.ID()] = k
tr.keysDB.AddKey(k)
}
// if the role has fewer keys than the threshold, it
// will never be able to create a valid targets file
// and should be considered invalid.