Beispiel #1
0
// adds a TUF Change template to the given roles
func addChange(cl *changelist.FileChangelist, c changelist.Change, roles ...string) error {

	if len(roles) == 0 {
		roles = []string{data.CanonicalTargetsRole}
	}

	var changes []changelist.Change
	for _, role := range roles {
		// Ensure we can only add targets to the CanonicalTargetsRole,
		// or a Delegation role (which is <CanonicalTargetsRole>/something else)
		if role != data.CanonicalTargetsRole && !data.IsDelegation(role) && !data.IsWildDelegation(role) {
			return data.ErrInvalidRole{
				Role:   role,
				Reason: "cannot add targets to this role",
			}
		}

		changes = append(changes, changelist.NewTUFChange(
			c.Action(),
			role,
			c.Type(),
			c.Path(),
			c.Content(),
		))
	}

	for _, c := range changes {
		if err := cl.Add(c); err != nil {
			return err
		}
	}
	return nil
}
Beispiel #2
0
func applyChangelist(repo *tuf.Repo, invalid *tuf.Repo, cl changelist.Changelist) error {
	it, err := cl.NewIterator()
	if err != nil {
		return err
	}
	index := 0
	for it.HasNext() {
		c, err := it.Next()
		if err != nil {
			return err
		}
		isDel := data.IsDelegation(c.Scope()) || data.IsWildDelegation(c.Scope())
		switch {
		case c.Scope() == changelist.ScopeTargets || isDel:
			err = applyTargetsChange(repo, invalid, c)
		case c.Scope() == changelist.ScopeRoot:
			err = applyRootChange(repo, c)
		default:
			return fmt.Errorf("scope not supported: %s", c.Scope())
		}
		if err != nil {
			logrus.Debugf("error attempting to apply change #%d: %s, on scope: %s path: %s type: %s", index, c.Action(), c.Scope(), c.Path(), c.Type())
			return err
		}
		index++
	}
	logrus.Debugf("applied %d change(s)", index)
	return nil
}
Beispiel #3
0
func changeTargetsDelegation(repo *tuf.Repo, c changelist.Change) error {
	switch c.Action() {
	case changelist.ActionCreate:
		td := changelist.TUFDelegation{}
		err := json.Unmarshal(c.Content(), &td)
		if err != nil {
			return err
		}

		// Try to create brand new role or update one
		// First add the keys, then the paths.  We can only add keys and paths in this scenario
		err = repo.UpdateDelegationKeys(c.Scope(), td.AddKeys, []string{}, td.NewThreshold)
		if err != nil {
			return err
		}
		return repo.UpdateDelegationPaths(c.Scope(), td.AddPaths, []string{}, false)
	case changelist.ActionUpdate:
		td := changelist.TUFDelegation{}
		err := json.Unmarshal(c.Content(), &td)
		if err != nil {
			return err
		}
		if data.IsWildDelegation(c.Scope()) {
			return repo.PurgeDelegationKeys(c.Scope(), td.RemoveKeys)
		}

		delgRole, err := repo.GetDelegationRole(c.Scope())
		if err != nil {
			return err
		}

		// We need to translate the keys from canonical ID to TUF ID for compatibility
		canonicalToTUFID := make(map[string]string)
		for tufID, pubKey := range delgRole.Keys {
			canonicalID, err := utils.CanonicalKeyID(pubKey)
			if err != nil {
				return err
			}
			canonicalToTUFID[canonicalID] = tufID
		}

		removeTUFKeyIDs := []string{}
		for _, canonID := range td.RemoveKeys {
			removeTUFKeyIDs = append(removeTUFKeyIDs, canonicalToTUFID[canonID])
		}

		err = repo.UpdateDelegationKeys(c.Scope(), td.AddKeys, removeTUFKeyIDs, td.NewThreshold)
		if err != nil {
			return err
		}
		return repo.UpdateDelegationPaths(c.Scope(), td.AddPaths, td.RemovePaths, td.ClearAllPaths)
	case changelist.ActionDelete:
		return repo.DeleteDelegation(c.Scope())
	default:
		return fmt.Errorf("unsupported action against delegations: %s", c.Action())
	}

}
Beispiel #4
0
// 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.
// It can also delete a key from all delegations under a parent using a name
// with a wildcard at the end.
func (r *NotaryRepository) RemoveDelegationKeys(name string, keyIDs []string) error {

	if !data.IsDelegation(name) && !data.IsWildDelegation(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)
}
Beispiel #5
0
// PurgeDelegationKeys removes the provided canonical key IDs from all delegations
// present in the subtree rooted at role. The role argument must be provided in a wildcard
// format, i.e. targets/* would remove the key from all delegations in the repo
func (tr *Repo) PurgeDelegationKeys(role string, removeKeys []string) error {
	if !data.IsWildDelegation(role) {
		return data.ErrInvalidRole{
			Role:   role,
			Reason: "only wildcard roles can be used in a purge",
		}
	}

	removeIDs := make(map[string]struct{})
	for _, id := range removeKeys {
		removeIDs[id] = struct{}{}
	}

	start := path.Dir(role)
	tufIDToCanon := make(map[string]string)

	purgeKeys := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} {
		var (
			deleteCandidates []string
			err              error
		)
		for id, key := range tgt.Signed.Delegations.Keys {
			var (
				canonID string
				ok      bool
			)
			if canonID, ok = tufIDToCanon[id]; !ok {
				canonID, err = utils.CanonicalKeyID(key)
				if err != nil {
					return err
				}
				tufIDToCanon[id] = canonID
			}
			if _, ok := removeIDs[canonID]; ok {
				deleteCandidates = append(deleteCandidates, id)
			}
		}
		if len(deleteCandidates) == 0 {
			// none of the interesting keys were present. We're done with this role
			return nil
		}
		// now we know there are changes, check if we'll be able to sign them in
		if err := tr.VerifyCanSign(validRole.Name); err != nil {
			logrus.Warnf(
				"role %s contains keys being purged but you do not have the necessary keys present to sign it; keys will not be purged from %s or its immediate children",
				validRole.Name,
				validRole.Name,
			)
			return nil
		}
		// we know we can sign in the changes, delete the keys
		for _, id := range deleteCandidates {
			delete(tgt.Signed.Delegations.Keys, id)
		}
		// delete candidate keys from all roles.
		for _, role := range tgt.Signed.Delegations.Roles {
			role.RemoveKeys(deleteCandidates)
			if len(role.KeyIDs) < role.Threshold {
				logrus.Warnf("role %s has fewer keys than its threshold of %d; it will not be usable until keys are added to it", role.Name, role.Threshold)
			}
		}
		tgt.Dirty = true
		return nil
	}
	return tr.WalkTargets("", start, purgeKeys)
}