diff --git a/tuf/formats.py b/tuf/formats.py index 1c03aad0..53aaa69f 100755 --- a/tuf/formats.py +++ b/tuf/formats.py @@ -76,8 +76,8 @@ # additional keys which are not defined. Thus, any additions to them will be # easily backwards compatible with clients that are already deployed. -# A date in 'YYYY-MM-DD HH:MM:SS' format. -TIME_SCHEMA = SCHEMA.RegularExpression(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}') +# A date in 'YYYY-MM-DD HH:MM:SS UTC' format. +TIME_SCHEMA = SCHEMA.RegularExpression(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} UTC') # A hexadecimal value in '23432df87ab..' format. HASH_SCHEMA = SCHEMA.RegularExpression(r'[a-fA-F0-9]+') @@ -403,7 +403,7 @@ def from_metadata(object): # Raise tuf.FormatError if not. TIMESTAMP_SCHEMA.check_match(object) - version = parse_time(object['version']) + version = object['version'] expires = parse_time(object['expires']) filedict = object['meta'] return TimestampFile(version, expires, filedict) @@ -441,7 +441,7 @@ def from_metadata(object): # Raise 'tuf.FormatError' if not. ROOT_SCHEMA.check_match(object) - version = parse_time(object['version']) + version = object['version'] expires = parse_time(object['expires']) keys = object['keys'] roles = object['roles'] @@ -485,7 +485,7 @@ def from_metadata(object): # Raise 'tuf.FormatError' if not. RELEASE_SCHEMA.check_match(object) - version = parse_time(object['version']) + version = object['version'] expires = parse_time(object['expires']) filedict = object['meta'] @@ -528,7 +528,7 @@ def from_metadata(object): # Raise tuf.FormatError if not. TARGETS_SCHEMA.check_match(object) - version = parse_time(object['version']) + version = object['version'] expires = parse_time(object['expires']) filedict = object.get('targets') delegations = object.get('delegations') @@ -603,16 +603,16 @@ def make_metadata(): def format_time(timestamp): """ - Encode 'timestamp' in YYYY-MM-DD HH:MM:SS format. + Encode 'timestamp' in 'YYYY-MM-DD HH:MM:SS UTC' format. 'timestamp' is a Unix timestamp value. For example, it is the time format returned by calendar.timegm(). >>> format_time(499137720) - '1985-10-26 01:22:00' + '1985-10-26 01:22:00 UTC' timestamp: - The time to format. + The time to format. This is a Unix timestamp. tuf.Error, if 'timestamp' is invalid. @@ -621,12 +621,16 @@ def format_time(timestamp): None. - A string in 'YYYY-MM-DD HH:MM:SS' format. + A string in 'YYYY-MM-DD HH:MM:SS UTC' format. """ try: - return time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(timestamp)) + # Convert the timestamp to 'yyyy-mm-dd HH:MM:SS' format. + formatted_time = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(timestamp)) + + # Attach 'UTC' to the formatted time string prior to returning. + return formatted_time+' UTC' except (ValueError, TypeError): raise tuf.FormatError('Invalid argument value') @@ -636,11 +640,11 @@ def format_time(timestamp): def parse_time(string): """ - Parse 'string' in YYYY-MM-DD HH:MM:SS format. + Parse 'string', in 'YYYY-MM-DD HH:MM:SS UTC' format, to a Unix timestamp. string: - A string representing the time (e.g., '1985-10-26 01:20:00'). + A string representing the time (e.g., '1985-10-26 01:20:00 UTC'). tuf.FormatError, if parsing 'string' fails. @@ -656,11 +660,14 @@ def parse_time(string): # Is 'string' properly formatted? # Raise 'tuf.FormatError' if there is a mismatch. TIME_SCHEMA.check_match(string) - + + # Strip the ' UTC' attached to the string. The string time, minus the ' UTC', + # is the time format expected by the time functions called below. + string = string[0:string.rfind(' UTC')] try: return calendar.timegm(time.strptime(string, '%Y-%m-%d %H:%M:%S')) except ValueError: - raise tuf.FormatError('Malformed time '+repr(string)) + raise tuf.FormatError('Malformed time: '+repr(string)) diff --git a/tuf/repo/signercli.py b/tuf/repo/signercli.py index 1ad35551..9f008b4b 100755 --- a/tuf/repo/signercli.py +++ b/tuf/repo/signercli.py @@ -441,7 +441,7 @@ def _get_metadata_expiration(): message = '\nCurrent time: '+tuf.formats.format_time(time.time())+' UTC.\n'+\ 'Enter the expiration date, in UTC, of the metadata file (yyyy-mm-dd HH:MM:SS): ' try: - input_date = _prompt(message) + input_date = _prompt(message, str) try: expiration_date = tuf.formats.parse_time(input_date) except tuf.FormatError, e: diff --git a/tuf/tests/repository_setup.py b/tuf/tests/repository_setup.py index 3b2d20f5..6abd1b51 100755 --- a/tuf/tests/repository_setup.py +++ b/tuf/tests/repository_setup.py @@ -19,9 +19,11 @@ import os import sys +import time import shutil import tempfile +import tuf.formats import tuf.rsa_key as rsa_key import tuf.repo.keystore as keystore import tuf.repo.signerlib as signerlib @@ -77,6 +79,12 @@ def build_server_repository(server_repository_dir, targets_dir): original_prompt = signercli._prompt original_get_password = signercli._get_password original_get_keyids = signercli._get_keyids + + # The expiration date for created metadata, required by the 'signercli.py' + # script. The expiration date is set to 259200 seconds ahead of the current + # time. Set all the metadata versions numbers to 1. + expiration_date = tuf.formats.format_time(time.time()+259200) + version = 1 server_metadata_dir = os.path.join(server_repository_dir, 'metadata') keystore_dir = os.path.join(server_repository_dir, 'keystore') @@ -103,11 +111,11 @@ def build_server_repository(server_repository_dir, targets_dir): # BUILD ROLE FILES. # Build root file. signerlib.build_root_file(config_filepath, role_keyids['root'], - server_metadata_dir) + server_metadata_dir, version) # Build targets file. signerlib.build_targets_file(targets_dir, role_keyids['targets'], - server_metadata_dir) + server_metadata_dir, version, expiration_date) # MAKE DELEGATIONS. # We will need to patch a few signercli prompts. @@ -143,6 +151,8 @@ def _mock_prompt(msg, junk): return parent_role elif msg.endswith('\nEnter the delegated role\'s name: '): return delegated_role_name + elif msg.startswith('\nCurrent time:'): + return expiration_date else: error_msg = ('Prompt: '+'\''+msg+'\''+ ' did not match any predefined mock prompts.') @@ -203,10 +213,12 @@ def _mock_get_keyids(junk): keystore._key_passwords = unittest_toolbox.Modified_TestCase.rsa_passwords # Build release file. - signerlib.build_release_file(role_keyids['release'], server_metadata_dir) + signerlib.build_release_file(role_keyids['release'], server_metadata_dir, + version, expiration_date) # Build timestamp file. - signerlib.build_timestamp_file(role_keyids['timestamp'], server_metadata_dir) + signerlib.build_timestamp_file(role_keyids['timestamp'], server_metadata_dir, + version, expiration_date) keystore._keystore = {} keystore._key_passwords = {} diff --git a/tuf/tests/test_formats.py b/tuf/tests/test_formats.py index abb6152c..b14ba0f7 100755 --- a/tuf/tests/test_formats.py +++ b/tuf/tests/test_formats.py @@ -37,7 +37,7 @@ def tearDown(self): def test_schemas(self): # Test conditions for valid schemas. valid_schemas = { - 'TIME_SCHEMA': (tuf.formats.TIME_SCHEMA, '2012-10-14 06:42:12'), + 'TIME_SCHEMA': (tuf.formats.TIME_SCHEMA, '2012-10-14 06:42:12 UTC'), 'HASH_SCHEMA': (tuf.formats.HASH_SCHEMA, 'A4582BCF323BCEF'), @@ -180,8 +180,8 @@ def test_schemas(self): 'ROOT_SCHEMA': (tuf.formats.ROOT_SCHEMA, {'_type': 'Root', - 'ts': '2012-10-14 06:42:12', - 'expires': '2012-10-16 06:42:12', + 'version': 8, + 'expires': '2012-10-16 06:42:12 UTC', 'keys': {'123abc': {'keytype': 'rsa', 'keyval': {'public': 'pubkey', 'private': 'privkey'}}}, @@ -191,8 +191,8 @@ def test_schemas(self): 'TARGETS_SCHEMA': (tuf.formats.TARGETS_SCHEMA, {'_type': 'Targets', - 'ts': '2012-10-14 06:42:12', - 'expires': '2012-10-16 06:42:12', + 'version': 8, + 'expires': '2012-10-16 06:42:12 UTC', 'targets': {'metadata/targets.txt': {'length': 1024, 'hashes': {'sha256': 'ABCD123'}, 'custom': {'type': 'metadata'}}}, @@ -205,16 +205,16 @@ def test_schemas(self): 'RELEASE_SCHEMA': (tuf.formats.RELEASE_SCHEMA, {'_type': 'Release', - 'ts': '2012-10-14 06:42:12', - 'expires': '2012-10-16 06:42:12', + 'version': 8, + 'expires': '2012-10-16 06:42:12 UTC', 'meta': {'metadata/release.txt': {'length': 1024, 'hashes': {'sha256': 'ABCD123'}, 'custom': {'type': 'metadata'}}}}), 'TIMESTAMP_SCHEMA': (tuf.formats.TIMESTAMP_SCHEMA, {'_type': 'Timestamp', - 'ts': '2012-10-14 06:42:12', - 'expires': '2012-10-16 06:42:12', + 'version': 8, + 'expires': '2012-10-16 06:42:12 UTC', 'meta': {'metadata/timestamp.txt': {'length': 1024, 'hashes': {'sha256': 'ABCD123'}, 'custom': {'type': 'metadata'}}}}), @@ -235,8 +235,8 @@ def test_schemas(self): 'MIRRORLIST_SCHEMA': (tuf.formats.MIRRORLIST_SCHEMA, {'_type': 'Mirrors', - 'ts': '2012-10-14 06:42:12', - 'expires': '2012-10-16 06:42:12', + 'version': 8, + 'expires': '2012-10-16 06:42:12 UTC', 'mirrors': [{'url_prefix': 'http://localhost:8001', 'metadata_path': 'metadata/', 'targets_path': 'targets/', @@ -263,9 +263,9 @@ 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, timestamp, expires): + def __init__(self, version, expires): self.info = {} - self.info['ts'] = timestamp + self.info['version'] = version self.info['expires'] = expires metadata = NewMetadataFile(123, 456) @@ -278,13 +278,15 @@ def __init__(self, timestamp, expires): self.assertFalse(metadata == metadata3) # Test the 'getattr' method. - self.assertEqual(123, getattr(metadata, 'ts')) + self.assertEqual(123, getattr(metadata, 'version')) self.assertRaises(AttributeError, getattr, metadata, 'bad') def test_TimestampFile(self): # Test conditions for valid instances of 'tuf.formats.TimestampFile'. + version = 8 + expires = '2012-10-16 06:42:12 UTC' filedict = {'metadata/timestamp.txt': {'length': 1024, 'hashes': {'sha256': 'ABCD123'}, 'custom': {'type': 'metadata'}}} @@ -293,13 +295,22 @@ def test_TimestampFile(self): from_metadata = tuf.formats.TimestampFile.from_metadata TIMESTAMP_SCHEMA = tuf.formats.TIMESTAMP_SCHEMA - self.assertTrue(TIMESTAMP_SCHEMA.matches(make_metadata(filedict))) - metadata = make_metadata(filedict) + 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. - filedict = 123 - self.assertRaises(tuf.FormatError, make_metadata, filedict) + bad_version = 'eight' + bad_expires = '2000' + bad_filedict = 123 + self.assertRaises(tuf.FormatError, make_metadata, bad_version, + expires, filedict) + self.assertRaises(tuf.FormatError, make_metadata, version, + bad_expires, filedict) + self.assertRaises(tuf.FormatError, make_metadata, version, + expires, bad_filedict) + self.assertRaises(tuf.FormatError, from_metadata, 123) @@ -307,6 +318,8 @@ def test_TimestampFile(self): def test_RootFile(self): # Test conditions for valid instances of 'tuf.formats.RootFile'. + version = 8 + expiration_seconds = 691200 keydict = {'123abc': {'keytype': 'rsa', 'keyval': {'public': 'pubkey', 'private': 'privkey'}}} @@ -319,17 +332,29 @@ def test_RootFile(self): from_metadata = tuf.formats.RootFile.from_metadata ROOT_SCHEMA = tuf.formats.ROOT_SCHEMA - self.assertTrue(ROOT_SCHEMA.matches(make_metadata(keydict, roledict, 12345))) - metadata = make_metadata(keydict, roledict, 12345) + self.assertTrue(ROOT_SCHEMA.matches(make_metadata(version, expiration_seconds, + keydict, roledict))) + metadata = make_metadata(version, expiration_seconds, keydict, roledict,) self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.RootFile)) # Test conditions for invalid arguments. + bad_version = '8' + bad_expiration_seconds = 'eight' bad_keydict = 123 bad_roledict = 123 - self.assertRaises(tuf.FormatError, make_metadata, bad_keydict, roledict, 123) - self.assertRaises(tuf.FormatError, make_metadata, keydict, bad_roledict, 123) - self.assertRaises(tuf.FormatError, make_metadata, keydict, roledict, 'bad') + self.assertRaises(tuf.FormatError, make_metadata, bad_version, + expiration_seconds, + keydict, roledict) + self.assertRaises(tuf.FormatError, make_metadata, version, + bad_expiration_seconds, + keydict, roledict) + self.assertRaises(tuf.FormatError, make_metadata, version, + expiration_seconds, + bad_keydict, roledict) + self.assertRaises(tuf.FormatError, make_metadata, version, + expiration_seconds, + keydict, bad_roledict) self.assertRaises(tuf.FormatError, from_metadata, 'bad') @@ -337,6 +362,8 @@ def test_RootFile(self): def test_ReleaseFile(self): # Test conditions for valid instances of 'tuf.formats.ReleaseFile'. + version = 8 + expires = '2012-10-16 06:42:12 UTC' filedict = {'metadata/release.txt': {'length': 1024, 'hashes': {'sha256': 'ABCD123'}, 'custom': {'type': 'metadata'}}} @@ -345,19 +372,30 @@ def test_ReleaseFile(self): from_metadata = tuf.formats.ReleaseFile.from_metadata RELEASE_SCHEMA = tuf.formats.RELEASE_SCHEMA - self.assertTrue(RELEASE_SCHEMA.matches(make_metadata(filedict))) - metadata = make_metadata(filedict) + self.assertTrue(RELEASE_SCHEMA.matches(make_metadata(version, expires, + filedict))) + metadata = make_metadata(version, expires, filedict) self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.ReleaseFile)) # Test conditions for invalid arguments. - filedict = 123 - self.assertRaises(tuf.FormatError, make_metadata, filedict) + bad_version = '8' + bad_expires = '2000' + bad_filedict = 123 + self.assertRaises(tuf.FormatError, make_metadata, version, + expires, bad_filedict) + self.assertRaises(tuf.FormatError, make_metadata, bad_version, expires, + filedict) + self.assertRaises(tuf.FormatError, make_metadata, version, bad_expires, + bad_filedict) + self.assertRaises(tuf.FormatError, from_metadata, 123) def test_TargetsFile(self): # Test conditions for valid instances of 'tuf.formats.TargetsFile'. + version = 8 + expires = '2012-10-16 06:42:12 UTC' filedict = {'metadata/targets.txt': {'length': 1024, 'hashes': {'sha256': 'ABCD123'}, 'custom': {'type': 'metadata'}}} @@ -373,16 +411,25 @@ def test_TargetsFile(self): from_metadata = tuf.formats.TargetsFile.from_metadata TARGETS_SCHEMA = tuf.formats.TARGETS_SCHEMA - self.assertTrue(TARGETS_SCHEMA.matches(make_metadata(filedict, delegations))) - metadata = make_metadata(filedict, delegations) + self.assertTrue(TARGETS_SCHEMA.matches(make_metadata(version, expires, + filedict, delegations))) + metadata = make_metadata(version, expires, filedict, delegations) self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.TargetsFile)) # Test conditions for invalid arguments. + bad_version = 'eight' + bad_expires = '2000' bad_filedict = 123 bad_delegations = 123 - self.assertRaises(tuf.FormatError, make_metadata, bad_filedict, delegations) - self.assertRaises(tuf.FormatError, make_metadata, filedict, bad_delegations) - self.assertRaises(tuf.Error, make_metadata) + self.assertRaises(tuf.FormatError, make_metadata, bad_version, expires, + filedict, delegations) + self.assertRaises(tuf.FormatError, make_metadata, version, bad_expires, + filedict, delegations) + self.assertRaises(tuf.FormatError, make_metadata, version, expires, + bad_filedict, delegations) + self.assertRaises(tuf.FormatError, make_metadata, version, expires, + filedict, bad_delegations) + self.assertRaises(tuf.Error, make_metadata, version, expires) self.assertRaises(tuf.FormatError, from_metadata, 123) @@ -392,7 +439,7 @@ def test_format_time(self): # Test conditions for valid arguments. TIME_SCHEMA = tuf.formats.TIME_SCHEMA self.assertTrue(TIME_SCHEMA.matches(tuf.formats.format_time(499137720))) - self.assertEqual('1985-10-26 01:22:00', tuf.formats.format_time(499137720)) + self.assertEqual('1985-10-26 01:22:00 UTC', tuf.formats.format_time(499137720)) # Test conditions for invalid arguments. self.assertRaises(tuf.FormatError, tuf.formats.format_time, 'bad') @@ -403,7 +450,7 @@ def test_format_time(self): def test_parse_time(self): # Test conditions for valid arguments. - self.assertEqual(499137600, tuf.formats.parse_time('1985-10-26 01:20:00')) + self.assertEqual(499137600, tuf.formats.parse_time('1985-10-26 01:20:00 UTC')) # Test conditions for invalid arguments. self.assertRaises(tuf.FormatError, tuf.formats.parse_time, 'bad') @@ -440,8 +487,8 @@ def test_parse_base64(self): def test_make_signable(self): # Test conditions for expected make_signable() behavior. root = {'_type': 'Root', - 'ts': '2012-10-14 06:42:12', - 'expires': '2012-10-16 06:42:12', + 'version': 8, + 'expires': '2012-10-16 06:42:12 UTC', 'keys': {'123abc': {'keytype': 'rsa', 'keyval': {'public': 'pubkey', 'private': 'privkey'}}}, @@ -551,8 +598,8 @@ def test_expected_meta_rolename(self): def test_check_signable_object_format(self): # Test condition for a valid argument. root = {'_type': 'Root', - 'ts': '2012-10-14 06:42:12', - 'expires': '2012-10-16 06:42:12', + 'version': 8, + 'expires': '2012-10-16 06:42:12 UTC', 'keys': {'123abc': {'keytype': 'rsa', 'keyval': {'public': 'pubkey', 'private': 'privkey'}}}, diff --git a/tuf/tests/test_keydb.py b/tuf/tests/test_keydb.py index fe61a976..36986057 100755 --- a/tuf/tests/test_keydb.py +++ b/tuf/tests/test_keydb.py @@ -171,8 +171,12 @@ def test_create_keydb_from_root_metadata(self): keydict = {keyid: rsakey, keyid2: rsakey2} roledict = {'Root': {'keyids': [keyid], 'threshold': 1}, 'Targets': {'keyids': [keyid2], 'threshold': 1}} + version = 8 + expiration_seconds = 200 - root_metadata = tuf.formats.RootFile.make_metadata(keydict, roledict, 12345) + root_metadata = tuf.formats.RootFile.make_metadata(version, + expiration_seconds, + keydict, roledict) self.assertEqual(None, tuf.keydb.create_keydb_from_root_metadata(root_metadata)) # Ensure 'keyid' and 'keyid2' were added to the keydb database. self.assertEqual(rsakey, tuf.keydb.get_key(keyid)) @@ -203,8 +207,12 @@ def test_create_keydb_from_root_metadata(self): keyid3 = KEYS[2]['keyid'] rsakey3['keytype'] = 'bad_keytype' keydict[keyid3] = rsakey3 + version = 8 + expiration_seconds = 200 - root_metadata = tuf.formats.RootFile.make_metadata(keydict, roledict, 12345) + root_metadata = tuf.formats.RootFile.make_metadata(version, + expiration_seconds, + keydict, roledict) 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/tuf/tests/test_quickstart.py b/tuf/tests/test_quickstart.py index 2c2220af..440cc136 100755 --- a/tuf/tests/test_quickstart.py +++ b/tuf/tests/test_quickstart.py @@ -81,7 +81,7 @@ def test_2_build_repository(self): def _mock_prompt(message, confirm=False, input_parameters=input_dict): if message.startswith('\nWhen would you like your '+ - 'certificates to expire?'): + '"root.txt" metadata file to expire?'): return input_parameters['expiration'] for role in self.role_list: # role_list=['root', 'targets', ...] if message.startswith('\nEnter the desired threshold '+ @@ -121,7 +121,8 @@ def _remove_repository_directories(repo_dir, keystore_dir, client_dir): input_dict['expiration'] = '5/8/2011' self.assertRaises(tuf.RepositoryError, quickstart.build_repository, proj_dir) - input_dict['expiration'] = self.random_string() # random string + # Random string. + input_dict['expiration'] = self.random_string() self.assertRaises(tuf.RepositoryError, quickstart.build_repository, proj_dir) _remove_repository_directories(repo_dir, keystore_dir, client_dir) diff --git a/tuf/tests/test_roledb.py b/tuf/tests/test_roledb.py index 63a34198..141dce1c 100755 --- a/tuf/tests/test_roledb.py +++ b/tuf/tests/test_roledb.py @@ -321,8 +321,12 @@ def test_create_roledb_from_root_metadata(self): keydict = {keyid: rsakey, keyid2: rsakey2} roledict = {'root': {'keyids': [keyid], 'threshold': 1}, 'targets': {'keyids': [keyid2], 'threshold': 1}} + version = 8 + expiration_seconds = 200 - root_metadata = tuf.formats.RootFile.make_metadata(keydict, roledict, 12345) + root_metadata = tuf.formats.RootFile.make_metadata(version, + expiration_seconds, + keydict, roledict) self.assertEqual(None, tuf.roledb.create_roledb_from_root_metadata(root_metadata)) # Ensure 'Root' and 'Targets' were added to the role database. @@ -352,17 +356,23 @@ def test_create_roledb_from_root_metadata(self): roledict = {'root': {'keyids': [keyid], 'threshold': 1}, 'targets/role1': {'keyids': [keyid2], 'threshold': 1}, 'release': {'keyids': [keyid3], 'threshold': 1}} + version = 8 + expiration_seconds = 200 # Add a third key for 'release'. keydict[keyid3] = rsakey3 - root_metadata = tuf.formats.RootFile.make_metadata(keydict, roledict, 12345) + root_metadata = tuf.formats.RootFile.make_metadata(version, + expiration_seconds, + keydict, roledict) self.assertRaises(tuf.Error, tuf.roledb.create_roledb_from_root_metadata, root_metadata) # Remove the invalid role and re-generate 'root_metadata' to test for the # other two roles. del roledict['targets/role1'] - root_metadata = tuf.formats.RootFile.make_metadata(keydict, roledict, 12345) + root_metadata = tuf.formats.RootFile.make_metadata(version, + expiration_seconds, + keydict, roledict) self.assertEqual(None, tuf.roledb.create_roledb_from_root_metadata(root_metadata)) diff --git a/tuf/tests/test_signercli.py b/tuf/tests/test_signercli.py index 2b8c96f3..7e4ff060 100755 --- a/tuf/tests/test_signercli.py +++ b/tuf/tests/test_signercli.py @@ -35,6 +35,7 @@ class guarantees the order of unit tests. So that, 'test_something_A' import os +import time import logging import tuf.formats @@ -60,8 +61,7 @@ class guarantees the order of unit tests. So that, 'test_something_A' class TestSignercli(unittest_toolbox.Modified_TestCase): - - + # SETUP original_prompt = signercli._prompt signercli._prompt = original_prompt @@ -106,12 +106,14 @@ def _mock_get_meta_dir(directory=directory): # This method patches signercli._prompt() that are called from # make_role_metadata methods (e.g., tuf.signercli.make_root_metadata()). - def make_metadata_mock_prompts(self, targ_dir, conf_path): + def make_metadata_mock_prompts(self, targ_dir, conf_path, expiration): def _mock_prompt(msg, junk): if msg.startswith('\nEnter the directory containing the target'): return targ_dir elif msg.startswith('\nEnter the configuration file path'): return conf_path + elif msg.startswith('\nCurrent time:'): + return expiration else: error_msg = ('Prompt: '+'\''+msg[1:]+'\''+ ' did not match any predefined mock prompts.') @@ -232,6 +234,10 @@ def test_4__list_keyids(self): original_get_metadata_directory = signercli._get_metadata_directory original_prompt = signercli._prompt original_get_password = signercli._get_password + + # Creating root and target metadata requires an expiration date to be set. + # Expiration date set to expires 100 seconds from the current time. + expiration_date = tuf.formats.format_time(time.time()+100) # The 'root.txt' and 'targets.txt' metadata files are # needed for _list_keyids() to determine the roles @@ -268,8 +274,9 @@ def test_4__list_keyids(self): # Mock method for signercli._prompt(). self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) - + conf_path=config_filepath, + expiration=expiration_date) + # Create the target metadata file that will be loaded by _list_keyids() # to extract the keyids for all the targets roles. signercli.make_targets_metadata(keystore_dir) @@ -531,7 +538,7 @@ def test_1__sign_and_write_metadata(self): self.top_level_role_info) # Create role's metadata. - signable_meta = signerlib.generate_root_metadata(config_filepath) + signable_meta = signerlib.generate_root_metadata(config_filepath, 8) # TESTS @@ -566,6 +573,10 @@ def test_4_change_password(self): original_prompt = signercli._prompt original_get_password = signercli._get_password + # Creating root and target metadata requires an expiration date to be set. + # Expiration date set to expires 100 seconds from the current time. + expiration_date = tuf.formats.format_time(time.time()+100) + # Create keystore and repo directories. keystore_dir = self.create_temp_keystore_directory() repo_dir = self.make_temp_directory() @@ -597,7 +608,8 @@ def test_4_change_password(self): # Mock method for signercli._prompt(). self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) + conf_path=config_filepath, + expiration=expiration_date) signercli.make_targets_metadata(keystore_dir) @@ -695,6 +707,10 @@ def test_4_dump_key(self): original_prompt = signercli._prompt original_get_password = signercli._get_password + # Creating root and target metadata requires an expiration date to be set. + # Expiration date set to expires 100 seconds from the current time. + expiration_date = tuf.formats.format_time(time.time()+100) + # Create keystore and repo directories. keystore_dir = self.create_temp_keystore_directory() repo_dir = self.make_temp_directory() @@ -726,8 +742,9 @@ def test_4_dump_key(self): # Mock method for signercli._prompt(). self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) - + conf_path=config_filepath, + expiration=expiration_date) + signercli.make_targets_metadata(keystore_dir) @@ -856,6 +873,10 @@ def test_3_make_targets_metadata(self): original_prompt = signercli._prompt original_get_password = signercli._get_password + # Creating target metadata requires an expiration date to be set. + # Expiration date set to expires 100 seconds from the current time. + expiration_date = tuf.formats.format_time(time.time()+100) + # Create a temp repository and metadata directories. repo_dir = self.make_temp_directory() meta_dir = self.make_temp_directory(directory=repo_dir) @@ -882,7 +903,8 @@ def test_3_make_targets_metadata(self): # Mock method for signercli._prompt(). self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) + conf_path=config_filepath, + expiration=expiration_date) # TESTS @@ -898,13 +920,15 @@ def test_3_make_targets_metadata(self): # Supply a non-existing targets directory. self.make_metadata_mock_prompts(targ_dir=self.random_path(), - conf_path=config_filepath) + conf_path=config_filepath, + expiration=expiration_date) self.assertRaises(tuf.RepositoryError, signercli.make_targets_metadata, keystore_dir) # Restore the targets directory. self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) + conf_path=config_filepath, + expiration=expiration_date) # Test: invalid config path. # Clear keystore's dictionaries. @@ -912,13 +936,31 @@ def test_3_make_targets_metadata(self): # Supply a non-existing config path. self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=self.random_path()) + conf_path=self.random_path(), + expiration=expiration_date) self.assertRaises(tuf.RepositoryError, signercli.make_targets_metadata, keystore_dir) # Restore the config file path. self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) + conf_path=config_filepath, + expiration=expiration_date) + + # Test: invalid expiration date. + # Clear keystore's dictionaries + keystore.clear_keystore() + + # Supply invalid expiration date. + self.make_metadata_mock_prompts(targ_dir=targets_dir, + conf_path=config_filepath, + expiration=self.random_string()) + self.assertRaises(tuf.RepositoryError, signercli.make_targets_metadata, + keystore_dir) + + # Restore the config file path. + self.make_metadata_mock_prompts(targ_dir=targets_dir, + conf_path=config_filepath, + expiration=expiration_date) # Test: incorrect 'targets' passwords. # Clear keystore's dictionaries. @@ -946,6 +988,10 @@ def test_4_make_release_metadata(self): original_prompt = signercli._prompt original_get_password = signercli._get_password + # Creating release metadata requires an expiration date to be set. + # Expiration date set to expires 100 seconds from the current time. + expiration_date = tuf.formats.format_time(time.time()+100) + # In order to build release metadata file (release.txt), # root and targets metadata files (root.txt, targets.txt) # must exist in the metadata directory. @@ -975,7 +1021,8 @@ def test_4_make_release_metadata(self): # Mock method for signercli._prompt(). self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) + conf_path=config_filepath, + expiration=expiration_date) # TESTS @@ -1017,13 +1064,13 @@ def test_4_make_release_metadata(self): # Test: invalid config path. # Supply a non-existing config file path. self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=self.random_path()) + conf_path=self.random_path(), expiration=expiration_date) self.assertRaises(tuf.RepositoryError, signercli.make_release_metadata, keystore_dir) # Restore the config file path. self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) + conf_path=config_filepath, expiration=expiration_date) # Test: incorrect 'release' passwords. # Clear keystore's dictionaries. @@ -1051,6 +1098,10 @@ def test_5_make_timestamp_metadata(self): original_prompt = signercli._prompt original_get_password = signercli._get_password + # Creating the top-level metadata requires an expiration date to be set. + # Expiration date set to expires 100 seconds from the current time. + expiration_date = tuf.formats.format_time(time.time()+100) + # In order to build timestamp metadata file (timestamp.txt), # root, targets and release metadata files (root.txt, targets.txt # release.txt) must exist in the metadata directory. @@ -1080,7 +1131,8 @@ def test_5_make_timestamp_metadata(self): # Mock method for signercli._prompt(). self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) + conf_path=config_filepath, + expiration=expiration_date) # TESTS @@ -1140,13 +1192,15 @@ def test_5_make_timestamp_metadata(self): # Test: invalid config path. # Supply a non-existing config file path. self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=self.random_path()) + conf_path=self.random_path(), + expiration=expiration_date) self.assertRaises(tuf.RepositoryError, signercli.make_release_metadata, keystore_dir) # Restore the config file path. self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) + conf_path=config_filepath, + expiration=expiration_date) # Test: incorrect 'release' passwords. @@ -1175,6 +1229,10 @@ def test_6_sign_metadata_file(self): original_prompt = signercli._prompt original_get_password = signercli._get_password + # Creating the top-level metadata requires an expiration date to be set. + # Expiration date set to expires 100 seconds from the current time. + expiration_date = tuf.formats.format_time(time.time()+100) + # To test this method, an RSA key will be created with # a password in addition to the existing RSA keys. # Create temp directory for config file. @@ -1203,7 +1261,8 @@ def test_6_sign_metadata_file(self): # Mock method for signercli._prompt(). self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) + conf_path=config_filepath, + expiration=expiration_date) # Create metadata files. signercli.make_root_metadata(keystore_dir) @@ -1290,7 +1349,11 @@ def test_7_make_delegation(self): original_get_metadata_directory = signercli._get_metadata_directory original_prompt = signercli._prompt original_get_password = signercli._get_password - + + # Creating the top-level metadata requires an expiration date to be set. + # Expiration date set to expires 100 seconds from the current time. + expiration_date = tuf.formats.format_time(time.time()+100) + # Create a temp repository and metadata directories. repo_dir = self.make_temp_directory() meta_dir = self.make_temp_directory(directory=repo_dir) @@ -1327,7 +1390,8 @@ def test_7_make_delegation(self): # Mock method for signercli._prompt() to generate targets.txt file. self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath) + conf_path=config_filepath, + expiration=expiration_date) # List of keyids to be returned by _get_keyids() signing_keyids = [new_keyid_1] @@ -1352,6 +1416,8 @@ def _mock_prompt(msg, junk): return parent_role elif msg.endswith('\nEnter the delegated role\'s name: '): return delegated_role + elif msg.startswith('\nCurrent time:'): + return expiration_date else: error_msg = ('Prompt: '+'\''+msg+'\''+ ' did not match any predefined mock prompts.') diff --git a/tuf/tests/test_signerlib.py b/tuf/tests/test_signerlib.py index ececc08e..c3a2fc79 100755 --- a/tuf/tests/test_signerlib.py +++ b/tuf/tests/test_signerlib.py @@ -213,6 +213,8 @@ def test_1_generate_targets_metadata(self): # SETUP generate_targets_meta = signerlib.generate_targets_metadata + version = 8 + expiration_date = '1985-10-26 01:20:00 UTC' # Generate target files. # 'repo_dir' represents repository base. @@ -223,20 +225,31 @@ def test_1_generate_targets_metadata(self): # TESTS # Test: Run the generate_targets_metadata(). Test its return value. # Its return value should correspond to tuf.formats.SIGNABLE_SCHEMA - target_signable_obj = generate_targets_meta(repo_dir, target_files) + target_signable_obj = generate_targets_meta(repo_dir, target_files, + version, expiration_date) # Test: Validate input. self.assertTrue(formats.SIGNABLE_SCHEMA.matches(target_signable_obj)) # Test: Incorrect arguments. self.assertRaises(tuf.FormatError, generate_targets_meta, - repo_dir, 1234) + self.random_string(), expiration_date, + repo_dir, target_files) self.assertRaises(tuf.FormatError, generate_targets_meta, - repo_dir, self.random_string()) + repo_dir, self.random_string(), + repo_dir, target_files) self.assertRaises(tuf.FormatError, generate_targets_meta, - repo_dir, [self.random_string(), 1234]) + version, expiration_date, + self.random_string(), target_files) + self.assertRaises(tuf.FormatError, generate_targets_meta, + version, expiration_date, + repo_dir, self.random_string()) + self.assertRaises(tuf.FormatError, generate_targets_meta, + version, expiration_date, + repo_dir, [self.random_string(), 1234]) self.assertRaises(tuf.Error, generate_targets_meta, - self.random_path(), target_files) + version, expiration_date, + self.random_path(), target_files) @@ -368,8 +381,8 @@ def test_3_generate_root_metadata(self): # SETUP original_get_key = tuf.repo.keystore.get_key - build_config = signerlib.build_config_file + version = 8 # Create a temp directory to hold a config file. config_dir = self.make_temp_directory() @@ -391,26 +404,29 @@ def test_3_generate_root_metadata(self): # TESTS # Test: What if keystore is not set up? self.assertRaises(tuf.UnknownKeyError, signerlib.generate_root_metadata, - config_path) + config_path, version) # Patch keystore's get_key method. No harm is done here since correct # arguments are passed and keystore methods are tested separately. tuf.repo.keystore.get_key = self.get_keystore_key # Test: normal case. Pass a correct config path. - root_meta = signerlib.generate_root_metadata(config_path) + root_meta = signerlib.generate_root_metadata(config_path, version) # Check if the returned dictionary corresponds to SIGNABLE_SCHEMA. self.assertTrue(formats.SIGNABLE_SCHEMA.matches(root_meta)) # Test: bogus arguments. self.assertRaises(tuf.Error, signerlib.generate_root_metadata, - notargets_conf_path) - self.assertRaises(tuf.Error, signerlib.generate_root_metadata, '') + notargets_conf_path, version) + self.assertRaises(tuf.Error, signerlib.generate_root_metadata, '', version) self.assertRaises(tuf.Error, signerlib.generate_root_metadata, - self.random_string()) + self.random_string(), version) self.assertRaises(tuf.Error, signerlib.generate_root_metadata, - {self.random_string(): self.random_string()}) + {self.random_string(): self.random_string()}, version) + self.assertRaises(tuf.FormatError, signerlib.generate_root_metadata, + config_path, self.random_string()) + # RESTORE tuf.repo.keystore.get_key = original_get_key @@ -483,6 +499,7 @@ def test_5_build_root_file(self): # SETUP original_get_key = tuf.repo.keystore.get_key + version = 8 signed_root_meta, root_info = self._get_signed_role_info('root') root_keyids = root_info[1] @@ -492,7 +509,8 @@ def test_5_build_root_file(self): # TESTS # Test: normal case. - root_filepath = signerlib.build_root_file(config_path, root_keyids, meta_dir) + root_filepath = signerlib.build_root_file(config_path, root_keyids, + meta_dir, version) # Check existence of the file and validity of it's content. self.assertTrue(os.path.exists(root_filepath)) @@ -503,11 +521,13 @@ def test_5_build_root_file(self): # Test: various exceptions. self.assertRaises(tuf.Error, signerlib.build_root_file, - self.random_path(), root_keyids, meta_dir) - self.assertRaises(tuf.Error, signerlib.build_root_file, - config_path, root_keyids, self.random_path()) + self.random_path(), root_keyids, meta_dir, version) self.assertRaises(tuf.FormatError, signerlib.build_root_file, - config_path, self.random_string(), meta_dir) + config_path, self.random_string(), meta_dir, version) + self.assertRaises(tuf.Error, signerlib.build_root_file, + config_path, root_keyids, self.random_path(), version) + self.assertRaises(tuf.Error, signerlib.build_root_file, + config_path, root_keyids, meta_dir, self.random_string()) # RESTORE tuf.repo.keystore.get_key = original_get_key @@ -525,7 +545,9 @@ def test_5_build_targets_file(self): # SETUP original_get_key = tuf.repo.keystore.get_key - + version = 8 + expiration_date = '1985-10-26 01:20:00 UTC' + signed_targets_meta, targets_info = self._get_signed_role_info('targets') # 'targets_info' is a tuple that includes targets meta, repository dir, @@ -539,7 +561,8 @@ def test_5_build_targets_file(self): # TESTS # Test: normal case. targets_filepath = signerlib.build_targets_file(targets_dir, - targets_keyids, meta_dir) + targets_keyids, meta_dir, + version, expiration_date) # Check existence of the file and validity of it's content. self.assertTrue(os.path.exists(targets_filepath)) @@ -550,11 +573,15 @@ def test_5_build_targets_file(self): # Test: various exceptions. self.assertRaises(tuf.Error, signerlib.build_targets_file, - self.random_path(), targets_keyids, meta_dir) - self.assertRaises(tuf.FormatError, signerlib.build_root_file, - targets_dir, self.random_string(), meta_dir) - self.assertRaises((tuf.FormatError, tuf.Error), signerlib.build_root_file, - targets_dir, targets_keyids, self.random_path()) + self.random_path(), targets_keyids, meta_dir, version, expiration_date) + self.assertRaises(tuf.FormatError, signerlib.build_targets_file, + targets_dir, self.random_string(), meta_dir, version, expiration_date) + self.assertRaises((tuf.FormatError, tuf.Error), signerlib.build_targets_file, + targets_dir, targets_keyids, self.random_path(), version, expiration_date) + self.assertRaises((tuf.FormatError, tuf.Error), signerlib.build_targets_file, + targets_dir, targets_keyids, meta_dir, self.random_string(), expiration_date) + self.assertRaises((tuf.FormatError, tuf.Error), signerlib.build_targets_file, + targets_dir, targets_keyids, meta_dir, version, self.random_string()) # RESTORE tuf.repo.keystore.get_key = original_get_key @@ -573,6 +600,8 @@ def test_6_generate_release_metadata(self): # SETUP original_get_key = tuf.repo.keystore.get_key + version = 8 + expiration_date = '1985-10-26 01:20:00 UTC' # Create root.txt and targets.txt as described above. meta_dir = self._create_root_and_targets_meta_files() @@ -580,7 +609,8 @@ def test_6_generate_release_metadata(self): # TESTS # Test: Run generate_release_metadata(). - release_meta = signerlib.generate_release_metadata(meta_dir) + release_meta = signerlib.generate_release_metadata(meta_dir, + version, expiration_date) # Verify that created metadata dictionary corresponds to # SIGNABLE_SCHEMA and its 'signed' value to RELEASE_SCHEMA. @@ -589,9 +619,14 @@ def test_6_generate_release_metadata(self): # Test: exceptions. self.assertRaises(tuf.Error, signerlib.generate_release_metadata, - self.random_path()) + self.random_path(), version, expiration_date) self.assertRaises(tuf.FormatError, signerlib.generate_release_metadata, - ['junk']) + ['junk'], version, expiration_date) + self.assertRaises(tuf.Error, signerlib.generate_release_metadata, + meta_dir, self.random_string(), expiration_date) + self.assertRaises(tuf.Error, signerlib.generate_release_metadata, + meta_dir, version, self.random_string()) + # RESTORE tuf.repo.keystore.get_key = original_get_key @@ -607,6 +642,8 @@ def test_7_build_release_file(self): # SETUP original_get_key = tuf.repo.keystore.get_key + version = 8 + expiration_date = '1985-10-26 01:20:00 UTC' # Create root.txt and targets.txt as described above. Also, get signed # release metadata to compare it with the content of the file @@ -617,7 +654,8 @@ def test_7_build_release_file(self): # TESTS # Test: normal case. - release_filepath = signerlib.build_release_file(release_keyids, meta_dir) + release_filepath = signerlib.build_release_file(release_keyids, meta_dir, + version, expiration_date) # Check if 'release.txt' file was created in metadata directory. self.assertTrue(os.path.exists(release_filepath)) @@ -628,9 +666,14 @@ def test_7_build_release_file(self): # Test: exceptions. self.assertRaises(tuf.Error, signerlib.build_release_file, release_keyids, - self.random_path()) + self.random_path(), version, expiration_date) self.assertRaises(tuf.FormatError, signerlib.build_release_file, - self.random_string(), meta_dir) + self.random_string(), meta_dir, version, expiration_date) + self.assertRaises(tuf.FormatError, signerlib.build_release_file, + release_keyids, meta_dir, self.random_string(), + expiration_date) + self.assertRaises(tuf.FormatError, signerlib.build_release_file, + release_keyids, meta_dir, version, self.random_string()) # RESTORE tuf.repo.keystore.get_key = original_get_key @@ -646,12 +689,15 @@ def test_8_generate_timestamp_metadata(self): # SETUP original_get_key = tuf.repo.keystore.get_key + version = 8 + expiration_date = '1985-10-26 01:20:00 UTC' generate_timestamp_meta = signerlib.generate_timestamp_metadata # Create release metadata and create 'release.txt' file. junk, release_keyids, meta_dir = self._get_role_info('release') - signerlib.build_release_file(release_keyids, meta_dir) + signerlib.build_release_file(release_keyids, meta_dir, version, + expiration_date) release_filepath = os.path.join(meta_dir, 'release.txt') # To test compression we need to create compressed 'release.txt'. @@ -665,21 +711,28 @@ def test_8_generate_timestamp_metadata(self): # TESTS # Test: normal case. - timestamp_meta = generate_timestamp_meta(release_filepath) + timestamp_meta = generate_timestamp_meta(release_filepath, version, + expiration_date) # Verify metadata formats. self.assertTrue(formats.SIGNABLE_SCHEMA.matches(timestamp_meta)) self.assertTrue(formats.TIMESTAMP_SCHEMA.matches(timestamp_meta['signed'])) # Test: normal case (with compression). - timestamp_meta = generate_timestamp_meta(release_filepath+'.gz') + timestamp_meta = generate_timestamp_meta(release_filepath+'.gz', version, + expiration_date) # Verify metadata formats. self.assertTrue(formats.SIGNABLE_SCHEMA.matches(timestamp_meta)) self.assertTrue(formats.TIMESTAMP_SCHEMA.matches(timestamp_meta['signed'])) # Test: invalid path. - self.assertRaises(tuf.Error, generate_timestamp_meta, self.random_path()) + self.assertRaises(tuf.Error, generate_timestamp_meta, self.random_path(), + version, expiration_date) + self.assertRaises(tuf.FormatError, generate_timestamp_meta, release_filepath, + self.random_string(), expiration_date) + self.assertRaises(tuf.FormatError, generate_timestamp_meta, release_filepath, + version, self.random_string()) # RESTORE tuf.repo.keystore.get_key = original_get_key @@ -695,6 +748,8 @@ def test_9_build_timestamp_file(self): # SETUP original_get_key = tuf.repo.keystore.get_key + version = 8 + expiration_date = '1985-10-26 01:20:00 UTC' # Create all necessary files and metadata i.e. signed timestamp # metadata, timestamp keyids, 'release.txt', 'root.txt', 'targets.txt', @@ -708,7 +763,9 @@ def test_9_build_timestamp_file(self): # TESTS # Test: normal case. - timestamp_filepath = signerlib.build_timestamp_file(timestamp_keyids, meta_dir) + timestamp_filepath = signerlib.build_timestamp_file(timestamp_keyids, + meta_dir, version, + expiration_date) # Check if 'timestamp.txt' file was created in metadata directory. self.assertTrue(os.path.exists(timestamp_filepath)) @@ -719,9 +776,15 @@ def test_9_build_timestamp_file(self): # Test: try bogus parameters. self.assertRaises(tuf.Error, signerlib.build_timestamp_file, - timestamp_keyids, self.random_path()) + timestamp_keyids, self.random_path(), version, + expiration_date) self.assertRaises(tuf.FormatError, signerlib.build_timestamp_file, - self.random_string(), meta_dir) + self.random_string(), meta_dir, version, expiration_date) + self.assertRaises(tuf.FormatError, signerlib.build_timestamp_file, + timestamp_keyids, meta_dir, self.random_string(), + expiration_date) + self.assertRaises(tuf.FormatError, signerlib.build_timestamp_file, + timestamp_keyids, meta_dir, version, self.random_string()) # RESTORE tuf.repo.keystore.get_key = original_get_key @@ -733,6 +796,8 @@ def test_9_get_target_keyids(self): # SETUP original_get_key = tuf.repo.keystore.get_key + version = 8 + expiration_date = '1985-10-26 01:20:00 UTC' # Create metadata directory and targets metadata file. meta_dir = self._create_root_and_targets_meta_files() @@ -750,7 +815,8 @@ def test_9_get_target_keyids(self): # TESTS # Test: normal case. targets_filepath = signerlib.build_targets_file(targets_dir, - targets_keyids, meta_dir) + targets_keyids, meta_dir, + version, expiration_date) # Check existence of the file and validity of it's content. self.assertTrue(os.path.exists(targets_filepath)) @@ -782,6 +848,11 @@ def _create_root_and_targets_meta_files(self, repo_dir=None): build_targets_file() """ + # The version number and expiration date for the root and target + # metadata created. + version = 8 + expiration_date = '1985-10-26 01:20:00 UTC' + if not repo_dir: # Create repository directory. repo_dir = self.make_temp_directory() @@ -793,14 +864,15 @@ def _create_root_and_targets_meta_files(self, repo_dir=None): # Create root.txt. junk, root_keyids, repo_dir, config_path = \ self._get_role_info('root', directory=repo_dir) - signerlib.build_root_file(config_path, root_keyids, meta_dir) + signerlib.build_root_file(config_path, root_keyids, meta_dir, version) self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt'))) # Create targets.txt. junk, targets_keyids, repo_dir, target_files = \ self._get_role_info('targets', directory=repo_dir) path_to_targets = os.path.join(repo_dir, 'targets') - signerlib.build_targets_file(path_to_targets, targets_keyids, meta_dir) + signerlib.build_targets_file(path_to_targets, targets_keyids, meta_dir, + version, expiration_date) self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt'))) return meta_dir @@ -824,6 +896,11 @@ def _get_role_info(self, role, directory=None): Tuple (role's metadata(not signed), role's keyids, directory, optional) """ + + # The version number and expiration date for metadata files created. + version = 8 + expiration_date = '1985-10-26 01:20:00 UTC' + if not directory: # Create a temp directory to hold a config file. @@ -842,7 +919,7 @@ def _get_role_info(self, role, directory=None): tuf.repo.keystore.get_key = self.get_keystore_key # Create root metadata. - root_meta = signerlib.generate_root_metadata(config_path) + root_meta = signerlib.generate_root_metadata(config_path, version) return root_meta, role_keyids, directory, config_path elif role == 'targets': @@ -857,26 +934,31 @@ def _get_role_info(self, role, directory=None): # Run the 'signerlib.generate_targets_metadata'. Test its return value. # Its return value should correspond to tuf.formats.SIGNABLE_SCHEMA - targets_meta = signerlib.generate_targets_metadata(repo_dir, - target_files) + targets_meta = signerlib.generate_targets_metadata(repo_dir, target_files, + version, + expiration_date) return targets_meta, role_keyids, repo_dir, target_files elif role == 'release': # Generate 'root.txt' and 'targets.txt' with targets directory in # the repository containing files and directories. meta_dir = self._create_root_and_targets_meta_files() - release_meta = signerlib.generate_release_metadata(meta_dir) + release_meta = signerlib.generate_release_metadata(meta_dir, version, + expiration_date) return release_meta, role_keyids, meta_dir elif role == 'timestamp': # Generate 'release.txt' which includes creation of 'root.txt', # 'targets.txt' and target files. junk, release_keyids, meta_dir = self._get_role_info('release') - signerlib.build_release_file(release_keyids, meta_dir) + signerlib.build_release_file(release_keyids, meta_dir, version, + expiration_date) release_filepath = os.path.join(meta_dir, 'release.txt') # Generate timestamp metadata. - timestamp_meta = signerlib.generate_timestamp_metadata(release_filepath) + timestamp_meta = signerlib.generate_timestamp_metadata(release_filepath, + version, + expiration_date) return timestamp_meta, role_keyids, meta_dir else: diff --git a/tuf/tests/test_updater.py b/tuf/tests/test_updater.py index 173df52f..0951e6ff 100755 --- a/tuf/tests/test_updater.py +++ b/tuf/tests/test_updater.py @@ -727,17 +727,20 @@ def test_2__delete_metadata(self): def test_2__ensure_not_expired(self): - # This test will verify that nothing is raised when a metadata file - # has future expiration date, and raises 'tuf.ExpiredMetadataError' - # when metadata is actually expired. + # This test condition will verify that nothing is raised when a metadata + # file has a future expiration date. self.Repository._ensure_not_expired('root') + + # 'tuf.ExpiredMetadataError' should be raised in this next test condition, + # because the expiration_date has expired by 10 seconds. expires = tuf.formats.format_time(time.time() - 10) self.Repository.metadata['current']['root']['expires'] = expires + + # Ensure the 'expires' field of the root file is properly formatted. self.assertTrue(tuf.formats.ROOT_SCHEMA.matches(self.Repository.metadata\ ['current']['root'])) self.assertRaises(tuf.ExpiredMetadataError, - self.Repository._ensure_not_expired, - 'root') + self.Repository._ensure_not_expired, 'root')