mirror of
https://github.com/theupdateframework/python-tuf
synced 2026-05-24 10:08:28 +00:00
1492 lines
48 KiB
Python
Executable file
1492 lines
48 KiB
Python
Executable file
#!/usr/bin/env python
|
|
|
|
"""
|
|
<Program Name>
|
|
test_signercli.py
|
|
|
|
<Author>
|
|
Konstantin Andrianov
|
|
|
|
<Started>
|
|
September 20, 2012
|
|
|
|
<Copyright>
|
|
See LICENSE for licensing information.
|
|
|
|
<Purpose>
|
|
test_signercli.py provides collection of methods that tries to test all the
|
|
units (methods) of the module under test.
|
|
|
|
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 a measure of dependence, where 1
|
|
is less dependent than 2.
|
|
|
|
"""
|
|
|
|
|
|
import os
|
|
import logging
|
|
|
|
import tuf.formats
|
|
import tuf.util
|
|
import tuf.repo.keystore as keystore
|
|
import tuf.repo.signerlib as signerlib
|
|
# Module to test: signercli.py
|
|
import tuf.repo.signercli as signercli
|
|
# Helper module unittest_toolbox.py
|
|
import tuf.tests.unittest_toolbox as unittest_toolbox
|
|
|
|
|
|
logger = logging.getLogger('tuf')
|
|
|
|
# Disable all logging calls of level CRITICAL and below.
|
|
# Comment the line below to enable logging.
|
|
logging.disable(logging.CRITICAL)
|
|
|
|
# Populating 'rsa_keystore' and 'rsa_passwords' dictionaries.
|
|
# We will need them when creating keystore directories.
|
|
unittest_toolbox.Modified_TestCase.bind_keys_to_roles()
|
|
|
|
|
|
|
|
class TestSignercli(unittest_toolbox.Modified_TestCase):
|
|
|
|
|
|
original_prompt = signercli._prompt
|
|
signercli._prompt = original_prompt
|
|
|
|
original_get_metadata_directory = signercli._get_metadata_directory
|
|
signercli._get_metadata_directory = original_get_metadata_directory
|
|
|
|
original_get_password = signercli._get_password
|
|
signercli._get_password = original_get_password
|
|
|
|
# HELPER METHODS.
|
|
|
|
# Generic patch for signerlib._prompt().
|
|
def mock_prompt(self, output):
|
|
|
|
# Method to patch signercli._prompt().
|
|
def _mock_prompt(junk1, junk2, ret=output):
|
|
return ret
|
|
|
|
# Patch signercli._prompt()
|
|
signercli._prompt = _mock_prompt
|
|
|
|
|
|
|
|
# Patch signercli._get_metadata_directory()
|
|
def mock_get_metadata_directory(self, directory=None):
|
|
|
|
# Create method to patch signercli._get_metadata_directory()
|
|
def _mock_get_meta_dir(directory=directory):
|
|
|
|
# If directory was specified, return that directory.
|
|
if directory:
|
|
return directory
|
|
|
|
# Else create a temporary directory and return it.
|
|
else:
|
|
return self.make_temp_directory()
|
|
|
|
# Patch signercli._get_metadata_directory()
|
|
signercli._get_metadata_directory = _mock_get_meta_dir
|
|
|
|
|
|
|
|
# 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 _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
|
|
else:
|
|
error_msg = ('Prompt: '+'\''+msg[1:]+'\''+
|
|
' did not match any predefined mock prompts.')
|
|
self.fail(error_msg)
|
|
|
|
# Patch signercli._prompt().
|
|
signercli._prompt = _mock_prompt
|
|
|
|
|
|
|
|
# This mock method can be easily modified, by altering unittest_toolbox's
|
|
# dictionaries. For instance, if you want to modify password for certain
|
|
# keyid just save the existing 'self.rsa_passwords[keyid]' and set it
|
|
# to some other value like self.random_string(), after the test reassign
|
|
# the saved value back to 'self.rsa_passwords[keyid]'.
|
|
def get_passwords(self):
|
|
# Mock '_get_password' method.
|
|
def _mock_get_password(msg):
|
|
for role in self.role_list:
|
|
if msg.startswith('\nEnter the password for the '+role):
|
|
for keyid in self.top_level_role_info[role]['keyids']:
|
|
if msg.endswith(keyid+'): '):
|
|
return self.rsa_passwords[keyid]
|
|
error_msg = ('Prompt: '+'\''+msg+'\''+
|
|
' did not match any predefined mock prompts.')
|
|
raise tuf.Error(error_msg)
|
|
|
|
# Monkey patch '_prompt'.
|
|
signercli._get_password = _mock_get_password
|
|
|
|
|
|
|
|
|
|
|
|
# UNIT TESTS.
|
|
# If a unit test starts with test_# followed by two underscores,
|
|
# (test_#__method) this means that it's an internal method of signercli.
|
|
# For instance the unit test for signercli._get_password() would
|
|
# look like this: test_1__get_password, whereas unit test for
|
|
# signercli.change_password would look like this:
|
|
# test_3_change_password().
|
|
|
|
def test_1__check_directory(self):
|
|
|
|
# SETUP
|
|
directory = self.make_temp_directory()
|
|
no_such_dir = self.random_path()
|
|
|
|
|
|
# TESTS
|
|
# Test: normal case.
|
|
self.assertEqual(signercli._check_directory(directory), directory)
|
|
|
|
# Test: invalid directory.
|
|
self.assertRaises(tuf.RepositoryError, signercli._check_directory,
|
|
no_such_dir)
|
|
|
|
# Test: invalid directory type.
|
|
self.assertRaises(tuf.RepositoryError, signercli._check_directory,
|
|
[no_such_dir])
|
|
self.assertRaises(tuf.RepositoryError, signercli._check_directory,
|
|
1234)
|
|
self.assertRaises(tuf.RepositoryError, signercli._check_directory,
|
|
{'directory':no_such_dir})
|
|
|
|
|
|
|
|
|
|
|
|
def test_1__get_password(self):
|
|
|
|
# SETUP
|
|
original_getpass = signercli.getpass.getpass
|
|
|
|
password = self.random_string()
|
|
def _mock_getpass(junk1, junk2, pw=password):
|
|
return pw
|
|
|
|
# Patch getpass.getpass().
|
|
signercli.getpass.getpass = _mock_getpass
|
|
|
|
|
|
# Test: normal case.
|
|
self.assertEqual(signercli._get_password(), password)
|
|
|
|
# RESTORE
|
|
signercli.getpass.getpass = original_getpass
|
|
|
|
|
|
|
|
|
|
def test_2__get_metadata_directory(self):
|
|
|
|
# SETUP
|
|
original_prompt = signercli._prompt
|
|
|
|
meta_directory = self.make_temp_directory()
|
|
self.mock_prompt(meta_directory)
|
|
|
|
|
|
# TESTS
|
|
self.assertEqual(signercli._get_metadata_directory(), meta_directory)
|
|
self.assertTrue(os.path.exists(signercli._get_metadata_directory()))
|
|
self.mock_prompt(self.random_string())
|
|
self.assertRaises(tuf.RepositoryError, signercli._get_metadata_directory)
|
|
self.mock_prompt([self.random_string()])
|
|
self.assertRaises(tuf.RepositoryError, signercli._get_metadata_directory)
|
|
|
|
# RESTORE
|
|
signercli._prompt = original_prompt
|
|
|
|
|
|
|
|
|
|
def test_4__list_keyids(self):
|
|
|
|
# SETUP
|
|
original_get_metadata_directory = signercli._get_metadata_directory
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# The 'root.txt' and 'targets.txt' metadata files are
|
|
# needed for _list_keyids() to determine the roles
|
|
# associated with each keyid.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
repo_dir = self.make_temp_directory()
|
|
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build a config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Create the metadata directory needed by _list_keyids().
|
|
meta_dir = self.make_temp_directory()
|
|
|
|
# Patch signercli._get_metadata_directory().
|
|
self.mock_get_metadata_directory(directory=meta_dir)
|
|
|
|
# Patch signercli._prompt().
|
|
self.mock_prompt(config_filepath)
|
|
|
|
# Patch signercli._get_password().
|
|
self.get_passwords()
|
|
|
|
# Create the root metadata file that will be loaded by _list_keyids()
|
|
# to extract the keyids for the top-level roles.
|
|
signercli.make_root_metadata(keystore_dir)
|
|
|
|
# Create a directory containing target files.
|
|
targets_dir, targets_paths =\
|
|
self.make_temp_directory_with_data_files(directory=repo_dir)
|
|
|
|
# Mock method for signercli._prompt().
|
|
self.make_metadata_mock_prompts(targ_dir=targets_dir,
|
|
conf_path=config_filepath)
|
|
|
|
# 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)
|
|
|
|
|
|
# TESTS
|
|
# Test: normal case.
|
|
signercli._list_keyids(keystore_dir, meta_dir)
|
|
|
|
# Test: Improperly formatted 'root.txt' file.
|
|
root_filename = os.path.join(meta_dir, 'root.txt')
|
|
root_signable = tuf.util.load_json_file(root_filename)
|
|
saved_roles = root_signable['signed']['roles']
|
|
del root_signable['signed']['roles']
|
|
tuf.repo.signerlib.write_metadata_file(root_signable, root_filename)
|
|
|
|
self.assertRaises(tuf.RepositoryError,
|
|
signercli._list_keyids, keystore_dir, meta_dir)
|
|
|
|
# Restore the properly formatted 'root.txt' file.
|
|
root_signable['signed']['roles'] = saved_roles
|
|
tuf.repo.signerlib.write_metadata_file(root_signable, root_filename)
|
|
|
|
# Test: Improperly formatted 'targets.txt' file.
|
|
targets_filename = os.path.join(meta_dir, 'targets.txt')
|
|
targets_signable = tuf.util.load_json_file(targets_filename)
|
|
saved_targets = targets_signable['signed']['targets']
|
|
del targets_signable['signed']['targets']
|
|
tuf.repo.signerlib.write_metadata_file(targets_signable, targets_filename)
|
|
|
|
self.assertRaises(tuf.RepositoryError,
|
|
signercli._list_keyids, keystore_dir, meta_dir)
|
|
|
|
# Restore the properly formatted 'targets.txt' file.
|
|
targets_signable['signed']['targets'] = saved_targets
|
|
tuf.repo.signerlib.write_metadata_file(targets_signable, targets_filename)
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._prompt = original_prompt
|
|
signercli._get_metadata_directory = original_get_metadata_directory
|
|
|
|
|
|
|
|
def test_2__get_keyids(self):
|
|
|
|
# SETUP
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# Create a temp keystore directory.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
|
|
# List of keyids including keyword 'quit'.
|
|
keyids = ['quit'] + self.rsa_keyids
|
|
|
|
# Patching signercli._prompt()
|
|
def _mock_prompt(msg, junk):
|
|
|
|
# Pop 'keyids' everytime signercli._prompt() is called.
|
|
keyid = keyids.pop()
|
|
if keyid != 'quit':
|
|
get_password(keyid)
|
|
return keyid
|
|
|
|
signercli._prompt = _mock_prompt
|
|
|
|
# Patching signercli._get_password().
|
|
def get_password(keyid):
|
|
password = self.rsa_passwords[keyid]
|
|
def _mock_get_password(msg):
|
|
return password
|
|
|
|
signercli._get_password = _mock_get_password
|
|
|
|
|
|
# TESTS
|
|
# Test: normal case.
|
|
loaded_keyids = signercli._get_keyids(keystore_dir)
|
|
self.assertTrue(tuf.formats.KEYIDS_SCHEMA.matches(loaded_keyids))
|
|
|
|
# Check if all the keysids were loaded.
|
|
for keyid in self.rsa_keyids:
|
|
if keyid not in loaded_keyids:
|
|
msg = 'Could not load the keyid: '+repr(keyid)
|
|
self.fail(msg)
|
|
|
|
# Test: invalid password.
|
|
keyids = ['quit', self.rsa_keyids[0]]
|
|
saved_pw = self.rsa_passwords[keyid]
|
|
|
|
# Invalid password
|
|
self.rsa_passwords[self.rsa_keyids[0]] = self.random_string()
|
|
self.assertEqual(signercli._get_keyids(keystore_dir), [])
|
|
|
|
# Restore the password.
|
|
self.rsa_passwords[self.rsa_keyids[0]] = saved_pw
|
|
|
|
# Test: invalid keyid.
|
|
keyid = self.random_string()
|
|
keyids = ['quit', keyid]
|
|
|
|
# Create an invalid entry in the passwords dictionary.
|
|
self.rsa_passwords[keyid] = self.random_string()
|
|
self.assertEqual(signercli._get_keyids(keystore_dir), [])
|
|
|
|
# Restore passwords dictionary.
|
|
del self.rsa_passwords[keyid]
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._prompt = original_prompt
|
|
|
|
|
|
|
|
def test_2__get_all_config_keyids(self):
|
|
|
|
# SETUP
|
|
original_get_password = signercli._get_password
|
|
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build the config file needed by '_get_all_config_keyids.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Create a temp keystore directory.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
|
|
# 'sample_keyid' used to test invalid keyid.
|
|
sample_keyid = self.rsa_keyids[0]
|
|
|
|
# Patch signercli._get_password()
|
|
self.get_passwords()
|
|
|
|
|
|
# TESTS
|
|
# Test: an incorrect password.
|
|
saved_pw = self.rsa_passwords[sample_keyid]
|
|
self.rsa_passwords[sample_keyid] = self.random_string()
|
|
self.assertRaises(tuf.Error, signercli._get_all_config_keyids,
|
|
config_filepath, keystore_dir)
|
|
|
|
# Restore the password.
|
|
self.rsa_passwords[sample_keyid] = saved_pw
|
|
|
|
# Test: missing top-level role in the config file.
|
|
# Clear keystore's dictionaries.
|
|
keystore.clear_keystore()
|
|
|
|
# Remove a role from 'top_level_role_info' which is used to construct
|
|
# config file.
|
|
targets_holder = self.top_level_role_info['targets']
|
|
del self.top_level_role_info['targets']
|
|
|
|
# Build config file without 'targets' role.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
self.assertRaises(tuf.Error, signercli._get_all_config_keyids,
|
|
config_filepath, keystore_dir)
|
|
|
|
# Rebuild config file and 'top_level_role_info'.
|
|
self.top_level_role_info['targets'] = targets_holder
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Test: non-existing config file path.
|
|
keystore.clear_keystore()
|
|
self.assertRaises(tuf.Error, signercli._get_all_config_keyids,
|
|
self.random_path(), keystore_dir)
|
|
|
|
# Test: normal case.
|
|
keystore.clear_keystore()
|
|
signercli._get_all_config_keyids(config_filepath, keystore_dir)
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
|
|
|
|
|
|
|
|
def test_2__get_role_config_keyids(self):
|
|
|
|
# SETUP
|
|
original_get_password = signercli._get_password
|
|
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build a config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
# Create a temp keystore directory.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
|
|
# Patch '_get_password' method.
|
|
self.get_passwords()
|
|
|
|
|
|
# TESTS
|
|
for role in self.role_list:
|
|
# Test: normal cases.
|
|
keystore.clear_keystore()
|
|
signercli._get_role_config_keyids(config_filepath, keystore_dir, role)
|
|
|
|
# Test: incorrect passwords.
|
|
keystore.clear_keystore()
|
|
role_keyids = self.top_level_role_info[role]['keyids']
|
|
for keyid in role_keyids:
|
|
saved_pw = self.rsa_passwords[keyid]
|
|
self.rsa_passwords[keyid] = self.random_string()
|
|
self.assertRaises(tuf.Error, signercli._get_role_config_keyids,
|
|
config_filepath, keystore_dir, role)
|
|
|
|
# Restore the password.
|
|
self.rsa_passwords[keyid] = saved_pw
|
|
|
|
# Test: non-existing config file path.
|
|
keystore.clear_keystore()
|
|
self.assertRaises(tuf.Error, signercli._get_role_config_keyids,
|
|
self.random_path(), keystore_dir, 'release')
|
|
|
|
# Test: non-existing role.
|
|
keystore.clear_keystore()
|
|
self.assertRaises(tuf.Error, signercli._get_role_config_keyids,
|
|
config_filepath, keystore_dir, 'no_such_role')
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
|
|
|
|
|
|
|
|
def test_1__sign_and_write_metadata(self):
|
|
|
|
# SETUP
|
|
# Role to test.
|
|
role = 'root'
|
|
|
|
# Create temp directory.
|
|
temp_dir = self.make_temp_directory()
|
|
|
|
# File name.
|
|
filename = os.path.join(temp_dir, role+'.txt')
|
|
|
|
# Role's keyids.
|
|
keyids = self.top_level_role_info[role]['keyids']
|
|
|
|
# Create a temp keystore directory.
|
|
keystore_dir =\
|
|
self.create_temp_keystore_directory(keystore_dicts=True)
|
|
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Create role's metadata.
|
|
signable_meta = signerlib.generate_root_metadata(config_filepath)
|
|
|
|
|
|
# TESTS
|
|
# Test: normal case.
|
|
signercli._sign_and_write_metadata(signable_meta, keyids, filename)
|
|
|
|
# Verify that the root meta file was created.
|
|
self.assertTrue(os.path.exists(filename))
|
|
|
|
Errors = (tuf.Error, tuf.FormatError)
|
|
|
|
# Test: invalid metadata.
|
|
self.assertRaises(Errors, signercli._sign_and_write_metadata,
|
|
self.random_string(), keyids, filename)
|
|
|
|
# Test: invalid keyids
|
|
invalid_keyids = self.random_string()
|
|
self.assertRaises(Errors, signercli._sign_and_write_metadata,
|
|
signable_meta, invalid_keyids, filename)
|
|
|
|
# Test: invalid filename
|
|
self.assertRaises(Errors, signercli._sign_and_write_metadata,
|
|
signable_meta, invalid_keyids, True)
|
|
|
|
|
|
|
|
|
|
def test_4_change_password(self):
|
|
|
|
# SETUP
|
|
original_get_metadata_directory = signercli._get_metadata_directory
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# Create keystore and repo directories.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
repo_dir = self.make_temp_directory()
|
|
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build a config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Create a temp metadata directory.
|
|
meta_dir = self.make_temp_directory()
|
|
|
|
# Patch signercli._get_metadata_directory().
|
|
self.mock_get_metadata_directory(directory=meta_dir)
|
|
|
|
# Patch signercli._prompt().
|
|
self.mock_prompt(config_filepath)
|
|
|
|
# Patch '_get_password' method.
|
|
self.get_passwords()
|
|
|
|
signercli.make_root_metadata(keystore_dir)
|
|
|
|
# Create a directory containing target files.
|
|
targets_dir, targets_paths =\
|
|
self.make_temp_directory_with_data_files(directory=repo_dir)
|
|
|
|
# Mock method for signercli._prompt().
|
|
self.make_metadata_mock_prompts(targ_dir=targets_dir,
|
|
conf_path=config_filepath)
|
|
|
|
signercli.make_targets_metadata(keystore_dir)
|
|
|
|
test_keyid = self.rsa_keyids[0]
|
|
self.mock_prompt(test_keyid)
|
|
|
|
# Specify old password and create a new password.
|
|
old_password = self.rsa_passwords[test_keyid]
|
|
new_password = self.random_string()
|
|
|
|
# Mock method for signercli._get_password()
|
|
def _mock_get_password(msg, confirm=False, old_pw=old_password,
|
|
new_pw=new_password):
|
|
if msg.startswith('\nEnter the old password for the keyid: '):
|
|
return old_pw
|
|
else:
|
|
return new_pw
|
|
|
|
# Patch signercli._get_password.
|
|
signercli._get_password = _mock_get_password
|
|
|
|
|
|
# TESTS
|
|
# Test: normal case.
|
|
signercli.change_password(keystore_dir)
|
|
|
|
# Verify password change.
|
|
self.assertEqual(keystore._key_passwords[test_keyid], new_password)
|
|
|
|
# Test: non-existing keyid.
|
|
keystore.clear_keystore()
|
|
self.mock_prompt(self.random_string(15))
|
|
self.assertRaises(tuf.RepositoryError, signercli.change_password,
|
|
keystore_dir)
|
|
|
|
# Restore the prompt input to existing keyid.
|
|
self.mock_prompt(test_keyid)
|
|
|
|
# Test: non-existing old password.
|
|
keystore.clear_keystore()
|
|
old_password = self.random_string()
|
|
self.assertRaises(tuf.RepositoryError, signercli.change_password,
|
|
keystore_dir)
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._prompt = original_prompt
|
|
signercli._get_metadata_directory = original_get_metadata_directory
|
|
|
|
|
|
|
|
|
|
def test_2_generate_rsa_key(self):
|
|
|
|
# SETUP
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# Method to patch signercli._get_password()
|
|
def _mock_get_password(junk, confirm=False):
|
|
return self.random_string()
|
|
|
|
# Patch signercli._get_password()
|
|
signercli._get_password = _mock_get_password
|
|
|
|
# Create a temp keystore directory.
|
|
keystore_dir = self.make_temp_directory()
|
|
|
|
|
|
# TESTS
|
|
# Test: invalid rsa bits.
|
|
self.mock_prompt(1024)
|
|
self.assertRaises(tuf.RepositoryError, signercli.generate_rsa_key,
|
|
keystore_dir)
|
|
# Input appropriate number of rsa bits.
|
|
self.mock_prompt(3072)
|
|
|
|
# Test: normal case.
|
|
signercli.generate_rsa_key(keystore_dir)
|
|
|
|
# Was the key file added to the directory?
|
|
self.assertTrue(os.listdir(keystore_dir))
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._prompt = original_prompt
|
|
|
|
|
|
|
|
|
|
def test_4_dump_key(self):
|
|
|
|
# SETUP
|
|
original_get_metadata_directory = signercli._get_metadata_directory
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# Create keystore and repo directories.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
repo_dir = self.make_temp_directory()
|
|
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build a config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Create a temp metadata directory.
|
|
meta_dir = self.make_temp_directory()
|
|
|
|
# Patch signercli._get_metadata_directory().
|
|
self.mock_get_metadata_directory(directory=meta_dir)
|
|
|
|
# Patch signercli._get_password().
|
|
self.get_passwords()
|
|
|
|
# Patch signercli._prompt().
|
|
self.mock_prompt(config_filepath)
|
|
|
|
signercli.make_root_metadata(keystore_dir)
|
|
|
|
# Create a directory containing target files.
|
|
targets_dir, targets_paths =\
|
|
self.make_temp_directory_with_data_files(directory=repo_dir)
|
|
|
|
# Mock method for signercli._prompt().
|
|
self.make_metadata_mock_prompts(targ_dir=targets_dir,
|
|
conf_path=config_filepath)
|
|
|
|
signercli.make_targets_metadata(keystore_dir)
|
|
|
|
|
|
keyid = self.rsa_keyids[0]
|
|
password = self.rsa_passwords[keyid]
|
|
show_priv = 'private'
|
|
|
|
|
|
# Mock method for signercli._get_password().
|
|
def _mock_get_password(msg):
|
|
return password
|
|
|
|
# Mock method for signercli._prompt().
|
|
def _mock_prompt(msg, junk):
|
|
if msg.startswith('\nEnter the keyid'):
|
|
return keyid
|
|
else:
|
|
return show_priv
|
|
|
|
# Patch signercli._get_password().
|
|
signercli._get_password = _mock_get_password
|
|
|
|
# Patch signercli._prompt().
|
|
signercli._prompt = _mock_prompt
|
|
|
|
|
|
# TESTS
|
|
# Test: normal case.
|
|
signercli.dump_key(keystore_dir)
|
|
|
|
# Test: incorrect password.
|
|
saved_pw = password
|
|
password = self.random_string()
|
|
self.assertRaises(tuf.RepositoryError, signercli.dump_key,
|
|
keystore_dir)
|
|
|
|
# Restore the correct password.
|
|
password = saved_pw
|
|
|
|
# Test: non-existing keyid.
|
|
keyid = self.random_string()
|
|
self.assertRaises(tuf.RepositoryError, signercli.dump_key,
|
|
keystore_dir)
|
|
keyid = self.rsa_keyids[0]
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._prompt = original_prompt
|
|
signercli._get_metadata_directory = original_get_metadata_directory
|
|
|
|
|
|
|
|
|
|
def test_3_make_root_metadata(self):
|
|
|
|
# SETUP
|
|
original_get_metadata_directory = signercli._get_metadata_directory
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build a config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Create a temp metadata directory.
|
|
meta_dir = self.make_temp_directory()
|
|
|
|
# Patch signercli._get_metadata_directory().
|
|
self.mock_get_metadata_directory(directory=meta_dir)
|
|
|
|
# Patch signercli._prompt().
|
|
self.mock_prompt(config_filepath)
|
|
|
|
# Patch signercli._get_password().
|
|
self.get_passwords()
|
|
|
|
# Create keystore directory.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
|
|
|
|
# TESTS
|
|
# Test: normal case.
|
|
signercli.make_root_metadata(keystore_dir)
|
|
|
|
# Verify that the root metadata path was created.
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt')))
|
|
|
|
# Test: invalid config path.
|
|
# Clear keystore's dictionaries.
|
|
keystore.clear_keystore()
|
|
|
|
# Supply a non-existing path to signercli._prompt().
|
|
self.mock_prompt(self.random_path())
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_root_metadata,
|
|
keystore_dir)
|
|
|
|
# Re-patch signercli._prompt() with valid config path.
|
|
self.mock_prompt(config_filepath)
|
|
|
|
# Test: incorrect 'root' passwords.
|
|
# Clear keystore's dictionaries.
|
|
keystore.clear_keystore()
|
|
keyids = self.top_level_role_info['root']['keyids']
|
|
for keyid in keyids:
|
|
saved_pw = self.rsa_passwords[keyid]
|
|
self.rsa_passwords[keyid] = self.random_string()
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_root_metadata,
|
|
keystore_dir)
|
|
self.rsa_passwords[keyid] = saved_pw
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._prompt = original_prompt
|
|
signercli._get_metadata_directory = original_get_metadata_directory
|
|
|
|
|
|
|
|
|
|
def test_3_make_targets_metadata(self):
|
|
|
|
# SETUP
|
|
original_get_metadata_directory = signercli._get_metadata_directory
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# Create a temp repository and metadata directories.
|
|
repo_dir = self.make_temp_directory()
|
|
meta_dir = self.make_temp_directory(directory=repo_dir)
|
|
|
|
# Create a directory containing target files.
|
|
targets_dir, targets_paths =\
|
|
self.make_temp_directory_with_data_files(directory=repo_dir)
|
|
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build a config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Patch signercli._get_metadata_directory()
|
|
self.mock_get_metadata_directory(directory=meta_dir)
|
|
|
|
# Patch signercli._get_password(). Used in _get_role_config_keyids()
|
|
self.get_passwords()
|
|
|
|
# Create keystore directory.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
|
|
# Mock method for signercli._prompt().
|
|
self.make_metadata_mock_prompts(targ_dir=targets_dir,
|
|
conf_path=config_filepath)
|
|
|
|
|
|
# TESTS
|
|
# Test: normal case.
|
|
signercli.make_targets_metadata(keystore_dir)
|
|
|
|
# Verify that targets metadata file was created.
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt')))
|
|
|
|
# Test: invalid targets path.
|
|
# Clear keystore's dictionaries.
|
|
keystore.clear_keystore()
|
|
|
|
# Supply a non-existing targets directory.
|
|
self.make_metadata_mock_prompts(targ_dir=self.random_path(),
|
|
conf_path=config_filepath)
|
|
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)
|
|
|
|
# Test: invalid config path.
|
|
# Clear keystore's dictionaries.
|
|
keystore.clear_keystore()
|
|
|
|
# Supply a non-existing config path.
|
|
self.make_metadata_mock_prompts(targ_dir=targets_dir,
|
|
conf_path=self.random_path())
|
|
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)
|
|
|
|
# Test: incorrect 'targets' passwords.
|
|
# Clear keystore's dictionaries.
|
|
keystore.clear_keystore()
|
|
keyids = self.top_level_role_info['targets']['keyids']
|
|
for keyid in keyids:
|
|
saved_pw = self.rsa_passwords[keyid]
|
|
self.rsa_passwords[keyid] = self.random_string()
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_targets_metadata,
|
|
keystore_dir)
|
|
self.rsa_passwords[keyid] = saved_pw
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._prompt = original_prompt
|
|
signercli._get_metadata_directory = original_get_metadata_directory
|
|
|
|
|
|
|
|
|
|
def test_4_make_release_metadata(self):
|
|
|
|
# SETUP
|
|
original_get_metadata_directory = signercli._get_metadata_directory
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# In order to build release metadata file (release.txt),
|
|
# root and targets metadata files (root.txt, targets.txt)
|
|
# must exist in the metadata directory.
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build a config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Create a temp repository and metadata directories.
|
|
repo_dir = self.make_temp_directory()
|
|
meta_dir = self.make_temp_directory(repo_dir)
|
|
|
|
# Create a directory containing target files.
|
|
targets_dir, targets_paths = \
|
|
self.make_temp_directory_with_data_files(directory=repo_dir)
|
|
|
|
# Patch signercli._get_metadata_directory().
|
|
self.mock_get_metadata_directory(directory=meta_dir)
|
|
|
|
# Patch signercli._get_password(). Used in _get_role_config_keyids().
|
|
self.get_passwords()
|
|
|
|
# Create keystore directory.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
|
|
# Mock method for signercli._prompt().
|
|
self.make_metadata_mock_prompts(targ_dir=targets_dir,
|
|
conf_path=config_filepath)
|
|
|
|
|
|
# TESTS
|
|
# Test: no root.txt in the metadata dir.
|
|
signercli.make_targets_metadata(keystore_dir)
|
|
|
|
# Verify that 'tuf.RepositoryError' is raised due to a missing root.txt.
|
|
keystore.clear_keystore()
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt')))
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_release_metadata,
|
|
keystore_dir)
|
|
os.remove(os.path.join(meta_dir,'targets.txt'))
|
|
keystore.clear_keystore()
|
|
|
|
# Test: no targets.txt in the metadatadir.
|
|
signercli.make_root_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
|
|
# Verify that 'tuf.RepositoryError' is raised due to a missing targets.txt.
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt')))
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_release_metadata,
|
|
keystore_dir)
|
|
os.remove(os.path.join(meta_dir,'root.txt'))
|
|
keystore.clear_keystore()
|
|
|
|
# Test: normal case.
|
|
signercli.make_root_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
signercli.make_targets_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
signercli.make_release_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
|
|
# Verify if the root, targets and release meta files were created.
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt')))
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt')))
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'release.txt')))
|
|
|
|
# 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())
|
|
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)
|
|
|
|
# Test: incorrect 'release' passwords.
|
|
# Clear keystore's dictionaries.
|
|
keystore.clear_keystore()
|
|
keyids = self.top_level_role_info['release']['keyids']
|
|
for keyid in keyids:
|
|
saved_pw = self.rsa_passwords[keyid]
|
|
self.rsa_passwords[keyid] = self.random_string()
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_release_metadata,
|
|
keystore_dir)
|
|
self.rsa_passwords[keyid] = saved_pw
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._prompt = original_prompt
|
|
signercli._get_metadata_directory = original_get_metadata_directory
|
|
|
|
|
|
|
|
|
|
def test_5_make_timestamp_metadata(self):
|
|
|
|
# SETUP
|
|
original_get_metadata_directory = signercli._get_metadata_directory
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# 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.
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build a config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Create a temp repository and metadata directories.
|
|
repo_dir = self.make_temp_directory()
|
|
meta_dir = self.make_temp_directory(repo_dir)
|
|
|
|
# Create a directory containing target files.
|
|
targets_dir, targets_paths = \
|
|
self.make_temp_directory_with_data_files(directory=repo_dir)
|
|
|
|
# Patch signercli._get_metadata_directory().
|
|
self.mock_get_metadata_directory(directory=meta_dir)
|
|
|
|
# Patch signercli._get_password(). Used in _get_role_config_keyids().
|
|
self.get_passwords()
|
|
|
|
# Create keystore directory.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
|
|
# Mock method for signercli._prompt().
|
|
self.make_metadata_mock_prompts(targ_dir=targets_dir,
|
|
conf_path=config_filepath)
|
|
|
|
|
|
# TESTS
|
|
# Test: no root.txt in the metadata dir.
|
|
signercli.make_targets_metadata(keystore_dir)
|
|
|
|
# Verify if the targets metadata file was created.
|
|
keystore.clear_keystore()
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt')))
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_timestamp_metadata,
|
|
keystore_dir)
|
|
os.remove(os.path.join(meta_dir,'targets.txt'))
|
|
keystore.clear_keystore()
|
|
|
|
# Test: no targets.txt in the metadatadir.
|
|
signercli.make_root_metadata(keystore_dir)
|
|
|
|
# Verify if the root metadata file was created.
|
|
keystore.clear_keystore()
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt')))
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_timestamp_metadata,
|
|
keystore_dir)
|
|
os.remove(os.path.join(meta_dir,'root.txt'))
|
|
keystore.clear_keystore()
|
|
|
|
# Test: no release.txt in the metadatadir.
|
|
signercli.make_root_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
signercli.make_targets_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
|
|
# Verify that 'tuf.Repository' is raised due to a missing release.txt.
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt')))
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt')))
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_timestamp_metadata,
|
|
keystore_dir)
|
|
os.remove(os.path.join(meta_dir,'root.txt'))
|
|
os.remove(os.path.join(meta_dir,'targets.txt'))
|
|
keystore.clear_keystore()
|
|
|
|
# Test: normal case.
|
|
signercli.make_root_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
signercli.make_targets_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
signercli.make_release_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
signercli.make_timestamp_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
|
|
# Verify if the root, targets and release metadata files were created.
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt')))
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt')))
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'release.txt')))
|
|
self.assertTrue(os.path.exists(os.path.join(meta_dir, 'timestamp.txt')))
|
|
|
|
# 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())
|
|
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)
|
|
|
|
# Test: incorrect 'release' passwords.
|
|
|
|
# Clear keystore's dictionaries.
|
|
keystore.clear_keystore()
|
|
|
|
keyids = self.top_level_role_info['release']['keyids']
|
|
for keyid in keyids:
|
|
saved_pw = self.rsa_passwords[keyid]
|
|
self.rsa_passwords[keyid] = self.random_string()
|
|
self.assertRaises(tuf.RepositoryError,
|
|
signercli.make_release_metadata, keystore_dir)
|
|
self.rsa_passwords[keyid] = saved_pw
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._get_metadata_directory = original_get_metadata_directory
|
|
|
|
|
|
|
|
|
|
def test_6_sign_metadata_file(self):
|
|
|
|
# SETUP
|
|
original_get_metadata_directory = signercli._get_metadata_directory
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# 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.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build a config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Create a temp repository and metadata directories.
|
|
repo_dir = self.make_temp_directory()
|
|
meta_dir = self.make_temp_directory(repo_dir)
|
|
|
|
# Create a directory containing target files.
|
|
targets_dir, targets_paths = \
|
|
self.make_temp_directory_with_data_files(directory=repo_dir)
|
|
|
|
# Patch signercli._get_metadata_directory().
|
|
self.mock_get_metadata_directory(directory=meta_dir)
|
|
|
|
# Patch signercli._get_password(). Used in _get_role_config_keyids().
|
|
self.get_passwords()
|
|
|
|
# Create keystore directory.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
|
|
# Mock method for signercli._prompt().
|
|
self.make_metadata_mock_prompts(targ_dir=targets_dir,
|
|
conf_path=config_filepath)
|
|
|
|
# Create metadata files.
|
|
signercli.make_root_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
signercli.make_targets_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
signercli.make_release_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
signercli.make_timestamp_metadata(keystore_dir)
|
|
keystore.clear_keystore()
|
|
|
|
# Verify if the root, targets and release meta files were created.
|
|
root_meta_filepath = os.path.join(meta_dir, 'root.txt')
|
|
targets_meta_filepath = os.path.join(meta_dir, 'targets.txt')
|
|
release_meta_filepath = os.path.join(meta_dir, 'release.txt')
|
|
timestamp_meta_filepath = os.path.join(meta_dir, 'timestamp.txt')
|
|
|
|
self.assertTrue(os.path.exists(root_meta_filepath))
|
|
self.assertTrue(os.path.exists(targets_meta_filepath))
|
|
self.assertTrue(os.path.exists(release_meta_filepath))
|
|
self.assertTrue(os.path.exists(timestamp_meta_filepath))
|
|
|
|
|
|
# Create a new RSA key, indicate metadata filename.
|
|
new_keyid = self.generate_rsakey()
|
|
meta_filename = targets_meta_filepath
|
|
|
|
# Create keystore directory. New key is untouched.
|
|
keystore_dir = self.create_temp_keystore_directory(keystore_dicts=True)
|
|
|
|
# List of keyids to be returned by _get_keyids()
|
|
signing_keyids = []
|
|
|
|
# Method to patch signercli._get_keyids()
|
|
def _mock_get_keyids(junk):
|
|
return signing_keyids
|
|
|
|
# Method to patch signercli._prompt().
|
|
def _mock_prompt(msg, junk):
|
|
return meta_filename
|
|
|
|
# Patch signercli._get_keyids()
|
|
signercli._get_keyids = _mock_get_keyids
|
|
|
|
# Patch signercli._prompt().
|
|
signercli._prompt = _mock_prompt
|
|
|
|
|
|
# TESTS
|
|
# Test: no loaded keyids.
|
|
self.assertRaises(tuf.RepositoryError,
|
|
signercli.sign_metadata_file, keystore_dir)
|
|
|
|
# Load new keyid.
|
|
signing_keyids = [new_keyid]
|
|
|
|
# Test: normal case.
|
|
signercli.sign_metadata_file(keystore_dir)
|
|
|
|
# Verify the change.
|
|
self.assertTrue(os.path.exists(targets_meta_filepath))
|
|
|
|
# Load targets metadata from the file ('targets.txt').
|
|
targets_metadata = tuf.util.load_json_file(targets_meta_filepath)
|
|
keyid_exists = False
|
|
for signature in targets_metadata['signatures']:
|
|
if new_keyid == signature['keyid']:
|
|
keyid_exists = True
|
|
break
|
|
|
|
self.assertTrue(keyid_exists)
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._prompt = original_prompt
|
|
signercli._get_metadata_directory = original_get_metadata_directory
|
|
|
|
|
|
|
|
|
|
def test_7_make_delegation(self):
|
|
|
|
# SETUP
|
|
original_get_metadata_directory = signercli._get_metadata_directory
|
|
original_prompt = signercli._prompt
|
|
original_get_password = signercli._get_password
|
|
|
|
# Create a temp repository and metadata directories.
|
|
repo_dir = self.make_temp_directory()
|
|
meta_dir = self.make_temp_directory(directory=repo_dir)
|
|
|
|
# Create targets directories.
|
|
targets_dir, targets_paths =\
|
|
self.make_temp_directory_with_data_files(directory=repo_dir)
|
|
delegated_targets_dir = os.path.join(targets_dir,'targets',
|
|
'delegated_level1')
|
|
|
|
# Assign parent role and name of the delegated role.
|
|
parent_role = 'targets'
|
|
delegated_role = 'delegated_role_1'
|
|
|
|
# Create couple new RSA keys for delegation levels 1 and 2.
|
|
new_keyid_1 = self.generate_rsakey()
|
|
new_keyid_2 = self.generate_rsakey()
|
|
|
|
# Create temp directory for config file.
|
|
config_dir = self.make_temp_directory()
|
|
|
|
# Build a config file.
|
|
config_filepath = signerlib.build_config_file(config_dir, 365,
|
|
self.top_level_role_info)
|
|
|
|
# Patch signercli._get_metadata_directory().
|
|
self.mock_get_metadata_directory(directory=meta_dir)
|
|
|
|
# Patch signercli._get_password(). Get passwords for parent's keyids.
|
|
self.get_passwords()
|
|
|
|
# Create keystore directory.
|
|
keystore_dir = self.create_temp_keystore_directory()
|
|
|
|
# Mock method for signercli._prompt() to generate targets.txt file.
|
|
self.make_metadata_mock_prompts(targ_dir=targets_dir,
|
|
conf_path=config_filepath)
|
|
|
|
# List of keyids to be returned by _get_keyids()
|
|
signing_keyids = [new_keyid_1]
|
|
|
|
# Load keystore.
|
|
load_keystore = keystore.load_keystore_from_keyfiles
|
|
|
|
# Build the root metadata file (root.txt).
|
|
signercli.make_root_metadata(keystore_dir)
|
|
|
|
# Build targets metadata file (targets.txt).
|
|
signercli.make_targets_metadata(keystore_dir)
|
|
|
|
# Clear kestore's dictionaries.
|
|
keystore.clear_keystore()
|
|
|
|
# Mock method for signercli._prompt().
|
|
def _mock_prompt(msg, junk):
|
|
if msg.startswith('\nThe directory entered'):
|
|
return delegated_targets_dir
|
|
elif msg.startswith('\nChoose and enter the parent'):
|
|
return parent_role
|
|
elif msg.startswith('\nEnter the delegated role\'s name: '):
|
|
return delegated_role
|
|
elif msg.startswith('Recursively walk the given directory? (Y)es/(N)o: '):
|
|
return 'N'
|
|
else:
|
|
error_msg = ('Prompt: '+'\''+msg+'\''+
|
|
' did not match any predefined mock prompts.')
|
|
self.fail(error_msg)
|
|
|
|
# Mock method for signercli._get_password().
|
|
def _mock_get_password(msg):
|
|
for keyid in self.rsa_keyids:
|
|
if msg.endswith('('+keyid+'): '):
|
|
return self.rsa_passwords[keyid]
|
|
|
|
# Method to patch signercli._get_keyids()
|
|
def _mock_get_keyids(junk):
|
|
if signing_keyids:
|
|
for keyid in signing_keyids:
|
|
password = self.rsa_passwords[keyid]
|
|
# Load the keyfile.
|
|
load_keystore(keystore_dir, [keyid], [password])
|
|
return signing_keyids
|
|
|
|
# Patch signercli._prompt().
|
|
signercli._prompt = _mock_prompt
|
|
|
|
# Patch signercli._get_password().
|
|
signercli._get_password = _mock_get_password
|
|
|
|
# Patch signercli._get_keyids().
|
|
signercli._get_keyids = _mock_get_keyids
|
|
|
|
|
|
# TESTS
|
|
# Test: invalid parent role.
|
|
# Assign a non-existing parent role.
|
|
parent_role = self.random_string()
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_delegation,
|
|
keystore_dir)
|
|
|
|
# Restore parent role.
|
|
parent_role = 'targets'
|
|
|
|
# Test: invalid password(s) for parent's keyids.
|
|
keystore.clear_keystore()
|
|
parent_keyids = self.top_level_role_info[parent_role]['keyids']
|
|
for keyid in parent_keyids:
|
|
saved_pw = self.rsa_passwords[keyid]
|
|
self.rsa_passwords[keyid] = self.random_string()
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_delegation,
|
|
keystore_dir)
|
|
self.rsa_passwords[keyid] = saved_pw
|
|
|
|
# Test: delegated_keyids == 0.
|
|
keystore.clear_keystore()
|
|
|
|
# Load 0 keyids (== 0).
|
|
signing_keyids = []
|
|
self.assertRaises(tuf.RepositoryError, signercli.make_delegation,
|
|
keystore_dir)
|
|
keystore.clear_keystore()
|
|
|
|
# Restore signing_keyids (== 1).
|
|
signing_keyids = [new_keyid_1]
|
|
|
|
# Test: normal case 1.
|
|
# Testing first level delegation.
|
|
signercli.make_delegation(keystore_dir)
|
|
|
|
# Verify delegated metadata file exists.
|
|
delegated_meta_file = os.path.join(meta_dir, parent_role,
|
|
delegated_role+'.txt')
|
|
self.assertTrue(os.path.exists(delegated_meta_file))
|
|
|
|
# Test: normal case 2.
|
|
# Testing second level delegation.
|
|
keystore.clear_keystore()
|
|
|
|
# Make necessary adjustments for the test.
|
|
signing_keyids = [new_keyid_2]
|
|
delegated_targets_dir = os.path.join(delegated_targets_dir,
|
|
'delegated_level2')
|
|
parent_role = os.path.join(parent_role, delegated_role)
|
|
delegated_role = 'delegated_role_2'
|
|
|
|
signercli.make_delegation(keystore_dir)
|
|
|
|
# Verify delegated metadata file exists.
|
|
delegated_meta_file = os.path.join(meta_dir, parent_role,
|
|
delegated_role+'.txt')
|
|
self.assertTrue(os.path.exists(delegated_meta_file))
|
|
|
|
# Test: normal case 3.
|
|
# Testing delegated_keyids > 1.
|
|
# Ensure make_delegation() sets 'threshold' = 2 for the delegated role.
|
|
keystore.clear_keystore()
|
|
|
|
# Populate 'signing_keyids' with multiple keys, so the
|
|
# the delegated metadata is set to a threshold > 1.
|
|
signing_keyids = [new_keyid_1, new_keyid_2]
|
|
parent_role = 'targets'
|
|
delegated_role = 'delegated_role_1'
|
|
|
|
signercli.make_delegation(keystore_dir)
|
|
|
|
# Verify delegated metadata file exists.
|
|
delegated_meta_file = os.path.join(meta_dir, parent_role,
|
|
delegated_role+'.txt')
|
|
self.assertTrue(os.path.exists(delegated_meta_file))
|
|
|
|
# Verify the threshold value of the delegated metadata file
|
|
# by inspecting the parent role's 'delegations' field.
|
|
parent_role_file = os.path.join(meta_dir, parent_role+'.txt')
|
|
signable = signerlib.read_metadata_file(parent_role_file)
|
|
delegated_rolename = parent_role+'/'+delegated_role
|
|
|
|
roles = signable['signed']['delegations']['roles']
|
|
role_index = signerlib.find_delegated_role(roles, delegated_rolename)
|
|
self.assertIsNotNone(role_index)
|
|
role = roles[role_index]
|
|
|
|
threshold = role['threshold']
|
|
self.assertTrue(threshold == 2)
|
|
|
|
# RESTORE
|
|
signercli._get_password = original_get_password
|
|
signercli._prompt = original_prompt
|
|
signercli._get_metadata_directory = original_get_metadata_directory
|
|
|
|
|
|
# Run unit tests.
|
|
loader = unittest_toolbox.unittest.TestLoader
|
|
suite = loader().loadTestsFromTestCase(TestSignercli)
|
|
try:
|
|
unittest_toolbox.unittest.TextTestRunner(verbosity=2).run(suite)
|
|
finally:
|
|
unittest_toolbox.Modified_TestCase.clear_toolbox()
|