Skip to content

Commit 41a6dac

Browse files
author
Jussi Kukkonen
committed
Metadata API: Add id to Key
This simplifies life for API users as usually a key needs its identifier: this is already visible in how update() becomes simpler in the API. The downside is that 'from_dict()' now has two arguments (so arguably the name is not great anymore but it still does _mostly_ the same job as other from_dicts). This is an API change, if a minor one. Signed-off-by: Jussi Kukkonen <[email protected]>
1 parent f935ea3 commit 41a6dac

File tree

2 files changed

+18
-15
lines changed

2 files changed

+18
-15
lines changed

tests/test_api.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -373,18 +373,18 @@ def test_key_class(self):
373373
# Testing that the workflow of deserializing and serializing
374374
# a key dictionary doesn't change the content.
375375
test_key_dict = key_dict.copy()
376-
key_obj = Key.from_dict(test_key_dict)
376+
key_obj = Key.from_dict("id", test_key_dict)
377377
self.assertEqual(key_dict, key_obj.to_dict())
378378
# Test creating an instance without a required attribute.
379379
for key in key_dict.keys():
380380
test_key_dict = key_dict.copy()
381381
del test_key_dict[key]
382382
with self.assertRaises(KeyError):
383-
Key.from_dict(test_key_dict)
383+
Key.from_dict("id", test_key_dict)
384384
# Test creating a Key instance with wrong keyval format.
385385
key_dict["keyval"] = {}
386386
with self.assertRaises(ValueError):
387-
Key.from_dict(key_dict)
387+
Key.from_dict("id", key_dict)
388388

389389

390390
def test_role_class(self):
@@ -413,7 +413,7 @@ def test_role_class(self):
413413
test_role_dict = role_dict.copy()
414414
del test_role_dict[role_attr]
415415
with self.assertRaises(KeyError):
416-
Key.from_dict(test_role_dict)
416+
Key.from_dict("id", test_role_dict)
417417
# Test creating a Role instance with keyid dublicates.
418418
# for keyid in role_dict["keyids"]:
419419
role_dict["keyids"].append(role_dict["keyids"][0])
@@ -433,15 +433,15 @@ def test_metadata_root(self):
433433

434434

435435
keyid = root_key2['keyid']
436-
key_metadata = Key(root_key2['keytype'], root_key2['scheme'],
436+
key_metadata = Key(keyid, root_key2['keytype'], root_key2['scheme'],
437437
root_key2['keyval'])
438438

439439
# Assert that root does not contain the new key
440440
self.assertNotIn(keyid, root.signed.roles['root'].keyids)
441441
self.assertNotIn(keyid, root.signed.keys)
442442

443443
# Add new root key
444-
root.signed.add_key('root', keyid, key_metadata)
444+
root.signed.add_key('root', key_metadata)
445445

446446
# Assert that key is added
447447
self.assertIn(keyid, root.signed.roles['root'].keyids)
@@ -453,7 +453,7 @@ def test_metadata_root(self):
453453

454454
# Try adding the same key again and assert its ignored.
455455
pre_add_keyid = root.signed.roles['root'].keyids.copy()
456-
root.signed.add_key('root', keyid, key_metadata)
456+
root.signed.add_key('root', key_metadata)
457457
self.assertEqual(pre_add_keyid, root.signed.roles['root'].keyids)
458458

459459
# Remove the key

tuf/api/metadata.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ class Key:
417417
"""A container class representing the public portion of a Key.
418418
419419
Attributes:
420+
keyid: An identifier string
420421
keytype: A string denoting a public key signature system,
421422
such as "rsa", "ed25519", and "ecdsa-sha2-nistp256".
422423
scheme: A string denoting a corresponding signature scheme. For example:
@@ -428,26 +429,28 @@ class Key:
428429

429430
def __init__(
430431
self,
432+
keyid: str,
431433
keytype: str,
432434
scheme: str,
433435
keyval: Dict[str, str],
434436
unrecognized_fields: Optional[Mapping[str, Any]] = None,
435437
) -> None:
436438
if not keyval.get("public"):
437439
raise ValueError("keyval doesn't follow the specification format!")
440+
self.keyid = keyid
438441
self.keytype = keytype
439442
self.scheme = scheme
440443
self.keyval = keyval
441444
self.unrecognized_fields: Mapping[str, Any] = unrecognized_fields or {}
442445

443446
@classmethod
444-
def from_dict(cls, key_dict: Dict[str, Any]) -> "Key":
447+
def from_dict(cls, keyid: str, key_dict: Dict[str, Any]) -> "Key":
445448
"""Creates Key object from its dict representation."""
446449
keytype = key_dict.pop("keytype")
447450
scheme = key_dict.pop("scheme")
448451
keyval = key_dict.pop("keyval")
449452
# All fields left in the key_dict are unrecognized.
450-
return cls(keytype, scheme, keyval, key_dict)
453+
return cls(keyid, keytype, scheme, keyval, key_dict)
451454

452455
def to_dict(self) -> Dict[str, Any]:
453456
"""Returns the dictionary representation of self."""
@@ -558,7 +561,7 @@ def from_dict(cls, root_dict: Dict[str, Any]) -> "Root":
558561
roles = root_dict.pop("roles")
559562

560563
for keyid, key_dict in keys.items():
561-
keys[keyid] = Key.from_dict(key_dict)
564+
keys[keyid] = Key.from_dict(keyid, key_dict)
562565
for role_name, role_dict in roles.items():
563566
roles[role_name] = Role.from_dict(role_dict)
564567

@@ -584,10 +587,10 @@ def to_dict(self) -> Dict[str, Any]:
584587
return root_dict
585588

586589
# Update key for a role.
587-
def add_key(self, role: str, keyid: str, key_metadata: Key) -> None:
588-
"""Adds new key for 'role' and updates the key store."""
589-
self.roles[role].keyids.add(keyid)
590-
self.keys[keyid] = key_metadata
590+
def add_key(self, role: str, key: Key) -> None:
591+
"""Adds new signing key for delegated role 'role'."""
592+
self.roles[role].keyids.add(key.keyid)
593+
self.keys[key.keyid] = key
591594

592595
def remove_key(self, role: str, keyid: str) -> None:
593596
"""Removes key from 'role' and updates the key store.
@@ -863,7 +866,7 @@ def from_dict(cls, delegations_dict: Dict[str, Any]) -> "Delegations":
863866
keys = delegations_dict.pop("keys")
864867
keys_res = {}
865868
for keyid, key_dict in keys.items():
866-
keys_res[keyid] = Key.from_dict(key_dict)
869+
keys_res[keyid] = Key.from_dict(keyid, key_dict)
867870
roles = delegations_dict.pop("roles")
868871
roles_res = []
869872
for role_dict in roles:

0 commit comments

Comments
 (0)