Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Reason to ErrInvalidKeys #237

Merged
merged 1 commit into from
Mar 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ func (e ErrInsufficientSignatures) Error() string {
}

type ErrInvalidRole struct {
Role string
Role string
Reason string
}

func (e ErrInvalidRole) Error() string {
return fmt.Sprintf("tuf: invalid role %s", e.Role)
return fmt.Sprintf("tuf: invalid role %s: %s", e.Role, e.Reason)
}

type ErrInvalidExpires struct {
Expand Down
23 changes: 14 additions & 9 deletions repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,18 @@ func (r *Repo) RootVersion() (int, error) {
}

func (r *Repo) GetThreshold(keyRole string) (int, error) {
if !roles.IsTopLevelRole(keyRole) {
// Delegations are not currently supported, so return an error if this is not a
// top-level metadata file.
return -1, ErrInvalidRole{keyRole, "only thresholds for top-level roles supported"}
}
root, err := r.root()
if err != nil {
return -1, err
}
role, ok := root.Roles[keyRole]
if !ok {
return -1, ErrInvalidRole{keyRole}
return -1, ErrInvalidRole{keyRole, "role missing from root metadata"}
}

return role.Threshold, nil
Expand All @@ -203,15 +208,15 @@ func (r *Repo) SetThreshold(keyRole string, t int) error {
if !roles.IsTopLevelRole(keyRole) {
// Delegations are not currently supported, so return an error if this is not a
// top-level metadata file.
return ErrInvalidRole{keyRole}
return ErrInvalidRole{keyRole, "only thresholds for top-level roles supported"}
}
root, err := r.root()
if err != nil {
return err
}
role, ok := root.Roles[keyRole]
if !ok {
return ErrInvalidRole{keyRole}
return ErrInvalidRole{keyRole, "role missing from root metadata"}
}
if role.Threshold == t {
// Change was a no-op.
Expand Down Expand Up @@ -318,7 +323,7 @@ func (r *Repo) timestamp() (*data.Timestamp, error) {

func (r *Repo) ChangePassphrase(keyRole string) error {
if !roles.IsTopLevelRole(keyRole) {
return ErrInvalidRole{keyRole}
return ErrInvalidRole{keyRole, "only support passphrases for top-level roles"}
}

if p, ok := r.local.(PassphraseChanger); ok {
Expand Down Expand Up @@ -351,7 +356,7 @@ func (r *Repo) AddPrivateKey(role string, signer keys.Signer) error {

func (r *Repo) AddPrivateKeyWithExpires(keyRole string, signer keys.Signer, expires time.Time) error {
if !roles.IsTopLevelRole(keyRole) {
return ErrInvalidRole{keyRole}
return ErrInvalidRole{keyRole, "only support adding keys for top-level roles"}
}

if !validExpires(expires) {
Expand Down Expand Up @@ -449,7 +454,7 @@ func (r *Repo) RevokeKey(role, id string) error {

func (r *Repo) RevokeKeyWithExpires(keyRole, id string, expires time.Time) error {
if !roles.IsTopLevelRole(keyRole) {
return ErrInvalidRole{keyRole}
return ErrInvalidRole{keyRole, "only revocations for top-level roles supported"}
}

if !validExpires(expires) {
Expand Down Expand Up @@ -552,7 +557,7 @@ func (r *Repo) setTopLevelMeta(roleFilename string, meta interface{}) error {
func (r *Repo) Sign(roleFilename string) error {
role := strings.TrimSuffix(roleFilename, ".json")
if !roles.IsTopLevelRole(role) {
return ErrInvalidRole{role}
return ErrInvalidRole{role, "only signing top-level metadata supported"}
}

s, err := r.SignedMeta(roleFilename)
Expand Down Expand Up @@ -588,7 +593,7 @@ func (r *Repo) Sign(roleFilename string) error {
func (r *Repo) AddOrUpdateSignature(roleFilename string, signature data.Signature) error {
role := strings.TrimSuffix(roleFilename, ".json")
if !roles.IsTopLevelRole(role) {
return ErrInvalidRole{role}
return ErrInvalidRole{role, "only signing top-level metadata supported"}
}

// Check key ID is in valid for the role.
Expand All @@ -598,7 +603,7 @@ func (r *Repo) AddOrUpdateSignature(roleFilename string, signature data.Signatur
}
roleData := db.GetRole(role)
if roleData == nil {
return ErrInvalidRole{role}
return ErrInvalidRole{role, "role missing from top-level keys"}
}
if !roleData.ValidKey(signature.KeyID) {
return verify.ErrInvalidKey
Expand Down
33 changes: 29 additions & 4 deletions repo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func (rs *RepoSuite) TestGenKey(c *C) {

// generate a key for an unknown role
_, err = r.GenKey("foo")
c.Assert(err, Equals, ErrInvalidRole{"foo"})
c.Assert(err, Equals, ErrInvalidRole{"foo", "only support adding keys for top-level roles"})

// generate a root key
ids := genKey(c, r, "root")
Expand Down Expand Up @@ -346,7 +346,7 @@ func (rs *RepoSuite) TestAddPrivateKey(c *C) {
signer, err := keys.GenerateEd25519Key()
c.Assert(err, IsNil)
err = r.AddPrivateKey("foo", signer)
c.Assert(err, Equals, ErrInvalidRole{"foo"})
c.Assert(err, Equals, ErrInvalidRole{"foo", "only support adding keys for top-level roles"})

// add a root key
ids := addPrivateKey(c, r, "root", signer)
Expand Down Expand Up @@ -511,7 +511,7 @@ func (rs *RepoSuite) TestRevokeKey(c *C) {
c.Assert(err, IsNil)

// revoking a key for an unknown role returns ErrInvalidRole
c.Assert(r.RevokeKey("foo", ""), DeepEquals, ErrInvalidRole{"foo"})
c.Assert(r.RevokeKey("foo", ""), DeepEquals, ErrInvalidRole{"foo", "only revocations for top-level roles supported"})

// revoking a key which doesn't exist returns ErrKeyNotFound
c.Assert(r.RevokeKey("root", "nonexistent"), DeepEquals, ErrKeyNotFound{"root", "nonexistent"})
Expand Down Expand Up @@ -632,6 +632,8 @@ func (rs *RepoSuite) TestSign(c *C) {
r, err := NewRepo(local)
c.Assert(err, IsNil)

c.Assert(r.Sign("foo.json"), Equals, ErrInvalidRole{"foo", "only signing top-level metadata supported"})

// signing with no keys returns ErrInsufficientKeys
c.Assert(r.Sign("root.json"), Equals, ErrInsufficientKeys{"root.json"})

Expand Down Expand Up @@ -676,6 +678,9 @@ func (rs *RepoSuite) TestSign(c *C) {
c.Assert(local.SaveSigner("root", newKey), IsNil)
c.Assert(r.Sign("root.json"), IsNil)
checkSigIDs(append(signer.PublicData().IDs(), newKey.PublicData().IDs()...)...)

// attempt to sign missing metadata
c.Assert(r.Sign("targets.json"), Equals, ErrMissingMetadata{"targets.json"})
}

func (rs *RepoSuite) TestCommit(c *C) {
Expand Down Expand Up @@ -1384,6 +1389,12 @@ func (rs *RepoSuite) TestKeyPersistence(c *C) {
tmp = newTmpDir(c)
store = FileSystemStore(tmp.path, testPassphraseFunc)

// 1.5. Changing passphrase only works for top-level roles.
r, err := NewRepo(store)
c.Assert(err, IsNil)

c.Assert(r.ChangePassphrase("foo"), DeepEquals, ErrInvalidRole{"foo", "only support passphrases for top-level roles"})

// 2. Test changing the passphrase when the keys file does not exist - should FAIL
c.Assert(store.(PassphraseChanger).ChangePassphrase("root"), NotNil)

Expand Down Expand Up @@ -1596,6 +1607,11 @@ func (rs *RepoSuite) TestThreshold(c *C) {
r, err := NewRepo(local)
c.Assert(err, IsNil)

_, err = r.GetThreshold("root")
c.Assert(err, DeepEquals, ErrInvalidRole{"root", "role missing from root metadata"})
err = r.SetThreshold("root", 2)
c.Assert(err, DeepEquals, ErrInvalidRole{"root", "role missing from root metadata"})

// Add one key to each role
genKey(c, r, "root")
genKey(c, r, "targets")
Expand All @@ -1605,6 +1621,11 @@ func (rs *RepoSuite) TestThreshold(c *C) {
c.Assert(err, IsNil)
c.Assert(t, Equals, 1)

_, err = r.GetThreshold("foo")
c.Assert(err, DeepEquals, ErrInvalidRole{"foo", "only thresholds for top-level roles supported"})
err = r.SetThreshold("foo", 2)
c.Assert(err, DeepEquals, ErrInvalidRole{"foo", "only thresholds for top-level roles supported"})

// commit the metadata to the store.
c.Assert(r.AddTargets([]string{}, nil), IsNil)
c.Assert(r.Snapshot(), IsNil)
Expand Down Expand Up @@ -1725,6 +1746,10 @@ func (rs *RepoSuite) TestBadAddOrUpdateSignatures(c *C) {
// don't use consistent snapshots to make the checks simpler
c.Assert(r.Init(false), IsNil)

c.Assert(r.AddOrUpdateSignature("targets.json", data.Signature{
KeyID: "foo",
Signature: nil}), Equals, ErrInvalidRole{"targets", "role missing from top-level keys"})

// generate root key offline and add as a verification key
rootKey, err := keys.GenerateEd25519Key()
c.Assert(err, IsNil)
Expand All @@ -1747,7 +1772,7 @@ func (rs *RepoSuite) TestBadAddOrUpdateSignatures(c *C) {
for _, id := range rootKey.PublicData().IDs() {
c.Assert(r.AddOrUpdateSignature("invalid_root.json", data.Signature{
KeyID: id,
Signature: rootSig}), Equals, ErrInvalidRole{"invalid_root"})
Signature: rootSig}), Equals, ErrInvalidRole{"invalid_root", "only signing top-level metadata supported"})
}

// add a root signature with an key ID that is for the targets role
Expand Down