python-tuf/tests/unit/test_signerlib.py

986 lines
35 KiB
Python
Executable file

"""
<Program Name>
test_signerlib.py
<Author>
Konstantin Andrianov
<Started>
September 6, 2012
<Copyright>
See LICENSE for licensing information.
<Purpose>
Test_signerlib.py provides collection of methods that tries to test all the
units (methods) of the module under test.
This unittest module requires setting of rsa keys, keyids and such.
There is a method in unittest_toolbox.Modified_TestCase class
'bind_keys_to_roles()'. This method will set dictionaries
'top_level_role_info' and 'rsa_keystore'.
'top_level_role_info' corresponds to ROLEDICT_SCHEMA and it looks like this:
{'rolename': {'keyids': ['34345df32093bd12...'], 'threshold': 1}, ...}
'rsa_keystore' looks like this: {keyid : { -- RSAKEY_SCHEMA --}, ... } or
{keyid : {'keytype': 'rsa', 'keyid': keyid,
'keyval': {'public': 'PUBLIC KEY',
'private ': 'PRIVATE KEY'}}, ... }
unittest_toolbox module was created to provide additional testing tools for
tuf's modules. For more info see unittest_toolbox.py.
<Methodology>
Unittests must follow a specific structure i.e. independent methods should
be tested prior to dependent methods. More accurately: least dependent methods
are tested before most dependent methods. There is no reason to rewrite or
construct other methods that replicate already-tested methods solely for
testing purposes. This is possible because 'unittest.TestCase' class guarantees
the order of unit tests. So that, 'test_something_A' method would be tested
before 'test_something_B'. To ensure the structure a number will be placed
after 'test' and before methods name like so 'test_1_check_directory'. The
number is sort of a measure of dependence, where 1 is less dependent than 2.
"""
import os
import tempfile
import filecmp
import shutil
import ConfigParser
import gzip
import logging
import unittest
import tuf
import tuf.log
import tuf.util
import tuf.formats as formats
import tuf.repo.signerlib as signerlib
import tuf.repo.keystore
import tuf.tests.unittest_toolbox as unittest_toolbox
logger = logging.getLogger('tuf.test_signerlib')
# 'unittest_toolbox.Modified_TestCase' is too long, I'll set it to 'unit_tbox'.
unit_tbox = unittest_toolbox.Modified_TestCase
class TestSignerlib(unit_tbox):
def setUp(self):
unit_tbox.setUp(self)
def tearDown(self):
unit_tbox.tearDown(self)
# Test methods.
def test_1_get_metadata_filenames(self):
# SETUP
metadata_dir = self.make_temp_directory()
empty_dir = ''
def _get_metadata_filenames(test_metadata_dir):
filenames = signerlib.get_metadata_filenames(test_metadata_dir)
if test_metadata_dir is None:
test_metadata_dir = '.'
# Check if a dictionary instance with 4 mappings is returned.
self.assertTrue(isinstance(filenames, dict))
self.assertFalse(not filenames, 'Empty dictionary returned.')
self.assertEqual(len(filenames), 4)
# Check if all the keys in 'filenames' dictionary
# correspond to 'role_list' items i.e. all top level
# roles are include in the 'filenames' with their
# appropriate paths as values.
for role in unit_tbox.role_list:
value_at_role = os.path.join(test_metadata_dir, role+'.txt')
self.assertTrue(role in filenames)
self.assertEqual(filenames[role], value_at_role)
# Run _get_metadata_filenames(arg) trying different arguments.
self.assertRaises(tuf.FormatError, signerlib.get_metadata_filenames, 123)
_get_metadata_filenames(metadata_dir)
_get_metadata_filenames(empty_dir)
def test_1_get_metadata_file_info(self):
# SETUP
temp_file_path = self.make_temp_data_file()
rand_str = self.random_string()
# TESTS
# Test: improper arguments that should raise exceptions.
self.assertRaises(tuf.Error, signerlib.get_metadata_file_info, '')
self.assertRaises(tuf.FormatError, signerlib.get_metadata_file_info,
123)
self.assertRaises(tuf.FormatError, signerlib.get_metadata_file_info,
{rand_str: rand_str})
self.assertRaises(tuf.FormatError, signerlib.get_metadata_file_info,
[rand_str, rand_str])
# Make sure the format return by 'get_metadata_file_info'
# matches tuf.formats.FILEINFO_SCHEMA.
file_info = signerlib.get_metadata_file_info(temp_file_path)
self.assertTrue(formats.FILEINFO_SCHEMA.matches(file_info))
def test_1_generate_and_save_rsa_key(self):
"""
generate_and_save_rsa_key() is independent from all the other methods in
signerlib. In order to test this method all we need is to create a temp
directory and a sample password.
"""
# SETUP
keystore_dir = self.make_temp_directory()
password = self.random_string()
# TESTS
# Test: Run generate_and_save_rsa_key().
rsakey = signerlib.generate_and_save_rsa_key(keystore_dir, password)
self.assertTrue(formats.RSAKEY_SCHEMA.matches(rsakey))
# Test: Check if rsa key file was created.
key_path = os.path.join(keystore_dir, rsakey['keyid']+'.key')
self.assertTrue(os.path.exists(key_path))
def test_1_read_config_file(self):
"""
A short test of 'read_config_file' method. Using a tuple
that contains config dictionary and a config file containing
the same dictionary, test if 'read_config_file' returns a
dictionary corresponding to the supplied config dictionary when
config file is passes.
"""
# SETUP
# 'base_config' is a tuple containing a config file path and
# a corresponding config dictionary. Note, make sure appropriate
# suffix is set. In our case it will be 'signerlib.CONFIG_FILENAME'.
base_config = self.make_temp_config_file(suffix=signerlib.CONFIG_FILENAME)
# TESTS
# Test: normal case.
self.assertTrue(signerlib.read_config_file(base_config[0]),
base_config[1])
# Test: Incorrect arguments.
self.assertRaises(tuf.FormatError, signerlib.read_config_file, 123)
self.assertRaises((tuf.Error, tuf.FormatError), signerlib.read_config_file,
'')
self.assertRaises((tuf.Error, tuf.FormatError), signerlib.read_config_file,
'junk/dir/'+self.random_string())
self.assertRaises(tuf.FormatError, signerlib.read_config_file,
[self.random_string()])
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.
# 'target_files' represents a list of relative target paths.
repo_dir, target_files = self.make_temp_directory_with_data_files()
# 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,
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,
self.random_string(), expiration_date,
repo_dir, target_files)
self.assertRaises(tuf.FormatError, generate_targets_meta,
repo_dir, self.random_string(),
repo_dir, target_files)
self.assertRaises(tuf.FormatError, generate_targets_meta,
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,
version, expiration_date,
self.random_path(), target_files)
def test_1_check_directory(self):
"""
Quick test to ensure that the method returns valid output.
"""
# SETUP
temp_dir, _junk = self.make_temp_directory_with_data_files()
rand_str = self.random_string()
# TESTS
# Test: normal case, check proper output.
self.assertEqual(signerlib.check_directory(temp_dir), temp_dir)
# Test: Incorrect arguments.
self.assertRaises(tuf.FormatError, signerlib.check_directory, 1234)
self.assertRaises(tuf.FormatError, signerlib.check_directory, [rand_str])
self.assertRaises(tuf.FormatError, signerlib.check_directory,
{rand_str: rand_str})
self.assertRaises(tuf.Error, signerlib.check_directory, self.random_path())
def test_1_write_metadata_file(self):
# SETUP
# Create temp directory to be prevent any relative path discrepancies.
meta_dir = self.make_temp_directory()
# Create a temp file to store 'metadata' info in.
meta_file = self.make_temp_file(directory=meta_dir)
# Use valid input for json obj.
signable_dict = {'signatures':[], 'signed':{'role':'info'}}
# TESTS
# Test: normal case.
signerlib.write_metadata_file(signable_dict, meta_file)
# Extract the content of the temp file.
stored_signable_dict = tuf.util.load_json_file(meta_file)
# Check if object stored in the file corresponds to SIGNABLE_SCHEMA.
self.assertTrue(formats.SIGNABLE_SCHEMA.matches(stored_signable_dict))
# Does original dictionary 'signable_dict' matches dictionary retrieved
# from the file - 'stored_signable_dict'?
self.assertEqual(signable_dict, stored_signable_dict)
# Test: Incorrect arguments.
self.assertRaises(tuf.FormatError, signerlib.write_metadata_file,'','')
self.assertRaises(tuf.FormatError, signerlib.write_metadata_file,
[self.random_string()], meta_file)
self.assertRaises(tuf.FormatError, signerlib.write_metadata_file,
signable_dict, [self.random_string()])
self.assertRaises(tuf.Error, signerlib.write_metadata_file, signable_dict,
self.random_path())
self.assertRaises(tuf.FormatError, signerlib.write_metadata_file,
{self.random_string(): self.random_string()},
self.random_path())
def test_2_build_config_file(self):
"""
This method tests build_config_file().
Previously tested signerlib's read_config_file() is used here.
"""
# SETUP
# Declare timeout.
days = 365 # number of days
# Make a temp directory for config file.
config_dir = self.make_temp_directory()
# For 'role_info' argument we going to use 'self.top_level_role_info'
# dictionary. There is more info in the beginning of this test
# module, also in the test.unittest_toolbox module.
roledict_info = self.top_level_role_info
# TESTS
# Test: normal case.
# Run build_config_file(). The method is expected to return file
# path of the config file. We'll compare it to 'roledict_info'.
build_config = signerlib.build_config_file
config_path = build_config(config_file_directory=config_dir,
timeout=days, role_info=roledict_info)
# Check if 'config_path' directory exists.
self.assertTrue(os.path.exists(config_path))
# Using 'signerlib.read_config_file' method extract config dictionary
# that was stored.
config_dict = signerlib.read_config_file(config_path)
# Remove 'expiration' key from the extracted config dictionary, since
# initial role dictionary does not have this field.
del config_dict['expiration']
# Compare the initial dictionary 'roledict_info' with extracted
# dictionary 'config_dict'. They have to match.
self.assertTrue(config_dict, roledict_info)
# Test: exceptions on bogus arguments.
self.assertRaises(tuf.Error, signerlib.build_config_file,
self.random_path(), 365, roledict_info)
self.assertRaises(tuf.FormatError, signerlib.build_config_file,
config_dir, -1, roledict_info)
self.assertRaises(tuf.FormatError, signerlib.build_config_file,
config_dir, 365, self.directory_dictionary)
def test_3_generate_root_metadata(self):
"""
test_3_build_root_metadata() is based on two other signerlib methods
i.e. build_config_file() and read_config_file(). Hence, 3rd level.
"""
# 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()
# Create config file using previously tested build_config_file().
config_path = build_config(config_dir, 365, self.top_level_role_info)
# Create a config file without a 'targets' role section.
notargets_conf_dir = self.make_temp_directory()
saved_targets_role = self.top_level_role_info['targets']
del self.top_level_role_info['targets']
notargets_conf_path = build_config(notargets_conf_dir, 365,
self.top_level_role_info)
# Restore top_level_role_info to initial state.
self.top_level_role_info['targets'] = saved_targets_role
# TESTS
# Test: What if keystore is not set up?
self.assertRaises(tuf.UnknownKeyError, signerlib.generate_root_metadata,
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, 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, version)
self.assertRaises(tuf.Error, signerlib.generate_root_metadata, '', version)
self.assertRaises(tuf.Error, signerlib.generate_root_metadata,
self.random_string(), version)
self.assertRaises(tuf.Error, signerlib.generate_root_metadata,
{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
def test_4_sign_metadata(self):
"""
test_4_sign_metadata() will require us to create metadata using one of
the generate_role_metadata() and use monkey patched keystore's get_key().
"""
# SETUP.
original_get_key = tuf.repo.keystore.get_key
for role in ['root', 'targets']:
role_info = self._get_role_info(role)
filename = role+'.txt'
# TESTS
# Test: normal case.
signable = signerlib.sign_metadata(role_info[0], role_info[1],
filename)
# Check if signable is returned.
self.assertTrue(formats.SIGNABLE_SCHEMA.matches(signable))
# Test: Incorrect arguments.
self.assertRaises(tuf.FormatError, signerlib.sign_metadata,
self.random_string(), role_info[1], filename)
self.assertRaises(tuf.FormatError, signerlib.sign_metadata,
role_info[0], 12345, filename)
# Test: Verifying 'keytype' value, once is sufficient.
if role == 'root':
# Alter 'keytype' value of the rsa key. Restore it after.
for keyid in role_info[1]:
key = self.get_keystore_key(keyid)
key['keytype'] = 'unknown_type'
self.assertRaises(tuf.Error, signerlib.sign_metadata, role_info[0],
role_info[1], filename)
# Restoring the initial state of rsa_keystore.
for keyid in role_info[1]:
key = self.get_keystore_key(keyid)
key['keytype'] = 'rsa'
# RESTORE
tuf.repo.keystore.get_key = original_get_key
def test_5_build_root_file(self):
"""
test_5_build_root_file() relies on previously tested signerlib's
generate_root_metadata(), sign_metadata() and write_metadata_file().
build_root_file() basically joins these methods together to create
root.txt.
Test Outline: Get signed metadata and other info of a root role.
'root_meta' is a tuple - see _get_role_meta() and _get_signed_role_info().
Run build_root_file() with created parameters 'config_path', 'root_keyids'
and 'meta_dir'. Verify existence of the created directory. Extract
content of the file and verify that it matches original 'signed_root_meta'
dictionary. Test various bogus parameters.
"""
# 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]
config_path = root_info[3]
meta_dir = root_info[2] # Reuse config's directory.
# TESTS
# Test: normal case.
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))
file_content = tuf.util.load_json_file(root_filepath)
self.assertTrue(tuf.formats.SIGNABLE_SCHEMA.matches(file_content))
root_metadata = file_content['signed']
self.assertTrue(tuf.formats.ROOT_SCHEMA.matches(root_metadata))
# Test: various exceptions.
self.assertRaises(tuf.Error, signerlib.build_root_file,
self.random_path(), root_keyids, meta_dir, version)
self.assertRaises(tuf.FormatError, signerlib.build_root_file,
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
def test_5_build_targets_file(self):
"""
test_5_build_targets_file() relies on previously tested signerlib's
generate_targets_metadata(), sign_metadata() and write_metadata_file().
build_targets_file() basically joins these methods together to create
targets.txt.
"""
# 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,
# list of target files.
targets_keyids = targets_info[1]
repo_dir = targets_info[2]
meta_dir = os.path.join(repo_dir, 'metadata')
os.mkdir(meta_dir)
targets_dir = os.path.join(repo_dir, 'targets')
# TESTS
# Test: normal case.
targets_filepath = signerlib.build_targets_file([targets_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))
file_content = tuf.util.load_json_file(targets_filepath)
self.assertTrue(tuf.formats.SIGNABLE_SCHEMA.matches(file_content))
targets_metadata = file_content['signed']
self.assertTrue(tuf.formats.TARGETS_SCHEMA.matches(targets_metadata))
# Test: various exceptions.
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
def test_6_generate_release_metadata(self):
"""
test_6_generate_release_metadata() uses previously tested
singnerlib's build_root_file(), build_targets_file()
and get_metadata_file_info. In order to use generate_release_metadata()
we need to have root.txt and targets.txt in the metadata directory,
plus we need to have targets directory (with target files/directories).
"""
# 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()
# TESTS
# Test: Run generate_release_metadata().
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.
self.assertTrue(formats.SIGNABLE_SCHEMA.matches(release_meta))
self.assertTrue(formats.RELEASE_SCHEMA.matches(release_meta['signed']))
# Test: exceptions.
self.assertRaises(tuf.Error, signerlib.generate_release_metadata,
self.random_path(), version, expiration_date)
self.assertRaises(tuf.FormatError, signerlib.generate_release_metadata,
['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
def test_7_build_release_file(self):
"""
test_7_build_release_file() uses previously tested
generate_release_metadata().
"""
# 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
signed_release_meta, release_info = self._get_signed_role_info('release')
meta_dir = release_info[2]
release_keyids = release_info[1]
# TESTS
# Test: normal case.
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))
file_content = tuf.util.load_json_file(release_filepath)
self.assertTrue(tuf.formats.SIGNABLE_SCHEMA.matches(file_content))
release_metadata = file_content['signed']
self.assertTrue(tuf.formats.RELEASE_SCHEMA.matches(release_metadata))
# Test: exceptions.
self.assertRaises(tuf.Error, signerlib.build_release_file, release_keyids,
self.random_path(), version, expiration_date)
self.assertRaises(tuf.FormatError, signerlib.build_release_file,
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
def test_8_generate_timestamp_metadata(self):
"""
test_8_generate_timestamp_metadata() uses previously tested
build_release_file()
"""
# 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, version,
expiration_date)
release_filepath = os.path.join(meta_dir, 'release.txt')
# To test compression we need to create compressed 'release.txt'.
# The 'release.txt' should exist at this point, compress it.
release_file = open(release_filepath, 'rb')
gzipped_release = open(release_filepath+'.gz', 'wb')
gzipped_release.writelines(release_file)
gzipped_release.close()
release_file.close()
# TESTS
# Test: normal case.
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', 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(),
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
def test_9_build_timestamp_file(self):
"""
test_9_build_timestamp_file() uses previously tested
generate_timestamp_metadata().
"""
# 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',
# target files, etc.
signed_timestamp_meta, timestamp_info = \
self._get_signed_role_info('timestamp')
timestamp_keyids = timestamp_info[1]
meta_dir = timestamp_info[2]
# TESTS
# Test: normal case.
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))
file_content = tuf.util.load_json_file(timestamp_filepath)
self.assertTrue(tuf.formats.SIGNABLE_SCHEMA.matches(file_content))
timestamp_metadata = file_content['signed']
self.assertTrue(tuf.formats.TIMESTAMP_SCHEMA.matches(timestamp_metadata))
# Test: try bogus parameters.
self.assertRaises(tuf.Error, signerlib.build_timestamp_file,
timestamp_keyids, self.random_path(), version,
expiration_date)
self.assertRaises(tuf.FormatError, signerlib.build_timestamp_file,
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
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()
signed_targets_meta, targets_info = self._get_signed_role_info('targets')
# 'targets_info' is a tuple that includes targets meta, repository dir,
# list of target files.
targets_keyids = targets_info[1]
repo_dir = targets_info[2]
meta_dir = os.path.join(repo_dir, 'metadata')
os.mkdir(meta_dir)
targets_dir = os.path.join(repo_dir, 'targets')
# TESTS
# Test: normal case.
targets_filepath = signerlib.build_targets_file([targets_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))
file_content = tuf.util.load_json_file(targets_filepath)
self.assertTrue(tuf.formats.SIGNABLE_SCHEMA.matches(file_content))
targets_metadata = file_content['signed']
self.assertTrue(tuf.formats.TARGETS_SCHEMA.matches(targets_metadata))
# TODO: Generate some delegation metadata files.
# Test: normal case.
_target_keyids = signerlib.get_target_keyids(meta_dir)
for keyid in targets_keyids:
self.assertTrue(keyid in _target_keyids['targets'])
# RESTORE
tuf.repo.keystore.get_key = original_get_key
# HELPER METHODS
# Call these non-test methods ONLY in methods that begin with 'test'.
def _create_root_and_targets_meta_files(self, repo_dir=None):
"""
This method generates temp root.txt and target.txt, it uses following
previously tested signerlib's methods:
build_root_file()
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()
# Create metadata directory.
meta_dir = os.path.join(repo_dir, 'metadata')
os.mkdir(meta_dir)
# 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, 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,
version, expiration_date)
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt')))
return meta_dir
def _get_role_info(self, role, directory=None):
"""
This method generates role's metadata dictionary, it uses previously
tested signerlib's methods. Note that at everything maintains the order.
Nothing that has not been tested previously is used in any of the
following conditions.
<Arguments>
directory:
Directory of a config file.
<Returns>
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.
directory = self.make_temp_directory()
# Get role's keyids.
role_keyids = self.top_level_role_info[role]['keyids']
if role == 'root':
# Create config file using previously tested build_config_file().
config_path = signerlib.build_config_file(directory, 365,
self.top_level_role_info)
# Patch keystore's get_key method.
tuf.repo.keystore.get_key = self.get_keystore_key
# Create root metadata.
root_meta = signerlib.generate_root_metadata(config_path, version)
return root_meta, role_keyids, directory, config_path
elif role == 'targets':
# Generate target files.
# 'repo_dir' represents repository base.
# 'target_files' represents a list of relative target paths.
repo_dir, target_files = \
self.make_temp_directory_with_data_files(directory=directory)
# Patch keystore's get_key method.
tuf.repo.keystore.get_key = self.get_keystore_key
# 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,
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, 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, version,
expiration_date)
release_filepath = os.path.join(meta_dir, 'release.txt')
# Generate timestamp metadata.
timestamp_meta = signerlib.generate_timestamp_metadata(release_filepath,
version,
expiration_date)
return timestamp_meta, role_keyids, meta_dir
else:
logger.warning('\nUnrecognized top-level role.')
def _get_signed_role_info(self, role, directory=None):
role_info = self._get_role_info(role, directory=directory)
filename = repr(role+'.txt')
# Try sign_metadata(), see if signable is returned.
signed_meta = signerlib.sign_metadata(role_info[0], role_info[1],
filename)
return signed_meta, role_info
def setUpModule():
# setUpModule() is called before any test cases run.
# Generate rsa keys and roles dictionary dictionaries.
unit_tbox.bind_keys_to_roles()
def tearDownModule():
# tearDownModule() is called after all the test cases have run.
unit_tbox.clear_toolbox()
tuf.repo.keystore.clear_keystore()
if __name__ == '__main__':
unittest.main()