Merge pull request #205 from vladimir-v-diaz/develop

Address Issue #146.  Replace custom datetime format with ISO 8601.
This commit is contained in:
Vladimir Diaz 2014-04-19 14:47:35 -04:00
commit ddb8b00948
176 changed files with 1048 additions and 13305 deletions

View file

@ -476,7 +476,10 @@
The KEYID of a key is the hexdigest of the SHA-256 hash of the
canonical JSON form of the key, where the "private" object key is excluded.
All times are given as strings of the format "YYYY-MM-DD HH:MM:SS UTC".
Metadata date-time data follows the ISO 8601 standard. The expected format
of the combined date and time string is "YYYY-MM-DDTHH:MM:SSZ". Time is
always in UTC, and the "Z" time zone designator is attached to indicate a
zero UTC offset. An example date-time string is "1985-10-21T01:21:00Z".
4.3. File formats: root.json

View file

@ -6,7 +6,7 @@
Vladimir Diaz <vladimir.v.diaz@gmail.com>
<Started>
September 2012
September 2012.
<Copyright>
See LICENSE for licensing information.
@ -16,13 +16,16 @@
utilizing The Update Framework may write to securely update files.
The 'basic_client.py' script can be used on the command-line to perform
an update that will download and update all available targets; writing
custom code is not required in this case.
custom code is not required with 'basic_client.py'.
The custom examples below demonstrate:
(1) updating all targets
(2) updating all the targets of a specified role
(3) updating a specific target explicitely named.
It assumes a server is listening on 'http://localhost:8001'. One can be
started by navigating to the 'examples/repository/' and starting:
$ python -m SimpleHTTPServer 8001
"""
import logging
@ -30,7 +33,7 @@
import tuf.client.updater
# Uncomment the line below to enable printing of debugging information.
#tuf.log.set_log_level(logging.DEBUG)
tuf.log.set_log_level(logging.INFO)
# Set the local repository directory containing the metadata files.
tuf.conf.repository_directory = '.'
@ -61,7 +64,8 @@
for target in updated_targets:
try:
updater.download_target(target, destination_directory)
except tuf.DownloadError, e:
except tuf.DownloadError as e:
pass
# Remove any files from the destination directory that are no longer being
@ -69,26 +73,22 @@
updater.remove_obsolete_targets(destination_directory)
"""
# Example demonstrating an update that only downloads the targets of
# a specific role (i.e., 'targets/role1')
# Example demonstrating an update that only downloads the targets of
# a specific role (i.e., 'targets/project')
updater.refresh()
targets_of_role1 = updater.targets_of_role('targets/role1')
targets_of_role1 = updater.targets_of_role('targets/project')
updated_targets = updater.updated_targets(targets_of_role1, destination_directory)
for target in updated_targets:
updater.download_target(target, destination_directory)
"""
"""
# Example demonstrating an update that downloads a specific target.
updater.refresh()
target = updater.target('LICENSE.txt')
target = updater.target('/file2.txt')
updated_target = updater.updated_targets([target], destination_directory)
for target in updated_target:
updater.download_target(target, destination_directory)
"""

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
5bc5cdc1e18ff3ccbfd7c33a88bec596@@@@313030303030@@@@39656230336534656264303863303733353832386465383466346232633863356362616234306430333863353239393966643333373730353231386262623339@@@@31caf11a40e9eb48f499dcc6f80c88e8@@@@0400a24989069098ce702d6a8f81826ba482ffd9a17fff5a10c6f986b9179bae1be4d246db2fceda93ce12bd465e896e4e4e847c934eb120c794e12fbcc8569e4aa6964995f1fda9af50057644236c4194ebb78a588804363dbce492db7e4ef2ce39391013a7c2d68260a0e785b6cec39fc02cdff11e9c7a168ae133292fdbe5f2f968d2a0ae098ca9453ec33d175de181f771b016c760ceba51d9c20c431702656e8b09ebda6cf884096b89d80dd6c2c1752c04312e934cd79d49b91e8c7ef4448bf3b969fa6ed9727cac48f91e3921f41d5bf8ec4130ff45fda51e07cd16a7fa8daca1feb6f2dced6881c736565a1b72dc705a97606a0480c0dd681e65bea82fc261762cdad203fd49d45f

View file

@ -0,0 +1 @@
{"keytype": "ed25519", "keyval": {"public": "b6e40fb71a6041212a3d84331336ecaa1f48a0c523f80ccc762a034c727606fa"}}

View file

@ -0,0 +1 @@
70b05482c00cad0fccfcab4ac2b86b50@@@@313030303030@@@@62626137313336626662363862333962636161306561326437336237643436306162323966303038326636306363613965396161353566646330346666356635@@@@5f6612c00c8ed8627dd33754812bb7e1@@@@f651c3db5ac02aa8337264f0badd1f40fbe174ec3f8de8fd95188d31cf41b4863d7a28db297b8a5abd25e49d2af3c6cb2e25789088dce2b5113b7d7db16deea1eadf109d5ec004a2b5bcbdc29e13a9e4c803659def851800969918fb5930c56b816b119be490667f2d629309bc7578dad43c6b0ca6ef0c6f48ad68390fb1fc711b8a40bb5b1c197ae6f72d2b1e83bbc9050f46a3c69efe3b11c55a52d3f68f6e9fe58ad7e67dd6b136681b6d800fed22f15d31ee71ad1ed78f36b6d19b0771c22123f1dcb54a6b2e9742d2661014931cbab8fbbb001e3ac836bc5c64b19fa4cb881485acdafa6a0fd87044534608f50ae13920517c6f2ab2669f8edd4bc6cbe2fc1fc272264a819e2e34bc83

View file

@ -0,0 +1 @@
{"keytype": "ed25519", "keyval": {"public": "66dd78c5c2a78abc6fc6b267ff1a8017ba0e8bfc853dd97af351949bba021275"}}

View file

@ -0,0 +1 @@
cff2ed748f0281d65c8eb535e81dbfd0@@@@313030303030@@@@30353732326564313863306632626336656631636635313666636330383537376466393833313937363261303638336632373530303938623665346239646230@@@@1eda960b65beefb9a2a4afcc9be973f6@@@@ea7c468f9e5ab91e874b2a0fa692a18056293261886400e5976a6c884b13cdd3905b0188f41b0c2b2846d36dabbeecf4d9d1c87123b5b236ccbce24f4b30c9ba25d00ccce270d3da1d202d2fd27a0a007381bf2284c58bb01a812050086264617f94a47cd3931b9129c6b105eec4ff56d1176e6fbde6bf5ade513a0f1c7551cecb04c678582e7fd0656936a1f232fa3a739df3dc4af07ad69580f54b1dd366c78e96c07249732621929aac056f4892af07772011246101cfb9886558fe2cfd1d09e9c280cbecdf2fb8dbeded4a628ef2fa04d5360dae327ccf15a12a00f2f32964ca03abaeaeb60bbece207e09c897413b8a630331df568822880be86359181664aa0806770ab11e30663594

View file

@ -0,0 +1 @@
{"keytype": "ed25519", "keyval": {"public": "01c61f8dc7d77fcef973f4267927541e355e8ceda757e2c402818dad850f856e"}}

View file

@ -0,0 +1 @@
a0fdf15a675c849cc7bd4cfb46273164@@@@313030303030@@@@62303735356165326132633766333932633137643234323961636166356135666433333234376163356665656330306362366363383332386430356133663831@@@@0d7ce5bc8687edc1a292ebbe203284b6@@@@155dee106e192009ed4dace179e514f518d403d7a83d136047683683090c8dd1e80d6d5f6bd480e1e9e76bf63a265dfdc7e5bce07418039c6457c6d454fd0114fd7311c8508ead020e59e0b5b2ee55101d49535980e598c02c70ecb7bca77a54d04040080ca9403cd23bd0ae4cc5e33131321d2a4c8a4544553f5c54b7af0986a437f37696b4e7d76efed24be9a4c6928542fb93cfd88018537703a1ff0f6ac8fcb625714a161aaa7a548b39963ded1481b47020b1346544a8a9d96f1eb03a6cad326af0f5be43c6756dc1d4e6c7dee550077d7689949a671acd370680d6b29e594675ade9d7525a4ad8af7a1b13a3e4692192d70c189115d52b814af5a53bc9d0528aec6c6417f6f7d0bcb3

View file

@ -0,0 +1 @@
{"keytype": "ed25519", "keyval": {"public": "68ead6e54a43f8f36f9717b10669d1ef0ebb38cee6b05317669341309f1069cb"}}

View file

@ -0,0 +1 @@
dd0f6b3bff19df2c4ab89e34a5b190e6@@@@313030303030@@@@37613435636666623966633230613439376661303631616635323365326636643039383236333638633162326262616231653531353066656262643265623566@@@@e6d72cc0a99144c4dbf509fa56092454@@@@10bb33112d4083f81d700740e78b315574a0d7b8c042921b1dcb7b8593caff1dbb10b8886ea2f4b7edcb49d3aabc9ec25db59dc0b121890555dc5d69291856f739b280de6fa6216e0ac92b9b95689b9f6ba1a414cb78ee6547968ea5ebd84e34972cf6d0e56cf0443b653f51d8e2742a7454e70039e548e4a69e97e73475940964307b5d5da440767531479b0c940dc8ffebafdf562e3a68d456f9438cb3c2253117180efd868b8b9fd4ea3e717501db8c0a9afe0bcdb34068eef4858103b2126b47d4c22a3d0f16cec0e5cd452201487eb6695139d8235a17a3c1a42fa7552d7ca45625b0000650f22851679ac00c7b71368d4dfc862a1823437b5cc244c282be0c01138fa39dc13511bd59

View file

@ -0,0 +1 @@
{"keytype": "ed25519", "keyval": {"public": "72378e5bc588793e58f81c8533da64a2e8f1565c1fcc7f253496394ffc52542c"}}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
This is an example target file.

View file

@ -0,0 +1 @@
This is an another example target file.

View file

@ -0,0 +1 @@
This is role1's target file.

View file

@ -101,7 +101,7 @@
'Topic :: Software Development'
],
install_requires = [],
packages = find_packages(exclude=['tests', 'tuf.tests']),
packages = find_packages(exclude=['tests']),
extras_require = extras,
scripts = [
'tuf/client/basic_client.py'

View file

@ -1,541 +0,0 @@
#!/usr/bin/env python
"""
<Program Name>
test_delegations.py
<Author>
Konstantin Andrianov
<Started>
February 19, 2012
<Copyright>
See LICENSE for licensing information.
<Purpose>
Ensure that TUF meets expectations about target delegations.
"""
import os
import time
import tempfile
import unittest
import tuf.formats
import tuf.repo.keystore as keystore
import tuf.repo.signercli as signercli
import tuf.repo.signerlib as signerlib
import tuf.tests.util_test_tools as util_test_tools
version = 1
# Modify the number of iterations (from the higher default count) so the unit
# tests run faster.
keystore._PBKDF2_ITERATIONS = 1000
class TestDelegationFunctions(unittest.TestCase):
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')
# Adjust client's configuration file.
tuf.conf.repository_directory = tuf_client
updater = tuf.client.updater.Updater('my_repo', self.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()
# Obtain a list of available targets.
targets = []
relative_target_filepaths = self.relpath_from_targets(self.target_filepaths)
for target_filepath in relative_target_filepaths:
target_info = updater.target(target_filepath)
targets.append(target_info)
# Download each of these updated targets and save them locally.
updated_targets = updater.updated_targets(targets, downloads_dir)
for target in updated_targets:
updater.download_target(target, downloads_dir)
# Return metadata about downloaded targets.
make_fileinfo = signerlib.get_metadata_file_info
targets_metadata = {}
for target_filepath in relative_target_filepaths:
download_filepath = os.path.join(downloads_dir, target_filepath)
target_fileinfo = signerlib.get_metadata_file_info(download_filepath)
targets_metadata[target_filepath] = target_fileinfo
return targets_metadata
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'."""
new_target_filepaths = []
for target in target_filepaths:
relative_targetpath = os.path.sep.join(target.split(os.path.sep)[1:])
new_target_filepaths.append(relative_targetpath)
return new_target_filepaths
def setUp(self):
"""
The target delegations tree is fixed as such:
targets -> [T1, T2]
T1 -> [T3]
"""
global version
version = version+1
expiration = tuf.formats.format_time(time.time()+86400)
root_repo, url, server_proc, keyids = util_test_tools.init_repo(using_tuf=True)
# 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')
# 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
# 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')
# 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)
# Relative to repository's targets directory.
target_filepaths = [target1, target2]
# 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'
# 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')
# 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, version, expiration)
signerlib.build_timestamp_file(keyids, metadata_dir, version, expiration)
# Unload all keys.
keystore.clear_keystore()
def tearDown(self):
util_test_tools.cleanup(self.root_repo, server_process=self.server_proc)
class TestInitialUpdateWithTargetDelegations(TestDelegationFunctions):
"""We show that making target delegations results in a successful initial
update of targets."""
def make_targets_metadata(self):
global version
version = version+1
expiration = tuf.formats.format_time(time.time()+86400)
make_metadata = signerlib.generate_targets_metadata
target1, target2 = self.target_filepaths
# Targets signed for by each of the targets roles.
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]
# Targets delegated to each of the delegated targets roles.
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],
version, expiration)
self.T1_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T1],
version, expiration)
self.T2_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T2],
version, expiration)
self.T3_metadata = \
make_metadata(self.tuf_repo, self.signed_targets[self.T3],
version, expiration)
def test_that_initial_update_works_with_target_delegations(self):
# Get relative target paths, because that is what TUF recognizes.
relative_target_filepaths = self.relpath_from_targets(self.target_filepaths)
# Get metadata about downloaded targets.
targets_metadata = self.do_update()
# Do we have metadata about all the expected targets?
for target_filepath in relative_target_filepaths:
self.assertIn(target_filepath, targets_metadata)
class TestBreachOfTargetDelegation(TestDelegationFunctions):
"""We show that a delegated targets role B cannot talk about targets that A
did not delegate to B."""
def make_targets_metadata(self):
global version
version = version+1
expiration = tuf.formats.format_time(time.time()+86400)
make_metadata = signerlib.generate_targets_metadata
target1, target2 = self.target_filepaths
# Targets signed for by each of the targets roles.
self.signed_targets[self.T0] = []
self.signed_targets[self.T1] = [target2]
self.signed_targets[self.T2] = [target1]
self.signed_targets[self.T3] = []
# Targets delegated to each of the delegated targets roles.
self.delegated_targets[self.T1] = [target1]
self.delegated_targets[self.T2] = [target2]
self.delegated_targets[self.T3] = []
self.T0_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T0],
version, expiration)
self.T1_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T1],
version, expiration)
self.T2_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T2],
version, expiration)
self.T3_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T3],
version, expiration)
def test_that_initial_update_fails_with_undelegated_signing_of_targets(self):
"""We expect to see ForbiddenTargetError on initial update because
delegated targets roles sign for targets that they were not delegated
to."""
# http://docs.python.org/2/library/unittest.html#unittest.TestCase.assertRaises
with self.assertRaises(tuf.NoWorkingMirrorError) as context_manager:
self.do_update()
mirror_errors = context_manager.exception.mirror_errors
forbidden_target_error = False
for mirror_url, mirror_error in mirror_errors.iteritems():
if isinstance(mirror_error, tuf.ForbiddenTargetError):
forbidden_target_error = True
break
self.assertEqual(forbidden_target_error, True)
class TestOrderOfTargetDelegationWithSuccess(TestDelegationFunctions):
"""We show that when multiple delegated targets roles talk about a target,
the first one in order of appearance of delegation wins.
In this case, the first role has the correct metadata about the target."""
def make_targets_metadata(self):
global version
version = version+1
expiration = tuf.formats.format_time(time.time()+86400)
make_metadata = signerlib.generate_targets_metadata
target1, target2 = self.target_filepaths
# Targets signed for by each of the targets roles.
self.signed_targets[self.T0] = [target2]
self.signed_targets[self.T1] = []
self.signed_targets[self.T2] = [target1]
self.signed_targets[self.T3] = [target1]
# Targets delegated to each of the delegated targets roles.
self.delegated_targets[self.T1] = [target1]
self.delegated_targets[self.T2] = [target1]
self.delegated_targets[self.T3] = [target1]
self.T0_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T0],
version, expiration)
self.T1_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T1],
version, expiration)
self.T2_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T2],
version, expiration)
self.T3_metadata = \
make_metadata(self.tuf_repo, self.signed_targets[self.T3],
version, expiration)
# Modify the hash for target1 in T2.
for target_filepath in self.relpath_from_targets([target1]):
target_metadata = self.T2_metadata['signed']['targets'][target_filepath]
sha256_hash = target_metadata['hashes']['sha256']
last_character = sha256_hash[-1]
last_character = chr(ord(last_character)-1)
# "Subtract" the last character of the hash.
target_metadata['hashes']['sha256'] = sha256_hash[:-1] + last_character
def test_that_initial_update_works_with_many_roles_sharing_a_target(self):
# Get relative target paths, because that is what TUF recognizes.
relative_target_filepaths = self.relpath_from_targets(self.target_filepaths)
# Get metadata about downloaded targets.
targets_metadata = self.do_update()
# Do we have metadata about all the expected targets?
for target_filepath in relative_target_filepaths:
self.assertIn(target_filepath, targets_metadata)
class TestOrderOfTargetDelegationWithFailure(TestDelegationFunctions):
"""We show that when multiple delegated targets roles talk about a target,
the first one in order of appearance of delegation wins.
In this case, the first role has the wrong metadata about the target."""
def make_targets_metadata(self):
global version
version = version+1
expiration = tuf.formats.format_time(time.time()+86400)
make_metadata = signerlib.generate_targets_metadata
target1, target2 = self.target_filepaths
# Targets signed for by each of the targets roles.
self.signed_targets[self.T0] = [target2]
self.signed_targets[self.T1] = []
self.signed_targets[self.T2] = [target1]
self.signed_targets[self.T3] = [target1]
# Targets delegated to each of the delegated targets roles.
self.delegated_targets[self.T1] = [target1]
self.delegated_targets[self.T2] = [target1]
self.delegated_targets[self.T3] = [target1]
self.T0_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T0],
version, expiration)
self.T1_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T1],
version, expiration)
self.T2_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T2],
version, expiration)
self.T3_metadata = \
make_metadata(self.tuf_repo, self.signed_targets[self.T3],
version, expiration)
# Modify the hash for target1 in T3.
for target_filepath in self.relpath_from_targets([target1]):
target_metadata = self.T3_metadata['signed']['targets'][target_filepath]
sha256_hash = target_metadata['hashes']['sha256']
last_character = sha256_hash[-1]
last_character = chr(ord(last_character)-1)
# "Subtract" the last character of the hash.
target_metadata['hashes']['sha256'] = sha256_hash[:-1] + last_character
def test_that_initial_update_fails_with_many_roles_sharing_a_target(self):
"""We expect to see BadHashError on initial update because the hash
metadata mismatches the target."""
# http://docs.python.org/2/library/unittest.html#unittest.TestCase.assertRaises
with self.assertRaises(tuf.NoWorkingMirrorError) as context_manager:
self.do_update()
mirror_errors = context_manager.exception.mirror_errors
bad_hash_error = False
for mirror_url, mirror_error in mirror_errors.iteritems():
if isinstance(mirror_error, tuf.BadHashError):
bad_hash_error = True
break
self.assertEqual(bad_hash_error, True)
class TestConservationOfTargetDelegation(TestDelegationFunctions):
"""We show that delegated targets roles have to neither sign for targets
delegated to them nor further delegate them."""
def make_targets_metadata(self):
global version
expiration = tuf.formats.format_time(time.time()+86400)
make_metadata = signerlib.generate_targets_metadata
target1, target2 = self.target_filepaths
# Targets signed for by each of the targets roles.
self.signed_targets[self.T0] = []
self.signed_targets[self.T1] = [target1]
self.signed_targets[self.T2] = [target2]
self.signed_targets[self.T3] = []
# Targets delegated to each of the delegated targets roles.
self.delegated_targets[self.T1] = [target1, target2]
self.delegated_targets[self.T2] = [target1, target2]
self.delegated_targets[self.T3] = []
self.T0_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T0],
version, expiration)
self.T1_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T1],
version, expiration)
self.T2_metadata =\
make_metadata(self.tuf_repo, self.signed_targets[self.T2],
version, expiration)
self.T3_metadata = \
make_metadata(self.tuf_repo, self.signed_targets[self.T3],
version, expiration)
def test_that_initial_update_works_with_unconserved_targets(self):
# Get relative target paths, because that is what TUF recognizes.
relative_target_filepaths = self.relpath_from_targets(self.target_filepaths)
# Get metadata about downloaded targets.
targets_metadata = self.do_update()
# Do we have metadata about all the expected targets?
for target_filepath in relative_target_filepaths:
self.assertIn(target_filepath, targets_metadata)
if __name__ == '__main__':
unittest.main()

View file

@ -22,6 +22,7 @@
"""
import shutil
import datetime
from tuf.repository_tool import *
import tuf.util
@ -105,11 +106,11 @@
# Set the top-level expiration times far into the future so that
# they do not expire anytime soon, or else the tests fail. Unit tests may
# modify the expiration datetimes (of the copied files), if they wish.
repository.root.expiration = "2088-01-01 00:00:00"
repository.targets.expiration = "2088-01-01 00:00:00"
repository.snapshot.expiration = "2088-01-01 00:00:00"
repository.timestamp.expiration = "2088-01-01 00:00:00"
repository.targets('role1').expiration = "2088-01-01 00:00:00"
repository.root.expiration = datetime.datetime(2030, 01, 01, 00, 00)
repository.targets.expiration = datetime.datetime(2030, 01, 01, 00, 00)
repository.snapshot.expiration = datetime.datetime(2030, 01, 01, 00, 00)
repository.timestamp.expiration = datetime.datetime(2030, 01, 01, 00, 00)
repository.targets('role1').expiration = datetime.datetime(2030, 01, 01, 00, 00)
# Compress the 'targets.json' role so that the unit tests have a pre-generated
# example of compressed metadata.

View file

@ -1,30 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,54482FB3B9B400FE
DEK-Info: DES-EDE3-CBC,31815D9E16C988F5
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
-----END RSA PRIVATE KEY-----

View file

@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoezivMqfuB87dx9HyAwa
o/V269HKfCz292vwiuk+BPxjIlhYNpBBYfKbukqaudRpzDCjEeouvtWgzgZXIKKv
9PtFwmVkNwYUdJ2mi0Vx5n9mso0/9W24Gma01QkXXUYY0RJRsG5/xWLtRs/CHAEH
XHO0CcCzeQhyFd7QkkJscUqFhB3JEr71Tu9sG+BJwbayZCE4K1E7ydDQgeQqenv1
vEHh/APs8+iTlRb/NeN4/t22GsjqFXi57fvllIhdKP/c94PZvK1tqcbWcpB8m+Cq
DPajNeUfB3tnhvbdiFpU66cNokkVOkiAM6F1Rc4TUWKOk1+nnKYK5xm2PUIeBOrI
qwIDAQAB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsD++h8KXKhrJpzYxvZTE
7GqTDKM3uAWL8qGcQnvh7CNbqR4WmZrCQj1zF9hO5OAV+lGVD+JxUXW+yOPw+RjN
i7mPVa12Mq+vCS7WuosoCoooLpnYhRRVYMgpnhbvnjS6xA+7myJ1Bob+7WUEZZlC
oWdsmjfYG82sA7TOTubPk0s9pqQllINMEsB4JTTt3P3DD9+uifCFhoAEKeAItcgA
p4PJw2ImNwJiuet5wTP1ssTclPPWB6ofkm8zXoJUywTIW+hcQhN88jQv4Egx1llj
pWZbEdkIpNxjm6BAEqfPfiuAt6MA8cmdRpDl+Jn030A1kI7NJossuvTcfHwvReZO
WwIDAQAB
-----END PUBLIC KEY-----

View file

@ -1,30 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,3FF3C80523E9427F
DEK-Info: DES-EDE3-CBC,820FC61841CA82E2
+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
-----END RSA PRIVATE KEY-----

View file

@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtEYs4bpRKf6eVbpOvNvg
aD7rVnFStWzYIdnWdCvzASga5pM3eI14nCalfS/Z4iGCpaCtArp1QURCf+8u09A2
t9Rvx6eLEnR6jp4bE1wCzOdghaKqpdR8mc5Aw5IqRzcnJi44X3WhDBe3MCVEYya3
UtTD7Y/FZtp0ZoH3nI8vYnaiYO/jPWmrz254GRGmbR+eu9YOmmtezJg3xQSX5/j1
hBGl7cnEDIa4kZi1aqdL9UsM2uikhC0f7A/OyNdlgvXVRAZd6fnFFQb44HDix0VG
VdAmRosI+U4J9JDVW7G4Bt+Z47CfQ5CCW1wCKPRwx9F681WpdkLFG2YQ0zYjfAvo
UQIDAQAB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA72PwhMhTpDZ/wuB5Bdst
gYsfEI931GcIZ46Iq2dqMNWEg2Qt9w6W0xEQj8M5R99XFwbhXL6U7hKGDt958FzT
OL6CnjrnnBgzjbFm1vT380Qi5DaUbJkPcNmjzV45gGZkJ6LnohnBtnWUM/IdbbwR
PdWaqBxWRJHECPHjgbKt6Y9kDwaO6tJQdUIDGwt2V9hz9orPqwiX+c6uO6qJ0naU
F31ZvI4AtHUDaesbyp2j2X2dfCKNiM2t2sgxz79/G6VQvKG30PXxVPXvOhCDowsk
5NdM67bWIkFyf1yNArrhw0D/c0aSGZhYZs+FqvBzKjCy+9+uEfLZsRra6zvx8Jw9
TwIDAQAB
-----END PUBLIC KEY-----

View file

@ -1,30 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,7349E671E697C1CC
DEK-Info: DES-EDE3-CBC,0E7D0C9F6987D107
arUjBpVwBb0yQnGJKrqGkqfYve73Jct2XUdUZ/we2eJIacJwdc1J8O/8wwKIe0PA
lIgjs++fMPvIFeAycaFE3a2nryY+8efn2eZTtNPusRf8SUyVkUKw5DnCSwPU2jrj
AflRGMYClJn+2miqYCQtu+C10/sR/R14rJzHRloFVxnI2OwcWfAbNJh638esdu8x
+qcmbf2FmZp1bEQ6EedWMpwW6O66obVjl0dt7lnQIf+YVK6zQWPCelY/V+mEp6oF
9uHyDKuK1Ehp04GuZfhry7hlYc9dVGBF4s4HHGaSKZ2Gi2PkzOv67lyyUQKugIzl
McQxk9WuWuldIYA1ZmxL5vknoBu0w19BuhkMSIRKIleYK3GhEsquOnksQUmukc3c
chg3hG/bRvFXA3AkOYCPVTDXR1fU+9XrWEqKZthp/FuoL2JcQHI6v+qbCQOq2WE2
OV/LPupSloS1kSVQJ5r95bRM+aRvhra/tNPM8dbxj6l3VSgeoCso+srXctJyoOnX
cHloKpiEeNSpNRUAviyQbhBZjvk5Q2kzrQ/LdFXf23TZmBvw9tUxE0FRthx/TMTR
Kmo9QMO/dLTzP7So7HO6q/i9VlOhkUozakH4vO5Ejiy561sa2nG7Xp0toSq+fe1o
DPP9EoBkRLs4xDNl05ySk1TBmEpz32ED8YI9T55a+oVCtDMIVU4pnpxKWUJlJlN6
YPKy8i8nMfQPVivMLV7Q1HGt/CP81tnq7V/Jp9p9TD7jDYtSZISr9G8oA/d91GA1
uk5sWHoFl8lI8ELSCN1x5YsoCOP32/DHNTH/+AMq0yqUtbvOKuY1cOk2kypYnZPJ
htF8Hr7bGBYcpHShfJoYYjqg1lujmNOjh6zRrMakPTF+7aq6H/aISncFxMneX+Ep
UIB/hYWw9Vzevis+NqXzIiq6y/DRb8x2Z3D7hOBpltQyOiyvYmJz2gg7f445QBrh
hydA8MWgOaVLVFfh8Fseu+DkfJ/BluEjXwNlK82fXVLowxXi/OeIWDxLr2CgUaU0
jeC6JEJPfDvZrNlNK+v2AR3brd7PVcrjZ5XsWaswtyscLvBqW26dDSdvHfopgxAm
/4kwdepCfHurrT3xUs4Uxaop6NAZeynKIHuVGCpn4SN1R7UMIHgfrjPS+foU/2Vk
qhMUX3pUCONUEtZh1JENWLIz2JnTrV7pzV8haQPR5XVp0Pa3dhkLpYWR3GVhgkZt
nacOb/0rDPjxph3PR7vbnqOX2GU3GJj9axHql1PCe96qQW0D4FTt6esc5CwXNp4p
fnXlj1/+hjeZ3o27ba0f1a28eWwLHhASvBMIIf7TAgI8xGMo3Le0Y331rDX0xxPu
hIBwvEwtNEFfqgBu5EtoJgZs2PCfmALCrlpAJtL2F8EcNRblD9MkIW7q8/QPln4y
jLvJnACAjubyhCi9ysL1owCGLrHEUty+XP+ey7gvkBT/n9QXixTqmJ1zUNZ0xQn+
9ktonQOQFb3WgMMkYgQxQ8pXsfItihJ/cz+12l6CdMLRQiyZNTQfQb9Wtlgc5f0J
7ggKRYUb3BxG95O0nEHyzsUzbTEil3rC0eZnSeoP7yFv6mTYbAL0bA==
XrHRVUpQ1wkE2qxhS6BlvK7KkI+d61vg3zfNbKzjE/TpBz/PW0N8wak7Y/CrpsMQ
JHHmaiFx3nGzy4NSq0tBR+ek8e0E+mUrvpICC7M4kyquxB2QA70Tn9cyCN1VfzEt
4p+VgZiNRPEj4gXmgE8eP8OVG7Kn9I0dfVwVAb+bsGeWitK+DdYuyW13fyhVnjlF
we7gpnAcqUYUrR6HpSvjLgo8WHnXTRlOHKzulduwF4udbLQmhUuRUYVupvI47AJi
syHgSkGWwoT76CXtO0cCJf17ykh6M++vB5xDB0Qlf3xepmvxQxbohFsrwFzJKiql
YZ4OzquasMKfdVKSWrskkCK62fLygmABx5zRXPOR5bgZiLBj/CxHhS7aUoYRAmYJ
1PUGN5n21YLl6NqAPKvSq20fc753e5anWopTysbJXpKQiihdmTxX5/uSSuBL9E+O
O8HC6l4LXXnCwuw4LVdWIN6gKRG7Urf3AT6966b9AeDwe2lHyvKgfyOjmwLkkm1q
5Oh+5lob5uL+1wzaQiQnRDnBpb5XGoi7MjJ2azcas2neOm0jWK3j7UhrM2JqIVd5
G2dk3kLsX3+Oj8G9YlS/O0xYEZUqajT+ktY6jku9uQfDYM7V1ZesbKrj2Zfyc/zD
+xjojZ4NJjL9T+4q5exTH5oC+n7zUPByNMggVbYt2xEOJYBrCIjw2If11Tmcucht
Cw2S3iv6mJsd50H6sOpSPH52usbi9NrAXgU4U3GmRSUiNS9/6wH8So3GPkIGRl36
fN/GxGGLQvUXyvP3nTJIpCdcbRPM38cGEoa3GorSquUMKHcKjwYHgn2MJVHfibai
RcLKqILbwZd2hJt84HskF/znwN69NHg+e+muNs/diPlhR5h0uvIjCw9tEA9CxMt9
++P26Hx1YNlyGtv6Sg/7m1EIVg8XcdkDe/qVDzHSAoKDRg3UoM/v4y7gXcoM1o4i
uO1bRAlEG837Oh77es3/qR0cIcirUMhPd4PGI+rHIUfIxdZe2YnpLQpHHCHMjzVi
hUungj3nYBxnwc93xA2zWEvyYIrKS8GtfKiuRVrQ8mjymL34sIWpK847pJQHYnFH
iLRPsLOUYR3k2eCxsw53yVXhgCJPslxwg/TGTIBz3ye+lXp+w6FZp1gBpz+8pqCl
tTTOPhu8H3aL1UTSQCJ8Ew6zcXSyQVFPGjmhKvvJIQH5OoUCVGcwOOICqNobc5Gz
6IGZ10TUWBlrsxgk17n8a5+4PKngrOwaU7Z+YUUqG62boLrmfpDL5laoDNcRPuVx
nh9vXgBurkvt1MmvHXDFsSyNmEs6G1NSjQnb6Ij6GbRRvsbvbWM/DuJ4iLK5BSUN
fnkfpiHyyBYoA6GNgHMhDmPuVQqyfgmikeX+haGDIgyg6P1H6mV9/5pxDg3arSNS
ivFbBhY9lCjmrr4yMHHH+ddFaWvSOA8IH5daM0Zanei2V8A4fzKEMFm2frUBDNTe
HhMcNzUf29lTO190L5ojdtDJEn72YZFW7xhA0UvQof85nyFNCE2TkhLGGyjtcuLK
kNucHkjRrfX1o6Ut8MypgCIFso+MPEJ+Pt0lrK7VHuMJjcHmeJ2abUPmrJNfvrb6
-----END RSA PRIVATE KEY-----

View file

@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo7FuATglySRO9/s6ZEN7
VYtwjcs7NBO7uMIPnk2+EnNlLrN5mcW4eFafrKNXXJYQXZP+/b2t0K1sin3J08eV
lTQo33ROtWOVKNLITGYfFewesGN8Rz0nREAkQmD9w8kFTCphNruCiDE0P8m7jRrC
AHYl7zqKuuhNqghfYqDiAa+f8GOhIhNxJPf6NreYCGHW2kaMURnOKoD1v+mV2QDs
QpTEP+/gPvck7rLdfCNUB7iBZnnQw2fVSga44klDQ0tmhHnik0YakX0F7F0dra2e
Kz0N385MnW1vqEH1/QnSZBsJuqSNwf8JdPQBjisX3Qvm1ddH10jpWFizPtwnkm1b
vwIDAQAB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs0uAxc1XwUIayVPNt9U/
gLM5hjG/6AJ86XiHVIq6BuzUtiuKONZXq3SJwY5eAxdjylNt/A3FrJwylQbVMZkh
wLj0eU1IMh23xV1wOGu63Q9ARkmBAaksM+6apo2CHjtQaNXorhJ3/WDti2hST/cc
HjP81+JwJ+T6lXGKvGDbh3h6Car99MWlMAeYODdNqvRaVkkiQ20HgNB+RSiyGZPi
bzqlMe+qCQU/vktmmy9Zw3bjY7b8GFBix+7PHzFCpX15xKwB4dITPmsiL2OOo/w/
1Vqu3wP7Ct170oK+bH9eIk6wSAQX3IljKhgzkiYFRyCC33XHRpWmSjMgAGErCcl6
cwIDAQAB
-----END PUBLIC KEY-----

View file

@ -1,30 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,25ACB134E522BFFF
DEK-Info: DES-EDE3-CBC,D32B3B70C5CB2933
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
-----END RSA PRIVATE KEY-----

View file

@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArto5S3epNKVy+k8BbqAx
0/YDt968iu/crducSS1Ys4HxvWFZ+XuEqegZb8zVp8aem4WbNFw4XpUDConwOW4w
wIaqmxJ4EgW0OzEmX+AeBlc6OQYW0wD6GEOWAMj5WjebJd54fE2zXn9p2dLdzm4q
JA7iVGWPE5vNPkqOYfX7mmoj73/vpM8q0Ghbi9+2/7v0QYlRgeaR82C+InfeO1vi
y7Wcu2M66iWxSmbF0whd7BAXaNHkyoH8AEl3dPVxHgtY8J7zdYoPrCN0/lx3mgUL
r9fEcTqy+Q7K/0zKPOG97FT1CqRoY1svPNYP48HmbnTQT/vESwo6dTmTU1PwL+2K
vQIDAQAB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqTXKgkuaAyfvjkInfVic
lJnwLvG9mCXOcxR3HPwHK/8k/E/DBx8YGIGk7NWCXQFYnAeMZZdx8v3dBmH7oGAn
1pW+LnaAI7Csark8sbgmwYqwTd2oLHHmp/fOZ1vNDWjqvMLwi1YUllR6wPWKAvP2
8i7q7GCT/MBHDyZ899FCR4f7HvlCW5EYNt+wjxdm79T++Ix7iqvs4iUhvllsfdty
cVPWc+wh60qqCCbnr1Fow8d2j42a8mHoIHWgDvEF9ch+ChDOzQ+53jVmXS3CC+a2
H6EWNvKMc/wXvIAwA/y6cIjCG+Kep9AvVgz1blHf4ReTlNJWu2OkanszuboAR6nt
+wIDAQAB
-----END PUBLIC KEY-----

View file

@ -1,30 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,FE4027E2AF1DF4E3
DEK-Info: DES-EDE3-CBC,D5B52C0993E278D0
Z9f8F36a/6A5YQA0VrGoE3Ah/WKtSnWNb0Jj8XRYtrw0/eEyMpYZlau7+nvmoiA6
zdU4ao7Z2Mww+Mr3UKDbh1DncJ2BXmcm/GdYkUZuNywqlSKoNLX3eIlzH/FPtLqh
mlziLTDcIK3rqAwbBpdE1PaAMsgJQAwkEDPsvXpeE65Zz9ngX3GlqOfFDKgPNokV
mCI95a4xm/tRA4CHQC8cVhmu9gNVPtT2yf6Fpbnzxx8lFLTsKVCxVy45kiSna7pE
AJr35OmbRwjBYxEZATsoWeKG1GmfkOmGS7zK1JZ+cPBYUXNv7D5AKKJk2RpIzbEo
wYGewbSTFt0sxl6S01tpeFEFxLH8FH6j3ZAKs/bLJw/KgiIbZj4/NHfv9KBgig/H
Da92m+RhRHRuQSzvpif0hMBgDVdmpbtO2TrKeamb9O7tYCxvaIR4SVCrzdffDZ7/
DZpvQ4jeOiiX6193FYsf7n9zjoZJUvWFE/XOgyX7wVXFOLABlZgyW0jJa10cCslc
6S96X3Yuz4Za4bkB2RUsUzUfHlGJ98XijtbA/SvcO+hc9yLGb6qN5GAErXTgz0Fe
i3Ek2sg9Fkcy1ruHmBsYtm7e0Fs8QCE3QQ9c3JWUD1OaM1vdiUKFDgCljkf7wJqc
/SARbzzo/wGvrpcwch6IKnbzlzBX4mNn1uuYlo5qK42xCYKAbj9kTmGrjRfUfNZf
vQTwP38IhsqtD+33gKDKOTf+46hDwrwaQdILWOwsWlXfGOmfQmszB3Ua3oinDV5l
qcnaU+nmL/xMQnXd6uHafFUv2KTTVDC+araCKIH+KzFYymFRe+am5Q7jZtH0qMgi
/DOuSLa5Ffap2Y693XBwZTHMqeI6XCeQPhPy9I/B4bQCeh/ELNQRzqsVub8bCD0+
TxP77CduoSIhg3bhwoQ5y0QDwVYBVbNQStJK+fSw/e6aotOuyJ//Bn1mcYwAXXL6
WRPSsTo2TdA1AfKhKT/pjdKn8raIbPmfY6BK6t4suqW0bPJWNEkAZQoN5uc+/A55
Rjq8w6Ls+DpeOcgpUewt2zvFhWFXOPTCuYsoq2KQjQKyjQ3ZxEIt9iV4ft1lfd10
noR77BgFjYzGt6zq8IqRKd0cpFzMfGaSnP4OToaHbd/FHGMNcR0shPsIRxM/VJy2
VWUJ+i0Trz8YCGq3shyKsB2RR+BAUUN42VDgi04APtJfDn1RYW4ESSl0CyMDhp1E
HJuYpoKBf5vAeXwLtNDY60b1QTn4yvKB9YEqCWXpHAiWLs8jhbCnbXSEndY4v3i6
0FEiWklGr7ZpqxgnSWAX89zEu+L14uysmiwoNm4MjEQbXV8AJNRGMsVtPjmxVjZl
61e7RCOVdCR36trYVpOYICVGG23WEY7o9Km06pNi4HKvoFRWJl0cTb0+Yi5EAU6V
WnQfvYOowI4Ij/8idc4PDdTKDQxlxH7ftyTwd9xskGewRc3mfITF9yNiQ/BRto+b
JLtUcBOUIS6Ki6O6o8UXDHdFcF+OugUzUDnz8mgzfVCdwonZOKOgk5y65F/JzhJz
wYo04t5BALUHCyVnzm1JkVTeva/Tlq8HXpsdGlcLlm6B+rORjlCgI9XSCQlkDbXw
BF+QhAzOH4XkGczsMFpWjDyMGhJVyxOdYa4y5Ik2jldvo/0pXjHFRbuYpsHjRQWf
F/mAdaCNZ6LcoggCMkN6AOeEq8fc7l1gDvn8H+wFgZb5pfdjcViBh0xvqHQRDMqj
t69QVJnywWhlbtK1967nqKWxKIeVh4EWnWkVO2ep2ZYDbnfX0o2yL8lGFgduWFKy
wpWPmeFYpHFo24lEAFQVN9tv0/1TvQGdJ5GEOYhd/Xnjmg+rDAm3qkZ54wUB1sPq
cR55/nC5iSySAtEsXud4lyx16vRtjsY5kKkF5lIDscLxcGaTUEsLRUcQq9NQmk7J
7VCvH1/wtB+h36hFltjr7N8AeEgfboRmquid6a2aNzcY7qTeQrLCzMeEqSC1FXNK
2KUGvRsvroLMAwNXme8WeBzC6EAsF7ffwQENS+IqwA35h+mecFDBDxmeuFZLvlOD
K0o6UF0t0wV6B83qu/ooWkJgeNlPOaYh6XcTrBdC0jpYfBJfdGS6TDxKSYgxCSNH
Y344hhmXoTUvMPLOydyrnQjaISSZY4W9F3cVPTAUg84uK8ZHyhnknKkKDj3sPfNC
/VLXIbDqa5COGpuY/oFo3IZGi5mb7vaKFQtaScu8HDIOE1PEkipMUrIMNebUxBhm
9VyG4kFcQB/jLzZQpOwyIwkuYERVhVrBBWqlWf3TOn7dyq+anD6WUfveSIqjWdyy
NolLMnvdZxk6R3Dm2eKBMRBv91VfJihh2gqu7SlnlK4wmDmu6hB42laPXlkA6DNP
EOuS0zsz+1bkwwrRZzAbxlhexykL+a3NnLGJuoJBPW0larO0xSqOd0/UmJ06A5L3
h8gVLjwWssqfHftRlxiAPB2KcCA0XHcXLbqdy/XVR4ttW2f9vp8Xb9W3qMxIJWjI
n+bTSOjameg5AYeYQlowXNY+W+P50xFmt/1Bbc5kWyzftQLT3b/SCiGAuLeJiJOP
13osdj3fL6ANj8QjSU6HSfV+oF6EYh9jmAt3fUmYq6eLTTFCFq1cszd093wy1weC
RO8/tB/x2y2jUoKZL2XNDcmfHSvrd93LHhc9BwDQ2XVd61/+iwOAmMuYcLjX717S
IAtKpICyfyiflc/WwPaCXFhaTlafzQKQHbER+b1Y61gvKhDkMxcrAKm+dwh7k7PA
DHcT8+3uhyJbXnK9YXqgvp3aj8ddDL7D5ooLGVhHkhsQNdowx7xfEXXGOTib0sec
FL722JXKaLY2PreL5rFj/sZLKpZZ3St2lIc9uAMOO6XVLbTpxB989B51wIZXXXe2
jlFzIC2oDx6XPSiOqZS5o/KnBuddEL4JXBRBPDvhPQiHWSh3iM0mDnOiCyYWoo+N
HjGioJZ1IvlMC7M+qyyWZjqPA35Y6kZMNmkg+VgvAfPO4lbgOSQBaenBvAk2AmJ4
S+3AAijBWJxKN9nIYnkb7DZ/Bpt/rdxdXfZUTbZg0C3LgE/JSvPAhj700+BVZekm
Bip9tuZ3fARxT6K5stVBepTVFM0ueR/97j/krFNQFEJopCmsiqJjM1pQPv+TRmfH
yLkmGDTO63P8xaunrOtoX8NkmcYAl2xwKXhVjSkCxscZj3kSkljYieiC0Sg3YMGu
-----END RSA PRIVATE KEY-----

View file

@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtmyfY/TyvGDt/N/L+x8+
hVpku3JNOvPrFG0QUEQYWjlNjS+DSqigQvo4hluKz++qGeSYFl+LJBw4YLa0RFAg
b5jz9NAVBZJgTseT762jYC7HnZgmBE8vHcmAbfnUzcU7tLVn44xk3akzWGBTIEr6
VBL6x8nMgKNqLylIMDIVBHUI/FkAMMnfccYhLQSm9y/VAF/uW+/vu7WTjQynlEAY
vvQZqLxLC9mmY1i/kYeLbsJxZowzFw5KfVXQLjeVj420r8L0d9Yrl7T9ZH6AxCoi
jC6qAV/T9EP/FSEmyTf0MbCZDVDXlRwia+0Eb+5UkWRLGkjJgvghC/zCcODLexXv
+QIDAQAB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAueyWz2lDPzyywmWegFTP
l0DDXVNr9XIYLNffLRC24Y9ZKJCqb6eIz3XlF/3On5dCCqKFOfneHm55SxyCzoQb
RAtr5+SmoXfsds7ZAnxv48iGLtk7aZEvHchhEJ+1HsKy5hMeqpXtOAMPJXqBfqgT
ZzXagdCHNnbLEvhyJmRAaK88I/93s57KRNvPp6NIUbQ8EHaX1jaWt+LhGfsA3C34
qcxlk16LXF45Wm2AgMFCtZ2BecUvSQds24b/ShxfeVRtXSSUMDd+dM+MbwclPsoP
eTeegQATmA4pu4dDaBeYUnS/hstUZS5QPUuvVw6K0Q2JHUWv6CS2kziUjPXGI44H
LwIDAQAB
-----END PUBLIC KEY-----

View file

@ -53,7 +53,7 @@ def do_GET(self):
if self.server.test_mode == 'mode_1':
# Before sending any data, the server does nothing for a long time.
DELAY = 60
DELAY = 40
time.sleep(DELAY)
self.wfile.write(data)

View file

@ -48,7 +48,7 @@
import tuf.util
import tuf.log
import tuf.client.updater as updater
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox
logger = logging.getLogger('tuf.test_arbitrary_package_attack')
@ -110,8 +110,7 @@ def setUp(self):
# Copy the original repository files provided in the test folder so that
# any modifications made to repository files are restricted to the copies.
# The 'repository_data' directory is expected to exist in 'tuf/tests/'.
original_repository_files = os.path.join(os.getcwd(), os.pardir,
'repository_data')
original_repository_files = os.path.join(os.getcwd(), 'repository_data')
temporary_repository_root = \
self.make_temp_directory(directory=self.temporary_directory)

View file

@ -5,7 +5,7 @@
test_download.py
<Author>
Konstantin Andrianov
Konstantin Andrianov.
<Started>
March 26, 2012.
@ -14,12 +14,10 @@
See LICENSE for licensing information.
<Purpose>
Test download.py module.
NOTE: Make sure test_download.py is ran in 'tuf/tests/' directory.
Otherwise, module that launches simple server would not be found.
Unit test for 'download.py'.
NOTE: Make sure test_download.py is ran in 'tuf/tests/' directory.
Otherwise, module that launches simple server would not be found.
"""
@ -37,7 +35,7 @@
import tuf.conf as conf
import tuf.download as download
import tuf.log
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox
logger = logging.getLogger('tuf.test_download')

View file

@ -51,7 +51,7 @@
import tuf.util
import tuf.log
import tuf.client.updater as updater
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox
logger = logging.getLogger('tuf.test_endless_data_attack')
@ -113,8 +113,7 @@ def setUp(self):
# Copy the original repository files provided in the test folder so that
# any modifications made to repository files are restricted to the copies.
# The 'repository_data' directory is expected to exist in 'tuf/tests/'.
original_repository_files = os.path.join(os.getcwd(), os.pardir,
'repository_data')
original_repository_files = os.path.join(os.getcwd(), 'repository_data')
temporary_repository_root = \
self.make_temp_directory(directory=self.temporary_directory)

View file

@ -52,7 +52,7 @@
import tuf.util
import tuf.log
import tuf.client.updater as updater
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox
logger = logging.getLogger('tuf.test_extraneous_dependencies_attack')
@ -116,8 +116,7 @@ def setUp(self):
# Copy the original repository files provided in the test folder so that
# any modifications made to repository files are restricted to the copies.
# The 'repository_data' directory is expected to exist in 'tuf/tests/'.
original_repository_files = os.path.join(os.getcwd(), os.pardir,
'repository_data')
original_repository_files = os.path.join(os.getcwd(), 'repository_data')
temporary_repository_root = \
self.make_temp_directory(directory=self.temporary_directory)

View file

@ -18,6 +18,7 @@
"""
import unittest
import datetime
import tuf
import tuf.formats
@ -39,7 +40,10 @@ def tearDown(self):
def test_schemas(self):
# Test conditions for valid schemas.
valid_schemas = {
'TIME_SCHEMA': (tuf.formats.TIME_SCHEMA, '2012-10-14 06:42:12 UTC'),
'ISO8601_DATETIME_SCHEMA': (tuf.formats.ISO8601_DATETIME_SCHEMA,
'1985-10-21T13:20:00Z'),
'UNIX_TIMESTAMP_SCHEMA': (tuf.formats.UNIX_TIMESTAMP_SCHEMA, 499137720),
'HASH_SCHEMA': (tuf.formats.HASH_SCHEMA, 'A4582BCF323BCEF'),
@ -53,7 +57,7 @@ def test_schemas(self):
'KEYIDS_SCHEMA': (tuf.formats.KEYIDS_SCHEMA,
['123456789abcdef', '123456789abcdef']),
'SIG_METHOD_SCHEMA': (tuf.formats.SIG_METHOD_SCHEMA, 'evp'),
'SIG_METHOD_SCHEMA': (tuf.formats.SIG_METHOD_SCHEMA, 'ed25519'),
'RELPATH_SCHEMA': (tuf.formats.RELPATH_SCHEMA, 'metadata/root/'),
@ -184,7 +188,7 @@ def test_schemas(self):
{'_type': 'Root',
'version': 8,
'consistent_snapshot': False,
'expires': '2012-10-16 06:42:12 UTC',
'expires': '1985-10-21T13:20:00Z',
'keys': {'123abc': {'keytype': 'rsa',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}},
@ -195,7 +199,7 @@ def test_schemas(self):
'TARGETS_SCHEMA': (tuf.formats.TARGETS_SCHEMA,
{'_type': 'Targets',
'version': 8,
'expires': '2012-10-16 06:42:12 UTC',
'expires': '1985-10-21T13:20:00Z',
'targets': {'metadata/targets.json': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'metadata'}}},
@ -209,7 +213,7 @@ def test_schemas(self):
'SNAPSHOT_SCHEMA': (tuf.formats.SNAPSHOT_SCHEMA,
{'_type': 'Snapshot',
'version': 8,
'expires': '2012-10-16 06:42:12 UTC',
'expires': '1985-10-21T13:20:00Z',
'meta': {'metadata/snapshot.json': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'metadata'}}}}),
@ -217,7 +221,7 @@ def test_schemas(self):
'TIMESTAMP_SCHEMA': (tuf.formats.TIMESTAMP_SCHEMA,
{'_type': 'Timestamp',
'version': 8,
'expires': '2012-10-16 06:42:12 UTC',
'expires': '1985-10-21T13:20:00Z',
'meta': {'metadata/timestamp.json': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'metadata'}}}}),
@ -239,7 +243,7 @@ def test_schemas(self):
'MIRRORLIST_SCHEMA': (tuf.formats.MIRRORLIST_SCHEMA,
{'_type': 'Mirrors',
'version': 8,
'expires': '2012-10-16 06:42:12 UTC',
'expires': '1985-10-21T13:20:00Z',
'mirrors': [{'url_prefix': 'http://localhost:8001',
'metadata_path': 'metadata/',
'targets_path': 'targets/',
@ -289,7 +293,7 @@ def __init__(self, version, expires):
def test_TimestampFile(self):
# Test conditions for valid instances of 'tuf.formats.TimestampFile'.
version = 8
expires = '2012-10-16 06:42:12 UTC'
expires = '1985-10-21T13:20:00Z'
filedict = {'metadata/timestamp.json': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'metadata'}}}
@ -323,7 +327,8 @@ def test_RootFile(self):
# Test conditions for valid instances of 'tuf.formats.RootFile'.
version = 8
consistent_snapshot = False
expires = '2018-10-16 06:42:12 UTC'
expires = '1985-10-21T13:20:00Z'
keydict = {'123abc': {'keytype': 'rsa',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}}
@ -373,7 +378,8 @@ def test_RootFile(self):
def test_SnapshotFile(self):
# Test conditions for valid instances of 'tuf.formats.SnapshotFile'.
version = 8
expires = '2012-10-16 06:42:12 UTC'
expires = '1985-10-21T13:20:00Z'
filedict = {'metadata/snapshot.json': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'metadata'}}}
@ -405,7 +411,8 @@ def test_SnapshotFile(self):
def test_TargetsFile(self):
# Test conditions for valid instances of 'tuf.formats.TargetsFile'.
version = 8
expires = '2012-10-16 06:42:12 UTC'
expires = '1985-10-21T13:20:00Z'
filedict = {'metadata/targets.json': {'length': 1024,
'hashes': {'sha256': 'ABCD123'},
'custom': {'type': 'metadata'}}}
@ -444,27 +451,30 @@ def test_TargetsFile(self):
def test_format_time(self):
def test_unix_timestamp_to_datetime(self):
# Test conditions for valid arguments.
TIME_SCHEMA = tuf.formats.TIME_SCHEMA
self.assertTrue(TIME_SCHEMA.matches(tuf.formats.format_time(499137720)))
self.assertEqual('1985-10-26 01:22:00 UTC', tuf.formats.format_time(499137720))
UNIX_TIMESTAMP_SCHEMA = tuf.formats.UNIX_TIMESTAMP_SCHEMA
self.assertTrue(datetime.datetime, tuf.formats.unix_timestamp_to_datetime(499137720))
datetime_object = datetime.datetime(1985, 10, 26, 01, 22)
self.assertEqual(datetime_object, tuf.formats.unix_timestamp_to_datetime(499137720))
# Test conditions for invalid arguments.
self.assertRaises(tuf.FormatError, tuf.formats.format_time, 'bad')
self.assertRaises(tuf.FormatError, tuf.formats.format_time, 1000000000000000000000)
self.assertRaises(tuf.FormatError, tuf.formats.format_time, ['5'])
self.assertRaises(tuf.FormatError, tuf.formats.unix_timestamp_to_datetime, 'bad')
self.assertRaises(tuf.FormatError, tuf.formats.unix_timestamp_to_datetime, 1000000000000000000000)
self.assertRaises(tuf.FormatError, tuf.formats.unix_timestamp_to_datetime, -1)
self.assertRaises(tuf.FormatError, tuf.formats.unix_timestamp_to_datetime, ['5'])
def test_parse_time(self):
def test_datetime_to_unix_timestamp(self):
# Test conditions for valid arguments.
self.assertEqual(499137600, tuf.formats.parse_time('1985-10-26 01:20:00 UTC'))
datetime_object = datetime.datetime(2015, 10, 21, 19, 28)
self.assertEqual(1445455680, tuf.formats.datetime_to_unix_timestamp(datetime_object))
# Test conditions for invalid arguments.
self.assertRaises(tuf.FormatError, tuf.formats.parse_time, 'bad')
self.assertRaises(tuf.FormatError, tuf.formats.parse_time, 1000000000000000000000)
self.assertRaises(tuf.FormatError, tuf.formats.parse_time, ['1'])
self.assertRaises(tuf.FormatError, tuf.formats.datetime_to_unix_timestamp, 'bad')
self.assertRaises(tuf.FormatError, tuf.formats.datetime_to_unix_timestamp, 1000000000000000000000)
self.assertRaises(tuf.FormatError, tuf.formats.datetime_to_unix_timestamp, ['1'])
@ -498,7 +508,7 @@ def test_make_signable(self):
root = {'_type': 'Root',
'version': 8,
'consistent_snapshot': False,
'expires': '2012-10-16 06:42:12 UTC',
'expires': '1985-10-21T13:20:00Z',
'keys': {'123abc': {'keytype': 'rsa',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}},
@ -625,7 +635,7 @@ def test_check_signable_object_format(self):
root = {'_type': 'Root',
'version': 8,
'consistent_snapshot': False,
'expires': '2012-10-16 06:42:12 UTC',
'expires': '1985-10-21T13:20:00Z',
'keys': {'123abc': {'keytype': 'rsa',
'keyval': {'public': 'pubkey',
'private': 'privkey'}}},

View file

@ -45,7 +45,7 @@
import tuf.log
import tuf.client.updater as updater
import tuf.repository_tool as repo_tool
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox
# The repository tool is imported and logs console messages by default. Disable
# console log messages generated by this unit test.
@ -111,8 +111,7 @@ def setUp(self):
# Copy the original repository files provided in the test folder so that
# any modifications made to repository files are restricted to the copies.
# The 'repository_data' directory is expected to exist in 'tuf/tests/'.
original_repository_files = os.path.join(os.getcwd(), os.pardir,
'repository_data')
original_repository_files = os.path.join(os.getcwd(), 'repository_data')
temporary_repository_root = \
self.make_temp_directory(directory=self.temporary_directory)
@ -177,9 +176,9 @@ def test_without_tuf(self):
'timestamp.json')
timestamp_metadata = tuf.util.load_json_file(timestamp_path)
timestamp_metadata['signed']['expires'] = \
tuf.formats.format_time(time.time() - 10)
expires = tuf.formats.unix_timestamp_to_datetime(int(time.time() - 10))
expires = expires.isoformat() + 'Z'
timestamp_metadata['signed']['expires'] = expires
tuf.formats.check_signable_object_format(timestamp_metadata)
with open(timestamp_path, 'wb') as file_object:
@ -226,9 +225,8 @@ def test_with_tuf(self):
repository.timestamp.load_signing_key(timestamp_private)
# expire in 1 second.
utc_timestamp = tuf.formats.format_time(time.time() + 1)
repository.timestamp.expiration = \
utc_timestamp[0:utc_timestamp.rfind(' UTC')]
datetime_object = tuf.formats.unix_timestamp_to_datetime(int(time.time() + 1))
repository.timestamp.expiration = datetime_object
repository.write()
# Move the staged metadata to the "live" metadata.
@ -237,8 +235,9 @@ def test_with_tuf(self):
os.path.join(self.repository_directory, 'metadata'))
# Verify that the TUF client detects outdated metadata and refuses to
# continue the update process.
time.sleep(1)
# continue the update process. Sleep for at least 2 seconds to ensure
# 'repository.timestamp.expiration' is reached.
time.sleep(2)
self.assertRaises(tuf.ExpiredMetadataError,
self.repository_updater.refresh)

View file

@ -171,7 +171,7 @@ def test_create_keydb_from_root_metadata(self):
'Targets': {'keyids': [keyid2], 'threshold': 1}}
version = 8
consistent_snapshot = False
expires = '2012-10-16 06:42:12 UTC'
expires = '1985-10-21T01:21:00Z'
root_metadata = tuf.formats.RootFile.make_metadata(version,
expires,
@ -208,7 +208,7 @@ def test_create_keydb_from_root_metadata(self):
rsakey3['keytype'] = 'bad_keytype'
keydict[keyid3] = rsakey3
version = 8
expires = '2012-10-16 06:42:12 UTC'
expires = '1985-10-21T01:21:00Z'
root_metadata = tuf.formats.RootFile.make_metadata(version,
expires,

View file

@ -12,8 +12,7 @@
See LICENSE for licensing information.
<Purpose>
Test mirrors.py module.
Unit test for 'mirrors.py'.
"""
import unittest
@ -21,7 +20,7 @@
import tuf
import tuf.formats as formats
import tuf.mirrors as mirrors
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox

View file

@ -50,7 +50,7 @@
import tuf.log
import tuf.client.updater as updater
import tuf.repository_tool as repo_tool
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox
# The repository tool is imported and logs console messages by default. Disable
# console log messages generated by this unit test.
@ -117,8 +117,7 @@ def setUp(self):
# Copy the original repository files provided in the test folder so that
# any modifications made to repository files are restricted to the copies.
# The 'repository_data' directory is expected to exist in 'tuf/tests/'.
original_repository_files = os.path.join(os.getcwd(), os.pardir,
'repository_data')
original_repository_files = os.path.join(os.getcwd(), 'repository_data')
temporary_repository_root = \
self.make_temp_directory(directory=self.temporary_directory)

View file

@ -39,6 +39,7 @@
import tempfile
import random
import time
import datetime
import shutil
import json
import subprocess
@ -50,7 +51,7 @@
import tuf.log
import tuf.client.updater as updater
import tuf.repository_tool as repo_tool
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox
# The repository tool is imported and logs console messages by default. Disable
# console log messages generated by this unit test.
@ -117,8 +118,7 @@ def setUp(self):
# Copy the original repository files provided in the test folder so that
# any modifications made to repository files are restricted to the copies.
# The 'repository_data' directory is expected to exist in 'tuf/tests/'.
original_repository_files = os.path.join(os.getcwd(), os.pardir,
'repository_data')
original_repository_files = os.path.join(os.getcwd(), 'repository_data')
temporary_repository_root = \
self.make_temp_directory(directory=self.temporary_directory)
@ -209,7 +209,7 @@ def test_without_tuf(self):
# Set an arbitrary expiration so that the repository tool generates a new
# version.
repository.timestamp.expiration = '2088-01-01 12:12:00'
repository.timestamp.expiration = datetime.datetime(2030, 01, 01, 12, 12)
repository.write()
# Move the staged metadata to the "live" metadata.
@ -280,7 +280,7 @@ def test_with_tuf(self):
# Set an arbitrary expiration so that the repository tool generates a new
# version.
repository.timestamp.expiration = '2088-01-01 12:12:00'
repository.timestamp.expiration = datetime.datetime(2030, 01, 01, 12, 12)
repository.write()
# Move the staged metadata to the "live" metadata.

View file

@ -17,6 +17,7 @@
import os
import time
import datetime
import unittest
import logging
import tempfile
@ -106,7 +107,7 @@ def test_write_and_write_partial(self):
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
targets_directory = os.path.join(temporary_directory, 'repository',
repo_tool.TARGETS_DIRECTORY_NAME)
original_targets_directory = os.path.join(os.pardir, 'repository_data',
original_targets_directory = os.path.join('repository_data',
'repository', 'targets')
shutil.copytree(original_targets_directory, targets_directory)
@ -120,7 +121,7 @@ def test_write_and_write_partial(self):
# (1) Load the public and private keys of the top-level roles, and one
# delegated role.
keystore_directory = os.path.join(os.pardir, 'repository_data', 'keystore')
keystore_directory = os.path.join('repository_data', 'keystore')
# Load the public keys.
root_pubkey_path = os.path.join(keystore_directory, 'root_key.pub')
@ -225,7 +226,7 @@ def test_write_and_write_partial(self):
# is made to a role.
repo_tool.load_repository(repository_directory)
repository.timestamp.expiration = '2084-01-01 12:00:00'
repository.timestamp.expiration = datetime.datetime(2030, 01, 01, 12, 00)
self.assertRaises(tuf.UnsignedMetadataError, repository.write)
# Verify that a write_partial() is allowed.
@ -261,8 +262,8 @@ def test_write_and_write_partial(self):
def test_get_filepaths_in_directory(self):
# Test normal case.
# Use the pre-generated metadata directory for testing.
metadata_directory = os.path.join(os.pardir, 'repository_data',
'repository', 'metadata')
metadata_directory = os.path.join('repository_data',
'repository', 'metadata')
# Test improperly formatted arguments.
@ -300,8 +301,9 @@ def __init__(self):
self._rolename = 'metadata_role'
# Expire in 86400 seconds (1 day).
expiration = tuf.formats.format_time(time.time() + 86400)
expiration = \
tuf.formats.unix_timestamp_to_datetime(int(time.time() + 86400))
expiration = expiration.isoformat() + 'Z'
roleinfo = {'keyids': [], 'signing_keyids': [], 'threshold': 1,
'signatures': [], 'version': 0,
'consistent_snapshot': False,
@ -354,31 +356,35 @@ def test_threshold(self):
def test_expiration(self):
# Test expiration getter.
expiration = self.metadata.expiration
self.assertTrue(tuf.formats.TIME_SCHEMA.matches(expiration))
self.assertTrue(isinstance(expiration, datetime.datetime))
# Test expiration setter.
self.metadata.expiration = '2088-01-01 12:00:00'
self.metadata.expiration = datetime.datetime(2030, 01, 01, 12, 00)
expiration = self.metadata.expiration
self.assertTrue(tuf.formats.TIME_SCHEMA.matches(expiration))
self.assertTrue(isinstance(expiration, datetime.datetime))
# Test improperly formatted datetime.
try:
self.metadata.expiration = '3'
except tuf.FormatError:
pass
else:
self.fail('Setter failed to detect improperly formatted datetime.')
# Test invalid argument (i.e., expiration has already expired.)
expired_datetime = tuf.formats.format_time(time.time() - 1)
expired_datetime = tuf.formats.unix_timestamp_to_datetime(int(time.time() - 1))
try:
self.metadata.expiration = expired_datetime
except tuf.FormatError:
except tuf.Error:
pass
else:
self.fail('Setter failted to detect an expired datetime.')
self.fail('Setter failed to detect an expired datetime.')
@ -388,7 +394,7 @@ def test_keys(self):
# Test keys() getter after a verification key has been loaded.
key_path = os.path.join(os.pardir, 'repository_data',
key_path = os.path.join('repository_data',
'keystore', 'root_key.pub')
key_object = repo_tool.import_rsa_publickey_from_file(key_path)
self.metadata.add_verification_key(key_object)
@ -404,7 +410,7 @@ def test_signing_keys(self):
# Test signing_keys() getter after a signing key has been loaded.
key_path = os.path.join(os.pardir, 'repository_data',
key_path = os.path.join('repository_data',
'keystore', 'root_key')
key_object = repo_tool.import_rsa_privatekey_from_file(key_path, 'password')
self.metadata.load_signing_key(key_object)
@ -436,7 +442,7 @@ def test_compressions(self):
def test_add_verification_key(self):
# Add verification key and verify with keys() that it was added.
key_path = os.path.join(os.pardir, 'repository_data',
key_path = os.path.join('repository_data',
'keystore', 'root_key.pub')
key_object = repo_tool.import_rsa_publickey_from_file(key_path)
self.metadata.add_verification_key(key_object)
@ -452,7 +458,7 @@ def test_add_verification_key(self):
def test_remove_verification_key(self):
# Add verification key so that remove_verifiation_key() can be tested.
key_path = os.path.join(os.pardir, 'repository_data',
key_path = os.path.join('repository_data',
'keystore', 'root_key.pub')
key_object = repo_tool.import_rsa_publickey_from_file(key_path)
self.metadata.add_verification_key(key_object)
@ -471,7 +477,7 @@ def test_remove_verification_key(self):
# Test non-existent public key argument.
key_path = os.path.join(os.pardir, 'repository_data',
key_path = os.path.join('repository_data',
'keystore', 'targets_key.pub')
unused_key_object = repo_tool.import_rsa_publickey_from_file(key_path)
@ -482,7 +488,7 @@ def test_remove_verification_key(self):
def test_load_signing_key(self):
# Test normal case.
key_path = os.path.join(os.pardir, 'repository_data',
key_path = os.path.join('repository_data',
'keystore', 'root_key')
key_object = repo_tool.import_rsa_privatekey_from_file(key_path, 'password')
self.metadata.load_signing_key(key_object)
@ -496,7 +502,7 @@ def test_load_signing_key(self):
# Test non-private key.
key_path = os.path.join(os.pardir, 'repository_data',
key_path = os.path.join('repository_data',
'keystore', 'root_key.pub')
key_object = repo_tool.import_rsa_publickey_from_file(key_path)
self.assertRaises(tuf.Error, self.metadata.load_signing_key, key_object)
@ -505,7 +511,7 @@ def test_load_signing_key(self):
def test_unload_signing_key(self):
# Load a signing key so that unload_signing_key() can have a key to unload.
key_path = os.path.join(os.pardir, 'repository_data',
key_path = os.path.join('repository_data',
'keystore', 'root_key')
key_object = repo_tool.import_rsa_privatekey_from_file(key_path, 'password')
self.metadata.load_signing_key(key_object)
@ -523,7 +529,7 @@ def test_unload_signing_key(self):
# Test non-existent key argument.
key_path = os.path.join(os.pardir, 'repository_data',
key_path = os.path.join('repository_data',
'keystore', 'targets_key')
unused_key_object = repo_tool.import_rsa_privatekey_from_file(key_path,
'password')
@ -537,7 +543,7 @@ def test_add_signature(self):
# Test normal case.
# Load signature list from any of pre-generated metadata; needed for
# testing.
metadata_directory = os.path.join(os.pardir, 'repository_data',
metadata_directory = os.path.join('repository_data',
'repository', 'metadata')
root_filepath = os.path.join(metadata_directory, 'root.json')
root_signable = tuf.util.load_json_file(root_filepath)
@ -556,7 +562,7 @@ def test_add_signature(self):
def test_remove_signature(self):
# Test normal case.
# Add a signature so remove_signature() has some signature to remove.
metadata_directory = os.path.join(os.pardir, 'repository_data',
metadata_directory = os.path.join('repository_data',
'repository', 'metadata')
root_filepath = os.path.join(metadata_directory, 'root.json')
root_signable = tuf.util.load_json_file(root_filepath)
@ -587,7 +593,7 @@ def test_signatures(self):
# Test getter after adding an example signature.
metadata_directory = os.path.join(os.pardir, 'repository_data',
metadata_directory = os.path.join('repository_data',
'repository', 'metadata')
root_filepath = os.path.join(metadata_directory, 'root.json')
root_signable = tuf.util.load_json_file(root_filepath)
@ -700,7 +706,7 @@ def setUp(self):
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
self.targets_directory = os.path.join(temporary_directory, 'repository',
'targets')
original_targets_directory = os.path.join(os.pardir, 'repository_data',
original_targets_directory = os.path.join('repository_data',
'repository', 'targets')
shutil.copytree(original_targets_directory, self.targets_directory)
self.targets_object = repo_tool.Targets(self.targets_directory)
@ -752,7 +758,7 @@ def test_get_delegated_rolenames(self):
# Test normal case.
# Perform two delegations so that get_delegated_rolenames() has roles to
# return.
keystore_directory = os.path.join(os.pardir, 'repository_data', 'keystore')
keystore_directory = os.path.join('repository_data', 'keystore')
public_keypath = os.path.join(keystore_directory, 'root_key.pub')
public_key = repo_tool.import_rsa_publickey_from_file(public_keypath)
target1_filepath = os.path.join(self.targets_directory, 'file1.txt')
@ -793,7 +799,7 @@ def test_delegations(self):
# Test normal case.
# Perform a delegation so that delegations() has a Targets() object to
# return.
keystore_directory = os.path.join(os.pardir, 'repository_data', 'keystore')
keystore_directory = os.path.join('repository_data', 'keystore')
public_keypath = os.path.join(keystore_directory, 'root_key.pub')
public_key = repo_tool.import_rsa_publickey_from_file(public_keypath)
target1_filepath = os.path.join(self.targets_directory, 'file1.txt')
@ -915,7 +921,7 @@ def test_delegate(self):
# Test normal case.
# Need at least one public key and valid target paths required by
# delegate().
keystore_directory = os.path.join(os.pardir, 'repository_data', 'keystore')
keystore_directory = os.path.join('repository_data', 'keystore')
public_keypath = os.path.join(keystore_directory, 'root_key.pub')
public_key = repo_tool.import_rsa_publickey_from_file(public_keypath)
target1_filepath = os.path.join(self.targets_directory, 'file1.txt')
@ -976,7 +982,7 @@ def test_delegate(self):
def test_delegate_hashed_bins(self):
# Test normal case.
keystore_directory = os.path.join(os.pardir, 'repository_data', 'keystore')
keystore_directory = os.path.join('repository_data', 'keystore')
public_keypath = os.path.join(keystore_directory, 'root_key.pub')
public_key = repo_tool.import_rsa_publickey_from_file(public_keypath)
target1_filepath = os.path.join(self.targets_directory, 'file1.txt')
@ -1033,7 +1039,7 @@ def test_add_restricted_paths(self):
# Test normal case.
# Perform a delegation so that add_restricted_paths() has a child role
# to restrict.
keystore_directory = os.path.join(os.pardir, 'repository_data', 'keystore')
keystore_directory = os.path.join('repository_data', 'keystore')
public_keypath = os.path.join(keystore_directory, 'root_key.pub')
public_key = repo_tool.import_rsa_publickey_from_file(public_keypath)
@ -1082,7 +1088,7 @@ def test_add_restricted_paths(self):
def test_revoke(self):
# Test normal case.
# Perform a delegation so that revoke() has a delegation to revoke.
keystore_directory = os.path.join(os.pardir, 'repository_data', 'keystore')
keystore_directory = os.path.join('repository_data', 'keystore')
public_keypath = os.path.join(keystore_directory, 'root_key.pub')
public_key = repo_tool.import_rsa_publickey_from_file(public_keypath)
target1_filepath = os.path.join(self.targets_directory, 'file1.txt')
@ -1188,7 +1194,7 @@ def test_create_new_repository(self):
def test_load_repository(self):
# Test normal case.
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
original_repository_directory = os.path.join(os.pardir, 'repository_data',
original_repository_directory = os.path.join('repository_data',
'repository')
repository_directory = os.path.join(temporary_directory, 'repository')
shutil.copytree(original_repository_directory, repository_directory)
@ -1279,7 +1285,7 @@ def test_import_rsa_privatekey_from_file(self):
# Load one of the pre-generated key files from 'tuf/tests/repository_data'.
# 'password' unlocks the pre-generated key files.
key_filepath = os.path.join(os.pardir, 'repository_data', 'keystore',
key_filepath = os.path.join('repository_data', 'keystore',
'root_key')
self.assertTrue(os.path.exists(key_filepath))
@ -1314,7 +1320,7 @@ def test_import_rsa_publickey_from_file(self):
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
# Load one of the pre-generated key files from 'tuf/tests/repository_data'.
key_filepath = os.path.join(os.pardir, 'repository_data', 'keystore',
key_filepath = os.path.join('repository_data', 'keystore',
'root_key.pub')
self.assertTrue(os.path.exists(key_filepath))
@ -1516,7 +1522,7 @@ def test_get_target_hash(self):
def test_generate_root_metadata(self):
# Test normal case.
# Load the root metadata provided in 'tuf/tests/repository_data/'.
root_filepath = os.path.join(os.pardir, 'repository_data', 'repository',
root_filepath = os.path.join('repository_data', 'repository',
'metadata', 'root.json')
root_signable = tuf.util.load_json_file(root_filepath)
@ -1524,25 +1530,26 @@ def test_generate_root_metadata(self):
# available in 'tuf.keydb' and 'tuf.roledb'.
tuf.roledb.create_roledb_from_root_metadata(root_signable['signed'])
tuf.keydb.create_keydb_from_root_metadata(root_signable['signed'])
expires = '1985-10-21T01:22:00Z'
root_metadata = repo_tool.generate_root_metadata(1, '2088-01-01 12:00:00 UTC',
root_metadata = repo_tool.generate_root_metadata(1, expires,
consistent_snapshot=False)
self.assertTrue(tuf.formats.ROOT_SCHEMA.matches(root_metadata))
# Test improperly formatted arguments.
self.assertRaises(tuf.FormatError, repo_tool.generate_root_metadata,
'3', '2088-01-01 12:00:00 UTC', False)
'3', expires, False)
self.assertRaises(tuf.FormatError, repo_tool.generate_root_metadata,
1, 3, False)
1, '3', False)
self.assertRaises(tuf.FormatError, repo_tool.generate_root_metadata,
1, '2088-01-01 12:00:00 UTC', 3)
1, expires, 3)
# Test for missing required roles and keys.
tuf.roledb.clear_roledb()
tuf.keydb.clear_keydb()
self.assertRaises(tuf.Error, repo_tool.generate_root_metadata,
1, '2088-01-01 12:00:00 UTC', False)
1, expires, False)
@ -1558,7 +1565,8 @@ def test_generate_targets_metadata(self):
# Set valid generate_targets_metadata() arguments.
version = 1
expiration_date = '2088-01-01 12:00:00 UTC'
datetime_object = datetime.datetime(2030, 01, 01, 12, 00)
expiration_date = datetime_object.isoformat() + 'Z'
target_files = ['file.txt']
delegations = {"keys": {
@ -1611,7 +1619,7 @@ def test_generate_targets_metadata(self):
self.assertRaises(tuf.FormatError, repo_tool.generate_targets_metadata,
targets_directory, target_files, '3', expiration_date)
self.assertRaises(tuf.FormatError, repo_tool.generate_targets_metadata,
targets_directory, target_files, version, 3)
targets_directory, target_files, version, '3')
# Improperly formatted 'delegations' and 'write_consistent_targets'
self.assertRaises(tuf.FormatError, repo_tool.generate_targets_metadata,
@ -1633,7 +1641,7 @@ def test_generate_targets_metadata(self):
def test_generate_snapshot_metadata(self):
# Test normal case.
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
original_repository_path = os.path.join(os.pardir, 'repository_data',
original_repository_path = os.path.join('repository_data',
'repository')
repository_directory = os.path.join(temporary_directory, 'repository')
shutil.copytree(original_repository_path, repository_directory)
@ -1643,7 +1651,7 @@ def test_generate_snapshot_metadata(self):
targets_filename = os.path.join(metadata_directory,
repo_tool.TARGETS_FILENAME)
version = 1
expiration_date = '2088-01-01 12:00:00 UTC'
expiration_date = '1985-10-21T13:20:00Z'
snapshot_metadata = \
repo_tool.generate_snapshot_metadata(metadata_directory, version,
@ -1661,7 +1669,7 @@ def test_generate_snapshot_metadata(self):
metadata_directory, '3', expiration_date,
root_filename, targets_filename, consistent_snapshot=False)
self.assertRaises(tuf.FormatError, repo_tool.generate_snapshot_metadata,
metadata_directory, version, 3,
metadata_directory, version, '3',
root_filename, targets_filename, consistent_snapshot=False)
self.assertRaises(tuf.FormatError, repo_tool.generate_snapshot_metadata,
metadata_directory, version, expiration_date,
@ -1678,7 +1686,7 @@ def test_generate_snapshot_metadata(self):
def test_generate_timestamp_metadata(self):
# Test normal case.
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
original_repository_path = os.path.join(os.pardir, 'repository_data',
original_repository_path = os.path.join('repository_data',
'repository')
repository_directory = os.path.join(temporary_directory, 'repository')
shutil.copytree(original_repository_path, repository_directory)
@ -1689,7 +1697,8 @@ def test_generate_timestamp_metadata(self):
# Set valid generate_timestamp_metadata() arguments.
version = 1
expiration_date = '2088-01-01 12:00:00 UTC'
expiration_date = '1985-10-21T13:20:00Z'
compressions = ['gz']
snapshot_metadata = \
@ -1704,7 +1713,7 @@ def test_generate_timestamp_metadata(self):
self.assertRaises(tuf.FormatError, repo_tool.generate_timestamp_metadata,
snapshot_filename, '3', expiration_date, compressions)
self.assertRaises(tuf.FormatError, repo_tool.generate_timestamp_metadata,
snapshot_filename, version, 3, compressions)
snapshot_filename, version, '3', compressions)
self.assertRaises(tuf.FormatError, repo_tool.generate_timestamp_metadata,
snapshot_filename, version, expiration_date, 3)
self.assertRaises(tuf.FormatError, repo_tool.generate_timestamp_metadata,
@ -1716,9 +1725,9 @@ def test_generate_timestamp_metadata(self):
def test_sign_metadata(self):
# Test normal case.
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
metadata_path = os.path.join(os.pardir, 'repository_data',
metadata_path = os.path.join('repository_data',
'repository', 'metadata')
keystore_path = os.path.join(os.pardir, 'repository_data',
keystore_path = os.path.join('repository_data',
'keystore')
root_filename = os.path.join(metadata_path, 'root.json')
root_metadata = tuf.util.load_json_file(root_filename)['signed']
@ -1757,7 +1766,7 @@ def test_sign_metadata(self):
def test_write_metadata_file(self):
# Test normal case.
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
metadata_directory = os.path.join(os.pardir, 'repository_data',
metadata_directory = os.path.join('repository_data',
'repository', 'metadata')
root_filename = os.path.join(metadata_directory, 'root.json')
root_signable = tuf.util.load_json_file(root_filename)
@ -1787,7 +1796,7 @@ def test_write_metadata_file(self):
def test_create_tuf_client_directory(self):
# Test normal case.
temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory)
repository_directory = os.path.join(os.pardir, 'repository_data',
repository_directory = os.path.join('repository_data',
'repository')
client_directory = os.path.join(temporary_directory, 'client')

View file

@ -320,7 +320,7 @@ def test_create_roledb_from_root_metadata(self):
'targets': {'keyids': [keyid2], 'threshold': 1}}
version = 8
consistent_snapshot = False
expires = '2012-10-16 06:42:12 UTC'
expires = '1985-10-21T01:21:00Z'
root_metadata = tuf.formats.RootFile.make_metadata(version,
expires,

View file

@ -53,7 +53,7 @@
import tuf.util
import tuf.log
import tuf.client.updater as updater
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox
logger = logging.getLogger('tuf.test_slow_retrieval_attack')
@ -124,8 +124,7 @@ def setUp(self):
# Copy the original repository files provided in the test folder so that
# any modifications made to repository files are restricted to the copies.
# The 'repository_data' directory is expected to exist in 'tuf/tests/'.
original_repository_files = os.path.join(os.getcwd(), os.pardir,
'repository_data')
original_repository_files = os.path.join(os.getcwd(), 'repository_data')
temporary_repository_root = \
self.make_temp_directory(directory=self.temporary_directory)

View file

@ -56,7 +56,7 @@
import tuf.keydb
import tuf.roledb
import tuf.repository_tool as repo_tool
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox
import tuf.client.updater as updater
logger = logging.getLogger('tuf.test_updater')
@ -120,8 +120,7 @@ def setUp(self):
# Copy the original repository files provided in the test folder so that
# any modifications made to repository files are restricted to the copies.
# The 'repository_data' directory is expected to exist in 'tuf.tests/'.
original_repository_files = os.path.join(os.getcwd(), os.pardir,
'repository_data')
original_repository_files = os.path.join(os.getcwd(), 'repository_data')
temporary_repository_root = \
self.make_temp_directory(directory=self.temporary_directory)
@ -465,7 +464,8 @@ def test_2__ensure_not_expired(self):
# 'tuf.ExpiredMetadataError' should be raised in this next test condition,
# because the expiration_date has expired by 10 seconds.
expires = tuf.formats.format_time(time.time() - 10)
expires = tuf.formats.unix_timestamp_to_datetime(int(time.time() - 10))
expires = expires.isoformat() + 'Z'
self.repository_updater.metadata['current']['root']['expires'] = expires
# Ensure the 'expires' value of the root file is valid by checking the

View file

@ -14,7 +14,7 @@
See LICENSE for licensing information.
<Purpose>
util.py unit tests.
Unit test for 'util.py'
"""
import os
@ -29,7 +29,7 @@
import tuf.log
import tuf.hash
import tuf.util as util
import tuf.tests.unittest_toolbox as unittest_toolbox
import tests.unittest_toolbox as unittest_toolbox
logger = logging.getLogger('tuf.test_util')

View file

@ -1,355 +0,0 @@
"""
<Program Name>
test_keystore.py
<Author>
Konstantin Andrianov
<Started>
April 27, 2012.
<Copyright>
See LICENSE for licensing information.
<Purpose>
Unit test for keystore.py.
"""
import unittest
import shutil
import os
import logging
import Crypto.Random
import Crypto.Protocol.KDF
import tuf
import tuf.repo.keystore
import tuf.keys
import tuf.formats
import tuf.util
import tuf.log
logger = logging.getLogger('tuf.test_keystore')
# We'll need json module for testing '_encrypt()' and '_decrypt()'
# internal function.
json = tuf.util.import_json()
tuf.repo.keystore._PBKDF2_ITERATIONS = 1000
# Creating a directory string in current directory.
_CURRENT_DIR = os.getcwd()
_DIR = os.path.join(_CURRENT_DIR, 'test_keystore')
# Check if directory '_DIR' exists.
if os.path.exists(_DIR):
msg = ('\''+_DIR+'\' directory already exists,'+
' please change '+'\'_DIR\''+' to something else.')
raise tuf.Error(msg)
KEYSTORE = tuf.repo.keystore
RSAKEYS = []
PASSWDS = []
temp_keys_info = []
temp_keys_vals = []
for i in range(3):
# Populating the original 'RSAKEYS' and 'PASSWDS' lists.
RSAKEYS.append(tuf.keys.generate_rsa_key())
PASSWDS.append('passwd_'+str(i))
# Saving original copies of 'RSAKEYS' and 'PASSWDS' to temp variables
# in order to repopulate them at the start of every test.
temp_keys_info.append(RSAKEYS[i].values())
temp_keys_vals.append(RSAKEYS[i]['keyval'].values())
temp_passwds=list(PASSWDS)
class TestKeystore(unittest.TestCase):
def setUp(self):
# Returning 'RSAKEY' and 'PASSWDS' to original state.
for i in range(len(temp_keys_info)):
RSAKEYS[i]['keytype'] = temp_keys_info[i][0]
RSAKEYS[i]['keyid'] = temp_keys_info[i][1]
RSAKEYS[i]['keyval'] = temp_keys_info[i][2]
RSAKEYS[i]['keyval']['public'] = temp_keys_vals[i][0]
RSAKEYS[i]['keyval']['private'] = temp_keys_vals[i][1]
PASSWDS[i] = temp_passwds[i]
def tearDown(self):
# Empty keystore's databases.
KEYSTORE.clear_keystore()
# Check if directory '_DIR' exists, remove it if it does.
if os.path.exists(_DIR):
shutil.rmtree(_DIR)
def test_clear_keystore(self):
# Populate KEYSTORE's internal databases '_keystore' and '_derived_keys'.
for i in range(3):
KEYSTORE.add_rsakey(RSAKEYS[i], PASSWDS[i], RSAKEYS[i]['keyid'])
# Verify KEYSTORE's internal databases ARE NOT EMPTY.
self.assertTrue(len(KEYSTORE._keystore) > 0)
self.assertTrue(len(KEYSTORE._derived_keys) > 0)
# Clear KEYSTORE's internal databases.
KEYSTORE.clear_keystore()
# Verify KEYSTORE's internal databases ARE EMPTY.
self.assertFalse(len(KEYSTORE._keystore) > 0)
self.assertFalse(len(KEYSTORE._derived_keys) > 0)
def test_add_rsakey(self):
# Passing 2 arguments to the function and verifying that the internal
# databases have been modified.
KEYSTORE.add_rsakey(RSAKEYS[0], PASSWDS[0])
self.assertEqual(RSAKEYS[0], KEYSTORE._keystore[RSAKEYS[0]['keyid']],
'Adding an rsa key dict was unsuccessful.')
self.assertTrue(len(KEYSTORE._derived_keys) == 1,
'Adding a password pertaining to \'_keyid\' was unsuccessful.')
# Passing three arguments to the function, i.e. including the 'keyid'.
KEYSTORE.add_rsakey(RSAKEYS[1], PASSWDS[1], RSAKEYS[1]['keyid'])
self.assertEqual(RSAKEYS[1],
KEYSTORE._keystore[RSAKEYS[1]['keyid']],
'Adding an rsa key dict was unsuccessful.')
self.assertTrue(len(KEYSTORE._derived_keys) == 2,
'Adding a password pertaining to \'_keyid\' was unsuccessful.')
# Passing a keyid that does not match the keyid in 'rsakey_dict'.
_keyid = 'somedifferentkey123456789'
self.assertRaises(tuf.Error, KEYSTORE.add_rsakey, RSAKEYS[2],
PASSWDS[2], _keyid)
# Passing an existing 'rsakey_dict' object.
self.assertRaises(tuf.KeyAlreadyExistsError, KEYSTORE.add_rsakey,
RSAKEYS[1], PASSWDS[1], RSAKEYS[1]['keyid'])
# Passing an 'rsakey_dict' that does not conform to the 'RSAKEY_SCHEMA'.
del RSAKEYS[2]['keytype']
self.assertRaises(tuf.FormatError, KEYSTORE.add_rsakey,
RSAKEYS[2], PASSWDS[2], RSAKEYS[2]['keyid'])
def test_save_keystore_to_keyfiles(self):
# Extract and store keyids in '_keyids' list.
keyids = []
# Populate KEYSTORE's internal databases '_keystore' and '_derived_keys'.
for i in range(3):
KEYSTORE.add_rsakey(RSAKEYS[i], PASSWDS[i], RSAKEYS[i]['keyid'])
keyids.append(RSAKEYS[i]['keyid'])
# Check if directory '_DIR' exists, remove it if it does.
if os.path.exists(_DIR):
shutil.rmtree(_DIR)
KEYSTORE.save_keystore_to_keyfiles(_DIR)
# Check if directory '_DIR' has been created.
self.assertTrue(os.path.exists(_DIR), 'Creating directory failed.')
# Check if all of the key files where created and that they are not empty.
for keyid in keyids:
key_file = os.path.join(_DIR, str(keyid)+'.key')
# Checks if key file has been created.
self.assertTrue(os.path.exists(key_file), 'Key file does not exist.')
file_stats = os.stat(key_file)
# Checks if key file is not empty.
self.assertTrue(file_stats.st_size > 0)
# Passing an invalid 'directory_name' argument - an integer value.
self.assertRaises(tuf.FormatError, KEYSTORE.save_keystore_to_keyfiles, 222)
def test_load_keystore_from_keyfiles(self):
keyids = []
# Check if '_DIR' directory exists, if not - create it.
if not os.path.exists(_DIR):
# Populate KEYSTORE's internal databases.
for i in range(3):
KEYSTORE.add_rsakey(RSAKEYS[i], PASSWDS[i], RSAKEYS[i]['keyid'])
keyids.append(RSAKEYS[i]['keyid'])
# Create the key files.
KEYSTORE.save_keystore_to_keyfiles(_DIR)
# Clearing internal databases.
KEYSTORE.clear_keystore()
# Test normal conditions where two valid arguments are passed.
loaded_keys = KEYSTORE.load_keystore_from_keyfiles(_DIR, keyids, PASSWDS)
# Loaded keys should all be contained in 'keyids'.
loaded_keys_set = set(loaded_keys)
keyids_set = set(keyids)
intersect = keyids_set.intersection(loaded_keys_set)
self.assertEquals(len(intersect), len(keyids))
for i in range(3):
self.assertEqual(RSAKEYS[i], KEYSTORE._keystore[RSAKEYS[i]['keyid']])
# Clearing internal databases.
KEYSTORE.clear_keystore()
_invalid_dir = os.path.join(_CURRENT_DIR, 'invalid_directory')
# Passing an invalid 'directory_name' argument - a directory that
# does not exist. AS EXPECTED, THIS CALL SHOULDN'T RAISE ANY ERRORS.
KEYSTORE.load_keystore_from_keyfiles(_invalid_dir, keyids, PASSWDS)
# The keystore should not have loaded any keys.
self.assertEqual(0, len(KEYSTORE._keystore))
self.assertEqual(0, len(KEYSTORE._derived_keys))
# Passing nonexistent 'keyids'.
# AS EXPECTED, THIS CALL SHOULDN'T RAISE ANY ERRORS.
invalid_keyids = ['333', '333', '333']
KEYSTORE.load_keystore_from_keyfiles(_DIR, invalid_keyids, PASSWDS)
# The keystore should not have loaded any keys.
self.assertEqual(0, len(KEYSTORE._keystore))
self.assertEqual(0, len(KEYSTORE._derived_keys))
# Passing an invalid 'directory_name' argument - an integer value.
self.assertRaises(tuf.FormatError, KEYSTORE.load_keystore_from_keyfiles,
333, keyids, PASSWDS)
# Passing an invalid 'passwords' argument - a string value.
self.assertRaises(tuf.FormatError, KEYSTORE.load_keystore_from_keyfiles,
_DIR, keyids, '333')
# Passing an invalid 'passwords' argument - an integer value.
self.assertRaises(tuf.FormatError, KEYSTORE.load_keystore_from_keyfiles,
_DIR, keyids, 333)
# Passing an invalid 'keyids' argument - a string value.
self.assertRaises(tuf.FormatError, KEYSTORE.load_keystore_from_keyfiles,
_DIR, '333', PASSWDS)
# Passing an invalid 'keyids' argument - an integer value.
self.assertRaises(tuf.FormatError, KEYSTORE.load_keystore_from_keyfiles,
_DIR, 333, PASSWDS)
def test_change_password(self):
# Populate KEYSTORE's internal databases.
for i in range(2):
KEYSTORE.add_rsakey(RSAKEYS[i], PASSWDS[i], RSAKEYS[i]['keyid'])
derived_key_0 = KEYSTORE._derived_keys[RSAKEYS[0]['keyid']]
# Create a new password.
new_passwd = 'changed_password'
# Change a password - normal case.
KEYSTORE.change_password(RSAKEYS[0]['keyid'], PASSWDS[0], new_passwd)
# Check if password was changed.
new_derived_key = KEYSTORE._derived_keys[RSAKEYS[0]['keyid']]['derived_key']
self.assertNotEqual(new_derived_key,
derived_key_0['derived_key'])
# Passing an invalid keyid (i.e., RSAKEY[2] that was not loaded into
# the '_keystore').
self.assertRaises(tuf.UnknownKeyError, KEYSTORE.change_password,
RSAKEYS[2]['keyid'], PASSWDS[1], new_passwd)
# Passing an incorrect old password.
self.assertRaises(tuf.BadPasswordError, KEYSTORE.change_password,
RSAKEYS[1]['keyid'], PASSWDS[2], new_passwd)
def test_get_key(self):
# Populate KEYSTORE's internal databases.
for i in range(2):
KEYSTORE.add_rsakey(RSAKEYS[i], PASSWDS[i], RSAKEYS[i]['keyid'])
# Get a key - normal case.
self.assertEqual(KEYSTORE.get_key(RSAKEYS[0]['keyid']), RSAKEYS[0])
# Passing an invalid keyid.
self.assertRaises(tuf.UnknownKeyError,
KEYSTORE.get_key, RSAKEYS[2]['keyid'])
# Passing an invalid keyid format.
self.assertRaises(tuf.FormatError, KEYSTORE.get_key, 123)
def test_internal_encrypt(self):
# Test for valid arguments to '_encrypt()' and a valid return type.
salt = Crypto.Random.new().read(16)
iterations = tuf.repo.keystore._PBKDF2_ITERATIONS
derived_key = Crypto.Protocol.KDF.PBKDF2(PASSWDS[0], salt)
derived_key_information = {'salt': salt, 'derived_key': derived_key,
'iterations': iterations}
encrypted_key = KEYSTORE._encrypt(json.dumps(RSAKEYS[0]),
derived_key_information)
self.assertEqual(type(encrypted_key), str)
def test_internal_decrypt(self):
del RSAKEYS[0]['keyid']
tuf.formats.KEY_SCHEMA.check_match(RSAKEYS[0])
salt = Crypto.Random.new().read(16)
salt, iterations, derived_key = \
tuf.repo.keystore._generate_derived_key(PASSWDS[0], salt)
derived_key_information = {'salt': salt,
'iterations': iterations,
'derived_key': derived_key}
# Getting a valid encrypted key using '_encrypt()'.
encrypted_key = KEYSTORE._encrypt(json.dumps(RSAKEYS[0]),
derived_key_information)
# Decrypting and decoding (using json's loads()) an encrypted file.
#tuf.util.load_json_string(KEYSTORE._decrypt(encrypted_key, PASSWDS[0]))
json.dumps(KEYSTORE._decrypt(encrypted_key, PASSWDS[0]))
self.assertEqual(RSAKEYS[0], tuf.util.load_json_string(
KEYSTORE._decrypt(encrypted_key, PASSWDS[0])))
# Passing an invalid password to try to decrypt the file.
self.assertRaises(tuf.CryptoError, KEYSTORE._decrypt,
encrypted_key, PASSWDS[1])
def setUpModule():
# setUpModule() is called before any test cases run.
# Ensure the keystore has not been modified by a previous test, which may
# affect assumptions (i.e., empty keystore) made by the tests cases in this
# unit test.
tuf.repo.keystore.clear_keystore()
def tearDownModule():
# tearDownModule() is called after all the tests have run.
# Ensure we clean up the keystore. They say courtesy is contagious.
tuf.repo.keystore.clear_keystore()
# Run the unit tests.
if __name__ == '__main__':
unittest.main()

View file

@ -1,166 +0,0 @@
"""
<Program Name>
test_push.py
<Author>
Konstantin Andrianov
<Started>
April 2013.
<Copyright>
See LICENSE for licensing information.
<Purpose>
Test push.py.
"""
import os
import getpass
import logging
import tempfile
import unittest
import ConfigParser
import tuf
import tuf.log
import tuf.pushtools.push as push
import tuf.pushtools.transfer.scp as scp
import tuf.pushtools.pushtoolslib as pushtoolslib
import tuf.tests.util_test_tools as util_test_tools
logger = logging.getLogger('tuf.test_push')
class TestPush(unittest.TestCase):
src_push_dict = {}
ORIGINAL_PUSH_CONFIG = pushtoolslib.PUSH_CONFIG
@staticmethod
def _mock_scp_transfer(config_dict):
pass
@staticmethod
def write_config_file(config_filename, config_dictionary):
"""Create a configuration file by writing supplied configuration
dictionary ('config_dictionary') into the file ('config_filename')."""
config = ConfigParser.RawConfigParser()
for section, values_dict in config_dictionary.iteritems():
config.add_section(section)
for key in values_dict:
config.set(section, key, values_dict[key])
# Writing our configuration file to 'config_filename'.
with open(config_filename, 'wb') as configfile:
config.write(configfile)
def setUp(self):
# Create push configuration file, general temporary dir 'root_repo'.
cwd = os.getcwd()
self.push_config = tempfile.mkstemp(prefix='tmp_push_conf_', dir=cwd)[1]
self.root_repo = tempfile.mkdtemp(prefix='tmp_tuf_repo_', dir=cwd)
# Drop target files into the working project directory 'reg_repo'.
# When targets metadata updates, the target files in the 'reg_repo'
# will be copied into the tuf's targets directory.
self.reg_repo = os.path.join(self.root_repo, 'reg_repo')
os.mkdir(self.reg_repo)
# Add a file to the 'reg_repo'.
util_test_tools.add_file_to_repository(self.reg_repo, data='Test String')
# Create TUF repository.
util_test_tools.init_tuf(self.root_repo)
# Update the tuf targets metadata.
util_test_tools.make_targets_meta(self.root_repo)
# Populate 'src_push_dict'.
targets_dir = os.path.join(self.root_repo, 'tuf_repo', 'targets')
metadate_path = os.path.join(self.root_repo, 'tuf_repo', 'metadata',
'targets.txt')
remote_dir = tempfile.mkdtemp(prefix='tmp_tuf_repo_', dir=self.root_repo)
self.src_push_dict = {'general':{'transfer_module':'scp',
'metadata_path':metadate_path,
'targets_directory':targets_dir},
'scp':{'host':'localhost',
'identity_file':None,
'user':getpass.getuser(),
'remote_directory':remote_dir}}
# Write the config dictionary into the push configuration file.
self.write_config_file(self.push_config, self.src_push_dict)
# Patch 'pushtoolslib.PUSH_CONFIG'.
pushtoolslib.PUSH_CONFIG = os.path.basename(self.push_config)
def tearDown(self):
# Remove tempfile.
os.remove(self.push_config)
# Remove TUF repository.
util_test_tools.cleanup(self.root_repo)
# Clear 'src_push_dict'.
self.src_push_dict.clear()
# # Reassign 'pushtoolslib.PUSH_CONFIG'.
pushtoolslib.PUSH_CONFIG = self.ORIGINAL_PUSH_CONFIG
def test_expected_behaviour_of_push_without_scp(self):
# Patch 'scp.transfer' function.
ORIGINAL_SCP_TRANSFER_MODULE = scp.transfer
scp.transfer = self._mock_scp_transfer
push.push(self.push_config)
# Restore 'scp.transfer' function.
scp.transfer = ORIGINAL_SCP_TRANSFER_MODULE
def test_exceptions_handeling_of_push_without_scp(self):
# Patch 'scp.transfer' function.
ORIGINAL_SCP_TRANSFER_MODULE = scp.transfer
scp.transfer = self._mock_scp_transfer
self.assertRaises(tuf.Error, push.push, self.root_repo)
self.assertRaises(tuf.FormatError, push.push, None)
self.assertRaises(tuf.FormatError, push.push, 12345)
self.assertRaises(tuf.FormatError, push.push, ['test'])
self.assertRaises(tuf.FormatError, push.push, {'test':'test'})
# Restore 'scp.transfer' function.
scp.transfer = ORIGINAL_SCP_TRANSFER_MODULE
# Unit test bellow executes secure copy 'scp' command. Hence user's
# password is requered. Comment-out or remove the line bellow to
# un-skip the unit test.
@unittest.skip("Requires user's password!")
def test_expected_behaviour_of_push_with_scp(self):
push.push(self.push_config)
# Run the unittests
if __name__ == '__main__':
unittest.main()

View file

@ -1,173 +0,0 @@
"""
<Program Name>
test_pushtoolslib.py
<Author>
Konstantin Andrianov
<Started>
April 2013.
<Copyright>
See LICENSE for licensing information.
<Purpose>
Test pushtoolslib.py.
"""
import os
import tempfile
import unittest
import ConfigParser
import logging
import tuf
import tuf.log
import tuf.formats
import tuf.pushtools.pushtoolslib as pushtoolslib
logger = logging.getLogger('tuf.test_pushtoolslib')
class TestPushtoolslib(unittest.TestCase):
src_push_dict = {}
src_receive_dict = {}
ORIGINAL_PUSH_CONFIG = pushtoolslib.PUSH_CONFIG
ORIGINAL_RECEIVE_CONFIG = pushtoolslib.RECEIVE_CONFIG
def setUp(self):
# Create config tempfiles.
cwd = os.getcwd()
self.push_config_file = tempfile.mkstemp(prefix='tmp_push_conf_', dir=cwd)[1]
self.receive_config_file = tempfile.mkstemp(prefix='tmp_receive_conf_', dir=cwd)[1]
# Populate 'src_push_dict' and 'src_receive_dict'.
self.src_push_dict = {'general':{'transfer_module':'scp',
'metadata_path':'some/path',
'targets_directory':'some/path'},
'scp':{'host':'localhost',
'user':'user',
'identity_file':None,
'remote_directory':'~/pushes'}}
self.src_receive_dict = {'general':{'pushroots':['some/path'],
'repository_directory':'some/path',
'metadata_directory':'some/path',
'targets_directory':'some/path',
'backup_directory':'some/path'}}
# Patch the 'pushtoolslib.PUSH_CONFIG' and 'pushtoolslib.RECEIVE_CONFIG'
pushtoolslib.PUSH_CONFIG = os.path.basename(self.push_config_file)
pushtoolslib.RECEIVE_CONFIG = os.path.basename(self.receive_config_file)
def tearDown(self):
# Remove tempfile.
os.remove(self.push_config_file)
os.remove(self.receive_config_file)
# Clear dictionaries.
self.src_push_dict.clear()
self.src_receive_dict.clear()
# Reassign 'pushtoolslib.PUSH_CONFIG' and 'pushtoolslib.RECEIVE_CONFIG'
# to original values.
pushtoolslib.PUSH_CONFIG = self.ORIGINAL_PUSH_CONFIG
pushtoolslib.RECEIVE_CONFIG = self.ORIGINAL_RECEIVE_CONFIG
@staticmethod
def write_config_file(config_filename, config_dictionary):
"""Create a configuration file by writing supplied configuration
dictionary ('config_dictionary') into the file ('config_filename')."""
config = ConfigParser.RawConfigParser()
for section, values_dict in config_dictionary.iteritems():
config.add_section(section)
for key in values_dict:
config.set(section, key, values_dict[key])
# Writing our configuration file to 'config_filename'.
with open(config_filename, 'wb') as configfile:
config.write(configfile)
def test_expected_behavior_of_read_config_file(self):
# Test 'push' configuration type.
self.write_config_file(self.push_config_file, self.src_push_dict)
config_dict = pushtoolslib.read_config_file(self.push_config_file, 'push')
tuf.formats.SCPCONFIG_SCHEMA.check_match(config_dict)
# Test 'receive' configuration type.
self.write_config_file(self.receive_config_file, self.src_receive_dict)
config_dict = pushtoolslib.read_config_file(self.receive_config_file, 'receive')
tuf.formats.RECEIVECONFIG_SCHEMA.check_match(config_dict)
def test_exceptions_handeling_of_read_config_file(self):
# Test an incorrect configuration file.
with open(self.push_config_file, 'wb') as configfile:
configfile.write('test')
self.assertRaises(tuf.Error, pushtoolslib.read_config_file,
self.push_config_file, 'push')
self.write_config_file(self.push_config_file, {})
self.assertRaises(tuf.Error, pushtoolslib.read_config_file,
self.push_config_file, 'push')
self.write_config_file(self.receive_config_file, self.src_receive_dict)
self.assertRaises(tuf.Error, pushtoolslib.read_config_file,
self.receive_config_file, 'push')
self.write_config_file(self.push_config_file, self.src_push_dict)
self.assertRaises(tuf.Error, pushtoolslib.read_config_file,
self.push_config_file, 'receive')
# Test incorrect configuration type.
self.write_config_file(self.push_config_file, self.src_push_dict)
self.assertRaises(tuf.Error, pushtoolslib.read_config_file,
self.push_config_file, 'junk')
# Test 'push' type configuration with 'transfer_module' absent from
# config_dict['general'].
saved_transfer_module = self.src_push_dict['general']['transfer_module']
del self.src_push_dict['general']['transfer_module']
self.write_config_file(self.push_config_file, self.src_push_dict)
self.assertRaises(tuf.Error, pushtoolslib.read_config_file,
self.push_config_file, 'push')
# Test 'push' type configuration with
# config_dict['general']['transfer_module'] != 'scp'.
self.src_push_dict['general']['transfer_module'] = 'test'
self.write_config_file(self.push_config_file, self.src_push_dict)
self.assertRaises(tuf.Error, pushtoolslib.read_config_file,
self.push_config_file, 'push')
# Test 'push' type configuration with one of the keys missing.
self.src_push_dict['general']['transfer_module'] = 'scp'
del self.src_push_dict['general']['metadata_path']
self.write_config_file(self.push_config_file, self.src_push_dict)
self.assertRaises(tuf.FormatError, pushtoolslib.read_config_file,
self.push_config_file, 'push')
# Test 'receive' type configuration with one of the keys missing.
del self.src_receive_dict['general']['repository_directory']
self.write_config_file(self.receive_config_file, self.src_receive_dict)
self.assertRaises(tuf.FormatError, pushtoolslib.read_config_file,
self.receive_config_file, 'receive')
# Run the unittests
if __name__ == '__main__':
unittest.main()

View file

@ -1,195 +0,0 @@
"""
<Program Name>
test_quickstart.py
<Author>
Konstantin Andrianov
<Started>
September 6, 2012
<Copyright>
See LICENSE for licensing information.
<Purpose>
To test quickstart.py for expected/unexpected input by the user, verifying
that all unexpected input is caught and an exception is raised.
Given that all message prompts don't change - this will work pretty well
for running quickstart without having to manually enter input to prompts
every time you want to run quickstart.
"""
import os
import shutil
import unittest
import logging
import tuf
import tuf.log
import tuf.repo.quickstart as quickstart
import tuf.util
import tuf.tests.unittest_toolbox as unittest_toolbox
logger = logging.getLogger('tuf.test_quickstart')
unit_tbox = unittest_toolbox.Modified_TestCase
logger.info('from test_quickstart')
class TestQuickstart(unit_tbox):
def test_1_get_password(self):
# SETUP
original_getpass = quickstart.getpass.getpass
# A quick test of _get_password.
password = self.random_string()
def _mock_getpass(junk1, junk2, pw = password):
return pw
# Monkey patch getpass.getpass().
quickstart.getpass.getpass = _mock_getpass
# Run _get_password().
self.assertEqual(quickstart._get_password(), password)
# RESTORE
quickstart.getpass.getpass = original_getpass
def test_2_build_repository(self):
# SETUP
original_prompt = quickstart._prompt
original_get_password = quickstart._get_password
# Create the project directories.
repo_dir = os.path.join(os.getcwd(), 'repository')
keystore_dir = os.path.join(os.getcwd(), 'keystore')
client_dir = os.path.join(os.getcwd(), 'client')
proj_files = self.make_temp_directory_with_data_files()
proj_dir = os.path.join(proj_files[0], 'targets')
input_dict = {'expiration':'12/12/2020',
'root':{'threshold':1, 'password':'pass'},
'targets':{'threshold':1, 'password':'pass'},
'release':{'threshold':1, 'password':'pass'},
'timestamp':{'threshold':1, 'password':'pass'}}
def _mock_prompt(message, confirm=False, input_parameters=input_dict):
if message.startswith('\nWhen would you like your '+
'"root.txt" metadata to expire?'):
return input_parameters['expiration']
for role in self.role_list: # role_list=['root', 'targets', ...]
if message.startswith('\nEnter the desired threshold '+
'for the role '+repr(role)):
return input_parameters[role]['threshold']
elif message.startswith('Enter a password for '+repr(role)):
for threshold in range(input_parameters[role]['threshold']):
if message.endswith(repr(role)+' ('+str(threshold+1)+'): '):
return input_parameters[role]['password']
print 'Cannot recognize message: '+message
# Monkey patching quickstart's _prompt() and _get_password.
quickstart._prompt = _mock_prompt
quickstart._get_password = _mock_prompt
def _remove_repository_directories(repo_dir, keystore_dir, client_dir):
"""
quickstart.py creates the 'client', 'keystore', and 'repository'
directories in the current working directory. Remove these
directories after every quickstart.build_repository() call.
"""
try:
shutil.rmtree(repo_dir)
shutil.rmtree(keystore_dir)
shutil.rmtree(client_dir)
except OSError, e:
pass
# TESTS
# TEST: various input parameters.
# Supplying bogus expiration.
input_dict['expiration'] = '5/8/2011'
self.assertRaises(tuf.RepositoryError, quickstart.build_repository,
proj_dir)
# Random string.
input_dict['expiration'] = self.random_string()
self.assertRaises(tuf.RepositoryError, quickstart.build_repository,
proj_dir)
_remove_repository_directories(repo_dir, keystore_dir, client_dir)
# Restore expiration.
input_dict['expiration'] = '10/10/2020'
# Supplying bogus 'root' threshold. Doing this for all roles slows
# the test significantly.
input_dict['root']['threshold'] = self.random_string()
self.assertRaises(tuf.RepositoryError, quickstart.build_repository,
proj_dir)
_remove_repository_directories(repo_dir, keystore_dir, client_dir)
input_dict['root']['threshold'] = 0
self.assertRaises(tuf.RepositoryError, quickstart.build_repository,
proj_dir)
_remove_repository_directories(repo_dir, keystore_dir, client_dir)
# Restore keystore directory.
input_dict['root']['threshold'] = 1
# TEST: normal case.
try:
quickstart.build_repository(proj_dir)
except Exception, e:
raise
# Verify the existence of metadata, target, and keystore files.
meta_dir = os.path.join(repo_dir, 'metadata')
targets_dir = os.path.join(repo_dir, 'targets')
client_current_meta_dir = os.path.join(client_dir, 'metadata', 'current')
client_previous_meta_dir = os.path.join(client_dir, 'metadata', 'previous')
target_files = os.listdir(targets_dir)
# Verify repository, keystore, metadata, and targets directories.
self.assertTrue(os.path.exists(repo_dir))
self.assertTrue(os.path.exists(keystore_dir))
self.assertTrue(os.path.exists(meta_dir))
self.assertTrue(os.path.exists(targets_dir))
self.assertTrue(os.path.exists(client_current_meta_dir))
self.assertTrue(os.path.exists(client_previous_meta_dir))
# Verify that target_files exist.
self.assertTrue(target_files)
for role in self.role_list:
meta_file = role+'.txt'
# Verify metadata file for a 'role'.
self.assertTrue(os.path.isfile(os.path.join(meta_dir, meta_file)))
# Get the metadata.
signable = tuf.util.load_json_file(os.path.join(meta_dir, meta_file))
for signature in range(len(signable['signatures'])):
# Extract a keyid.
keyid = signable['signatures'][signature]['keyid']
key_file = os.path.join(keystore_dir, keyid+'.key')
# Verify existence of a key for the keyid that belong to the 'role'.
self.assertTrue(os.path.isfile(key_file))
_remove_repository_directories(repo_dir, keystore_dir, client_dir)
# RESTORE
quickstart._prompt = original_prompt
quickstart._get_password = original_get_password
# Run the unit tests.
if __name__ == '__main__':
unittest.main()

File diff suppressed because it is too large Load diff

View file

@ -1,986 +0,0 @@
"""
<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()

View file

@ -1,48 +0,0 @@
"""
<Program>
simple_server.py
<Author>
Konstantin Andrianov
<Started>
February 15, 2012
<Copyright>
See LICENSE for licensing information.
<Purpose>
This is a basic server that was designed to be used in conjunction with
test_download.py to test download.py module.
<Referencesi>
SimpleHTTPServer:
http://docs.python.org/library/simplehttpserver.html#module-SimpleHTTPServer
"""
import sys
import random
import SimpleHTTPServer
import SocketServer
PORT = 0
def _port_gen():
return random.randint(30000, 45000)
if len(sys.argv) > 1:
try:
PORT = int(sys.argv[1])
if PORT < 30000 or PORT > 45000:
raise ValueError
except ValueError:
PORT = _port_gen()
else:
PORT = _port_gen()
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
#print "PORT: ", PORT
httpd.serve_forever()

View file

@ -1,86 +0,0 @@
"""
<Program Name>
statement_coverage.py
<Author>
Konstantin Andrianov
<Started>
March 20, 2013.
<Copyright>
See LICENSE for licensing information.
<Purpose>
Measure test coverage.
NOTE: This script is based on third party software. In order to use this
script install Ned Batchelder's coverage.py:
http://nedbatchelder.com/code/coverage/
"""
import os
import sys
# Try to import coverage.py. Coverage.py is a third party software.
try:
coverage = __import__('coverage')
except ImportError, error:
error_msg = ("\nIt appears that coverage.py is not installed. Install "+
"Ned Batchelder's coverage.py "+
"('http://nedbatchelder.com/code/coverage/') and try again.\n")
print error_msg
raise
cov = coverage.coverage()
cov.start()
try:
current_directory = os.getcwd()
current_directory_content = os.listdir(current_directory)
# Find test scripts and import them.
test_modules = [] # Test modules.
tested_modules = [] # Modules that are tested by the 'test_modules'.
for _file in current_directory_content:
if _file.startswith('test') and _file.endswith('.py'):
_file = os.path.splitext(_file)[0]
test_modules.append(_file)
# Import the module.
try:
module = __import__(_file)
except ImportError, error:
print 'Unable to load the module: '+_file
raise
_file = '.'+_file[5:]
tested_modules.append(_file)
finally:
cov.stop()
# Include quickstart.
tested_modules.remove('.quickstart')
tested_modules.append('quickstart')
# Extracting tuf modules.
tuf_modules = {} # list of all loaded tuf modules.
for module_name in sys.modules:
if module_name.startswith('tuf') or module_name.startswith('quickstart'):
tuf_modules[module_name] = sys.modules[module_name]
# Tested module paths.
tested_module_paths = []
for module_name in tuf_modules:
for tested_module in tested_modules:
if module_name.endswith(tested_module):
tested_module_paths.append(tuf_modules[module_name].__file__)
cov.report(tested_module_paths)

View file

@ -1,171 +0,0 @@
#!/usr/bin/env python
"""
<Program Name>
test_util_test_tools.py
<Author>
Konstantin Andrianov
<Started>
February 26, 2012
<Copyright>
See LICENSE for licensing information.
<Purpose>
Test util_test_tools.
"""
import os
import urllib
import unittest
import tuf.tests.util_test_tools as util_test_tools
import tuf.repo.keystore
class test_UtilTestTools(unittest.TestCase):
def setUp(self):
unittest.TestCase.setUp(self)
# Ensure the keystore is empty prior to initializing the repository
# generated by 'util_test_tools'.
tuf.repo.keystore.clear_keystore()
# Unpacking necessary parameters returned from init_repo()
essential_params = util_test_tools.init_repo(using_tuf=True)
self.root_repo = essential_params[0]
self.url = essential_params[1]
self.server_proc = essential_params[2]
self.keyids = essential_params[3]
# TODO: In the line below, 'util_test_tools.init_repo' does
# not return the interposition config and this unit test
# does not directly use it. WIP?
#self.interpose_json = essential_params[4]
def tearDown(self):
unittest.TestCase.tearDown(self)
# 'util_test_tools.cleanup()' should clear the keystore...
util_test_tools.cleanup(self.root_repo, self.server_proc)
# Clear the keystore here just in case.
tuf.repo.keystore.clear_keystore()
#================================================#
# Below are a few quick tests that make sure #
# everything works smoothly in util_test_tools. #
#================================================#
# A few quick internal tests to see if everything runs smoothly.
def test_direct_download(self):
# Setup.
reg_repo = os.path.join(self.root_repo, 'reg_repo')
downloads = os.path.join(self.root_repo, 'downloads')
filepath = util_test_tools.add_file_to_repository(reg_repo, 'Test')
file_basename = os.path.basename(filepath)
url_to_reg_repo = self.url+'reg_repo/'+file_basename
downloaded_file = os.path.join(downloads, file_basename)
# Test direct download using 'urllib.urlretrieve'.
urllib.urlretrieve(url_to_reg_repo, downloaded_file)
self.assertTrue(os.path.isfile(downloaded_file))
# Verify the content of the downloaded file.
downloaded_content = util_test_tools.read_file_content(downloaded_file)
self.assertEquals('Test', downloaded_content)
def test_correct_directory_structure(self):
# Verify following directories exists: '{root_repo}/reg_repo/',
# '{root_repo}/downloads/.
self.assertTrue(os.path.isdir(os.path.join(self.root_repo, 'reg_repo')))
self.assertTrue(os.path.isdir(os.path.join(self.root_repo, 'downloads')))
# Verify that all necessary TUF-paths exist.
tuf_repo = os.path.join(self.root_repo, 'tuf_repo')
tuf_client = os.path.join(self.root_repo, 'tuf_client')
metadata_dir = os.path.join(tuf_repo, 'metadata')
current_dir = os.path.join(tuf_client, 'metadata', 'current')
# Verify '{root_repo}/tuf_repo/metadata/role.json' paths exists.
for role in ['root', 'targets', 'snapshot', 'timestamp']:
# Repository side.
role_file = os.path.join(metadata_dir, role+'.json')
self.assertTrue(os.path.isfile(role_file))
# Client side.
role_file = os.path.join(current_dir, role+'.json')
self.assertTrue(os.path.isfile(role_file))
# Verify '{root_repo}/tuf_repo/keystore/keyid.key' exists.
keys_list = os.listdir(os.path.join(tuf_repo, 'keystore'))
self.assertEquals(len(keys_list), 1)
# Verify '{root_repo}/tuf_repo/targets/' directory exists.
self.assertTrue(os.path.isdir(os.path.join(tuf_repo, 'targets')))
def test_methods(self):
"""
Making sure following methods work as intended:
- add_file_to_repository(data)
- modify_file_at_repository(filepath, data)
- delete_file_at_repository(filepath)
- read_file_content(filepath)
- tuf_refresh_repo()
- tuf_refresh_and_download()
Note: here file at the 'filepath' and the 'target' file at tuf-targets
directory are identical files.
Ex: filepath = '{root_repo}/reg_repo/file.json'
target = '{root_repo}/tuf_repo/targets/file.json'
"""
reg_repo = os.path.join(self.root_repo, 'reg_repo')
tuf_repo = os.path.join(self.root_repo, 'tuf_repo')
downloads = os.path.join(self.root_repo, 'downloads')
# Test 'add_file_to_repository(directory, data)' and
# read_file_content(filepath) methods.
filepath = util_test_tools.add_file_to_repository(reg_repo, 'Test')
self.assertTrue(os.path.isfile(filepath))
self.assertEquals(os.path.dirname(filepath), reg_repo)
filepath_content = util_test_tools.read_file_content(filepath)
self.assertEquals('Test', filepath_content)
# Test 'modify_file_at_repository(filepath, data)' method.
filepath = util_test_tools.modify_file_at_repository(filepath, 'Modify')
self.assertTrue(os.path.exists(filepath))
filepath_content = util_test_tools.read_file_content(filepath)
self.assertEquals('Modify', filepath_content)
# Test 'tuf_refresh_repo' method.
util_test_tools.tuf_refresh_repo(self.root_repo, self.keyids)
file_basename = os.path.basename(filepath)
target = os.path.join(tuf_repo, 'targets', file_basename)
self.assertTrue(os.path.isfile(target))
# Test 'delete_file_at_repository(filepath)' method.
util_test_tools.delete_file_at_repository(filepath)
self.assertFalse(os.path.exists(filepath))
# Test 'tuf_refresh_repo' method once more.
util_test_tools.tuf_refresh_repo(self.root_repo, self.keyids)
file_basename = os.path.basename(filepath)
target = os.path.join(tuf_repo, 'targets', file_basename)
self.assertFalse(os.path.isfile(target))
if __name__ == '__main__':
unittest.main()

Some files were not shown because too many files have changed in this diff Show more