1package client
2
3import (
4	"github.com/theupdateframework/notary/client/changelist"
5	"github.com/theupdateframework/notary/tuf"
6	"github.com/theupdateframework/notary/tuf/data"
7)
8
9// Witness creates change objects to witness (i.e. re-sign) the given
10// roles on the next publish. One change is created per role
11func (r *repository) Witness(roles ...data.RoleName) ([]data.RoleName, error) {
12	var err error
13	successful := make([]data.RoleName, 0, len(roles))
14	for _, role := range roles {
15		// scope is role
16		c := changelist.NewTUFChange(
17			changelist.ActionUpdate,
18			role,
19			changelist.TypeWitness,
20			"",
21			nil,
22		)
23		err = r.changelist.Add(c)
24		if err != nil {
25			break
26		}
27		successful = append(successful, role)
28	}
29	return successful, err
30}
31
32func witnessTargets(repo *tuf.Repo, invalid *tuf.Repo, role data.RoleName) error {
33	if r, ok := repo.Targets[role]; ok {
34		// role is already valid, mark for re-signing/updating
35		r.Dirty = true
36		return nil
37	}
38
39	if roleObj, err := repo.GetDelegationRole(role); err == nil && invalid != nil {
40		// A role with a threshold > len(keys) is technically invalid, but we let it build in the builder because
41		// we want to be able to download the role (which may still have targets on it), add more keys, and then
42		// witness the role, thus bringing it back to valid.  However, if no keys have been added before witnessing,
43		// then it is still an invalid role, and can't be witnessed because nothing can bring it back to valid.
44		if roleObj.Threshold > len(roleObj.Keys) {
45			return data.ErrInvalidRole{
46				Role:   role,
47				Reason: "role does not specify enough valid signing keys to meet its required threshold",
48			}
49		}
50		if r, ok := invalid.Targets[role]; ok {
51			// role is recognized but invalid, move to valid data and mark for re-signing
52			repo.Targets[role] = r
53			r.Dirty = true
54			return nil
55		}
56	}
57	// role isn't recognized, even as invalid
58	return data.ErrInvalidRole{
59		Role:   role,
60		Reason: "this role is not known",
61	}
62}
63