Skip to content

Commit 69f8688

Browse files
committed
Update error messages, comments, and tests for snapshot merkle tree functionality.
Signed-off-by: marinamoore <[email protected]>
1 parent 0b4561c commit 69f8688

File tree

5 files changed

+45
-30
lines changed

5 files changed

+45
-30
lines changed

tests/test_repository_lib.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,8 +439,7 @@ def test_build_merkle_tree(self):
439439
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
440440
storage_backend = securesystemslib.storage.FilesystemBackend()
441441

442-
# Test building the tree one node at a time with identical nodes
443-
# to verify the hashes
442+
# Test building the tree one node at a time to verify the hashes
444443

445444
test_nodes = {}
446445
test_nodes['file1'] = tuf.formats.make_metadata_fileinfo(5, None, None)

tests/test_repository_tool.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,17 @@ def test_writeall(self):
264264
repository.mark_dirty(['role1', 'targets', 'root', 'snapshot', 'timestamp'])
265265
repository.writeall(snapshot_merkle=True)
266266

267+
# Were the merkle snapshots written?
267268
targets_snapshot_filepath = os.path.join(metadata_directory,
268269
'targets-snapshot.json')
269270
targets_snapshot = securesystemslib.util.load_json_file(targets_snapshot_filepath)
270271
tuf.formats.SNAPSHOT_MERKLE_SCHEMA.check_match(targets_snapshot)
271272

273+
# Does timestamp have the root hash?
274+
timestamp_filepath = os.path.join(metadata_directory, 'timestamp.json')
275+
timestamp = securesystemslib.util.load_json_file(timestamp_filepath)
276+
timestamp['signed']['merkle_root']
277+
272278
# Verify that status() does not raise
273279
# 'tuf.exceptions.InsufficientKeysError' if a top-level role
274280
# does not contain a threshold of keys.

tests/test_updater.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,6 @@ def test_2__ensure_not_expired(self):
699699

700700

701701

702-
703702
def test_3__update_metadata(self):
704703
# Setup
705704
# _update_metadata() downloads, verifies, and installs the specified
@@ -843,6 +842,7 @@ def test_3__get_metadata_file(self):
843842

844843

845844

845+
846846
def test_3__update_metadata_if_changed(self):
847847
# Setup.
848848
# The client repository is initially loaded with only four top-level roles.
@@ -1786,6 +1786,13 @@ def test_snapshot_merkle(self):
17861786

17871787
self.assertEqual(snapshot_info['version'], 1)
17881788

1789+
# verify merkle path with invalid role
1790+
self.assertRaises(tuf.exceptions.NoWorkingMirrorError,
1791+
repository_updater._verify_merkle_path, 'foo')
1792+
1793+
# Test get_one_valid_targetinfo with snapshot merkle
1794+
repository_updater.get_one_valid_targetinfo('file1.txt')
1795+
17891796

17901797

17911798

tuf/client/updater.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,11 +1083,9 @@ def refresh(self, unsafely_update_root_if_necessary=True):
10831083
# require strict checks on its required length.
10841084
self._update_metadata('timestamp', DEFAULT_TIMESTAMP_UPPERLENGTH)
10851085

1086-
try:
1086+
if 'merkle_root' not in self.metadata['current']['timestamp']:
10871087
# If merkle root is set, do not update snapshot metadata. Instead,
10881088
# download the relevant merkle path when downloading a target.
1089-
self.metadata['current']['timestamp']['merkle_root']
1090-
except KeyError:
10911089
self._update_metadata_if_changed('snapshot',
10921090
referenced_metadata='timestamp')
10931091
self._update_metadata_if_changed('targets')
@@ -1846,6 +1844,7 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None,
18461844
# 'current_metadata_object' set to 'None' if there is not an object
18471845
# stored for 'metadata_role'.
18481846
if snapshot_merkle:
1847+
# Snaphot merkle files are not signed
18491848
updated_metadata_object=metadata_signable
18501849
else:
18511850
updated_metadata_object = metadata_signable['signed']
@@ -1865,9 +1864,16 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None,
18651864

18661865

18671866

1868-
def _verify_merkle_path(self, metadata_role, referenced_metadata='snapshot'):
1867+
def _verify_merkle_path(self, metadata_role):
18691868
"""
1870-
Download the merkle path associated with metadata_role and verify the hashes.
1869+
<Purpose>
1870+
Download the merkle path associated with metadata_role and verify the hashes.
1871+
<Arguments>
1872+
metadata_role:
1873+
The name of the metadata role. This should not include a file extension.
1874+
<Exceptions>
1875+
tuf.exceptions.RepositoryError:
1876+
If the snapshot merkle file is invalid or the verification fails
18711877
Returns the snapshot information about metadata role.
18721878
"""
18731879
merkle_root = self.metadata['current']['timestamp']['merkle_root']
@@ -1910,30 +1916,33 @@ def _verify_merkle_path(self, metadata_role, referenced_metadata='snapshot'):
19101916
# If merkle_path and path_directions have different lengths,
19111917
# the verification will not be possible
19121918
if len(merkle_path) != len(path_directions):
1913-
# error
1914-
return
1919+
raise tuf.exceptions.RepositoryError('Invalid merkle path for ' +
1920+
metadata_role)
19151921

19161922
for index in range(len(merkle_path)):
19171923
i = str(index)
19181924
if path_directions[i] < 0:
1925+
# The current node is a left node
19191926
digest_object = securesystemslib.hash.digest()
19201927
digest_object.update((node_hash + merkle_path[i]).encode('utf-8'))
19211928
else:
1929+
# The current node is a right node
19221930
digest_object = securesystemslib.hash.digest()
19231931
digest_object.update((merkle_path[i] + node_hash).encode('utf-8'))
19241932
node_hash = digest_object.hexdigest()
19251933

19261934
# Does the result match the merkle root?
19271935
if node_hash != merkle_root:
1928-
# error
1929-
return 1
1936+
raise tuf.exceptions.RepositoryError('The merkle root does not match ' +
1937+
'the hash for ' + metadata_role)
19301938

19311939
# return the verified snapshot contents
19321940
return contents
19331941

19341942
else:
1935-
# No merkle path found, error?
1936-
return 2
1943+
# No merkle path found
1944+
raise tuf.exceptions.RepositoryError('No snapshot merkle file for ' +
1945+
metadata_role)
19371946

19381947

19391948

@@ -2017,10 +2026,9 @@ def _update_metadata_if_changed(self, metadata_role,
20172026
repr(referenced_metadata)+ '. ' + repr(metadata_role) +
20182027
' may be updated.')
20192028

2020-
if 'merkle_root' in self.metadata['current'][referenced_metadata]:
2029+
if 'merkle_root' in self.metadata['current']['timestamp']:
20212030
# Download version information from merkle tree
2022-
contents = self._verify_merkle_path(metadata_filename,
2023-
referenced_metadata=referenced_metadata)
2031+
contents = self._verify_merkle_path(metadata_role)
20242032
expected_versioninfo = contents
20252033

20262034
else:

tuf/repository_lib.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,6 @@ def _generate_and_write_metadata(rolename, metadata_filename,
138138
use_length=use_snapshot_length, use_hashes=use_snapshot_hashes,
139139
snapshot_merkle=True)
140140

141-
print_merkle_tree(root)
142-
143141
# Add the merkle tree root hash to the timestamp roleinfo
144142
timestamp_roleinfo = tuf.roledb.get_roleinfo('timestamp', repository_name)
145143
timestamp_roleinfo['merkle_root'] = root.hash()
@@ -2013,17 +2011,14 @@ def generate_timestamp_metadata(snapshot_file_path, version, expiration_date,
20132011
tuf.formats.make_metadata_fileinfo(snapshot_version['version'],
20142012
length, hashes)
20152013

2016-
if(roleinfo):
2017-
try:
2018-
merkle_root = roleinfo['merkle_root']
2019-
return tuf.formats.build_dict_conforming_to_schema(
2020-
tuf.formats.TIMESTAMP_SCHEMA,
2021-
version=version,
2022-
expires=expiration_date,
2023-
meta=snapshot_fileinfo,
2024-
merkle_root=merkle_root)
2025-
except KeyError:
2026-
pass
2014+
if roleinfo and 'merkle_root' in roleinfo:
2015+
merkle_root = roleinfo['merkle_root']
2016+
return tuf.formats.build_dict_conforming_to_schema(
2017+
tuf.formats.TIMESTAMP_SCHEMA,
2018+
version=version,
2019+
expires=expiration_date,
2020+
meta=snapshot_fileinfo,
2021+
merkle_root=merkle_root)
20272022

20282023
# Generate the timestamp metadata object.
20292024
# Use generalized build_dict_conforming_to_schema func to produce a dict that

0 commit comments

Comments
 (0)