Restructing of delegations integration test.

This commit is contained in:
dachshund 2013-06-30 12:19:44 +08:00
parent c138b67828
commit b40191ba1f
2 changed files with 206 additions and 202 deletions

View file

@ -1501,8 +1501,13 @@ def target(self, target_filepath):
child_role_paths = child_role['paths']
# Ensure that we explore only delegated roles trusted with the target.
# Assuming conservation of delegated paths in the complete tree of
# delegations.
# We assume conservation of delegated paths in the complete tree of
# delegations. Note that the call to _ensure_all_targets_allowed in
# _update_metadata should already ensure that all targets metadata is
# valid; i.e. that the targets signed by a delegatee is a proper
# subset of the targets delegated to it by the delegator.
# Nevertheless, we check it again here for performance and safety
# reasons.
if target_filepath in child_role_paths:
role_names.append(child_role_name)
except:

View file

@ -14,103 +14,69 @@
See LICENSE for licensing information.
<Purpose>
Ensure that TUF meets expectations about target delegations.
"""
import os
import sys
import tempfile
import time
import unittest
import urllib
import tuf.formats
from tuf.interposition import urllib_tuf
import tuf.repo.keystore as keystore
import tuf.repo.signercli as signercli
import tuf.repo.signerlib as signerlib
import util_test_tools
# Disable logging.
#util_test_tools.disable_logging()
def setup_tuf_repository():
root_repo, url, server_proc, keyids = util_test_tools.init_repo(tuf=True)
class TestDelegationFunctions(unittest.TestCase):
# Server side repository.
tuf_repo = os.path.join(root_repo, 'tuf_repo')
keystore_dir = os.path.join(tuf_repo, 'keystore')
metadata_dir = os.path.join(tuf_repo, 'metadata')
targets_dir = os.path.join(tuf_repo, 'targets')
# Add files to the server side repository.
# target1 = 'targets_dir/target1_rand.txt'
# target2 = 'targets_dir/target2_rand.txt'
# target3 = 'targets_dir/level1_rand/target3_rand.txt'
# target4 = 'targets_dir/level1_rand/target4_rand.txt'
# target5 = 'targets_dir/level1_rand/level2_rand/target5_rand.txt'
# target6 = 'targets_dir/level1_rand/level2_rand/target6_rand.txt'
add_target = util_test_tools.add_file_to_repository
level1 = tempfile.mkdtemp(dir=targets_dir, prefix='level1_')
level2 = tempfile.mkdtemp(dir=level1, prefix='level2_')
target1_path = add_target(targets_dir, data='target1')
target2_path = add_target(targets_dir, data='target2')
target3_path = add_target(level1, data='target3')
target4_path = add_target(level1, data='target4')
target5_path = add_target(level2, data='target5')
target6_path = add_target(level2, data='target6')
# Target paths relative to the 'targets_dir'.
# Ex: targetX = 'level1_rand/targetX_rand.txt'
target1 = os.path.relpath(target1_path, tuf_repo)
target2 = os.path.relpath(target2_path, tuf_repo)
target3 = os.path.relpath(target3_path, tuf_repo)
target4 = os.path.relpath(target4_path, tuf_repo)
target5 = os.path.relpath(target5_path, tuf_repo)
target6 = os.path.relpath(target6_path, tuf_repo)
def do_update(self):
# Client side repository.
tuf_client = os.path.join(self.root_repo, 'tuf_client')
downloads_dir = os.path.join(self.root_repo, 'downloads')
# Relative to repository's targets directory.
target_filepaths = [target1, target2, target3, target4, target5, target6]
# Adjust client's configuration file.
tuf.conf.repository_directory = tuf_client
# Tracked targets.
targets_tracked_targets = [target1]
delegatee1_tracked_targets = [target1, target4]
delegatee2_tracked_targets = [target2, target4, target5]
delegatee3_tracked_targets = [target3, target4, target5, target6]
updater = tuf.client.updater.Updater('my_repo', self.mirrors)
# Assigned targets.
delegatee1_assigned_targets = [target1, target3, target4, target5, target6]
delegatee2_assigned_targets = [target2, target3, target4, target5, target6]
delegatee3_assigned_targets = [target3, target4, target5, target6]
# Refresh the repository's top-level roles, store the target information for
# all the targets tracked, and determine which of these targets have been
# updated.
updater.refresh()
# Make delegation directories at the server's repository.
metadata_targets_dir = os.path.join(metadata_dir, 'targets')
metadata_delegatee1_dir = os.path.join(metadata_targets_dir, 'delegatee1')
os.makedirs(metadata_delegatee1_dir)
targets = []
for target_filepath in self.relpath_from_targets(self.target_filepaths):
target_info = updater.target(target_filepath)
targets.append(target_info)
# Delegations metadata paths.
delegatee1_path = os.path.join(metadata_targets_dir, 'delegatee1.txt')
delegatee2_path = os.path.join(metadata_targets_dir, 'delegatee2.txt')
delegatee3_path = os.path.join(metadata_delegatee1_dir, 'delegatee3.txt')
updated_targets = updater.updated_targets(targets, downloads_dir)
# Download each of these updated targets and save them locally.
for target in updated_targets:
print('Downloading target '+str(target))
updater.download_target(target, downloads_dir)
# Generate delegation metadata.
generate_meta = signerlib.generate_targets_metadata
delegatee1 = generate_meta(tuf_repo, delegatee1_tracked_targets)
delegatee2 = generate_meta(tuf_repo, delegatee2_tracked_targets)
delegatee3 = generate_meta(tuf_repo, delegatee3_tracked_targets)
# Generate a set of RSA keys that will be assigned to the delegatees.
key1 = signerlib.generate_and_save_rsa_key(keystore_dir, 'delegatee1')
key2 = signerlib.generate_and_save_rsa_key(keystore_dir, 'delegatee2')
key3 = signerlib.generate_and_save_rsa_key(keystore_dir, 'delegatee3')
def make_targets_metadata(self):
"""Subclasses will override this method to generate metadata for all
targets roles, with the understanding that there is a fixed structure of
the targets roles."""
raise NotImplementedError()
def relpath_from_targets(self, target_filepaths):
"""Ex: 'targets/more_targets/somefile.txt' -> 'more_targets/somefile.txt'
i.e. 'targets/' is removed from 'target'."""
def _relative_path_to_targets(target_filepaths):
# Ex: 'targets/more_targets/somefile.txt' -> 'more_targets/somefile.txt'
# i.e. 'targets/' is removed from 'target'.
new_target_filepaths = []
for target in target_filepaths:
relative_targetpath = os.path.sep.join(target.split(os.path.sep)[1:])
@ -118,156 +84,189 @@ def _relative_path_to_targets(target_filepaths):
return new_target_filepaths
# Create delegatee role metadata in order to later create 'delegations'
# object:
delegatee1_role_meta = \
tuf.formats.make_role_metadata([key1['keyid']], 1, name='targets/delegatee1',
paths=_relative_path_to_targets(delegatee1_assigned_targets))
delegatee2_role_meta = \
tuf.formats.make_role_metadata([key2['keyid']], 1, name='targets/delegatee2',
paths=_relative_path_to_targets(delegatee2_assigned_targets))
delegatee3_role_meta = \
tuf.formats.make_role_metadata([key3['keyid']], 1, name='targets/delegatee1/delegatee3',
paths=_relative_path_to_targets(delegatee3_assigned_targets))
def setUp(self):
"""
The target delegations tree is fixed as such:
targets -> [T1, T2]
T1 -> [T3]
"""
# Create 'delegations' object for targets metadata:
targets_delegations = {}
key1_val = tuf.rsa_key.create_in_metadata_format(key1['keyval'])
key2_val = tuf.rsa_key.create_in_metadata_format(key2['keyval'])
targets_delegations['keys'] = {key1['keyid']:key1_val,
key2['keyid']:key2_val}
targets_delegations['roles'] = [delegatee1_role_meta, delegatee2_role_meta]
root_repo, url, server_proc, keyids = util_test_tools.init_repo(tuf=True)
# Create 'delegations' object for delegatee2 metadata:
delegatee1_delegations = {}
key3_val = tuf.rsa_key.create_in_metadata_format(key3['keyval'])
delegatee1_delegations['keys'] = {key3['keyid']:key3_val}
delegatee1_delegations['roles'] = [delegatee3_role_meta]
delegatee1['signed']['delegations'] = delegatee1_delegations
# Server side repository.
tuf_repo = os.path.join(root_repo, 'tuf_repo')
keystore_dir = os.path.join(tuf_repo, 'keystore')
metadata_dir = os.path.join(tuf_repo, 'metadata')
targets_dir = os.path.join(tuf_repo, 'targets')
# Read targets.txt metadata and add the 'delegations' field.
targets_metadata_path = os.path.join(metadata_dir, 'targets.txt')
targets_signable = signerlib.read_metadata_file(targets_metadata_path)
targets_metadata = targets_signable['signed']
targets_metadata['delegations'] = targets_delegations
# We need to provide clients with a way to reach the tuf repository.
tuf_repo_relpath = os.path.basename(tuf_repo)
tuf_url = url+tuf_repo_relpath
sign = signerlib.sign_metadata
write = signerlib.write_metadata_file
# Add files to the server side repository.
# target1 = 'targets_dir/[random].txt'
# target2 = 'targets_dir/[random].txt'
add_target = util_test_tools.add_file_to_repository
target1_path = add_target(targets_dir, data='target1')
target2_path = add_target(targets_dir, data='target2')
# Sign and save new metadata objects.
targets_signable = sign(targets_metadata, keyids, targets_metadata_path)
delegatee1_signable = sign(delegatee1, [key1['keyid']], delegatee1_path)
delegatee2_signable = sign(delegatee2, [key2['keyid']], delegatee2_path)
delegatee3_signable = sign(delegatee3, [key3['keyid']], delegatee3_path)
write(targets_signable, targets_metadata_path)
write(delegatee1_signable, delegatee1_path)
write(delegatee2_signable, delegatee2_path)
write(delegatee3_signable, delegatee3_path)
# Target paths relative to the 'targets_dir'.
# Ex: targetX = 'targets/delegator/delegatee.txt'
target1 = os.path.relpath(target1_path, tuf_repo)
target2 = os.path.relpath(target2_path, tuf_repo)
# Repository is set up. Refresh release and timestamp metadata to reflect
# the new changes.
signerlib.build_release_file(keyids, metadata_dir)
signerlib.build_timestamp_file(keyids, metadata_dir)
# Relative to repository's targets directory.
target_filepaths = [target1, target2]
# Unload all keys.
keystore.clear_keystore()
# Store in self only the variables relevant for tests.
self.root_repo = root_repo
self.tuf_repo = tuf_repo
self.server_proc = server_proc
self.target_filepaths = target_filepaths
# Targets delegated from A to B.
self.delegated_targets = {}
# Targets actually signed by B.
self.signed_targets = {}
self.mirrors = {
"mirror1": {
"url_prefix": tuf_url,
"metadata_path": "metadata",
"targets_path": "targets",
"confined_target_dirs": [""]
}
}
# Aliases for targets roles.
self.T0 = 'targets'
self.T1 = 'targets/T1'
self.T2 = 'targets/T2'
self.T3 = 'targets/T1/T3'
# We need to provide clients with a way to reach the tuf repository.
tuf_repo_relpath = os.path.basename(tuf_repo)
tuf_url = url+tuf_repo_relpath
mirrors = {"mirror1":
{"url_prefix": tuf_url,
"metadata_path": "metadata",
"targets_path": "targets",
"confined_target_dirs": [ "" ]}}
# Get tracked and assigned targets, and generate targets metadata.
self.make_targets_metadata()
assert hasattr(self, 'T0_metadata')
assert hasattr(self, 'T1_metadata')
assert hasattr(self, 'T2_metadata')
assert hasattr(self, 'T3_metadata')
return (root_repo, mirrors, server_proc, keyids,
_relative_path_to_targets(target_filepaths))
# Make delegation directories at the server's repository.
metadata_targets_dir = os.path.join(metadata_dir, 'targets')
metadata_T1_dir = os.path.join(metadata_targets_dir, 'T1')
os.makedirs(metadata_T1_dir)
# Delegations metadata paths for the 3 delegated targets roles.
T0_path = os.path.join(metadata_dir, 'targets.txt')
T1_path = os.path.join(metadata_targets_dir, 'T1.txt')
T2_path = os.path.join(metadata_targets_dir, 'T2.txt')
T3_path = os.path.join(metadata_T1_dir, 'T3.txt')
# Generate RSA keys for the 3 delegatees.
key1 = signerlib.generate_and_save_rsa_key(keystore_dir, 'T1')
key2 = signerlib.generate_and_save_rsa_key(keystore_dir, 'T2')
key3 = signerlib.generate_and_save_rsa_key(keystore_dir, 'T3')
# ID for each of the 3 keys.
key1_id = key1['keyid']
key2_id = key2['keyid']
key3_id = key3['keyid']
# ID, in a list, for each of the 3 keys.
key1_ids = [key1_id]
key2_ids = [key2_id]
key3_ids = [key3_id]
# Public-key JSON for each of the 3 keys.
key1_val = tuf.rsa_key.create_in_metadata_format(key1['keyval'])
key2_val = tuf.rsa_key.create_in_metadata_format(key2['keyval'])
key3_val = tuf.rsa_key.create_in_metadata_format(key3['keyval'])
# Create delegation role metadata for each of the 3 delegated targets roles.
make_role_metadata = tuf.formats.make_role_metadata
T1_targets = self.relpath_from_targets(self.delegated_targets[self.T1])
T1_role = make_role_metadata(key1_ids, 1, name=self.T1, paths=T1_targets)
T2_targets = self.relpath_from_targets(self.delegated_targets[self.T2])
T2_role = make_role_metadata(key2_ids, 1, name=self.T2, paths=T2_targets)
T3_targets = self.relpath_from_targets(self.delegated_targets[self.T3])
T3_role = make_role_metadata(key3_ids, 1, name=self.T3, paths=T3_targets)
# Assign 'delegations' object for 'targets':
self.T0_metadata['signed']['delegations'] = {
'keys': {key1_id: key1_val, key2_id: key2_val},
'roles': [T1_role, T2_role]
}
# Assign 'delegations' object for 'targets/T1':
self.T1_metadata['signed']['delegations'] = {
'keys': {key3_id: key3_val},
'roles': [T3_role]
}
sign = signerlib.sign_metadata
write = signerlib.write_metadata_file
# Sign new metadata objects.
T0_signable = sign(self.T0_metadata, keyids, T0_path)
T1_signable = sign(self.T1_metadata, key1_ids, T1_path)
T2_signable = sign(self.T2_metadata, key2_ids, T2_path)
T3_signable = sign(self.T3_metadata, key3_ids, T3_path)
# Save new metadata objects.
write(T0_signable, T0_path)
write(T1_signable, T1_path)
write(T2_signable, T2_path)
write(T3_signable, T3_path)
# Timestamp a new release to reflect latest targets.
signerlib.build_release_file(keyids, metadata_dir)
signerlib.build_timestamp_file(keyids, metadata_dir)
# Unload all keys.
keystore.clear_keystore()
def tearDown(self):
util_test_tools.cleanup(self.root_repo, server_process=self.server_proc)
def test(rm_repo=True):
"""
rm_repo:
Boolean signalling whether or not we should remove the created repos.
"""
# Setup.
root_repo, mirrors, server_proc, keyids, target_filepaths = \
setup_tuf_repository()
# Server side repository.
tuf_repo = os.path.join(root_repo, 'tuf_repo')
keystore_dir = os.path.join(tuf_repo, 'keystore')
metadata_dir = os.path.join(tuf_repo, 'metadata')
targets_dir = os.path.join(tuf_repo, 'targets')
# Client side repository.
tuf_client = os.path.join(root_repo, 'tuf_client')
current_dir = os.path.join(tuf_client, 'metadata', 'current')
previous_dir = os.path.join(tuf_client, 'metadata', 'previous')
downloads_dir = os.path.join(root_repo, 'downloads')
# Adjust client's configuration file.
# Here the repository_directory is referred to client's local repository.
original_repo = tuf.conf.repository_directory
tuf.conf.repository_directory = tuf_client
# At this point all metadata at the server's repository is in sync.
start_time = time.time()
_client_update(mirrors, downloads_dir, target_filepaths)
end_time = time.time()
print "Client update takes",
print end_time - start_time,
print "seconds."
# TearDown and restore value of previous repository directory.
tuf.conf.repository_directory = original_repo
if rm_repo:
server_proc.kill()
else:
util_test_tools.cleanup(root_repo, server_proc)
class Test1(TestDelegationFunctions):
"""We test that the basic update mechanism works."""
def make_targets_metadata(self):
make_metadata = signerlib.generate_targets_metadata
target1, target2 = self.target_filepaths
# Tracked targets.
self.signed_targets[self.T0] = [target1]
self.signed_targets[self.T1] = [target1]
self.signed_targets[self.T2] = [target2]
self.signed_targets[self.T3] = [target1, target2]
# Assigned targets.
self.delegated_targets[self.T1] = [target1]
self.delegated_targets[self.T2] = [target2]
self.delegated_targets[self.T3] = [target1, target2]
self.T0_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T0])
self.T1_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T1])
self.T2_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T2])
self.T3_metadata = \
make_metadata(self.tuf_repo, self.signed_targets[self.T3])
def _client_update(mirrors, dest, target_filepaths=[], initial_update=False):
# We need to initialize an updater class.
updater = tuf.client.updater.Updater('my_repo', mirrors)
# Refresh the repository's top-level roles, store the target information for
# all the targets tracked, and determine which of these targets have been
# updated.
updater.refresh()
if initial_update:
targets = updater.all_targets()
else:
targets = []
for target_filepath in target_filepaths:
target_info = updater.target(target_filepath)
targets.append(target_info)
updated_targets = updater.updated_targets(targets, dest)
# Download each of these updated targets and save them locally.
for target in updated_targets:
try:
print('Downloading target '+str(target))
updater.download_target(target, dest)
except tuf.DownloadError, e:
pass
def test_update_works_with_delegations(self):
self.do_update()
if __name__ == '__main__':
start_time = time.time()
test(True)
end_time = time.time()
print end_time - start_time
unittest.main()