Skip to content

Commit

Permalink
Raise if none of paths and path_hash_prefixes is set
Browse files Browse the repository at this point in the history
The specification does not state clearly what is the
behaviour when none of delegation's "paths" and
"path_hash_prefixes" is set. See #1497.

Until this issue is clarified, copy current
Updater which raises an error in such case.

Signed-off-by: Teodora Sechkova <tsechkova@vmware.com>
  • Loading branch information
sechkova committed Aug 6, 2021
1 parent 2f8f8c2 commit 34f59c9
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 14 deletions.
28 changes: 21 additions & 7 deletions tests/test_metadata_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,10 +242,9 @@ def test_snapshot_serialization(self, test_case_data: str):
"no path attribute":
'{"keyids": ["keyid"], "name": "a", "terminating": false, \
"path_hash_prefixes": ["h1", "h2"], "threshold": 99}',
"no hash or path prefix":
'{"keyids": ["keyid"], "name": "a", "terminating": true, "threshold": 3}',
"unrecognized field":
'{"keyids": ["keyid"], "name": "a", "terminating": true, "threshold": 3, "foo": "bar"}',
'{"keyids": ["keyid"], "name": "a", "paths": ["fn1", "fn2"], \
"terminating": true, "threshold": 3, "foo": "bar"}',
}

@run_sub_tests_with_dataset(valid_delegated_roles)
Expand All @@ -255,12 +254,27 @@ def test_delegated_role_serialization(self, test_case_data: str):
self.assertDictEqual(case_dict, deserialized_role.to_dict())


invalid_delegated_roles: DataSet = {
"missing hash prefixes and paths":
'{"name": "a", "keyids": ["keyid"], "threshold": 1, "terminating": false}',
"both hash prefixes and paths":
'{"name": "a", "keyids": ["keyid"], "threshold": 1, "terminating": false, \
"paths": ["fn1", "fn2"], "path_hash_prefixes": ["h1", "h2"]}',
}

@run_sub_tests_with_dataset(invalid_delegated_roles)
def test_invalid_delegated_role_serialization(self, test_case_data: str):
case_dict = json.loads(test_case_data)
with self.assertRaises(ValueError):
DelegatedRole.from_dict(copy.copy(case_dict))


valid_delegations: DataSet = {
"all": '{"keys": {"keyid" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \
"roles": [ {"keyids": ["keyid"], "name": "a", "terminating": true, "threshold": 3} ]}',
"roles": [ {"keyids": ["keyid"], "name": "a", "paths": ["fn1", "fn2"], "terminating": true, "threshold": 3} ]}',
"unrecognized field":
'{"keys": {"keyid" : {"keytype": "rsa", "scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"}}}, \
"roles": [ {"keyids": ["keyid"], "name": "a", "terminating": true, "threshold": 3} ], \
"roles": [ {"keyids": ["keyid"], "name": "a", "paths": ["fn1", "fn2"], "terminating": true, "threshold": 3} ], \
"foo": "bar"}',
}

Expand Down Expand Up @@ -305,13 +319,13 @@ def test_targetfile_serialization(self, test_case_data: str):
"targets": { "file.txt": {"length": 12, "hashes": {"sha256" : "abc"} } }, \
"delegations": {"keys": {"keyid" : {"keytype": "rsa", \
"scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"} }}, \
"roles": [ {"keyids": ["keyid"], "name": "a", "terminating": true, "threshold": 3} ]} \
"roles": [ {"keyids": ["keyid"], "name": "a", "paths": ["fn1", "fn2"], "terminating": true, "threshold": 3} ]} \
}',
"empty targets": '{"_type": "targets", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", \
"targets": {}, \
"delegations": {"keys": {"keyid" : {"keytype": "rsa", \
"scheme": "rsassa-pss-sha256", "keyval": {"public": "foo"} }}, \
"roles": [ {"keyids": ["keyid"], "name": "a", "terminating": true, "threshold": 3} ]} \
"roles": [ {"keyids": ["keyid"], "name": "a", "paths": ["fn1", "fn2"], "terminating": true, "threshold": 3} ]} \
}',
"no delegations": '{"_type": "targets", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", \
"targets": { "file.txt": {"length": 12, "hashes": {"sha256" : "abc"} } } \
Expand Down
15 changes: 8 additions & 7 deletions tuf/api/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -962,12 +962,12 @@ def update(self, rolename: str, role_info: MetaFile) -> None:
class DelegatedRole(Role):
"""A container with information about a delegated role.
A delegation can happen in three ways:
- paths is None and path_hash_prefixes is None: delegates all targets
A delegation can happen in two ways:
- paths is set: delegates targets matching any path pattern in paths
- path_hash_prefixes is set: delegates targets whose target path hash
starts with any of the prefixes in path_hash_prefixes
paths and path_hash_prefixes are mutually exclusive: both cannot be set.
paths and path_hash_prefixes are mutually exclusive: both cannot be set,
at least one of them must be set.
Attributes:
name: A string giving the name of the delegated role.
Expand All @@ -992,10 +992,11 @@ def __init__(
self.name = name
self.terminating = terminating
if paths is not None and path_hash_prefixes is not None:
raise ValueError(
"Only one of the attributes 'paths' and"
"'path_hash_prefixes' can be set!"
)
raise ValueError("Either paths or path_hash_prefixes can be set")

if paths is None and path_hash_prefixes is None:
raise ValueError("One of paths or path_hash_prefixes must be set")

self.paths = paths
self.path_hash_prefixes = path_hash_prefixes

Expand Down

0 comments on commit 34f59c9

Please sign in to comment.