Skip to content

Commit 7d81f70

Browse files
committed
Add verification_fn to _get_metadata_file
The verification_fn moves the verification for signable metadata into a separate function. Files that are not signable, such as snapshot merkle files, do not use the verification for signable metadata. Signed-off-by: marinamoore <[email protected]>
1 parent 561428c commit 7d81f70

2 files changed

Lines changed: 95 additions & 86 deletions

File tree

tests/test_updater.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ def test_3__get_metadata_file(self):
823823
upperbound_filelength = tuf.settings.DEFAULT_TIMESTAMP_REQUIRED_LENGTH
824824
try:
825825
self.repository_updater._get_metadata_file('timestamp', 'timestamp.json',
826-
upperbound_filelength, 1)
826+
upperbound_filelength, 1, self.repository_updater.signable_verification)
827827

828828
except tuf.exceptions.NoWorkingMirrorError as e:
829829
# Note that this test provides a piece of metadata which would fail to

tuf/client/updater.py

Lines changed: 94 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,8 @@ def _verify_metadata_file(self, metadata_file_object,
14991499

15001500

15011501
def _get_metadata_file(self, metadata_role, remote_filename,
1502-
upperbound_filelength, expected_version, snapshot_merkle=False):
1502+
upperbound_filelength, expected_version,
1503+
verification_fn):
15031504
"""
15041505
<Purpose>
15051506
Non-public method that tries downloading, up to a certain length, a
@@ -1554,88 +1555,9 @@ def _get_metadata_file(self, metadata_role, remote_filename,
15541555
upperbound_filelength)
15551556
file_object.seek(0)
15561557

1557-
# Verify 'file_object' according to the callable function.
1558-
# 'file_object' is also verified if decompressed above (i.e., the
1559-
# uncompressed version).
1560-
metadata_signable = \
1561-
securesystemslib.util.load_json_string(file_object.read().decode('utf-8'))
1562-
1563-
1564-
# If this is a merkle tree snapshot, it will not be signed.
1565-
if snapshot_merkle:
1566-
return file_object
1567-
1568-
# Determine if the specification version number is supported. It is
1569-
# assumed that "spec_version" is in (major.minor.fix) format, (for
1570-
# example: "1.4.3") and that releases with the same major version
1571-
# number maintain backwards compatibility. Consequently, if the major
1572-
# version number of new metadata equals our expected major version
1573-
# number, the new metadata is safe to parse.
1574-
try:
1575-
metadata_spec_version = metadata_signable['signed']['spec_version']
1576-
metadata_spec_version_split = metadata_spec_version.split('.')
1577-
metadata_spec_major_version = int(metadata_spec_version_split[0])
1578-
metadata_spec_minor_version = int(metadata_spec_version_split[1])
1579-
1580-
code_spec_version_split = tuf.SPECIFICATION_VERSION.split('.')
1581-
code_spec_major_version = int(code_spec_version_split[0])
1582-
code_spec_minor_version = int(code_spec_version_split[1])
1583-
1584-
if metadata_spec_major_version != code_spec_major_version:
1585-
raise tuf.exceptions.UnsupportedSpecificationError(
1586-
'Downloaded metadata that specifies an unsupported '
1587-
'spec_version. This code supports major version number: ' +
1588-
repr(code_spec_major_version) + '; however, the obtained '
1589-
'metadata lists version number: ' + str(metadata_spec_version))
1590-
1591-
#report to user if minor versions do not match, continue with update
1592-
if metadata_spec_minor_version != code_spec_minor_version:
1593-
logger.info("Downloaded metadata that specifies a different minor " +
1594-
"spec_version. This code has version " +
1595-
str(tuf.SPECIFICATION_VERSION) +
1596-
" and the metadata lists version number " +
1597-
str(metadata_spec_version) +
1598-
". The update will continue as the major versions match.")
1599-
1600-
except (ValueError, TypeError) as error:
1601-
six.raise_from(securesystemslib.exceptions.FormatError('Improperly'
1602-
' formatted spec_version, which must be in major.minor.fix format'),
1603-
error)
1604-
1605-
# If the version number is unspecified, ensure that the version number
1606-
# downloaded is greater than the currently trusted version number for
1607-
# 'metadata_role'.
1608-
version_downloaded = metadata_signable['signed']['version']
1609-
1610-
if expected_version is not None:
1611-
# Verify that the downloaded version matches the version expected by
1612-
# the caller.
1613-
if version_downloaded != expected_version:
1614-
raise tuf.exceptions.BadVersionNumberError('Downloaded'
1615-
' version number: ' + repr(version_downloaded) + '. Version'
1616-
' number MUST be: ' + repr(expected_version))
1617-
1618-
# The caller does not know which version to download. Verify that the
1619-
# downloaded version is at least greater than the one locally
1620-
# available.
1621-
else:
1622-
# Verify that the version number of the locally stored
1623-
# 'timestamp.json', if available, is less than what was downloaded.
1624-
# Otherwise, accept the new timestamp with version number
1625-
# 'version_downloaded'.
1626-
1627-
try:
1628-
current_version = \
1629-
self.metadata['current'][metadata_role]['version']
1630-
1631-
if version_downloaded < current_version:
1632-
raise tuf.exceptions.ReplayedMetadataError(metadata_role,
1633-
version_downloaded, current_version)
1634-
1635-
except KeyError:
1636-
logger.info(metadata_role + ' not available locally.')
1637-
1638-
self._verify_metadata_file(file_object, metadata_role)
1558+
# Verify the file object using the provided function, if any
1559+
if verification_fn is not None:
1560+
verification_fn(metadata_role, file_object, expected_version)
16391561

16401562
except Exception as exception:
16411563
# Remember the error from this mirror, and "reset" the target file.
@@ -1657,6 +1579,89 @@ def _get_metadata_file(self, metadata_role, remote_filename,
16571579

16581580

16591581

1582+
def signable_verification(self, metadata_role, file_object, expected_version):
1583+
# Verify 'file_object' according to the callable function.
1584+
# 'file_object' is also verified if decompressed above (i.e., the
1585+
# uncompressed version).
1586+
metadata_signable = \
1587+
securesystemslib.util.load_json_string(file_object.read().decode('utf-8'))
1588+
1589+
# Determine if the specification version number is supported. It is
1590+
# assumed that "spec_version" is in (major.minor.fix) format, (for
1591+
# example: "1.4.3") and that releases with the same major version
1592+
# number maintain backwards compatibility. Consequently, if the major
1593+
# version number of new metadata equals our expected major version
1594+
# number, the new metadata is safe to parse.
1595+
try:
1596+
metadata_spec_version = metadata_signable['signed']['spec_version']
1597+
metadata_spec_version_split = metadata_spec_version.split('.')
1598+
metadata_spec_major_version = int(metadata_spec_version_split[0])
1599+
metadata_spec_minor_version = int(metadata_spec_version_split[1])
1600+
1601+
code_spec_version_split = tuf.SPECIFICATION_VERSION.split('.')
1602+
code_spec_major_version = int(code_spec_version_split[0])
1603+
code_spec_minor_version = int(code_spec_version_split[1])
1604+
1605+
if metadata_spec_major_version != code_spec_major_version:
1606+
raise tuf.exceptions.UnsupportedSpecificationError(
1607+
'Downloaded metadata that specifies an unsupported '
1608+
'spec_version. This code supports major version number: ' +
1609+
repr(code_spec_major_version) + '; however, the obtained '
1610+
'metadata lists version number: ' + str(metadata_spec_version))
1611+
1612+
#report to user if minor versions do not match, continue with update
1613+
if metadata_spec_minor_version != code_spec_minor_version:
1614+
logger.info("Downloaded metadata that specifies a different minor " +
1615+
"spec_version. This code has version " +
1616+
str(tuf.SPECIFICATION_VERSION) +
1617+
" and the metadata lists version number " +
1618+
str(metadata_spec_version) +
1619+
". The update will continue as the major versions match.")
1620+
1621+
except (ValueError, TypeError) as error:
1622+
six.raise_from(securesystemslib.exceptions.FormatError('Improperly'
1623+
' formatted spec_version, which must be in major.minor.fix format'),
1624+
error)
1625+
1626+
# If the version number is unspecified, ensure that the version number
1627+
# downloaded is greater than the currently trusted version number for
1628+
# 'metadata_role'.
1629+
version_downloaded = metadata_signable['signed']['version']
1630+
1631+
if expected_version is not None:
1632+
# Verify that the downloaded version matches the version expected by
1633+
# the caller.
1634+
if version_downloaded != expected_version:
1635+
raise tuf.exceptions.BadVersionNumberError('Downloaded'
1636+
' version number: ' + repr(version_downloaded) + '. Version'
1637+
' number MUST be: ' + repr(expected_version))
1638+
1639+
# The caller does not know which version to download. Verify that the
1640+
# downloaded version is at least greater than the one locally
1641+
# available.
1642+
else:
1643+
# Verify that the version number of the locally stored
1644+
# 'timestamp.json', if available, is less than what was downloaded.
1645+
# Otherwise, accept the new timestamp with version number
1646+
# 'version_downloaded'.
1647+
1648+
try:
1649+
current_version = \
1650+
self.metadata['current'][metadata_role]['version']
1651+
1652+
if version_downloaded < current_version:
1653+
raise tuf.exceptions.ReplayedMetadataError(metadata_role,
1654+
version_downloaded, current_version)
1655+
1656+
except KeyError:
1657+
logger.info(metadata_role + ' not available locally.')
1658+
1659+
self._verify_metadata_file(file_object, metadata_role)
1660+
1661+
1662+
1663+
1664+
16601665

16611666
def _get_file(self, filepath, verify_file_function, file_type, file_length,
16621667
download_safely=True):
@@ -1822,9 +1827,13 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None,
18221827
remote_filename = os.path.join(
18231828
dirname, str(filename_version) + '.' + basename)
18241829

1830+
verification_fn = None
1831+
if not snapshot_merkle:
1832+
verification_fn = self.signable_verification
1833+
18251834
metadata_file_object = \
18261835
self._get_metadata_file(metadata_role, remote_filename,
1827-
upperbound_filelength, version, snapshot_merkle)
1836+
upperbound_filelength, version, verification_fn)
18281837

18291838
# The metadata has been verified. Move the metadata file into place.
18301839
# First, move the 'current' metadata file to the 'previous' directory
@@ -1855,7 +1864,7 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None,
18551864
# stored for 'metadata_role'.
18561865
if snapshot_merkle:
18571866
# Snaphot merkle files are not signed
1858-
updated_metadata_object=metadata_signable
1867+
updated_metadata_object = metadata_signable
18591868
else:
18601869
updated_metadata_object = metadata_signable['signed']
18611870
current_metadata_object = self.metadata['current'].get(metadata_role)

0 commit comments

Comments
 (0)