python-tuf/tuf/tests/repository_setup.py

365 lines
11 KiB
Python
Executable file

"""
<Program Name>
repository_setup.py
<Author>
Konstantin Andrianov
<Started>
October 15, 2012
<Copyright>
See LICENSE for licensing information.
<Purpose>
To provide a quick repository structure to be used in conjunction with
test modules like test_updater.py for instance.
"""
import os
import sys
import shutil
import tempfile
import tuf.rsa_key as rsa_key
import tuf.repo.keystore as keystore
import tuf.repo.signerlib as signerlib
import tuf.repo.signercli as signercli
import tuf.tests.unittest_toolbox as unittest_toolbox
# Populating 'rsa_keystore' and 'rsa_passwords' dictionaries.
# We will need them in creating keystore directory.
unittest_toolbox.Modified_TestCase.bind_keys_to_roles()
# Role:keyids dictionary.
role_keyids = {}
for role in unittest_toolbox.Modified_TestCase.semi_roledict.keys():
role_keyids[role] = unittest_toolbox.Modified_TestCase.semi_roledict[role]['keyids']
def _create_keystore(keystore_directory):
"""
<Purpose>
Populate 'keystore_directory' with keys (.key files).
"""
_rsa_keystore = unittest_toolbox.Modified_TestCase.rsa_keystore
_rsa_passwords = unittest_toolbox.Modified_TestCase.rsa_passwords
if not _rsa_keystore or not _rsa_passwords:
msg = 'Populate \'rsa_keystore\' and \'rsa_passwords\''+\
' before invoking this method.'
sys.exit(msg)
keystore._keystore = _rsa_keystore
keystore._key_passwords = _rsa_passwords
keystore.save_keystore_to_keyfiles(keystore_directory)
def build_server_repository(server_repository_dir, targets_dir):
"""
<Purpose>
'build_server_repository' builds a complete repository based on target
files provided in the 'targets_dir'. Delegated roles are included.
"""
# Save the originals of the functions patched by this function.
# The patched functions will be restored prior to returning.
original_get_metadata = signercli._get_metadata_directory
original_prompt = signercli._prompt
original_get_password = signercli._get_password
original_get_keyids = signercli._get_keyids
server_metadata_dir = os.path.join(server_repository_dir, 'metadata')
keystore_dir = os.path.join(server_repository_dir, 'keystore')
# Remove 'server_metadata_dir' and 'keystore_dir' if they already exist.
if os.path.exists(server_metadata_dir):
shutil.rmtree(server_metadata_dir)
if os.path.exists(keystore_dir):
shutil.rmtree(keystore_dir)
# Make metadata directory inside server repository dir.
os.mkdir(server_metadata_dir)
# Make a keystore directory inside server's repository and populate it.
os.mkdir(keystore_dir)
_create_keystore(keystore_dir)
# Build config file.
build_config = signerlib.build_config_file
top_level_role_info = unittest_toolbox.Modified_TestCase.top_level_role_info
config_filepath = build_config(server_repository_dir, 365, top_level_role_info)
# BUILD ROLE FILES.
# Build root file.
signerlib.build_root_file(config_filepath, role_keyids['root'],
server_metadata_dir)
# Build targets file.
signerlib.build_targets_file(targets_dir, role_keyids['targets'],
server_metadata_dir)
# MAKE DELEGATIONS.
# We will need to patch a few signercli prompts.
# Specifically, signercli.make_delegations() asks user input for:
# metadata directory, delegated targets directory, parent role,
# passwords for parent role's keyids, delegated role's name, and
# the keyid to be assigned to the delegated role. Take a look at
# signercli's make_delegation() to gain bit more insight in what is
# happening.
# 'load_key' is a reference to the 'load_keystore_from_keyfiles function'.
load_keys = keystore.load_keystore_from_keyfiles
# Setup first level delegated role.
delegated_level1 = os.path.join(targets_dir, 'delegated_level1')
delegated_targets_dir = delegated_level1
parent_role = 'targets'
delegated_role_name = 'delegated_role1'
signing_keyids = role_keyids['targets/delegated_role1']
# Patching the 'signercli' prompts.
# Mock method for signercli._get_metadata_directory().
def _mock_get_metadata_directory():
return server_metadata_dir
# 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.endswith('\nEnter the delegated role\'s name: '):
return delegated_role_name
else:
error_msg = ('Prompt: '+'\''+msg+'\''+
' did not match any predefined mock prompts.')
sys.exit(error_msg)
# Mock method for signercli._get_password().
def _mock_get_password(msg):
for keyid in unittest_toolbox.Modified_TestCase.rsa_keyids:
if msg.endswith('('+keyid+'): '):
return unittest_toolbox.Modified_TestCase.rsa_passwords[keyid]
# Method to patch signercli._get_keyids()
def _mock_get_keyids(junk):
if signing_keyids:
for keyid in signing_keyids:
password = unittest_toolbox.Modified_TestCase.rsa_passwords[keyid]
# Load the keyfile.
load_keys(keystore_dir, [keyid], [password])
return signing_keyids
# Patch signercli._get_metadata_directory().
signercli._get_metadata_directory = _mock_get_metadata_directory
# 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
# Clear kestore's dictionaries, by detaching them from unittest_toolbox's
# dictionaries.
keystore._keystore = {}
keystore._key_passwords = {}
# Make first level delegation.
signercli.make_delegation(keystore_dir)
# Setup second level delegated role.
delegated_level2 = os.path.join(delegated_level1, 'delegated_level2')
delegated_targets_dir = delegated_level2
parent_role = 'targets/delegated_role1'
delegated_role_name = 'delegated_role2'
signing_keyids = role_keyids['targets/delegated_role1/delegated_role2']
# Clear kestore's dictionaries.
keystore.clear_keystore()
# Make second level delegation.
signercli.make_delegation(keystore_dir)
keystore._keystore = unittest_toolbox.Modified_TestCase.rsa_keystore
keystore._key_passwords = unittest_toolbox.Modified_TestCase.rsa_passwords
# Build release file.
signerlib.build_release_file(role_keyids['release'], server_metadata_dir)
# Build timestamp file.
signerlib.build_timestamp_file(role_keyids['timestamp'], server_metadata_dir)
keystore._keystore = {}
keystore._key_passwords = {}
# RESTORE
signercli._get_metadata_directory = original_get_metadata
signercli._prompt = original_prompt
signercli._get_password = original_get_password
signercli._get_keyids = original_get_keyids
# Create a complete server and client repositories.
def create_repositories():
"""
Main directories have the following structure:
main_repository
|
------------------
| |
client_repository_dir server_repository_dir
client_repository
|
metadata
|
----------------
| |
previous current
server_repository
|
----------------------------
| | |
metadata targets keystore
|
delegation_level1
|
delegation_level2
NOTE: Do not forget to remove the directory using remove_all_repositories
after the tests.
<Return>
A dictionary of all repositories, with the following keys:
(main_repository, client_repository, server_repository)
"""
# Make a temporary general repository directory.
repository_dir = tempfile.mkdtemp()
# Make server repository and client repository directories.
server_repository_dir = os.path.join(repository_dir, 'server_repository')
client_repository_dir = os.path.join(repository_dir, 'client_repository')
os.mkdir(server_repository_dir)
os.mkdir(client_repository_dir)
# Make metadata directory inside client repository dir.
client_metadata_dir = os.path.join(client_repository_dir, 'metadata')
os.mkdir(client_metadata_dir)
# Create a 'targets' directory.
targets = os.path.join(server_repository_dir, 'targets')
delegated_level1 = os.path.join(targets, 'delegated_level1')
delegated_level2 = os.path.join(delegated_level1, 'delegated_level2')
os.makedirs(delegated_level2)
# Populate the project directory with files.
file_path_1 = tempfile.mkstemp(suffix='.txt', dir=targets)
file_path_2 = tempfile.mkstemp(suffix='.txt', dir=targets)
file_path_3 = tempfile.mkstemp(suffix='.txt', dir=delegated_level1)
file_path_4 = tempfile.mkstemp(suffix='.txt', dir=delegated_level2)
def data():
return 'Stored data: '+unittest_toolbox.Modified_TestCase.random_string()
file_1 = open(file_path_1[1], 'wb')
file_1.write(data())
file_1.close()
file_2 = open(file_path_2[1], 'wb')
file_2.write(data())
file_2.close()
file_3 = open(file_path_3[1], 'wb')
file_3.write(data())
file_3.close()
file_4 = open(file_path_4[1], 'wb')
file_4.write(data())
file_4.close()
# Build server's repository.
build_server_repository(server_repository_dir, targets)
# Build client's repository.
client_repository_include_all_role_files(repository_dir)
repositories = {'main_repository': repository_dir,
'client_repository': client_repository_dir,
'server_repository': server_repository_dir,
'targets_directory': targets}
return repositories
# client_repository_include_all_role_files() copies all of the metadata file.
def client_repository_include_all_role_files(repository_dir):
if repository_dir is None:
msg = ('Please provide main repository directory where client '+
'repository is located.')
sys.exit(msg)
# Destination directories.
current_dir = os.path.join(repository_dir, 'client_repository', 'metadata',
'current')
previous_dir = os.path.join(repository_dir, 'client_repository', 'metadata',
'previous')
# Source directory.
metadata_files = os.path.join(repository_dir, 'server_repository',
'metadata')
# Copy the whole source directory to destination directories.
shutil.copytree(metadata_files, current_dir)
shutil.copytree(metadata_files, previous_dir)
# Supply the main repository directory.
def remove_all_repositories(repository_directory):
# Check if 'repository_directory' is an existing directory.
if os.path.isdir(repository_directory):
shutil.rmtree(repository_directory)
else:
print '\nInvalid repository directory.'
if __name__ == '__main__':
repos = create_repositories()
remove_all_repositories(repos['main_repository'])