diff --git a/tests/test_formats.py b/tests/test_formats.py index af97af353d..25c27f289d 100755 --- a/tests/test_formats.py +++ b/tests/test_formats.py @@ -286,69 +286,107 @@ def test_schemas(self): - def test_MetaFile(self): - # Test conditions for instantiations of a class that inherits from - # 'tuf.formats.MetaFile'. - class NewMetadataFile(tuf.formats.MetaFile): - def __init__(self, version, expires): - self.info = {} - self.info['version'] = version - self.info['expires'] = expires - metadata = NewMetadataFile(123, 456) - metadata2 = NewMetadataFile(123, 456) - metadata3 = NewMetadataFile(333, 333) - # Test the comparison operators. - self.assertTrue(metadata == metadata2) - self.assertFalse(metadata != metadata2) - self.assertFalse(metadata == metadata3) + def test_build_dict_conforming_to_schema(self): + # Test construction of a few metadata formats using + # build_dict_conforming_to_schema(). - # Test the 'getattr' method. - self.assertEqual(123, getattr(metadata, 'version')) - self.assertRaises(AttributeError, getattr, metadata, 'bad') + # Try the wrong type of schema object. + STRING_SCHEMA = securesystemslib.schema.AnyString() + with self.assertRaises(ValueError): + tuf.formats.build_dict_conforming_to_schema( + STRING_SCHEMA, string='some string') - - def test_TimestampFile(self): - # Test conditions for valid instances of 'tuf.formats.TimestampFile'. + # Try building Timestamp metadata. + spec_version = tuf.SPECIFICATION_VERSION version = 8 length = 88 hashes = {'sha256': '3c7fe3eeded4a34'} expires = '1985-10-21T13:20:00Z' filedict = {'snapshot.json': {'length': length, 'hashes': hashes}} - make_metadata = tuf.formats.TimestampFile.make_metadata - from_metadata = tuf.formats.TimestampFile.from_metadata - TIMESTAMP_SCHEMA = tuf.formats.TIMESTAMP_SCHEMA - - self.assertTrue(TIMESTAMP_SCHEMA.matches(make_metadata(version, expires, - filedict))) - metadata = make_metadata(version, expires, filedict) - self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.TimestampFile)) - # Test conditions for invalid arguments. + # Try with and without _type and spec_version, both of which are + # automatically populated if they are not included. + self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches( # both + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TIMESTAMP_SCHEMA, + _type='timestamp', + spec_version=spec_version, + version=version, + expires=expires, + meta=filedict))) + self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches( # neither + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TIMESTAMP_SCHEMA, + version=version, + expires=expires, + meta=filedict))) + self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches( # one + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TIMESTAMP_SCHEMA, + spec_version=spec_version, + version=version, + expires=expires, + meta=filedict))) + self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches( # the other + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TIMESTAMP_SCHEMA, + _type='timestamp', + version=version, + expires=expires, + meta=filedict))) + + + # Try test arguments for invalid Timestamp creation. + bad_spec_version = 123 bad_version = 'eight' bad_expires = '2000' bad_filedict = 123 - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, bad_version, - expires, filedict) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, version, - bad_expires, filedict) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, version, - expires, bad_filedict) - - self.assertRaises(securesystemslib.exceptions.FormatError, from_metadata, 123) - - - - - - def test_RootFile(self): - # Test conditions for valid instances of 'tuf.formats.RootFile'. - version = 8 + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TIMESTAMP_SCHEMA, + _type='timestamp', + spec_version=bad_spec_version, + version=version, + expires=expires, + meta=filedict) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TIMESTAMP_SCHEMA, + _type='timestamp', + spec_version=spec_version, + version=bad_version, + expires=expires, + meta=filedict) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TIMESTAMP_SCHEMA, + _type='timestamp', + spec_version=spec_version, + version=version, + expires=bad_expires, + meta=filedict) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TIMESTAMP_SCHEMA, + _type='timestamp', + spec_version=spec_version, + version=version, + expires=expires, + meta=bad_filedict) + + with self.assertRaises(ValueError): + tuf.formats.build_dict_conforming_to_schema(123) + + + # Try building Root metadata. consistent_snapshot = False - expires = '1985-10-21T13:20:00Z' keydict = {'123abc': {'keytype': 'rsa', 'scheme': 'rsassa-pss-sha256', @@ -359,70 +397,153 @@ def test_RootFile(self): 'threshold': 1, 'paths': ['path1/', 'path2']}} - make_metadata = tuf.formats.RootFile.make_metadata - from_metadata = tuf.formats.RootFile.from_metadata - ROOT_SCHEMA = tuf.formats.ROOT_SCHEMA - self.assertTrue(ROOT_SCHEMA.matches(make_metadata(version, expires, - keydict, roledict, consistent_snapshot))) - metadata = make_metadata(version, expires, keydict, roledict, - consistent_snapshot) - self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.RootFile)) + self.assertTrue(tuf.formats.ROOT_SCHEMA.matches( + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + _type='root', + spec_version=spec_version, + version=version, + expires=expires, + keys=keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot))) - # Test conditions for invalid arguments. - bad_version = '8' - bad_expires = 'eight' + + # Additional test arguments for invalid Root creation. bad_keydict = 123 bad_roledict = 123 - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, - bad_version, expires, keydict, roledict, consistent_snapshot) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, - version, bad_expires, keydict, roledict, consistent_snapshot) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, - version, expires, bad_keydict, roledict, consistent_snapshot) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, - version, expires, keydict, bad_roledict, consistent_snapshot) - - self.assertRaises(securesystemslib.exceptions.FormatError, from_metadata, 'bad') - - - - def test_SnapshotFile(self): - # Test conditions for valid instances of 'tuf.formats.SnapshotFile'. - version = 8 - expires = '1985-10-21T13:20:00Z' + # TODO: Later on, write a test looper that takes pairs of key-value args + # to substitute in on each run to shorten this.... There's a lot of + # test code that looks like this, and it'd be easier to use a looper. + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + _type='root', + spec_version=bad_spec_version, + version=version, + expires=expires, + keys=keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + _type='root', + spec_version=spec_version, + version=bad_version, + expires=expires, + keys=keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + _type='root', + spec_version=spec_version, + version=version, + expires=bad_expires, + keys=keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + _type='root', + spec_version=spec_version, + version=version, + expires=expires, + keys=bad_keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + _type='root', + spec_version=spec_version, + version=version, + expires=expires, + keys=keydict, + roles=bad_roledict, + consistent_snapshot=consistent_snapshot) + + with self.assertRaises(TypeError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, 'bad') + + with self.assertRaises(ValueError): + tuf.formats.build_dict_conforming_to_schema( + 'bad', + _type='root', + spec_version=spec_version, + version=version, + expires=expires, + keys=keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot) + + + + # Try building Snapshot metadata. versiondict = {'targets.json' : {'version': version}} - make_metadata = tuf.formats.SnapshotFile.make_metadata - from_metadata = tuf.formats.SnapshotFile.from_metadata - SNAPSHOT_SCHEMA = tuf.formats.SNAPSHOT_SCHEMA - - self.assertTrue(SNAPSHOT_SCHEMA.matches(make_metadata(version, expires, - versiondict))) - metadata = make_metadata(version, expires, versiondict) - self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.SnapshotFile)) + self.assertTrue(tuf.formats.SNAPSHOT_SCHEMA.matches( + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.SNAPSHOT_SCHEMA, + _type='snapshot', + spec_version=spec_version, + version=version, + expires=expires, + meta=versiondict))) - # Test conditions for invalid arguments. - bad_version = '8' - bad_expires = '2000' + # Additional test arguments for invalid Snapshot creation. bad_versiondict = 123 - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, version, - expires, bad_versiondict) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, bad_version, expires, - versiondict) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, version, bad_expires, - bad_versiondict) - - self.assertRaises(securesystemslib.exceptions.FormatError, from_metadata, 123) - - - - def test_TargetsFile(self): - # Test conditions for valid instances of 'tuf.formats.TargetsFile'. - version = 8 - expires = '1985-10-21T13:20:00Z' + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.SNAPSHOT_SCHEMA, + _type='snapshot', + spec_version=bad_spec_version, + version=version, + expires=expires, + meta=versiondict) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.SNAPSHOT_SCHEMA, + _type='snapshot', + spec_version=spec_version, + version=bad_version, + expires=expires, + meta=versiondict) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.SNAPSHOT_SCHEMA, + _type='snapshot', + spec_version=spec_version, + version=version, + expires=bad_expires, + meta=versiondict) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.SNAPSHOT_SCHEMA, + _type='snapshot', + spec_version=spec_version, + version=version, + expires=expires, + meta=bad_versiondict) + + + + # Try building Targets metadata. filedict = {'metadata/targets.json': {'length': 1024, 'hashes': {'sha256': 'ABCD123'}, 'custom': {'type': 'metadata'}}} @@ -434,61 +555,73 @@ def test_TargetsFile(self): 'roles': [{'name': 'root', 'keyids': ['123abc'], 'threshold': 1, 'paths': ['path1/', 'path2']}]} - make_metadata = tuf.formats.TargetsFile.make_metadata - from_metadata = tuf.formats.TargetsFile.from_metadata - TARGETS_SCHEMA = tuf.formats.TARGETS_SCHEMA - self.assertTrue(TARGETS_SCHEMA.matches(make_metadata(version, expires, - filedict, delegations))) - self.assertTrue(TARGETS_SCHEMA.matches(make_metadata(version, expires, filedict))) - - metadata = make_metadata(version, expires, filedict, delegations) - self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.TargetsFile)) - - # Test conditions for different combination of required arguments (i.e., - # a filedict or delegations argument is required.) - metadata = make_metadata(version, expires, filedict) - self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.TargetsFile)) - - metadata = make_metadata(version, expires, delegations=delegations) - self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.TargetsFile)) - - # Directly instantiating a TargetsFile object. - tuf.formats.TargetsFile(version, expires) - tuf.formats.TargetsFile(version, expires, filedict) - tuf.formats.TargetsFile(version, expires, delegations=delegations) - - # Test conditions for invalid arguments. - bad_version = 'eight' - bad_expires = '2000' + self.assertTrue(tuf.formats.TARGETS_SCHEMA.matches( + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TARGETS_SCHEMA, + _type='targets', + spec_version=spec_version, + version=version, + expires=expires, + targets=filedict, + delegations=delegations))) + + # Try with no delegations included (should work, since they're optional). + self.assertTrue(tuf.formats.TARGETS_SCHEMA.matches( + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TARGETS_SCHEMA, + _type='targets', + spec_version=spec_version, + version=version, + expires=expires, + targets=filedict))) + + + # Additional test arguments for invalid Targets creation. bad_filedict = 123 bad_delegations = 123 - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, bad_version, expires, - filedict, delegations) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, version, bad_expires, - filedict, delegations) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, version, expires, - bad_filedict, delegations) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, version, expires, - filedict, bad_delegations) - self.assertRaises(securesystemslib.exceptions.Error, make_metadata, version, expires) - - self.assertRaises(securesystemslib.exceptions.FormatError, from_metadata, 123) - - - - def test_MirrorsFile(self): - # Test normal case. - version = 8 - expires = '1985-10-21T13:20:00Z' - mirrors_file = tuf.formats.MirrorsFile(version, expires) + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TARGETS_SCHEMA, + _type='targets', + spec_version=spec_version, + version=bad_version, + expires=expires, + targets=filedict, + delegations=delegations) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TARGETS_SCHEMA, + _type='targets', + spec_version=spec_version, + version=version, + expires=bad_expires, + targets=filedict, + delegations=delegations) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TARGETS_SCHEMA, + _type='targets', + spec_version=spec_version, + version=version, + expires=expires, + targets=bad_filedict, + delegations=delegations) + + with self.assertRaises(securesystemslib.exceptions.FormatError): + tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TARGETS_SCHEMA, + _type='targets', + spec_version=spec_version, + version=version, + expires=expires, + targets=filedict, + delegations=bad_delegations) - make_metadata = tuf.formats.MirrorsFile.make_metadata - from_metadata = tuf.formats.MirrorsFile.from_metadata - self.assertRaises(NotImplementedError, make_metadata) - self.assertRaises(NotImplementedError, from_metadata, mirrors_file) @@ -616,66 +749,6 @@ def test_make_versioninfo(self): - def test_make_role_metadata(self): - # Test conditions for valid arguments. - keyids = ['123abc', 'abc123'] - threshold = 2 - paths = ['path1/', 'path2'] - path_hash_prefixes = ['000', '003'] - name = '123' - - ROLE_SCHEMA = tuf.formats.ROLE_SCHEMA - make_role = tuf.formats.make_role_metadata - - self.assertTrue(ROLE_SCHEMA.matches(make_role(keyids, threshold))) - self.assertTrue(ROLE_SCHEMA.matches(make_role(keyids, threshold, name=name))) - self.assertTrue(ROLE_SCHEMA.matches(make_role(keyids, threshold, paths=paths))) - self.assertTrue(ROLE_SCHEMA.matches(make_role(keyids, threshold, name=name, paths=paths))) - self.assertTrue(ROLE_SCHEMA.matches(make_role(keyids, threshold, name=name, - path_hash_prefixes=path_hash_prefixes))) - - # Test conditions for invalid arguments. - bad_keyids = 'bad' - bad_threshold = 'bad' - bad_paths = 'bad' - bad_name = 123 - - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, bad_keyids, threshold) - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, keyids, bad_threshold) - - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, bad_keyids, threshold, paths=paths) - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, keyids, bad_threshold, paths=paths) - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, keyids, threshold, paths=bad_paths) - - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, bad_keyids, threshold, name=name) - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, keyids, bad_threshold, name=name) - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, keyids, threshold, name=bad_name) - - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, bad_keyids, threshold, name=name, paths=paths) - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, keyids, bad_threshold, name=name, paths=paths) - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, keyids, threshold, name=bad_name, paths=paths) - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, keyids, threshold, name=name, paths=bad_paths) - - # 'paths' and 'path_hash_prefixes' cannot both be specified. - self.assertRaises(securesystemslib.exceptions.FormatError, make_role, keyids, threshold, name, paths, path_hash_prefixes) - - def test_get_role_class(self): - # Test conditions for valid arguments. - get_role_class = tuf.formats.get_role_class - - self.assertEqual(tuf.formats.RootFile, get_role_class('Root')) - self.assertEqual(tuf.formats.TargetsFile, get_role_class('Targets')) - self.assertEqual(tuf.formats.SnapshotFile, get_role_class('Snapshot')) - self.assertEqual(tuf.formats.TimestampFile, get_role_class('Timestamp')) - self.assertEqual(tuf.formats.MirrorsFile, get_role_class('Mirrors')) - - # Test conditions for invalid arguments. - self.assertRaises(securesystemslib.exceptions.FormatError, get_role_class, 'role') - self.assertRaises(securesystemslib.exceptions.FormatError, get_role_class, 'ROLE') - self.assertRaises(securesystemslib.exceptions.FormatError, get_role_class, 'abcd') - self.assertRaises(securesystemslib.exceptions.FormatError, get_role_class, 123) - self.assertRaises(securesystemslib.exceptions.FormatError, get_role_class, tuf.formats.RootFile) - def test_expected_meta_rolename(self): @@ -692,7 +765,7 @@ def test_expected_meta_rolename(self): # Test conditions for invalid arguments. self.assertRaises(securesystemslib.exceptions.FormatError, expected_rolename, 123) - self.assertRaises(securesystemslib.exceptions.FormatError, expected_rolename, tuf.formats.RootFile) + self.assertRaises(securesystemslib.exceptions.FormatError, expected_rolename, tuf.formats.ROOT_SCHEMA) self.assertRaises(securesystemslib.exceptions.FormatError, expected_rolename, True) @@ -719,7 +792,7 @@ def test_check_signable_object_format(self): check_signable = tuf.formats.check_signable_object_format self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, 'root') self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, 123) - self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, tuf.formats.RootFile) + self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, tuf.formats.ROOT_SCHEMA) self.assertRaises(securesystemslib.exceptions.FormatError, check_signable, True) saved_type = root['signed']['_type'] @@ -758,7 +831,7 @@ def test_encode_canonical(self): self.assertEqual('[1,2,3]', ''.join(result)) # Test conditions for invalid arguments. - self.assertRaises(securesystemslib.exceptions.FormatError, encode, tuf.formats.RootFile) + self.assertRaises(securesystemslib.exceptions.FormatError, encode, tuf.formats.ROOT_SCHEMA) self.assertRaises(securesystemslib.exceptions.FormatError, encode, 8.0) self.assertRaises(securesystemslib.exceptions.FormatError, encode, {"x": 8.0}) self.assertRaises(securesystemslib.exceptions.FormatError, encode, 8.0, output) diff --git a/tests/test_keydb.py b/tests/test_keydb.py index 51969a8741..0630442508 100755 --- a/tests/test_keydb.py +++ b/tests/test_keydb.py @@ -315,8 +315,16 @@ def test_create_keydb_from_root_metadata(self): consistent_snapshot = False expires = '1985-10-21T01:21:00Z' - root_metadata = tuf.formats.RootFile.make_metadata(version, expires, - keydict, roledict, consistent_snapshot) + root_metadata = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + _type='root', + spec_version='1.0', + version=version, + expires=expires, + keys=keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot) + self.assertEqual(None, tuf.keydb.create_keydb_from_root_metadata(root_metadata)) tuf.keydb.create_keydb_from_root_metadata(root_metadata) @@ -367,8 +375,16 @@ def test_create_keydb_from_root_metadata(self): version = 8 expires = '1985-10-21T01:21:00Z' - root_metadata = tuf.formats.RootFile.make_metadata(version, expires, - keydict, roledict, consistent_snapshot) + root_metadata = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + _type='root', + spec_version='1.0', + version=version, + expires=expires, + keys=keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot) + self.assertEqual(None, tuf.keydb.create_keydb_from_root_metadata(root_metadata)) # Ensure only 'keyid2' was added to the keydb database. 'keyid' and diff --git a/tests/test_roledb.py b/tests/test_roledb.py index 9b296e77fc..ebb33a20fe 100755 --- a/tests/test_roledb.py +++ b/tests/test_roledb.py @@ -546,8 +546,16 @@ def test_create_roledb_from_root_metadata(self): consistent_snapshot = False expires = '1985-10-21T01:21:00Z' - root_metadata = tuf.formats.RootFile.make_metadata(version, - expires, keydict, roledict, consistent_snapshot) + root_metadata = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + _type='root', + spec_version='1.0', + version=version, + expires=expires, + keys=keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot) + self.assertEqual(None, tuf.roledb.create_roledb_from_root_metadata(root_metadata)) @@ -592,8 +600,17 @@ def test_create_roledb_from_root_metadata(self): # Generate 'root_metadata' to verify that 'release' and 'root' are added # to the role database. - root_metadata = tuf.formats.RootFile.make_metadata(version, - expires, keydict, roledict, consistent_snapshot) + + root_metadata = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + _type='root', + spec_version='1.0', + version=version, + expires=expires, + keys=keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot) + self.assertEqual(None, tuf.roledb.create_roledb_from_root_metadata(root_metadata)) diff --git a/tests/test_sig.py b/tests/test_sig.py index f8730b86d3..de671a6468 100755 --- a/tests/test_sig.py +++ b/tests/test_sig.py @@ -108,8 +108,10 @@ def test_get_signature_status_bad_sig(self): tuf.keydb.add_key(KEYS[0]) threshold = 1 - roleinfo = tuf.formats.make_role_metadata( - [KEYS[0]['keyid']], threshold) + + roleinfo = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, keyids=[KEYS[0]['keyid']], threshold=threshold) + tuf.roledb.add_role('Root', roleinfo) sig_status = tuf.sig.get_signature_status(signable, 'Root') @@ -139,8 +141,10 @@ def test_get_signature_status_unknown_signing_scheme(self): KEYS[0]['scheme'] = 'unknown_signing_scheme' tuf.keydb.add_key(KEYS[0]) threshold = 1 - roleinfo = tuf.formats.make_role_metadata( - [KEYS[0]['keyid']], threshold) + + roleinfo = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, keyids=[KEYS[0]['keyid']], threshold=threshold) + tuf.roledb.add_role('root', roleinfo) sig_status = tuf.sig.get_signature_status(signable, 'root') @@ -169,8 +173,9 @@ def test_get_signature_status_single_key(self): KEYS[0], signable['signed'])) threshold = 1 - roleinfo = tuf.formats.make_role_metadata( - [KEYS[0]['keyid']], threshold) + + roleinfo = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, keyids=[KEYS[0]['keyid']], threshold=threshold) tuf.roledb.add_role('Root', roleinfo) tuf.keydb.add_key(KEYS[0]) @@ -210,9 +215,12 @@ def test_get_signature_status_below_threshold(self): tuf.keydb.add_key(KEYS[0]) threshold = 2 - roleinfo = tuf.formats.make_role_metadata( - [KEYS[0]['keyid'], - KEYS[2]['keyid']], threshold) + + roleinfo = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, + keyids=[KEYS[0]['keyid'], KEYS[2]['keyid']], + threshold=threshold) + tuf.roledb.add_role('Root', roleinfo) sig_status = tuf.sig.get_signature_status(signable, 'Root') @@ -245,9 +253,12 @@ def test_get_signature_status_below_threshold_unrecognized_sigs(self): tuf.keydb.add_key(KEYS[0]) tuf.keydb.add_key(KEYS[1]) threshold = 2 - roleinfo = tuf.formats.make_role_metadata( - [KEYS[0]['keyid'], - KEYS[1]['keyid']], threshold) + + roleinfo = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, + keyids=[KEYS[0]['keyid'], KEYS[1]['keyid']], + threshold=threshold) + tuf.roledb.add_role('Root', roleinfo) sig_status = tuf.sig.get_signature_status(signable, 'Root') @@ -282,11 +293,19 @@ def test_get_signature_status_below_threshold_unauthorized_sigs(self): tuf.keydb.add_key(KEYS[0]) tuf.keydb.add_key(KEYS[1]) threshold = 2 - roleinfo = tuf.formats.make_role_metadata( - [KEYS[0]['keyid'], KEYS[2]['keyid']], threshold) + + roleinfo = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, + keyids=[KEYS[0]['keyid'], KEYS[2]['keyid']], + threshold=threshold) + tuf.roledb.add_role('Root', roleinfo) - roleinfo = tuf.formats.make_role_metadata( - [KEYS[1]['keyid'], KEYS[2]['keyid']], threshold) + + roleinfo = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, + keyids=[KEYS[1]['keyid'], KEYS[2]['keyid']], + threshold=threshold) + tuf.roledb.add_role('Release', roleinfo) sig_status = tuf.sig.get_signature_status(signable, 'Root') @@ -339,8 +358,10 @@ def test_verify_single_key(self): tuf.keydb.add_key(KEYS[0]) threshold = 1 - roleinfo = tuf.formats.make_role_metadata( - [KEYS[0]['keyid']], threshold) + + roleinfo = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, keyids=[KEYS[0]['keyid']], threshold=threshold) + tuf.roledb.add_role('Root', roleinfo) # This will call verify() and return True if 'signable' is valid, @@ -366,8 +387,12 @@ def test_verify_unrecognized_sig(self): tuf.keydb.add_key(KEYS[0]) tuf.keydb.add_key(KEYS[1]) threshold = 2 - roleinfo = tuf.formats.make_role_metadata( - [KEYS[0]['keyid'], KEYS[1]['keyid']], threshold) + + roleinfo = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, + keyids=[KEYS[0]['keyid'], KEYS[1]['keyid']], + threshold=threshold) + tuf.roledb.add_role('Root', roleinfo) self.assertFalse(tuf.sig.verify(signable, 'Root')) @@ -412,8 +437,10 @@ def test_may_need_new_keys(self): tuf.keydb.add_key(KEYS[1]) threshold = 1 - roleinfo = tuf.formats.make_role_metadata( - [KEYS[1]['keyid']], threshold) + + roleinfo = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, keyids=[KEYS[1]['keyid']], threshold=threshold) + tuf.roledb.add_role('Root', roleinfo) sig_status = tuf.sig.get_signature_status(signable, 'Root') diff --git a/tuf/formats.py b/tuf/formats.py index 78a03a20c2..2c5128db57 100755 --- a/tuf/formats.py +++ b/tuf/formats.py @@ -23,9 +23,8 @@ Note: 'formats.py' depends heavily on 'schema.py', so the 'schema.py' module should be read and understood before tackling this module. - 'formats.py' can be broken down into three sections. (1) Schemas and object - matching. (2) Classes that represent Role Metadata and help produce correctly - formatted files. (3) Functions that help produce or verify TUF objects. + 'formats.py' can be broken down into two sections. (1) Schemas and object + matching. (2) Functions that help produce or verify TUF objects. The first section deals with schemas and object matching based on format. There are two ways of checking the format of objects. The first method @@ -49,17 +48,7 @@ the match fails. There are numerous variations of object checking provided by 'formats.py' and 'schema.py'. - The second section deals with the role metadata classes. There are - multiple top-level roles, each with differing metadata formats. - Example: - - root_object = tuf.formats.RootFile.from_metadata(root_metadata_file) - targets_metadata = tuf.formats.TargetsFile.make_metadata(...) - - The input and output of these classes are checked against their respective - schema to ensure correctly formatted metadata. - - The last section contains miscellaneous functions related to the format of + The second section contains miscellaneous functions related to the format of TUF objects. Example: @@ -78,12 +67,13 @@ import calendar import datetime import time - -import tuf +import copy import securesystemslib.formats import securesystemslib.schema as SCHEMA +import tuf + import six @@ -108,6 +98,8 @@ # Role object in {'keyids': [keydids..], 'name': 'ABC', 'threshold': 1, # 'paths':[filepaths..]} format. +# TODO: This is not a role. In further #660-related PRs, fix it, similar to +# the way I did in Uptane's TUF fork. ROLE_SCHEMA = SCHEMA.Object( object_name = 'ROLE_SCHEMA', name = SCHEMA.Optional(securesystemslib.formats.ROLENAME_SCHEMA), @@ -356,6 +348,7 @@ TIMESTAMP_SCHEMA = SCHEMA.Object( object_name = 'TIMESTAMP_SCHEMA', _type = SCHEMA.String('timestamp'), + spec_version = SPECIFICATION_VERSION_SCHEMA, version = securesystemslib.formats.METADATAVERSION_SCHEMA, expires = securesystemslib.formats.ISO8601_DATETIME_SCHEMA, meta = securesystemslib.formats.FILEDICT_SCHEMA) @@ -474,227 +467,106 @@ def make_signable(role_schema): -class MetaFile(object): - """ - - Base class for all metadata file classes. - Classes representing metadata files such as RootFile - and SnapshotFile all inherit from MetaFile. The - __eq__, __ne__, perform 'equal' and 'not equal' comparisons - between Metadata File objects. - """ - - info = {} - - def __eq__(self, other): - return isinstance(other, MetaFile) and self.info == other.info - - __hash__ = None - - def __ne__(self, other): - return not self.__eq__(other) - - - def __getattr__(self, name): - """ - Allow all metafile objects to have their interesting attributes - referred to directly without the info dict. The info dict is just - to be able to do the __eq__ comparison generically. - """ - - if name in self.info: - return self.info[name] - - else: - raise AttributeError(name) - - - -class TimestampFile(MetaFile): - def __init__(self, version, expires, filedict): - self.info = {} - self.info['version'] = version - self.info['expires'] = expires - self.info['meta'] = filedict - - - @staticmethod - def from_metadata(timestamp_metadata): - # Is 'timestamp_metadata' a Timestamp metadata file? - # Raise securesystemslib.exceptions.FormatError if not. - TIMESTAMP_SCHEMA.check_match(timestamp_metadata) - - version = timestamp_metadata['version'] - expires = timestamp_metadata['expires'] - filedict = timestamp_metadata['meta'] - - return TimestampFile(version, expires, filedict) - @staticmethod - def make_metadata(version, expiration_date, filedict): - result = {'_type' : 'timestamp'} - result['spec_version'] = tuf.SPECIFICATION_VERSION - result['version'] = version - result['expires'] = expiration_date - result['meta'] = filedict - # Is 'result' a Timestamp metadata file? - # Raise 'securesystemslib.exceptions.FormatError' if not. - TIMESTAMP_SCHEMA.check_match(result) - - return result - - - -class RootFile(MetaFile): - def __init__(self, version, expires, keys, roles, consistent_snapshot): - self.info = {} - self.info['version'] = version - self.info['expires'] = expires - self.info['keys'] = keys - self.info['roles'] = roles - self.info['consistent_snapshot'] = consistent_snapshot - - @staticmethod - def from_metadata(root_metadata): - # Is 'root_metadata' a Root metadata file? - # Raise 'securesystemslib.exceptions.FormatError' if not. - tuf.formats.ROOT_SCHEMA.check_match(root_metadata) - - version = root_metadata['version'] - expires = root_metadata['expires'] - keys = root_metadata['keys'] - roles = root_metadata['roles'] - consistent_snapshot = root_metadata['consistent_snapshot'] - - return RootFile(version, expires, keys, roles, consistent_snapshot) - - - @staticmethod - def make_metadata(version, expiration_date, keydict, roledict, consistent_snapshot): - result = {'_type' : 'root'} - result['spec_version'] = tuf.SPECIFICATION_VERSION - result['version'] = version - result['expires'] = expiration_date - result['keys'] = keydict - result['roles'] = roledict - result['consistent_snapshot'] = consistent_snapshot - - # Is 'result' a Root metadata file? - # Raise 'securesystemslib.exceptions.FormatError' if not. - ROOT_SCHEMA.check_match(result) - - return result - - - - -class SnapshotFile(MetaFile): - def __init__(self, version, expires, versiondict): - self.info = {} - self.info['version'] = version - self.info['expires'] = expires - self.info['meta'] = versiondict - - - @staticmethod - def from_metadata(snapshot_metadata): - # Is 'snapshot_metadata' a Snapshot metadata file? - # Raise 'securesystemslib.exceptions.FormatError' if not. - SNAPSHOT_SCHEMA.check_match(snapshot_metadata) - - version = snapshot_metadata['version'] - expires = snapshot_metadata['expires'] - versiondict = snapshot_metadata['meta'] - - return SnapshotFile(version, expires, versiondict) - - - @staticmethod - def make_metadata(version, expiration_date, versiondict): - result = {'_type' : 'snapshot'} - result['spec_version'] = tuf.SPECIFICATION_VERSION - result['version'] = version - result['expires'] = expiration_date - result['meta'] = versiondict - - # Is 'result' a Snapshot metadata file? - # Raise 'securesystemslib.exceptions.FormatError' if not. - SNAPSHOT_SCHEMA.check_match(result) - - return result +def build_dict_conforming_to_schema(schema, **kwargs): + """ + + Given a schema.Object object (for example, TIMESTAMP_SCHEMA from this + module) and a set of keyword arguments, create a dictionary that conforms + to the given schema, using the keyword arguments to define the elements of + the new dict. + Checks the result to make sure that it conforms to the given schema, raising + an error if not. + + schema + A schema.Object, like TIMESTAMP_SCHEMA, FILEINFO_SCHEMA, + securesystemslib.formats.SIGNATURE_SCHEMA, etc. + + **kwargs + A keyword argument for each element of the schema. Optional arguments + may be included or skipped, but all required arguments must be included. + + For example, for TIMESTAMP_SCHEMA, a call might look like: + build_dict_conforming_to_schema( + TIMESTAMP_SCHEMA, + _type='timestamp', + spec_version='1.0', + version=1, + expires='2020-01-01T00:00:00Z', + meta={...}) + Some arguments will be filled in if excluded: _type, spec_version + + A dictionary conforming to the given schema. Adds certain required fields + if they are missing and can be deduced from the schema. The data returned + is a deep copy. -class TargetsFile(MetaFile): - def __init__(self, version, expires, filedict=None, delegations=None): - if filedict is None: - filedict = {} - if delegations is None: - delegations = {} - self.info = {} - self.info['version'] = version - self.info['expires'] = expires - self.info['targets'] = filedict - self.info['delegations'] = delegations + + securesystemslib.exceptions.FormatError + if the provided data does not match the schema when assembled. + + None. In particular, the provided values are not modified, and the + returned dictionary does not include references to them. - @staticmethod - def from_metadata(targets_metadata): - # Is 'targets_metadata' a Targets metadata file? - # Raise securesystemslib.exceptions.FormatError if not. - tuf.formats.TARGETS_SCHEMA.check_match(targets_metadata) + """ - version = targets_metadata['version'] - expires = targets_metadata['expires'] - filedict = targets_metadata.get('targets') - delegations = targets_metadata.get('delegations') + # Check the schema argument type (must provide check_match and _required). + if not isinstance(schema, SCHEMA.Object): + raise ValueError( + 'The first argument must be a schema.Object instance, but is not. ' + 'Given schema: ' + repr(schema)) - return TargetsFile(version, expires, filedict, delegations) + # Make a copy of the provided fields so that the caller's provided values + # do not change when the returned values are changed. + dictionary = copy.deepcopy(kwargs) - @staticmethod - def make_metadata(version, expiration_date, filedict=None, delegations=None): - if filedict is None and delegations is None: - raise securesystemslib.exceptions.Error('We don\'t allow completely' - ' empty targets metadata.') + # Automatically provide certain schema properties if they are not already + # provided and are required in objects of class . + # This includes: + # _type: + # spec_version: SPECIFICATION_VERSION_SCHEMA + # + # (Please note that _required is slightly misleading, as it includes both + # required and optional elements. It should probably be called _components.) + # + for key, element_type in schema._required: #pylint: disable=protected-access - result = {'_type' : 'targets'} - result['spec_version'] = tuf.SPECIFICATION_VERSION - result['version'] = version - result['expires'] = expiration_date - result['targets'] = {} + if key in dictionary: + # If the field has been provided, proceed normally. + continue - if filedict is not None: - result['targets'] = filedict - if delegations is not None: - result['delegations'] = delegations + elif isinstance(element_type, SCHEMA.Optional): + # If the field has NOT been provided but IS optional, proceed without it. + continue - # Is 'result' a Targets metadata file? - # Raise 'securesystemslib.exceptions.FormatError' if not. - tuf.formats.TARGETS_SCHEMA.check_match(result) + else: + # If the field has not been provided and is required, check to see if + # the field is one of the fields we automatically fill. - return result + # Currently, the list is limited to ['_type', 'spec_version']. + if key == '_type' and isinstance(element_type, SCHEMA.String): + # A SCHEMA.String stores its expected value in _string, so use that. + dictionary[key] = element_type._string #pylint: disable=protected-access + elif (key == 'spec_version' and + element_type == SPECIFICATION_VERSION_SCHEMA): + # If not provided, use the specification version in tuf/__init__.py + dictionary[key] = tuf.SPECIFICATION_VERSION -class MirrorsFile(MetaFile): - def __init__(self, version, expires): - self.info = {} - self.info['version'] = version - self.info['expires'] = expires + # If what we produce does not match the provided schema, raise a FormatError. + schema.check_match(dictionary) - @staticmethod - def from_metadata(mirrors_metadata): - raise NotImplementedError + return dictionary - @staticmethod - def make_metadata(): - raise NotImplementedError @@ -706,15 +578,6 @@ def make_metadata(): 'timestamp' : TIMESTAMP_SCHEMA, 'mirrors' : MIRRORLIST_SCHEMA} -# A dict holding the recognized class names for the top-level roles. -# That is, the role classes listed in this module (e.g., class TargetsFile()). -ROLE_CLASSES_BY_TYPE = { - 'Root' : RootFile, - 'Targets' : TargetsFile, - 'Snapshot' : SnapshotFile, - 'Timestamp' : TimestampFile, - 'Mirrors' : MirrorsFile} - def datetime_to_unix_timestamp(datetime_object): @@ -956,124 +819,6 @@ def make_versioninfo(version_number): -def make_role_metadata(keyids, threshold, name=None, paths=None, - path_hash_prefixes=None): - """ - - Create a dictionary conforming to 'tuf.formats.ROLE_SCHEMA', - representing the role with 'keyids', 'threshold', and 'paths' - as field values. 'paths' is optional (i.e., used only by the - 'Target' role). - - - keyids: a list of key ids. - - threshold: - An integer denoting the number of required keys - for the signing role. - - name: - A string that is the name of this role. - - paths: - The 'Target' role stores the paths of target files - in its metadata file. 'paths' is a list of - file paths. - - path_hash_prefixes: - The 'Target' role stores the paths of target files in its metadata file. - 'path_hash_prefixes' is a succint way to describe a set of paths to - target files. - - - securesystemslib.exceptions.FormatError, if the returned role meta is - formatted incorrectly. - - - If any of the arguments do not have a proper format, a - securesystemslib.exceptions.FormatError exception is raised when the - 'ROLE_SCHEMA' dict is created. - - - A properly formatted role meta dict, conforming to - 'ROLE_SCHEMA'. - """ - - role_meta = {} - role_meta['keyids'] = keyids - role_meta['threshold'] = threshold - - if name is not None: - role_meta['name'] = name - - # According to the specification, the 'paths' and 'path_hash_prefixes' must - # be mutually exclusive. However, at the time of writing we do not always - # ensure that this is the case with the schema checks (see #83). Therefore, - # we must do it for ourselves. - - if paths is not None and path_hash_prefixes is not None: - raise securesystemslib.exceptions.FormatError('Both "paths" and' - ' "path_hash_prefixes" are specified.') - - if path_hash_prefixes is not None: - role_meta['path_hash_prefixes'] = path_hash_prefixes - elif paths is not None: - role_meta['paths'] = paths - - # Does 'role_meta' have the correct type? - # This check ensures 'role_meta' conforms to tuf.formats.ROLE_SCHEMA. - ROLE_SCHEMA.check_match(role_meta) - - return role_meta - - - -def get_role_class(expected_rolename): - """ - - Return the role class corresponding to - 'expected_rolename'. The role name returned - by expected_meta_rolename() should be the name - passed as an argument to this function. If - 'expected_rolename' is 'Root', the class - RootFile is returned. - - - expected_rolename: - The role name used to determine which role class - to return. - - - securesystemslib.exceptions.FormatError, if 'expected_rolename' is not a - supported role. - - - None. - - - The class corresponding to 'expected_rolename'. - E.g., 'Snapshot' as an argument to this function causes - SnapshotFile' to be returned. - """ - - # Does 'expected_rolename' have the correct type? - # This check ensures 'expected_rolename' conforms to - # 'securesystemslib.formats.NAME_SCHEMA'. - # Raise 'securesystemslib.exceptions.FormatError' if there is a mismatch. - securesystemslib.formats.NAME_SCHEMA.check_match(expected_rolename) - - try: - role_class = ROLE_CLASSES_BY_TYPE[expected_rolename] - - except KeyError: - raise securesystemslib.exceptions.FormatError(repr(expected_rolename) + ' ' - 'not supported.') - - else: - return role_class - - - def expected_meta_rolename(meta_rolename): """ diff --git a/tuf/repository_lib.py b/tuf/repository_lib.py index a2b56567fe..10a1444b98 100755 --- a/tuf/repository_lib.py +++ b/tuf/repository_lib.py @@ -1311,16 +1311,30 @@ def generate_root_metadata(version, expiration_date, consistent_snapshot, # Add the loaded keyid for the role being processed. keyids.append(keyid) - # Generate and store the role data belonging to the processed role. + # Generate the authentication information Root establishes for each + # top-level role. role_threshold = tuf.roledb.get_role_threshold(rolename, repository_name) - role_metadata = tuf.formats.make_role_metadata(keyids, role_threshold) + role_metadata = tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROLE_SCHEMA, + keyids=keyids, + threshold=role_threshold) roledict[rolename] = role_metadata - # Generate the root metadata object. - root_metadata = tuf.formats.RootFile.make_metadata(version, expiration_date, - keydict, roledict, consistent_snapshot) - - return root_metadata + # Use generalized build_dict_conforming_to_schema func to produce a dict that + # contains all the appropriate information for this type of metadata, + # checking that the result conforms to the appropriate schema. + # TODO: Later, probably after the rewrite for TUF Issue #660, generalize + # further, upward, by replacing generate_targets_metadata, + # generate_root_metadata, etc. with one function that generates + # metadata, possibly rolling that upwards into the calling function. + # There are very few things that really need to be done differently. + return tuf.formats.build_dict_conforming_to_schema( + tuf.formats.ROOT_SCHEMA, + version=version, + expires=expiration_date, + keys=keydict, + roles=roledict, + consistent_snapshot=consistent_snapshot) @@ -1442,10 +1456,32 @@ def generate_targets_metadata(targets_directory, target_files, version, shutil.copyfile(target_path, digest_target) # Generate the targets metadata object. - targets_metadata = tuf.formats.TargetsFile.make_metadata(version, - expiration_date, filedict, delegations) - - return targets_metadata + # Use generalized build_dict_conforming_to_schema func to produce a dict that + # contains all the appropriate information for targets metadata, + # checking that the result conforms to the appropriate schema. + # TODO: Later, probably after the rewrite for TUF Issue #660, generalize + # further, upward, by replacing generate_targets_metadata, + # generate_root_metadata, etc. with one function that generates + # metadata, possibly rolling that upwards into the calling function. + # There are very few things that really need to be done differently. + if delegations is not None: + return tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TARGETS_SCHEMA, + version=version, + expires=expiration_date, + targets=filedict, + delegations=delegations) + else: + return tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TARGETS_SCHEMA, + version=version, + expires=expiration_date, + targets=filedict) + # TODO: As an alternative to the odd if/else above where we decide whether or + # not to include the delegations argument based on whether or not it is + # None, consider instead adding a check in + # build_dict_conforming_to_schema that skips a keyword if that keyword + # is optional in the schema and the value passed in is set to None.... @@ -1561,10 +1597,19 @@ def generate_snapshot_metadata(metadata_directory, version, expiration_date, ' extension: ' + metadata_filename) # Generate the Snapshot metadata object. - snapshot_metadata = tuf.formats.SnapshotFile.make_metadata(version, - expiration_date, fileinfodict) - - return snapshot_metadata + # Use generalized build_dict_conforming_to_schema func to produce a dict that + # contains all the appropriate information for snapshot metadata, + # checking that the result conforms to the appropriate schema. + # TODO: Later, probably after the rewrite for TUF Issue #660, generalize + # further, upward, by replacing generate_targets_metadata, + # generate_root_metadata, etc. with one function that generates + # metadata, possibly rolling that upwards into the calling function. + # There are very few things that really need to be done differently. + return tuf.formats.build_dict_conforming_to_schema( + tuf.formats.SNAPSHOT_SCHEMA, + version=version, + expires=expiration_date, + meta=fileinfodict) @@ -1629,10 +1674,19 @@ def generate_timestamp_metadata(snapshot_filename, version, expiration_date, # excluded. # Generate the timestamp metadata object. - timestamp_metadata = tuf.formats.TimestampFile.make_metadata(version, - expiration_date, snapshot_fileinfo) - - return timestamp_metadata + # Use generalized build_dict_conforming_to_schema func to produce a dict that + # contains all the appropriate information for timestamp metadata, + # checking that the result conforms to the appropriate schema. + # TODO: Later, probably after the rewrite for TUF Issue #660, generalize + # further, upward, by replacing generate_targets_metadata, + # generate_root_metadata, etc. with one function that generates + # metadata, possibly rolling that upwards into the calling function. + # There are very few things that really need to be done differently. + return tuf.formats.build_dict_conforming_to_schema( + tuf.formats.TIMESTAMP_SCHEMA, + version=version, + expires=expiration_date, + meta=snapshot_fileinfo)