Skip to content

Commit

Permalink
Metadata API: Add key helpers in Delegations
Browse files Browse the repository at this point in the history
Root class has the functionality to add and remove keys for delegated
metadata (add_key()/remove_key()) but the other delegator Targets does
not.
It should provide the same/similar functionality.

It seems logical to me that those functions will be part of the
"Delegations" class instead of "Targets" as those helper functions are
related to the delegated roles.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
  • Loading branch information
MVrachev committed Aug 26, 2021
1 parent 346c3eb commit ba09c66
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
50 changes: 50 additions & 0 deletions tests/test_api.py
Expand Up @@ -507,6 +507,56 @@ def test_metadata_root(self):
root.signed.remove_key('root', 'nosuchkey')


def test_delegation_class(self):
delegations_dict = {
"keys": {},
"roles": [{
"keyids": [],
"name": "project.json",
"paths": ["fn1", "fn2"],
"terminating": False,
"threshold": 1
}]}
delegations = Delegations.from_dict(delegations_dict)
key_dict = {
"keytype": "ed25519",
"keyval": {
"public": "edcd0a32a07dce33f7c7873aaffbff36d20ea30787574ead335eefd337e4dacd"
},
"scheme": "ed25519"
}
key = Key.from_dict("id2", key_dict)

# Assert that delegated role "project.json" does not contain the new key
self.assertNotIn(key.keyid, delegations.roles["project.json"].keyids)
delegations.add_key("project.json", key)

# Assert that the new key is added to the delegated role "project.json"
self.assertIn(key.keyid, delegations.roles["project.json"].keyids)

# Confirm that the newly added key does not break the obj serialization
delegations.to_dict()

# Try adding the same key again and assert its ignored.
past_keyid = delegations.roles["project.json"].keyids.copy()
delegations.add_key("project.json", key)
self.assertEqual(past_keyid, delegations.roles["project.json"].keyids)

# Try adding a key to a delegated role that doesn't exists
with self.assertRaises(KeyError):
delegations.add_key("abc", key)

# Remove a key from the delegated "project.json" role
delegations.remove_key("project.json", key.keyid)

# Assert that delegated role "project.json" doesn't contain the key.
self.assertNotIn(key.keyid, delegations.roles["project.json"].keyids)

# Try removing a key from delegated role that doesn't exists
with self.assertRaises(KeyError):
delegations.remove_key("abc", key.keyid)


def test_metadata_targets(self):
targets_path = os.path.join(
self.repo_dir, 'metadata', 'targets.json')
Expand Down
22 changes: 22 additions & 0 deletions tuf/api/metadata.py
Expand Up @@ -1138,6 +1138,28 @@ def to_dict(self) -> Dict[str, Any]:
**self.unrecognized_fields,
}

def add_key(self, role: str, key: Key) -> None:
"""Adds new signing key for delegated role 'role'.
Raises:
KeyError: If there is no role 'role' in this Delegations object.
"""
self.roles[role].keyids.add(key.keyid)
self.keys[key.keyid] = key

def remove_key(self, role: str, keyid: str) -> None:
"""Removes key from 'role' and updates the key store.
Raises:
KeyError: If there is no role 'role' in this Delegations object.
"""
self.roles[role].keyids.remove(keyid)
for keyinfo in self.roles.values():
if keyid in keyinfo.keyids:
return

del self.keys[keyid]


class TargetFile(BaseFile):
"""A container with information about a particular target file.
Expand Down

0 comments on commit ba09c66

Please sign in to comment.