Reference all metadata in <version>.rolename.json format

This commit is contained in:
Vladimir Diaz 2016-07-14 10:31:16 -04:00
parent 70cc1b8abd
commit 65d23fa5a7
50 changed files with 68 additions and 51 deletions

View file

@ -0,0 +1 @@
This is an example target file.

View file

@ -0,0 +1 @@
This is an another example target file.

View file

@ -0,0 +1 @@
This is role1's target file.

View file

@ -0,0 +1 @@
{"project_name": "test-flat", "targets_location": "/home/santiago/Documents/v2014/TUF/tuf/tests/repository_data/project/targets", "prefix": "prefix", "metadata_location": "test-flat", "threshold": 1, "public_keys": {"6986b667c736a3b37471e030cf4ce7aa6c7e0d530325e64c2660276b77be3754": {"keytype": "rsa", "keyval": {"public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7J15ZaeDQPrhQsRj29wB\nPhibH+Do59xsT2396L+uCg793gZlar5wZN2eHSh725cNQWyTAa9LwG+lXaKMukQ+\n8176CKR2J5sv3DezrGVu3x8V1qhyJyy79FlNZRVYTVqNaYzvJzxsVnFPpg7f8B7C\nffiqWJr9XkpqwRlCpxooXm4hplZ7uek5Ku21CzQ4OWg7hbuc+ZjCGzpXfm8NuosU\n7TipnKGpEt0Agiph5g6TB2/scoeFar1CKMONIl80maxzAQk+xkWgiJ00+Z2qFCsx\nESfis/YkILS6RMFyZz7oa1WwMtUjYmrsRuz+jlFcbNuxZpIkaISiG9a2YdGcJ1Aj\n3QIDAQAB\n-----END PUBLIC KEY-----"}}}, "layout_type": "flat"}

View file

@ -0,0 +1 @@
{"project_name": "test-repo-like", "targets_location": "targets", "prefix": "prefix", "metadata_location": "metadata", "threshold": 1, "public_keys": {"6986b667c736a3b37471e030cf4ce7aa6c7e0d530325e64c2660276b77be3754": {"keytype": "rsa", "keyval": {"public": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7J15ZaeDQPrhQsRj29wB\nPhibH+Do59xsT2396L+uCg793gZlar5wZN2eHSh725cNQWyTAa9LwG+lXaKMukQ+\n8176CKR2J5sv3DezrGVu3x8V1qhyJyy79FlNZRVYTVqNaYzvJzxsVnFPpg7f8B7C\nffiqWJr9XkpqwRlCpxooXm4hplZ7uek5Ku21CzQ4OWg7hbuc+ZjCGzpXfm8NuosU\n7TipnKGpEt0Agiph5g6TB2/scoeFar1CKMONIl80maxzAQk+xkWgiJ00+Z2qFCsx\nESfis/YkILS6RMFyZz7oa1WwMtUjYmrsRuz+jlFcbNuxZpIkaISiG9a2YdGcJ1Aj\n3QIDAQAB\n-----END PUBLIC KEY-----"}}}, "layout_type": "repo-like"}

View file

@ -0,0 +1 @@
This is an example target file.

View file

@ -0,0 +1 @@
This is an another example target file.

View file

@ -0,0 +1 @@
This is role1's target file.

View file

@ -2766,7 +2766,7 @@ def load_repository(repository_directory):
# Strip the version number if 'consistent_snapshot' is True.
# Example: '10.django.json' --> 'django.json'
metadata_name, version_number_junk = \
repo_lib._strip_consistent_snapshot_version_number(metadata_name,
repo_lib._strip_version_number(metadata_name,
consistent_snapshot)
if metadata_name.endswith(METADATA_EXTENSION):

View file

@ -577,11 +577,12 @@ def test_make_fileinfo(self):
# Test conditions for valid arguments.
length = 1024
hashes = {'sha256': 'A4582BCF323BCEF', 'sha512': 'A4582BCF323BFEF'}
version = 8
custom = {'type': 'paintjob'}
FILEINFO_SCHEMA = tuf.formats.FILEINFO_SCHEMA
make_fileinfo = tuf.formats.make_fileinfo
self.assertTrue(FILEINFO_SCHEMA.matches(make_fileinfo(length, hashes, custom)))
self.assertTrue(FILEINFO_SCHEMA.matches(make_fileinfo(length, hashes, version, custom)))
self.assertTrue(FILEINFO_SCHEMA.matches(make_fileinfo(length, hashes)))
# Test conditions for invalid arguments.

View file

@ -89,8 +89,8 @@ def setUp(self):
def tearDown(self):
tuf.roledb.clear_roledb()
tuf.keydb.clear_keydb()
tuf.roledb.clear_roledb()
tuf.keydb.clear_keydb()
@ -615,17 +615,26 @@ def test_generate_timestamp_metadata(self):
shutil.copytree(original_repository_path, repository_directory)
metadata_directory = os.path.join(repository_directory,
repo_lib.METADATA_STAGED_DIRECTORY_NAME)
targets_directory = os.path.join(repository_directory, repo_lib.TARGETS_DIRECTORY_NAME)
snapshot_filename = os.path.join(metadata_directory,
repo_lib.SNAPSHOT_FILENAME)
# Set valid generate_timestamp_metadata() arguments.
version = 1
expiration_date = '1985-10-21T13:20:00Z'
# Load a valid repository so that top-level roles exist in roledb and
# generate_snapshot_metadata() has roles to specify in snapshot metadata.
repository = repo_tool.Repository(repository_directory, metadata_directory,
targets_directory)
repository_junk = repo_tool.load_repository(repository_directory)
snapshot_metadata = \
timestamp_metadata = \
repo_lib.generate_timestamp_metadata(snapshot_filename, version,
expiration_date)
self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches(snapshot_metadata))
self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches(timestamp_metadata))
# Test improperly formatted arguments.

View file

@ -273,6 +273,7 @@
object_name = 'FILEINFO_SCHEMA',
length = LENGTH_SCHEMA,
hashes = HASHDICT_SCHEMA,
version = SCHEMA.Optional(METADATAVERSION_SCHEMA),
custom = SCHEMA.Optional(SCHEMA.Object()))
# Version information specified in "snapshot.json" for each role available on
@ -287,7 +288,7 @@
# A dict holding the version or file information for a particular metadata
# role. The dict keys hold the relative file paths, and the dict values the
# corresponding version numbers or file information.
# corresponding version numbers and/or file information.
FILEINFODICT_SCHEMA = SCHEMA.DictOf(
key_schema = RELPATH_SCHEMA,
value_schema = SCHEMA.OneOf([VERSIONINFO_SCHEMA, FILEINFO_SCHEMA]))
@ -993,7 +994,7 @@ def make_signable(object):
def make_fileinfo(length, hashes, custom=None):
def make_fileinfo(length, hashes, version=None, custom=None):
"""
<Purpose>
Create a dictionary conformant to 'FILEINFO_SCHEMA'.
@ -1007,6 +1008,9 @@ def make_fileinfo(length, hashes, custom=None):
A dict of hashes in 'HASHDICT_SCHEMA' format, which has the form:
{'sha256': 123df8a9b12, 'sha512': 324324dfc121, ...}
version:
An optional integer representing the version of the file.
custom:
An optional object providing additional information about the file.
@ -1025,6 +1029,10 @@ def make_fileinfo(length, hashes, custom=None):
"""
fileinfo = {'length' : length, 'hashes' : hashes}
if version is not None:
fileinfo['version'] = version
if custom is not None:
fileinfo['custom'] = custom

View file

@ -447,14 +447,15 @@ def _delete_obsolete_metadata(metadata_directory, snapshot_metadata,
metadata_path[len(metadata_directory):].lstrip(os.path.sep)
# Strip the version number if 'consistent_snapshot' is True. Example:
# '10.django.json' --> 'django.json', or '123456789abcdef.root.json'
# --> 'root.json' . Consistent and non-consistent metadata might
# co-exist if write() and write(consistent_snapshot=True) are mixed, so
# ensure only '<version_number or hash>.filename' metadata is stripped.
# '10.django.json' --> 'django.json'. Consistent and non-consistent
# metadata might co-exist if write() and
# write(consistent_snapshot=True) are mixed, so ensure only
# '<version_number>.filename' metadata is stripped.
embedded_version_number = None
if metadata_name not in snapshot_metadata['meta']:
metadata_name, embedded_version_number = \
_strip_version_number_or_digest(metadata_name, consistent_snapshot)
_strip_version_number(metadata_name, consistent_snapshot)
# Strip filename extensions. The role database does not include the
# metadata extension.
@ -502,25 +503,23 @@ def _get_written_metadata(metadata_signable):
def _strip_version_number_or_digest(metadata_filename,
consistent_snapshot):
def _strip_version_number(metadata_filename, consistent_snapshot):
"""
Strip from 'metadata_filename' any version / digest information (in the
expected '{dirname}/<version_number_or_digest>.rolename.<ext>' format) that
it may contain, and return the stripped filename and consistent attachment,
Strip from 'metadata_filename' any version number (in the
expected '{dirname}/<version_number>.rolename.<ext>' format) that
it may contain, and return the stripped filename and version number,
as a tuple. 'consistent_snapshot' is a boolean indicating if a version
number or digest is appended to 'metadata_filename'.
number is prepended to 'metadata_filename'.
"""
# Strip the version number or digest if 'consistent_snapshot' is True.
# Example: '10.django.json' --> 'django.json', or
# '123456789abcdef.root.json' --> 'root.json'.
# Strip the version number if 'consistent_snapshot' is True.
# Example: '10.django.json' --> 'django.json'
if consistent_snapshot:
dirname, basename = os.path.split(metadata_filename)
consistent_attachment, basename = basename.split('.', 1)
version_number, basename = basename.split('.', 1)
stripped_metadata_filename = os.path.join(dirname, basename)
return stripped_metadata_filename, embedded_version_number
return stripped_metadata_filename, version_number
else:
return metadata_filename, ''
@ -594,7 +593,7 @@ def _load_top_level_metadata(repository, top_level_filenames):
roleinfo = tuf.roledb.get_roleinfo('timestamp')
roleinfo['expires'] = timestamp_metadata['expires']
roleinfo['version'] = timestamp_metadata['version']
if os.path.exists(timestamp_filename+'.gz'):
if os.path.exists(timestamp_filename + '.gz'):
roleinfo['compressions'].append('gz')
if _metadata_is_partially_loaded('timestamp', signable, roleinfo):
@ -614,10 +613,11 @@ def _load_top_level_metadata(repository, top_level_filenames):
if consistent_snapshot:
snapshot_hashes = timestamp_metadata['meta'][SNAPSHOT_FILENAME]['hashes']
snapshot_hash = random.choice(list(snapshot_hashes.values()))
snapshot_version = timestamp_metadata['meta'][SNAPSHOT_FILENAME]['version']
dirname, basename = os.path.split(snapshot_filename)
basename = basename.split(METADATA_EXTENSION, 1)[0]
snapshot_filename = os.path.join(dirname, basename + '.' + str(snapshot_hash) + METADATA_EXTENSION)
snapshot_filename = os.path.join(dirname, str(snapshot_version) + '.' + basename + METADATA_EXTENSION)
if os.path.exists(snapshot_filename):
signable = tuf.util.load_json_file(snapshot_filename)
@ -1272,7 +1272,7 @@ def get_metadata_fileinfo(filename, custom=None):
filesize, filehashes = \
tuf.util.get_file_details(filename, tuf.conf.REPOSITORY_HASH_ALGORITHMS)
return tuf.formats.make_fileinfo(filesize, filehashes, custom)
return tuf.formats.make_fileinfo(filesize, filehashes, custom=custom)
@ -1662,7 +1662,8 @@ def generate_snapshot_metadata(metadata_directory, version, expiration_date,
fileinfodict = {}
root_path = os.path.join(metadata_directory, root_filename + '.json')
length, hashes = tuf.util.get_file_details(root_path)
fileinfodict[ROOT_FILENAME] = tuf.formats.make_fileinfo(length, hashes)
root_version = get_metadata_versioninfo('root')
fileinfodict[ROOT_FILENAME] = tuf.formats.make_fileinfo(length, hashes, version=root_version['version'])
fileinfodict[TARGETS_FILENAME] = get_metadata_versioninfo(targets_filename)
# We previously also stored the compressed versions of roles in
@ -1678,7 +1679,7 @@ def generate_snapshot_metadata(metadata_directory, version, expiration_date,
# Strip the version number if 'consistent_snapshot' is True.
# Example: '10.django.json' --> 'django.json'
metadata_name, version_number_junk = \
_strip_version_number_or_digest(metadata_filename, consistent_snapshot)
_strip_version_number(metadata_filename, consistent_snapshot)
# All delegated roles are added to the snapshot file.
for metadata_extension in METADATA_EXTENSIONS:
@ -1746,7 +1747,9 @@ def generate_timestamp_metadata(snapshot_filename, version, expiration_date):
# Retrieve the versioninfo of the Snapshot metadata file.
snapshot_fileinfo = {}
length, hashes = tuf.util.get_file_details(snapshot_filename)
snapshot_fileinfo[SNAPSHOT_FILENAME] = tuf.formats.make_fileinfo(length, hashes)
snapshot_version = get_metadata_versioninfo('snapshot')
snapshot_fileinfo[SNAPSHOT_FILENAME] = \
tuf.formats.make_fileinfo(length, hashes, version=snapshot_version['version'])
# We previously saved the versioninfo of the compressed versions of
# 'snapshot.json' in 'versioninfo'. Since version numbers are now stored,
@ -1965,20 +1968,9 @@ def write_metadata_file(metadata, filename, version_number,
if consistent_snapshot:
dirname, basename = os.path.split(written_filename)
if basename in ['root.json', 'snapshot.json']:
hash_algorithms = tuf.conf.REPOSITORY_HASH_ALGORITHMS
file_length_junk, digests = \
tuf.util.get_file_details(written_filename, hash_algorithms)
for digest in digests.values():
basename= basename.split(METADATA_EXTENSION, 1)[0]
digest_and_filename = str(digest) + '.' + basename + METADATA_EXTENSION
written_consistent_filename = os.path.join(dirname, digest_and_filename)
else:
basename = basename.split(METADATA_EXTENSION, 1)[0]
version_and_filename = str(version_number) + '.' + basename + METADATA_EXTENSION
written_consistent_filename = os.path.join(dirname, version_and_filename)
basename = basename.split(METADATA_EXTENSION, 1)[0]
version_and_filename = str(version_number) + '.' + basename + METADATA_EXTENSION
written_consistent_filename = os.path.join(dirname, version_and_filename)
logger.info('Linking ' + repr(written_consistent_filename))
os.link(written_filename, written_consistent_filename)
@ -2017,7 +2009,7 @@ def write_metadata_file(metadata, filename, version_number,
# unexpectedly change (gzip includes a timestamp) even though content has
# not changed.
_write_compressed_metadata(file_object, compressed_filename,
write_new_metadata, consistent_snapshot)
write_new_metadata, consistent_snapshot, version_number)
return written_filename
@ -2025,7 +2017,7 @@ def write_metadata_file(metadata, filename, version_number,
def _write_compressed_metadata(file_object, compressed_filename,
write_new_metadata, consistent_snapshot):
write_new_metadata, consistent_snapshot, version_number):
"""
Write compressed versions of metadata, ensuring compressed file that have
not changed are not re-written, the digest of the compressed file is properly
@ -2060,15 +2052,15 @@ def _write_compressed_metadata(file_object, compressed_filename,
digest_object.update(compressed_content)
new_digests.append(digest_object.hexdigest())
# Attach each digest to the compressed consistent snapshot filename.
# Attach each version nu to the compressed consistent snapshot filename.
for new_digest in new_digests:
dirname, basename = os.path.split(compressed_filename)
for compression_extension in SUPPORTED_COMPRESSION_EXTENSIONS:
if basename.endswith(compression_extension):
basename = basename.split(compression_extension, 1)[0]
digest_and_filename = basename + '.' + new_digest + compression_extension
version_and_filename = str(version_number) + '.' + basename + compression_extension
consistent_filenames.append(os.path.join(dirname, digest_and_filename))
consistent_filenames.append(os.path.join(dirname, version_and_filename))
# Move the 'tuf.util.TempFile' object to one of the filenames so that it is
# saved and the temporary file closed. Any remaining consistent snapshots

View file

@ -2821,8 +2821,7 @@ def load_repository(repository_directory):
# Strip the version number if 'consistent_snapshot' is True.
# Example: '10.django.json' --> 'django.json'
metadata_name, version_number_junk = \
repo_lib._strip_version_number_or_digest(metadata_name,
consistent_snapshot)
repo_lib._strip_version_number(metadata_name, consistent_snapshot)
if metadata_name.endswith(METADATA_EXTENSION):
extension_length = len(METADATA_EXTENSION)