diff --git a/docs/tuf-spec.txt b/docs/tuf-spec.txt index e54069a4..a4c679da 100644 --- a/docs/tuf-spec.txt +++ b/docs/tuf-spec.txt @@ -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 diff --git a/tuf/examples/example_client.py b/examples/client/example_client.py similarity index 85% rename from tuf/examples/example_client.py rename to examples/client/example_client.py index 78b1103f..53b18142 100755 --- a/tuf/examples/example_client.py +++ b/examples/client/example_client.py @@ -6,7 +6,7 @@ Vladimir Diaz - September 2012 + September 2012. 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) -""" diff --git a/examples/client/metadata/current/root.json b/examples/client/metadata/current/root.json new file mode 100644 index 00000000..8128041e Binary files /dev/null and b/examples/client/metadata/current/root.json differ diff --git a/examples/client/metadata/previous/root.json b/examples/client/metadata/previous/root.json new file mode 100644 index 00000000..8128041e Binary files /dev/null and b/examples/client/metadata/previous/root.json differ diff --git a/examples/keystore/project_key b/examples/keystore/project_key new file mode 100644 index 00000000..ad2c31d8 --- /dev/null +++ b/examples/keystore/project_key @@ -0,0 +1 @@ +5bc5cdc1e18ff3ccbfd7c33a88bec596@@@@313030303030@@@@39656230336534656264303863303733353832386465383466346232633863356362616234306430333863353239393966643333373730353231386262623339@@@@31caf11a40e9eb48f499dcc6f80c88e8@@@@0400a24989069098ce702d6a8f81826ba482ffd9a17fff5a10c6f986b9179bae1be4d246db2fceda93ce12bd465e896e4e4e847c934eb120c794e12fbcc8569e4aa6964995f1fda9af50057644236c4194ebb78a588804363dbce492db7e4ef2ce39391013a7c2d68260a0e785b6cec39fc02cdff11e9c7a168ae133292fdbe5f2f968d2a0ae098ca9453ec33d175de181f771b016c760ceba51d9c20c431702656e8b09ebda6cf884096b89d80dd6c2c1752c04312e934cd79d49b91e8c7ef4448bf3b969fa6ed9727cac48f91e3921f41d5bf8ec4130ff45fda51e07cd16a7fa8daca1feb6f2dced6881c736565a1b72dc705a97606a0480c0dd681e65bea82fc261762cdad203fd49d45f \ No newline at end of file diff --git a/examples/keystore/project_key.pub b/examples/keystore/project_key.pub new file mode 100644 index 00000000..0f1c3193 --- /dev/null +++ b/examples/keystore/project_key.pub @@ -0,0 +1 @@ +{"keytype": "ed25519", "keyval": {"public": "b6e40fb71a6041212a3d84331336ecaa1f48a0c523f80ccc762a034c727606fa"}} \ No newline at end of file diff --git a/examples/keystore/root_key b/examples/keystore/root_key new file mode 100644 index 00000000..0f87c374 --- /dev/null +++ b/examples/keystore/root_key @@ -0,0 +1 @@ +70b05482c00cad0fccfcab4ac2b86b50@@@@313030303030@@@@62626137313336626662363862333962636161306561326437336237643436306162323966303038326636306363613965396161353566646330346666356635@@@@5f6612c00c8ed8627dd33754812bb7e1@@@@f651c3db5ac02aa8337264f0badd1f40fbe174ec3f8de8fd95188d31cf41b4863d7a28db297b8a5abd25e49d2af3c6cb2e25789088dce2b5113b7d7db16deea1eadf109d5ec004a2b5bcbdc29e13a9e4c803659def851800969918fb5930c56b816b119be490667f2d629309bc7578dad43c6b0ca6ef0c6f48ad68390fb1fc711b8a40bb5b1c197ae6f72d2b1e83bbc9050f46a3c69efe3b11c55a52d3f68f6e9fe58ad7e67dd6b136681b6d800fed22f15d31ee71ad1ed78f36b6d19b0771c22123f1dcb54a6b2e9742d2661014931cbab8fbbb001e3ac836bc5c64b19fa4cb881485acdafa6a0fd87044534608f50ae13920517c6f2ab2669f8edd4bc6cbe2fc1fc272264a819e2e34bc83 \ No newline at end of file diff --git a/examples/keystore/root_key.pub b/examples/keystore/root_key.pub new file mode 100644 index 00000000..7cf01390 --- /dev/null +++ b/examples/keystore/root_key.pub @@ -0,0 +1 @@ +{"keytype": "ed25519", "keyval": {"public": "66dd78c5c2a78abc6fc6b267ff1a8017ba0e8bfc853dd97af351949bba021275"}} \ No newline at end of file diff --git a/examples/keystore/snapshot_key b/examples/keystore/snapshot_key new file mode 100644 index 00000000..9f999f94 --- /dev/null +++ b/examples/keystore/snapshot_key @@ -0,0 +1 @@ +cff2ed748f0281d65c8eb535e81dbfd0@@@@313030303030@@@@30353732326564313863306632626336656631636635313666636330383537376466393833313937363261303638336632373530303938623665346239646230@@@@1eda960b65beefb9a2a4afcc9be973f6@@@@ea7c468f9e5ab91e874b2a0fa692a18056293261886400e5976a6c884b13cdd3905b0188f41b0c2b2846d36dabbeecf4d9d1c87123b5b236ccbce24f4b30c9ba25d00ccce270d3da1d202d2fd27a0a007381bf2284c58bb01a812050086264617f94a47cd3931b9129c6b105eec4ff56d1176e6fbde6bf5ade513a0f1c7551cecb04c678582e7fd0656936a1f232fa3a739df3dc4af07ad69580f54b1dd366c78e96c07249732621929aac056f4892af07772011246101cfb9886558fe2cfd1d09e9c280cbecdf2fb8dbeded4a628ef2fa04d5360dae327ccf15a12a00f2f32964ca03abaeaeb60bbece207e09c897413b8a630331df568822880be86359181664aa0806770ab11e30663594 \ No newline at end of file diff --git a/examples/keystore/snapshot_key.pub b/examples/keystore/snapshot_key.pub new file mode 100644 index 00000000..cebf0249 --- /dev/null +++ b/examples/keystore/snapshot_key.pub @@ -0,0 +1 @@ +{"keytype": "ed25519", "keyval": {"public": "01c61f8dc7d77fcef973f4267927541e355e8ceda757e2c402818dad850f856e"}} \ No newline at end of file diff --git a/examples/keystore/targets_key b/examples/keystore/targets_key new file mode 100644 index 00000000..f56772a5 --- /dev/null +++ b/examples/keystore/targets_key @@ -0,0 +1 @@ +a0fdf15a675c849cc7bd4cfb46273164@@@@313030303030@@@@62303735356165326132633766333932633137643234323961636166356135666433333234376163356665656330306362366363383332386430356133663831@@@@0d7ce5bc8687edc1a292ebbe203284b6@@@@155dee106e192009ed4dace179e514f518d403d7a83d136047683683090c8dd1e80d6d5f6bd480e1e9e76bf63a265dfdc7e5bce07418039c6457c6d454fd0114fd7311c8508ead020e59e0b5b2ee55101d49535980e598c02c70ecb7bca77a54d04040080ca9403cd23bd0ae4cc5e33131321d2a4c8a4544553f5c54b7af0986a437f37696b4e7d76efed24be9a4c6928542fb93cfd88018537703a1ff0f6ac8fcb625714a161aaa7a548b39963ded1481b47020b1346544a8a9d96f1eb03a6cad326af0f5be43c6756dc1d4e6c7dee550077d7689949a671acd370680d6b29e594675ade9d7525a4ad8af7a1b13a3e4692192d70c189115d52b814af5a53bc9d0528aec6c6417f6f7d0bcb3 \ No newline at end of file diff --git a/examples/keystore/targets_key.pub b/examples/keystore/targets_key.pub new file mode 100644 index 00000000..5e1d1e1a --- /dev/null +++ b/examples/keystore/targets_key.pub @@ -0,0 +1 @@ +{"keytype": "ed25519", "keyval": {"public": "68ead6e54a43f8f36f9717b10669d1ef0ebb38cee6b05317669341309f1069cb"}} \ No newline at end of file diff --git a/examples/keystore/timestamp_key b/examples/keystore/timestamp_key new file mode 100644 index 00000000..42dc9bda --- /dev/null +++ b/examples/keystore/timestamp_key @@ -0,0 +1 @@ +dd0f6b3bff19df2c4ab89e34a5b190e6@@@@313030303030@@@@37613435636666623966633230613439376661303631616635323365326636643039383236333638633162326262616231653531353066656262643265623566@@@@e6d72cc0a99144c4dbf509fa56092454@@@@10bb33112d4083f81d700740e78b315574a0d7b8c042921b1dcb7b8593caff1dbb10b8886ea2f4b7edcb49d3aabc9ec25db59dc0b121890555dc5d69291856f739b280de6fa6216e0ac92b9b95689b9f6ba1a414cb78ee6547968ea5ebd84e34972cf6d0e56cf0443b653f51d8e2742a7454e70039e548e4a69e97e73475940964307b5d5da440767531479b0c940dc8ffebafdf562e3a68d456f9438cb3c2253117180efd868b8b9fd4ea3e717501db8c0a9afe0bcdb34068eef4858103b2126b47d4c22a3d0f16cec0e5cd452201487eb6695139d8235a17a3c1a42fa7552d7ca45625b0000650f22851679ac00c7b71368d4dfc862a1823437b5cc244c282be0c01138fa39dc13511bd59 \ No newline at end of file diff --git a/examples/keystore/timestamp_key.pub b/examples/keystore/timestamp_key.pub new file mode 100644 index 00000000..3224de62 --- /dev/null +++ b/examples/keystore/timestamp_key.pub @@ -0,0 +1 @@ +{"keytype": "ed25519", "keyval": {"public": "72378e5bc588793e58f81c8533da64a2e8f1565c1fcc7f253496394ffc52542c"}} \ No newline at end of file diff --git a/examples/repository/metadata.staged/root.json b/examples/repository/metadata.staged/root.json new file mode 100644 index 00000000..8128041e Binary files /dev/null and b/examples/repository/metadata.staged/root.json differ diff --git a/examples/repository/metadata.staged/snapshot.json b/examples/repository/metadata.staged/snapshot.json new file mode 100644 index 00000000..3294c89e Binary files /dev/null and b/examples/repository/metadata.staged/snapshot.json differ diff --git a/examples/repository/metadata.staged/targets.json b/examples/repository/metadata.staged/targets.json new file mode 100644 index 00000000..6387d30e Binary files /dev/null and b/examples/repository/metadata.staged/targets.json differ diff --git a/examples/repository/metadata.staged/targets.json.gz b/examples/repository/metadata.staged/targets.json.gz new file mode 100644 index 00000000..85fa0890 Binary files /dev/null and b/examples/repository/metadata.staged/targets.json.gz differ diff --git a/examples/repository/metadata.staged/targets/project.json b/examples/repository/metadata.staged/targets/project.json new file mode 100644 index 00000000..57f4195a Binary files /dev/null and b/examples/repository/metadata.staged/targets/project.json differ diff --git a/examples/repository/metadata.staged/timestamp.json b/examples/repository/metadata.staged/timestamp.json new file mode 100644 index 00000000..93e124e1 Binary files /dev/null and b/examples/repository/metadata.staged/timestamp.json differ diff --git a/examples/repository/metadata/root.json b/examples/repository/metadata/root.json new file mode 100644 index 00000000..8128041e Binary files /dev/null and b/examples/repository/metadata/root.json differ diff --git a/examples/repository/metadata/snapshot.json b/examples/repository/metadata/snapshot.json new file mode 100644 index 00000000..3294c89e Binary files /dev/null and b/examples/repository/metadata/snapshot.json differ diff --git a/examples/repository/metadata/targets.json b/examples/repository/metadata/targets.json new file mode 100644 index 00000000..6387d30e Binary files /dev/null and b/examples/repository/metadata/targets.json differ diff --git a/examples/repository/metadata/targets.json.gz b/examples/repository/metadata/targets.json.gz new file mode 100644 index 00000000..85fa0890 Binary files /dev/null and b/examples/repository/metadata/targets.json.gz differ diff --git a/examples/repository/metadata/targets/project.json b/examples/repository/metadata/targets/project.json new file mode 100644 index 00000000..57f4195a Binary files /dev/null and b/examples/repository/metadata/targets/project.json differ diff --git a/examples/repository/metadata/timestamp.json b/examples/repository/metadata/timestamp.json new file mode 100644 index 00000000..93e124e1 Binary files /dev/null and b/examples/repository/metadata/timestamp.json differ diff --git a/examples/repository/targets/file1.txt b/examples/repository/targets/file1.txt new file mode 100644 index 00000000..7bf3499f --- /dev/null +++ b/examples/repository/targets/file1.txt @@ -0,0 +1 @@ +This is an example target file. \ No newline at end of file diff --git a/examples/repository/targets/file2.txt b/examples/repository/targets/file2.txt new file mode 100644 index 00000000..606f18ef --- /dev/null +++ b/examples/repository/targets/file2.txt @@ -0,0 +1 @@ +This is an another example target file. \ No newline at end of file diff --git a/examples/repository/targets/project/file3.txt b/examples/repository/targets/project/file3.txt new file mode 100644 index 00000000..60464604 --- /dev/null +++ b/examples/repository/targets/project/file3.txt @@ -0,0 +1 @@ +This is role1's target file. \ No newline at end of file diff --git a/setup.py b/setup.py index 98e3b093..17867ca0 100755 --- a/setup.py +++ b/setup.py @@ -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' diff --git a/tuf/pushtools/__init__.py b/tests/__init__.py similarity index 100% rename from tuf/pushtools/__init__.py rename to tests/__init__.py diff --git a/tests/unit/aggregate_tests.py b/tests/aggregate_tests.py similarity index 100% rename from tests/unit/aggregate_tests.py rename to tests/aggregate_tests.py diff --git a/tests/integration/test_delegations.py b/tests/integration/test_delegations.py deleted file mode 100755 index 8b216efe..00000000 --- a/tests/integration/test_delegations.py +++ /dev/null @@ -1,541 +0,0 @@ -#!/usr/bin/env python - -""" - - test_delegations.py - - - Konstantin Andrianov - - - February 19, 2012 - - - See LICENSE for licensing information. - - - 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() diff --git a/tests/repository_data/client/metadata/current/root.json b/tests/repository_data/client/metadata/current/root.json index bfe2d990..37993bf1 100644 Binary files a/tests/repository_data/client/metadata/current/root.json and b/tests/repository_data/client/metadata/current/root.json differ diff --git a/tests/repository_data/client/metadata/current/snapshot.json b/tests/repository_data/client/metadata/current/snapshot.json index 3e46e1fd..9a960dcd 100644 Binary files a/tests/repository_data/client/metadata/current/snapshot.json and b/tests/repository_data/client/metadata/current/snapshot.json differ diff --git a/tests/repository_data/client/metadata/current/targets.json b/tests/repository_data/client/metadata/current/targets.json index 06710067..0a7b4a8b 100644 Binary files a/tests/repository_data/client/metadata/current/targets.json and b/tests/repository_data/client/metadata/current/targets.json differ diff --git a/tests/repository_data/client/metadata/current/targets.json.gz b/tests/repository_data/client/metadata/current/targets.json.gz index 848797c0..757cff50 100644 Binary files a/tests/repository_data/client/metadata/current/targets.json.gz and b/tests/repository_data/client/metadata/current/targets.json.gz differ diff --git a/tests/repository_data/client/metadata/current/targets/role1.json b/tests/repository_data/client/metadata/current/targets/role1.json index c72f2ba9..d4d3c560 100644 Binary files a/tests/repository_data/client/metadata/current/targets/role1.json and b/tests/repository_data/client/metadata/current/targets/role1.json differ diff --git a/tests/repository_data/client/metadata/current/timestamp.json b/tests/repository_data/client/metadata/current/timestamp.json index 3956e20c..55099610 100644 Binary files a/tests/repository_data/client/metadata/current/timestamp.json and b/tests/repository_data/client/metadata/current/timestamp.json differ diff --git a/tests/repository_data/client/metadata/previous/root.json b/tests/repository_data/client/metadata/previous/root.json index bfe2d990..37993bf1 100644 Binary files a/tests/repository_data/client/metadata/previous/root.json and b/tests/repository_data/client/metadata/previous/root.json differ diff --git a/tests/repository_data/client/metadata/previous/snapshot.json b/tests/repository_data/client/metadata/previous/snapshot.json index 3e46e1fd..9a960dcd 100644 Binary files a/tests/repository_data/client/metadata/previous/snapshot.json and b/tests/repository_data/client/metadata/previous/snapshot.json differ diff --git a/tests/repository_data/client/metadata/previous/targets.json b/tests/repository_data/client/metadata/previous/targets.json index 06710067..0a7b4a8b 100644 Binary files a/tests/repository_data/client/metadata/previous/targets.json and b/tests/repository_data/client/metadata/previous/targets.json differ diff --git a/tests/repository_data/client/metadata/previous/targets.json.gz b/tests/repository_data/client/metadata/previous/targets.json.gz index 848797c0..757cff50 100644 Binary files a/tests/repository_data/client/metadata/previous/targets.json.gz and b/tests/repository_data/client/metadata/previous/targets.json.gz differ diff --git a/tests/repository_data/client/metadata/previous/targets/role1.json b/tests/repository_data/client/metadata/previous/targets/role1.json index c72f2ba9..d4d3c560 100644 Binary files a/tests/repository_data/client/metadata/previous/targets/role1.json and b/tests/repository_data/client/metadata/previous/targets/role1.json differ diff --git a/tests/repository_data/client/metadata/previous/timestamp.json b/tests/repository_data/client/metadata/previous/timestamp.json index 3956e20c..55099610 100644 Binary files a/tests/repository_data/client/metadata/previous/timestamp.json and b/tests/repository_data/client/metadata/previous/timestamp.json differ diff --git a/tests/repository_data/generate.py b/tests/repository_data/generate.py index ca1f2e1e..2bc1c67c 100755 --- a/tests/repository_data/generate.py +++ b/tests/repository_data/generate.py @@ -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. diff --git a/tests/repository_data/keystore/delegation_key b/tests/repository_data/keystore/delegation_key index 89210ee6..fbdd0d1e 100644 --- a/tests/repository_data/keystore/delegation_key +++ b/tests/repository_data/keystore/delegation_key @@ -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----- \ No newline at end of file diff --git a/tests/repository_data/keystore/delegation_key.pub b/tests/repository_data/keystore/delegation_key.pub index 1ff0f7d3..780c740d 100644 --- a/tests/repository_data/keystore/delegation_key.pub +++ b/tests/repository_data/keystore/delegation_key.pub @@ -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----- \ No newline at end of file diff --git a/tests/repository_data/keystore/root_key b/tests/repository_data/keystore/root_key index 4b892c3e..7445b409 100644 --- a/tests/repository_data/keystore/root_key +++ b/tests/repository_data/keystore/root_key @@ -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----- \ No newline at end of file diff --git a/tests/repository_data/keystore/root_key.pub b/tests/repository_data/keystore/root_key.pub index 89949d85..9fdf180e 100644 --- a/tests/repository_data/keystore/root_key.pub +++ b/tests/repository_data/keystore/root_key.pub @@ -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----- \ No newline at end of file diff --git a/tests/repository_data/keystore/snapshot_key b/tests/repository_data/keystore/snapshot_key index 5979b9f0..5fe431e4 100644 --- a/tests/repository_data/keystore/snapshot_key +++ b/tests/repository_data/keystore/snapshot_key @@ -1,30 +1,30 @@ -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,7349E671E697C1CC +DEK-Info: DES-EDE3-CBC,0E7D0C9F6987D107 -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 -----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/tests/repository_data/keystore/snapshot_key.pub b/tests/repository_data/keystore/snapshot_key.pub index 4225472b..f892e210 100644 --- a/tests/repository_data/keystore/snapshot_key.pub +++ b/tests/repository_data/keystore/snapshot_key.pub @@ -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----- \ No newline at end of file diff --git a/tests/repository_data/keystore/targets_key b/tests/repository_data/keystore/targets_key index c18a6806..107f8ffa 100644 --- a/tests/repository_data/keystore/targets_key +++ b/tests/repository_data/keystore/targets_key @@ -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----- \ No newline at end of file diff --git a/tests/repository_data/keystore/targets_key.pub b/tests/repository_data/keystore/targets_key.pub index 7a99a115..a7bd1580 100644 --- a/tests/repository_data/keystore/targets_key.pub +++ b/tests/repository_data/keystore/targets_key.pub @@ -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----- \ No newline at end of file diff --git a/tests/repository_data/keystore/timestamp_key b/tests/repository_data/keystore/timestamp_key index dcedad06..eb8c5bc5 100644 --- a/tests/repository_data/keystore/timestamp_key +++ b/tests/repository_data/keystore/timestamp_key @@ -1,30 +1,30 @@ -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,FE4027E2AF1DF4E3 +DEK-Info: DES-EDE3-CBC,D5B52C0993E278D0 -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 -----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/tests/repository_data/keystore/timestamp_key.pub b/tests/repository_data/keystore/timestamp_key.pub index 6f129cb0..ee92796c 100644 --- a/tests/repository_data/keystore/timestamp_key.pub +++ b/tests/repository_data/keystore/timestamp_key.pub @@ -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----- \ No newline at end of file diff --git a/tests/repository_data/repository/metadata.staged/root.json b/tests/repository_data/repository/metadata.staged/root.json index bfe2d990..37993bf1 100644 Binary files a/tests/repository_data/repository/metadata.staged/root.json and b/tests/repository_data/repository/metadata.staged/root.json differ diff --git a/tests/repository_data/repository/metadata.staged/snapshot.json b/tests/repository_data/repository/metadata.staged/snapshot.json index 3e46e1fd..9a960dcd 100644 Binary files a/tests/repository_data/repository/metadata.staged/snapshot.json and b/tests/repository_data/repository/metadata.staged/snapshot.json differ diff --git a/tests/repository_data/repository/metadata.staged/targets.json b/tests/repository_data/repository/metadata.staged/targets.json index 06710067..0a7b4a8b 100644 Binary files a/tests/repository_data/repository/metadata.staged/targets.json and b/tests/repository_data/repository/metadata.staged/targets.json differ diff --git a/tests/repository_data/repository/metadata.staged/targets.json.gz b/tests/repository_data/repository/metadata.staged/targets.json.gz index 848797c0..757cff50 100644 Binary files a/tests/repository_data/repository/metadata.staged/targets.json.gz and b/tests/repository_data/repository/metadata.staged/targets.json.gz differ diff --git a/tests/repository_data/repository/metadata.staged/targets/role1.json b/tests/repository_data/repository/metadata.staged/targets/role1.json index c72f2ba9..d4d3c560 100644 Binary files a/tests/repository_data/repository/metadata.staged/targets/role1.json and b/tests/repository_data/repository/metadata.staged/targets/role1.json differ diff --git a/tests/repository_data/repository/metadata.staged/timestamp.json b/tests/repository_data/repository/metadata.staged/timestamp.json index 3956e20c..55099610 100644 Binary files a/tests/repository_data/repository/metadata.staged/timestamp.json and b/tests/repository_data/repository/metadata.staged/timestamp.json differ diff --git a/tests/repository_data/repository/metadata/root.json b/tests/repository_data/repository/metadata/root.json index bfe2d990..37993bf1 100644 Binary files a/tests/repository_data/repository/metadata/root.json and b/tests/repository_data/repository/metadata/root.json differ diff --git a/tests/repository_data/repository/metadata/snapshot.json b/tests/repository_data/repository/metadata/snapshot.json index 3e46e1fd..9a960dcd 100644 Binary files a/tests/repository_data/repository/metadata/snapshot.json and b/tests/repository_data/repository/metadata/snapshot.json differ diff --git a/tests/repository_data/repository/metadata/targets.json b/tests/repository_data/repository/metadata/targets.json index 06710067..0a7b4a8b 100644 Binary files a/tests/repository_data/repository/metadata/targets.json and b/tests/repository_data/repository/metadata/targets.json differ diff --git a/tests/repository_data/repository/metadata/targets.json.gz b/tests/repository_data/repository/metadata/targets.json.gz index 848797c0..757cff50 100644 Binary files a/tests/repository_data/repository/metadata/targets.json.gz and b/tests/repository_data/repository/metadata/targets.json.gz differ diff --git a/tests/repository_data/repository/metadata/targets/role1.json b/tests/repository_data/repository/metadata/targets/role1.json index c72f2ba9..d4d3c560 100644 Binary files a/tests/repository_data/repository/metadata/targets/role1.json and b/tests/repository_data/repository/metadata/targets/role1.json differ diff --git a/tests/repository_data/repository/metadata/timestamp.json b/tests/repository_data/repository/metadata/timestamp.json index 3956e20c..55099610 100644 Binary files a/tests/repository_data/repository/metadata/timestamp.json and b/tests/repository_data/repository/metadata/timestamp.json differ diff --git a/tests/integration/simple_server.py b/tests/simple_server.py similarity index 100% rename from tests/integration/simple_server.py rename to tests/simple_server.py diff --git a/tests/integration/slow_retrieval_server.py b/tests/slow_retrieval_server.py similarity index 99% rename from tests/integration/slow_retrieval_server.py rename to tests/slow_retrieval_server.py index 29ac2ccf..69e03dd2 100755 --- a/tests/integration/slow_retrieval_server.py +++ b/tests/slow_retrieval_server.py @@ -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) diff --git a/tests/integration/test_arbitrary_package_attack.py b/tests/test_arbitrary_package_attack.py similarity index 98% rename from tests/integration/test_arbitrary_package_attack.py rename to tests/test_arbitrary_package_attack.py index 54fc67e0..3a45b028 100755 --- a/tests/integration/test_arbitrary_package_attack.py +++ b/tests/test_arbitrary_package_attack.py @@ -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) diff --git a/tests/unit/test_download.py b/tests/test_download.py similarity index 95% rename from tests/unit/test_download.py rename to tests/test_download.py index 75690717..e67f1f56 100755 --- a/tests/unit/test_download.py +++ b/tests/test_download.py @@ -5,7 +5,7 @@ test_download.py - Konstantin Andrianov + Konstantin Andrianov. March 26, 2012. @@ -14,12 +14,10 @@ See LICENSE for licensing information. - 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') diff --git a/tests/unit/test_ed25519_keys.py b/tests/test_ed25519_keys.py similarity index 100% rename from tests/unit/test_ed25519_keys.py rename to tests/test_ed25519_keys.py diff --git a/tests/integration/test_endless_data_attack.py b/tests/test_endless_data_attack.py similarity index 98% rename from tests/integration/test_endless_data_attack.py rename to tests/test_endless_data_attack.py index f4a47209..7a820327 100755 --- a/tests/integration/test_endless_data_attack.py +++ b/tests/test_endless_data_attack.py @@ -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) diff --git a/tests/integration/test_extraneous_dependencies_attack.py b/tests/test_extraneous_dependencies_attack.py similarity index 98% rename from tests/integration/test_extraneous_dependencies_attack.py rename to tests/test_extraneous_dependencies_attack.py index 9545b5b1..0fa1c1d1 100755 --- a/tests/integration/test_extraneous_dependencies_attack.py +++ b/tests/test_extraneous_dependencies_attack.py @@ -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) diff --git a/tests/unit/test_formats.py b/tests/test_formats.py similarity index 93% rename from tests/unit/test_formats.py rename to tests/test_formats.py index 387c1a25..10133b08 100755 --- a/tests/unit/test_formats.py +++ b/tests/test_formats.py @@ -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'}}}, diff --git a/tests/unit/test_hash.py b/tests/test_hash.py similarity index 100% rename from tests/unit/test_hash.py rename to tests/test_hash.py diff --git a/tests/integration/test_indefinite_freeze_attack.py b/tests/test_indefinite_freeze_attack.py similarity index 94% rename from tests/integration/test_indefinite_freeze_attack.py rename to tests/test_indefinite_freeze_attack.py index a5fa933f..2c90a409 100755 --- a/tests/integration/test_indefinite_freeze_attack.py +++ b/tests/test_indefinite_freeze_attack.py @@ -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) diff --git a/tests/unit/test_keydb.py b/tests/test_keydb.py similarity index 99% rename from tests/unit/test_keydb.py rename to tests/test_keydb.py index 7fd0d293..df405b63 100755 --- a/tests/unit/test_keydb.py +++ b/tests/test_keydb.py @@ -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, diff --git a/tests/unit/test_keys.py b/tests/test_keys.py similarity index 100% rename from tests/unit/test_keys.py rename to tests/test_keys.py diff --git a/tests/unit/test_mirrors.py b/tests/test_mirrors.py similarity index 97% rename from tests/unit/test_mirrors.py rename to tests/test_mirrors.py index 8aac13a4..603d5bf1 100755 --- a/tests/unit/test_mirrors.py +++ b/tests/test_mirrors.py @@ -12,8 +12,7 @@ See LICENSE for licensing information. - 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 diff --git a/tests/integration/test_mix_and_match_attack.py b/tests/test_mix_and_match_attack.py similarity index 98% rename from tests/integration/test_mix_and_match_attack.py rename to tests/test_mix_and_match_attack.py index 7d4512a0..5d7aa0bb 100755 --- a/tests/integration/test_mix_and_match_attack.py +++ b/tests/test_mix_and_match_attack.py @@ -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) diff --git a/tests/unit/test_pycrypto_keys.py b/tests/test_pycrypto_keys.py similarity index 100% rename from tests/unit/test_pycrypto_keys.py rename to tests/test_pycrypto_keys.py diff --git a/tests/integration/test_replay_attack.py b/tests/test_replay_attack.py similarity index 97% rename from tests/integration/test_replay_attack.py rename to tests/test_replay_attack.py index 1f0064e4..8906e665 100755 --- a/tests/integration/test_replay_attack.py +++ b/tests/test_replay_attack.py @@ -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. diff --git a/tests/unit/test_repository_tool.py b/tests/test_repository_tool.py similarity index 95% rename from tests/unit/test_repository_tool.py rename to tests/test_repository_tool.py index 62dc92f4..67fc3f23 100755 --- a/tests/unit/test_repository_tool.py +++ b/tests/test_repository_tool.py @@ -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') diff --git a/tests/unit/test_roledb.py b/tests/test_roledb.py similarity index 99% rename from tests/unit/test_roledb.py rename to tests/test_roledb.py index 630ccaef..117d4eba 100755 --- a/tests/unit/test_roledb.py +++ b/tests/test_roledb.py @@ -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, diff --git a/tests/unit/test_schema.py b/tests/test_schema.py similarity index 100% rename from tests/unit/test_schema.py rename to tests/test_schema.py diff --git a/tests/unit/test_sig.py b/tests/test_sig.py similarity index 100% rename from tests/unit/test_sig.py rename to tests/test_sig.py diff --git a/tests/integration/test_slow_retrieval_attack.py b/tests/test_slow_retrieval_attack.py similarity index 98% rename from tests/integration/test_slow_retrieval_attack.py rename to tests/test_slow_retrieval_attack.py index 7e696ee4..3e4cf023 100755 --- a/tests/integration/test_slow_retrieval_attack.py +++ b/tests/test_slow_retrieval_attack.py @@ -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) diff --git a/tests/unit/test_updater.py b/tests/test_updater.py similarity index 99% rename from tests/unit/test_updater.py rename to tests/test_updater.py index d8e1a5b4..97348b84 100755 --- a/tests/unit/test_updater.py +++ b/tests/test_updater.py @@ -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 diff --git a/tests/unit/test_util.py b/tests/test_util.py similarity index 99% rename from tests/unit/test_util.py rename to tests/test_util.py index 465ed0c8..4f4ae895 100755 --- a/tests/unit/test_util.py +++ b/tests/test_util.py @@ -14,7 +14,7 @@ See LICENSE for licensing information. - 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') diff --git a/tests/unit/deprecated/test_keystore.py b/tests/unit/deprecated/test_keystore.py deleted file mode 100755 index e1a8c7f2..00000000 --- a/tests/unit/deprecated/test_keystore.py +++ /dev/null @@ -1,355 +0,0 @@ -""" - - test_keystore.py - - - Konstantin Andrianov - - - April 27, 2012. - - - See LICENSE for licensing information. - - - 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() diff --git a/tests/unit/deprecated/test_push.py b/tests/unit/deprecated/test_push.py deleted file mode 100755 index 4acc8d75..00000000 --- a/tests/unit/deprecated/test_push.py +++ /dev/null @@ -1,166 +0,0 @@ -""" - - test_push.py - - - Konstantin Andrianov - - - April 2013. - - - See LICENSE for licensing information. - - - 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() diff --git a/tests/unit/deprecated/test_pushtoolslib.py b/tests/unit/deprecated/test_pushtoolslib.py deleted file mode 100755 index e0cf6694..00000000 --- a/tests/unit/deprecated/test_pushtoolslib.py +++ /dev/null @@ -1,173 +0,0 @@ -""" - - test_pushtoolslib.py - - - Konstantin Andrianov - - - April 2013. - - - See LICENSE for licensing information. - - - 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() diff --git a/tests/unit/deprecated/test_quickstart.py b/tests/unit/deprecated/test_quickstart.py deleted file mode 100755 index e1bca8c4..00000000 --- a/tests/unit/deprecated/test_quickstart.py +++ /dev/null @@ -1,195 +0,0 @@ -""" - - test_quickstart.py - - - Konstantin Andrianov - - - September 6, 2012 - - - See LICENSE for licensing information. - - - 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() diff --git a/tests/unit/deprecated/test_signercli.py b/tests/unit/deprecated/test_signercli.py deleted file mode 100755 index 297eee18..00000000 --- a/tests/unit/deprecated/test_signercli.py +++ /dev/null @@ -1,1573 +0,0 @@ -#!/usr/bin/env python - -""" - - test_signercli.py - - - Konstantin Andrianov - - - September 20, 2012 - - - See LICENSE for licensing information. - - - test_signercli.py provides collection of methods that tries to test all the - units (methods) of the module under test. - - unittest_toolbox module was created to provide additional testing tools for - tuf's modules. For more info see unittest_toolbox.py. - - - - Unittests must follow a specific structure i.e. independent methods should - be tested prior to dependent methods. More accurately: least dependent - methods are tested before most dependent methods. There is no reason to - rewrite or construct other methods that replicate already-tested methods - solely for testing purposes. This is possible because 'unittest.TestCase' - class guarantees the order of unit tests. So that, 'test_something_A' - method would be tested before 'test_something_B'. To ensure the structure - a number will be placed after 'test' and before methods name like so: - 'test_1_check_directory'. The number is a measure of dependence, where 1 - is less dependent than 2. - -""" - - -import os -import time -import logging -import unittest - -import tuf -import tuf.log -import tuf.formats -import tuf.util -import tuf.repo.keystore as keystore -import tuf.repo.signerlib as signerlib - -# Module to test: signercli.py -import tuf.repo.signercli as signercli - -# Helper module unittest_toolbox.py -import tuf.tests.unittest_toolbox as unittest_toolbox - -logger = logging.getLogger('tuf.test_signercli') - - - -class TestSignercli(unittest_toolbox.Modified_TestCase): - # SETUP - original_prompt = signercli._prompt - signercli._prompt = original_prompt - - original_get_metadata_directory = signercli._get_metadata_directory - signercli._get_metadata_directory = original_get_metadata_directory - - original_get_password = signercli._get_password - signercli._get_password = original_get_password - - # HELPER METHODS. - - # Generic patch for signerlib._prompt(). - def mock_prompt(self, output): - - # Method to patch signercli._prompt(). - def _mock_prompt(junk1, junk2, ret=output): - return ret - - # Patch signercli._prompt() - signercli._prompt = _mock_prompt - - - - # Patch signercli._get_metadata_directory() - def mock_get_metadata_directory(self, directory=None): - - # Create method to patch signercli._get_metadata_directory() - def _mock_get_meta_dir(directory=directory): - - # If directory was specified, return that directory. - if directory: - return directory - - # Else create a temporary directory and return it. - else: - return self.make_temp_directory() - - # Patch signercli._get_metadata_directory() - signercli._get_metadata_directory = _mock_get_meta_dir - - - - # This method patches signercli._prompt() that are called from - # make_role_metadata methods (e.g., tuf.signercli.make_root_metadata()). - def make_metadata_mock_prompts(self, targ_dir, conf_path, expiration): - def _mock_prompt(msg, junk): - if msg.startswith('\nInput may be a directory, directories, or'): - return targ_dir - elif msg.startswith('\nEnter the configuration file path'): - return conf_path - elif msg.startswith('\nCurrent time:'): - return expiration - else: - error_msg = ('Prompt: '+'\''+msg[1:]+'\''+ - ' did not match any predefined mock prompts.') - self.fail(error_msg) - - # Patch signercli._prompt(). - signercli._prompt = _mock_prompt - - - - # This mock method can be easily modified, by altering unittest_toolbox's - # dictionaries. For instance, if you want to modify password for certain - # keyid just save the existing 'self.rsa_passwords[keyid]' and set it - # to some other value like self.random_string(), after the test reassign - # the saved value back to 'self.rsa_passwords[keyid]'. - def get_passwords(self): - # Mock '_get_password' method. - def _mock_get_password(msg): - for role in self.role_list: - if msg.startswith('\nEnter the password for the '+role): - for keyid in self.top_level_role_info[role]['keyids']: - if msg.endswith(keyid+'): '): - return self.rsa_passwords[keyid] - error_msg = ('Prompt: '+'\''+msg+'\''+ - ' did not match any predefined mock prompts.') - raise tuf.Error(error_msg) - - # Monkey patch '_prompt'. - signercli._get_password = _mock_get_password - - - - - - # UNIT TESTS. - # If a unit test starts with test_# followed by two underscores, - # (test_#__method) this means that it's an internal method of signercli. - # For instance the unit test for signercli._get_password() would - # look like this: test_1__get_password, whereas unit test for - # signercli.change_password would look like this: - # test_3_change_password(). - - def test_1__check_directory(self): - - # SETUP - directory = self.make_temp_directory() - no_such_dir = self.random_path() - - - # TESTS - # Test: normal case. - self.assertEqual(signercli._check_directory(directory), directory) - - # Test: invalid directory. - self.assertRaises(tuf.RepositoryError, signercli._check_directory, - no_such_dir) - - # Test: invalid directory type. - self.assertRaises(tuf.RepositoryError, signercli._check_directory, - [no_such_dir]) - self.assertRaises(tuf.RepositoryError, signercli._check_directory, - 1234) - self.assertRaises(tuf.RepositoryError, signercli._check_directory, - {'directory':no_such_dir}) - - - - - - def test_1__get_password(self): - - # SETUP - original_getpass = signercli.getpass.getpass - - password = self.random_string() - def _mock_getpass(junk1, junk2, pw=password): - return pw - - # Patch getpass.getpass(). - signercli.getpass.getpass = _mock_getpass - - - # Test: normal case. - self.assertEqual(signercli._get_password(), password) - - # RESTORE - signercli.getpass.getpass = original_getpass - - - - - def test_2__get_metadata_directory(self): - - # SETUP - original_prompt = signercli._prompt - - meta_directory = self.make_temp_directory() - self.mock_prompt(meta_directory) - - - # TESTS - self.assertEqual(signercli._get_metadata_directory(), meta_directory) - self.assertTrue(os.path.exists(signercli._get_metadata_directory())) - self.mock_prompt(self.random_string()) - self.assertRaises(tuf.RepositoryError, signercli._get_metadata_directory) - self.mock_prompt([self.random_string()]) - self.assertRaises(tuf.RepositoryError, signercli._get_metadata_directory) - - # RESTORE - signercli._prompt = original_prompt - - - - - def test_4__list_keyids(self): - - # SETUP - original_get_metadata_directory = signercli._get_metadata_directory - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Creating root and target metadata requires an expiration date to be set. - # Expiration date set to expires 100 seconds from the current time. - expiration_date = tuf.formats.format_time(time.time()+100) - expiration_date = expiration_date[0:expiration_date.rfind(' UTC')] - - # The 'root.txt' and 'targets.txt' metadata files are - # needed for _list_keyids() to determine the roles - # associated with each keyid. - keystore_dir = self.create_temp_keystore_directory() - repo_dir = self.make_temp_directory() - - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build a config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Create the metadata directory needed by _list_keyids(). - meta_dir = self.make_temp_directory() - - # Patch signercli._get_metadata_directory(). - self.mock_get_metadata_directory(directory=meta_dir) - - # Patch signercli._prompt(). - self.mock_prompt(config_filepath) - - # Patch signercli._get_password(). - self.get_passwords() - - # Create the root metadata file that will be loaded by _list_keyids() - # to extract the keyids for the top-level roles. - signercli.make_root_metadata(keystore_dir) - - # Create a directory containing target files. - targets_dir, targets_paths =\ - self.make_temp_directory_with_data_files(directory=repo_dir) - - # Mock method for signercli._prompt(). - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - # Create the target metadata file that will be loaded by _list_keyids() - # to extract the keyids for all the targets roles. - signercli.make_targets_metadata(keystore_dir) - - - # TESTS - # Test: normal case. - signercli._list_keyids(keystore_dir, meta_dir) - - # Test: Improperly formatted 'root.txt' file. - root_filename = os.path.join(meta_dir, 'root.txt') - root_signable = tuf.util.load_json_file(root_filename) - saved_roles = root_signable['signed']['roles'] - del root_signable['signed']['roles'] - tuf.repo.signerlib.write_metadata_file(root_signable, root_filename) - - self.assertRaises(tuf.RepositoryError, - signercli._list_keyids, keystore_dir, meta_dir) - - # Restore the properly formatted 'root.txt' file. - root_signable['signed']['roles'] = saved_roles - tuf.repo.signerlib.write_metadata_file(root_signable, root_filename) - - # Test: Improperly formatted 'targets.txt' file. - targets_filename = os.path.join(meta_dir, 'targets.txt') - targets_signable = tuf.util.load_json_file(targets_filename) - saved_targets = targets_signable['signed']['targets'] - del targets_signable['signed']['targets'] - tuf.repo.signerlib.write_metadata_file(targets_signable, targets_filename) - - self.assertRaises(tuf.RepositoryError, - signercli._list_keyids, keystore_dir, meta_dir) - - # Restore the properly formatted 'targets.txt' file. - targets_signable['signed']['targets'] = saved_targets - tuf.repo.signerlib.write_metadata_file(targets_signable, targets_filename) - - # RESTORE - signercli._get_password = original_get_password - signercli._prompt = original_prompt - signercli._get_metadata_directory = original_get_metadata_directory - - - - def test_2__get_keyids(self): - - # SETUP - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Create a temp keystore directory. - keystore_dir = self.create_temp_keystore_directory() - - # List of keyids including keyword 'quit'. - keyids = ['quit'] + self.rsa_keyids - - # Patching signercli._prompt() - def _mock_prompt(msg, junk): - - # Pop 'keyids' everytime signercli._prompt() is called. - keyid = keyids.pop() - if keyid != 'quit': - get_password(keyid) - return keyid - - signercli._prompt = _mock_prompt - - # Patching signercli._get_password(). - def get_password(keyid): - password = self.rsa_passwords[keyid] - def _mock_get_password(msg): - return password - - signercli._get_password = _mock_get_password - - - # TESTS - # Test: normal case. - loaded_keyids = signercli._get_keyids(keystore_dir) - self.assertTrue(tuf.formats.KEYIDS_SCHEMA.matches(loaded_keyids)) - - # Check if all the keysids were loaded. - for keyid in self.rsa_keyids: - if keyid not in loaded_keyids: - msg = 'Could not load the keyid: '+repr(keyid) - self.fail(msg) - - # Test: invalid password. - keyids = ['quit', self.rsa_keyids[0]] - saved_pw = self.rsa_passwords[self.rsa_keyids[0]] - - # Invalid password - self.rsa_passwords[self.rsa_keyids[0]] = self.random_string() - self.assertEqual(signercli._get_keyids(keystore_dir), []) - - # Restore the password. - self.rsa_passwords[self.rsa_keyids[0]] = saved_pw - - # Test: invalid keyid. - keyid = self.random_string() - keyids = ['quit', keyid] - - # Create an invalid entry in the passwords dictionary. - self.rsa_passwords[keyid] = self.random_string() - self.assertEqual(signercli._get_keyids(keystore_dir), []) - - # Restore passwords dictionary. - del self.rsa_passwords[keyid] - - # RESTORE - signercli._get_password = original_get_password - signercli._prompt = original_prompt - - - - def test_2__get_all_config_keyids(self): - - # SETUP - original_get_password = signercli._get_password - - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build the config file needed by '_get_all_config_keyids. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Create a temp keystore directory. - keystore_dir = self.create_temp_keystore_directory() - - # 'sample_keyid' used to test invalid keyid. - sample_keyid = self.rsa_keyids[0] - - # Patch signercli._get_password() - self.get_passwords() - - - # TESTS - # Test: an incorrect password. - saved_pw = self.rsa_passwords[sample_keyid] - self.rsa_passwords[sample_keyid] = self.random_string() - self.assertRaises(tuf.Error, signercli._get_all_config_keyids, - config_filepath, keystore_dir) - - # Restore the password. - self.rsa_passwords[sample_keyid] = saved_pw - - # Test: missing top-level role in the config file. - # Clear keystore's dictionaries. - keystore.clear_keystore() - - # Remove a role from 'top_level_role_info' which is used to construct - # config file. - targets_holder = self.top_level_role_info['targets'] - del self.top_level_role_info['targets'] - - # Build config file without 'targets' role. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - self.assertRaises(tuf.Error, signercli._get_all_config_keyids, - config_filepath, keystore_dir) - - # Rebuild config file and 'top_level_role_info'. - self.top_level_role_info['targets'] = targets_holder - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Test: non-existing config file path. - keystore.clear_keystore() - self.assertRaises(tuf.Error, signercli._get_all_config_keyids, - self.random_path(), keystore_dir) - - # Test: normal case. - keystore.clear_keystore() - signercli._get_all_config_keyids(config_filepath, keystore_dir) - - # RESTORE - signercli._get_password = original_get_password - - - - - def test_2__get_role_config_keyids(self): - - # SETUP - original_get_password = signercli._get_password - - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build a config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - # Create a temp keystore directory. - keystore_dir = self.create_temp_keystore_directory() - - # Patch '_get_password' method. - self.get_passwords() - - # TESTS - for role in self.role_list: - # Test: normal cases. - keystore.clear_keystore() - signercli._get_role_config_keyids(config_filepath, keystore_dir, role) - - # Test: incorrect passwords. - keystore.clear_keystore() - role_keyids = self.top_level_role_info[role]['keyids'] - for keyid in role_keyids: - saved_pw = self.rsa_passwords[keyid] - self.rsa_passwords[keyid] = self.random_string() - self.assertRaises(tuf.Error, signercli._get_role_config_keyids, - config_filepath, keystore_dir, role) - - # Restore the password. - self.rsa_passwords[keyid] = saved_pw - - # Test: non-existing config file path. - keystore.clear_keystore() - self.assertRaises(tuf.Error, signercli._get_role_config_keyids, - self.random_path(), keystore_dir, 'release') - - # Test: non-existing role. - keystore.clear_keystore() - self.assertRaises(tuf.Error, signercli._get_role_config_keyids, - config_filepath, keystore_dir, 'no_such_role') - - # RESTORE - signercli._get_password = original_get_password - - - - - def test_1__sign_and_write_metadata(self): - - # SETUP - # Role to test. - role = 'root' - - # Create temp directory. - temp_dir = self.make_temp_directory() - - # File name. - filename = os.path.join(temp_dir, role+'.txt') - - # Role's keyids. - keyids = self.top_level_role_info[role]['keyids'] - - # Create a temp keystore directory. - keystore_dir =\ - self.create_temp_keystore_directory(keystore_dicts=True) - - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Create role's metadata. - signable_meta = signerlib.generate_root_metadata(config_filepath, 8) - - - # TESTS - # Test: normal case. - signercli._sign_and_write_metadata(signable_meta, keyids, filename) - - # Verify that the root meta file was created. - self.assertTrue(os.path.exists(filename)) - - Errors = (tuf.Error, tuf.FormatError) - - # Test: invalid metadata. - self.assertRaises(Errors, signercli._sign_and_write_metadata, - self.random_string(), keyids, filename) - - # Test: invalid keyids - invalid_keyids = self.random_string() - self.assertRaises(Errors, signercli._sign_and_write_metadata, - signable_meta, invalid_keyids, filename) - - # Test: invalid filename - self.assertRaises(Errors, signercli._sign_and_write_metadata, - signable_meta, invalid_keyids, True) - - - - - def test_4_change_password(self): - - # SETUP - original_get_metadata_directory = signercli._get_metadata_directory - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Creating root and target metadata requires an expiration date to be set. - # Expiration date set to expires 100 seconds from the current time. - expiration_date = tuf.formats.format_time(time.time()+100) - expiration_date = expiration_date[0:expiration_date.rfind(' UTC')] - - # Create keystore and repo directories. - keystore_dir = self.create_temp_keystore_directory() - repo_dir = self.make_temp_directory() - - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build a config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Create a temp metadata directory. - meta_dir = self.make_temp_directory() - - # Patch signercli._get_metadata_directory(). - self.mock_get_metadata_directory(directory=meta_dir) - - # Patch signercli._prompt(). - self.mock_prompt(config_filepath) - - # Patch '_get_password' method. - self.get_passwords() - - signercli.make_root_metadata(keystore_dir) - - # Create a directory containing target files. - targets_dir, targets_paths =\ - self.make_temp_directory_with_data_files(directory=repo_dir) - - # Mock method for signercli._prompt(). - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - signercli.make_targets_metadata(keystore_dir) - - test_keyid = self.rsa_keyids[0] - self.mock_prompt(test_keyid) - - # Specify old password and create a new password. - old_password = self.rsa_passwords[test_keyid] - new_password = self.random_string() - - # Mock method for signercli._get_password() - def _mock_get_password(msg, confirm=False, old_pw=old_password, - new_pw=new_password): - if msg.startswith('\nEnter the old password for the keyid: '): - return old_pw - else: - return new_pw - - # Patch signercli._get_password. - signercli._get_password = _mock_get_password - - - # TESTS - # Test: normal case. - # Verify that the derived key is modified. A new salt is generated, so - # we cannot predict or verify a specific derived key corresponding for - # the new password. Save the derived key for 'test_keyid' and check that - # is updated. - old_derived_key = keystore._derived_keys[test_keyid] - signercli.change_password(keystore_dir) - - # Verify password change. - self.assertNotEqual(keystore._derived_keys[test_keyid], old_derived_key) - - # Test: non-existing keyid. - keystore.clear_keystore() - self.mock_prompt(self.random_string(15)) - self.assertRaises(tuf.RepositoryError, signercli.change_password, - keystore_dir) - - # Restore the prompt input to existing keyid. - self.mock_prompt(test_keyid) - - # Test: non-existing old password. - keystore.clear_keystore() - old_password = self.random_string() - self.assertRaises(tuf.RepositoryError, signercli.change_password, - keystore_dir) - - # RESTORE - signercli._get_password = original_get_password - signercli._prompt = original_prompt - signercli._get_metadata_directory = original_get_metadata_directory - - - - - def test_2_generate_rsa_key(self): - - # SETUP - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Method to patch signercli._get_password() - def _mock_get_password(junk, confirm=False): - return self.random_string() - - # Patch signercli._get_password() - signercli._get_password = _mock_get_password - - # Create a temp keystore directory. - keystore_dir = self.make_temp_directory() - - - # TESTS - # Test: invalid rsa bits. - self.mock_prompt(1024) - self.assertRaises(tuf.RepositoryError, signercli.generate_rsa_key, - keystore_dir) - # Input appropriate number of rsa bits. - self.mock_prompt(3072) - - # Test: normal case. - signercli.generate_rsa_key(keystore_dir) - - # Was the key file added to the directory? - self.assertTrue(os.listdir(keystore_dir)) - - # RESTORE - signercli._get_password = original_get_password - signercli._prompt = original_prompt - - - - - def test_4_dump_key(self): - - # SETUP - original_get_metadata_directory = signercli._get_metadata_directory - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Creating root and target metadata requires an expiration date to be set. - # Expiration date set to expires 100 seconds from the current time. - expiration_date = tuf.formats.format_time(time.time()+100) - expiration_date = expiration_date[0:expiration_date.rfind(' UTC')] - - # Create keystore and repo directories. - keystore_dir = self.create_temp_keystore_directory() - repo_dir = self.make_temp_directory() - - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build a config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Create a temp metadata directory. - meta_dir = self.make_temp_directory() - - # Patch signercli._get_metadata_directory(). - self.mock_get_metadata_directory(directory=meta_dir) - - # Patch signercli._get_password(). - self.get_passwords() - - # Patch signercli._prompt(). - self.mock_prompt(config_filepath) - - signercli.make_root_metadata(keystore_dir) - - # Create a directory containing target files. - targets_dir, targets_paths =\ - self.make_temp_directory_with_data_files(directory=repo_dir) - - # Mock method for signercli._prompt(). - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - signercli.make_targets_metadata(keystore_dir) - - - keyid = self.rsa_keyids[0] - password = self.rsa_passwords[keyid] - show_priv = 'private' - - - # Mock method for signercli._get_password(). - def _mock_get_password(msg): - return password - - # Mock method for signercli._prompt(). - def _mock_prompt(msg, junk): - if msg.startswith('\nEnter the keyid'): - return keyid - else: - return show_priv - - # Patch signercli._get_password(). - signercli._get_password = _mock_get_password - - # Patch signercli._prompt(). - signercli._prompt = _mock_prompt - - - # TESTS - # Test: normal case. - signercli.dump_key(keystore_dir) - - # Test: incorrect password. - saved_pw = password - password = self.random_string() - self.assertRaises(tuf.RepositoryError, signercli.dump_key, - keystore_dir) - - # Restore the correct password. - password = saved_pw - - # Test: non-existing keyid. - keyid = self.random_string() - self.assertRaises(tuf.RepositoryError, signercli.dump_key, - keystore_dir) - keyid = self.rsa_keyids[0] - - # RESTORE - signercli._get_password = original_get_password - signercli._prompt = original_prompt - signercli._get_metadata_directory = original_get_metadata_directory - - - - - def test_3_make_root_metadata(self): - - # SETUP - original_get_metadata_directory = signercli._get_metadata_directory - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build a config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Create a temp metadata directory. - meta_dir = self.make_temp_directory() - - # Patch signercli._get_metadata_directory(). - self.mock_get_metadata_directory(directory=meta_dir) - - # Patch signercli._prompt(). - self.mock_prompt(config_filepath) - - # Patch signercli._get_password(). - self.get_passwords() - - # Create keystore directory. - keystore_dir = self.create_temp_keystore_directory() - - - # TESTS - # Test: normal case. - signercli.make_root_metadata(keystore_dir) - - # Verify that the root metadata path was created. - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt'))) - - # Test: invalid config path. - # Clear keystore's dictionaries. - keystore.clear_keystore() - - # Supply a non-existing path to signercli._prompt(). - self.mock_prompt(self.random_path()) - self.assertRaises(tuf.RepositoryError, signercli.make_root_metadata, - keystore_dir) - - # Re-patch signercli._prompt() with valid config path. - self.mock_prompt(config_filepath) - - # Test: incorrect 'root' passwords. - # Clear keystore's dictionaries. - keystore.clear_keystore() - keyids = self.top_level_role_info['root']['keyids'] - for keyid in keyids: - saved_pw = self.rsa_passwords[keyid] - self.rsa_passwords[keyid] = self.random_string() - self.assertRaises(tuf.RepositoryError, signercli.make_root_metadata, - keystore_dir) - self.rsa_passwords[keyid] = saved_pw - - # RESTORE - signercli._get_password = original_get_password - signercli._prompt = original_prompt - signercli._get_metadata_directory = original_get_metadata_directory - - - - - def test_3_make_targets_metadata(self): - - # SETUP - original_get_metadata_directory = signercli._get_metadata_directory - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Creating target metadata requires an expiration date to be set. - # Expiration date set to expires 100 seconds from the current time. - expiration_date = tuf.formats.format_time(time.time()+100) - expiration_date = expiration_date[0:expiration_date.rfind(' UTC')] - - # Create a temp repository and metadata directories. - repo_dir = self.make_temp_directory() - meta_dir = self.make_temp_directory(directory=repo_dir) - - # Create a directory containing target files. - targets_dir, targets_paths =\ - self.make_temp_directory_with_data_files(directory=repo_dir) - - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build a config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Patch signercli._get_metadata_directory() - self.mock_get_metadata_directory(directory=meta_dir) - - # Patch signercli._get_password(). Used in _get_role_config_keyids() - self.get_passwords() - - # Create keystore directory. - keystore_dir = self.create_temp_keystore_directory() - - # Mock method for signercli._prompt(). - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - - # TESTS - # Test: normal case. - signercli.make_targets_metadata(keystore_dir) - - # Verify that targets metadata file was created. - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt'))) - - # Test: invalid targets path. - # Clear keystore's dictionaries. - keystore.clear_keystore() - - # Supply a non-existing targets directory. - """ - self.make_metadata_mock_prompts(targ_dir=self.random_path(), - conf_path=config_filepath, - expiration=expiration_date) - self.assertRaises(tuf.RepositoryError, signercli.make_targets_metadata, - keystore_dir) - """ - - # Restore the targets directory. - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - # Test: invalid config path. - # Clear keystore's dictionaries. - keystore.clear_keystore() - - # Supply a non-existing config path. - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=self.random_path(), - expiration=expiration_date) - self.assertRaises(tuf.RepositoryError, signercli.make_targets_metadata, - keystore_dir) - - # Restore the config file path. - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - # Test: invalid expiration date. - # Clear keystore's dictionaries - keystore.clear_keystore() - - # Supply invalid expiration date. - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=self.random_string()) - self.assertRaises(tuf.RepositoryError, signercli.make_targets_metadata, - keystore_dir) - - # Restore the config file path. - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - # Test: incorrect 'targets' passwords. - # Clear keystore's dictionaries. - keystore.clear_keystore() - keyids = self.top_level_role_info['targets']['keyids'] - for keyid in keyids: - saved_pw = self.rsa_passwords[keyid] - self.rsa_passwords[keyid] = self.random_string() - self.assertRaises(tuf.RepositoryError, signercli.make_targets_metadata, - keystore_dir) - self.rsa_passwords[keyid] = saved_pw - - # RESTORE - signercli._get_password = original_get_password - signercli._prompt = original_prompt - signercli._get_metadata_directory = original_get_metadata_directory - - - - - def test_4_make_release_metadata(self): - - # SETUP - original_get_metadata_directory = signercli._get_metadata_directory - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Creating release metadata requires an expiration date to be set. - # Expiration date set to expires 100 seconds from the current time. - expiration_date = tuf.formats.format_time(time.time()+100) - expiration_date = expiration_date[0:expiration_date.rfind(' UTC')] - - # In order to build release metadata file (release.txt), - # root and targets metadata files (root.txt, targets.txt) - # must exist in the metadata directory. - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build a config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Create a temp repository and metadata directories. - repo_dir = self.make_temp_directory() - meta_dir = self.make_temp_directory(repo_dir) - - # Create a directory containing target files. - targets_dir, targets_paths = \ - self.make_temp_directory_with_data_files(directory=repo_dir) - - # Patch signercli._get_metadata_directory(). - self.mock_get_metadata_directory(directory=meta_dir) - - # Patch signercli._get_password(). Used in _get_role_config_keyids(). - self.get_passwords() - - # Create keystore directory. - keystore_dir = self.create_temp_keystore_directory() - - # Mock method for signercli._prompt(). - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - - # TESTS - # Test: no root.txt in the metadata dir. - signercli.make_targets_metadata(keystore_dir) - - # Verify that 'tuf.RepositoryError' is raised due to a missing root.txt. - keystore.clear_keystore() - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt'))) - self.assertRaises(tuf.RepositoryError, signercli.make_release_metadata, - keystore_dir) - os.remove(os.path.join(meta_dir,'targets.txt')) - keystore.clear_keystore() - - # Test: no targets.txt in the metadatadir. - signercli.make_root_metadata(keystore_dir) - keystore.clear_keystore() - - # Verify that 'tuf.RepositoryError' is raised due to a missing targets.txt. - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt'))) - self.assertRaises(tuf.RepositoryError, signercli.make_release_metadata, - keystore_dir) - os.remove(os.path.join(meta_dir,'root.txt')) - keystore.clear_keystore() - - # Test: normal case. - signercli.make_root_metadata(keystore_dir) - keystore.clear_keystore() - signercli.make_targets_metadata(keystore_dir) - keystore.clear_keystore() - signercli.make_release_metadata(keystore_dir) - keystore.clear_keystore() - - # Verify if the root, targets and release meta files were created. - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt'))) - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt'))) - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'release.txt'))) - - # Test: invalid config path. - # Supply a non-existing config file path. - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=self.random_path(), expiration=expiration_date) - self.assertRaises(tuf.RepositoryError, signercli.make_release_metadata, - keystore_dir) - - # Restore the config file path. - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, expiration=expiration_date) - - # Test: incorrect 'release' passwords. - # Clear keystore's dictionaries. - keystore.clear_keystore() - keyids = self.top_level_role_info['release']['keyids'] - for keyid in keyids: - saved_pw = self.rsa_passwords[keyid] - self.rsa_passwords[keyid] = self.random_string() - self.assertRaises(tuf.RepositoryError, signercli.make_release_metadata, - keystore_dir) - self.rsa_passwords[keyid] = saved_pw - - # RESTORE - signercli._get_password = original_get_password - signercli._prompt = original_prompt - signercli._get_metadata_directory = original_get_metadata_directory - - - - - def test_5_make_timestamp_metadata(self): - - # SETUP - original_get_metadata_directory = signercli._get_metadata_directory - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Creating the top-level metadata requires an expiration date to be set. - # Expiration date set to expires 100 seconds from the current time. - expiration_date = tuf.formats.format_time(time.time()+100) - expiration_date = expiration_date[0:expiration_date.rfind(' UTC')] - - # In order to build timestamp metadata file (timestamp.txt), - # root, targets and release metadata files (root.txt, targets.txt - # release.txt) must exist in the metadata directory. - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build a config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Create a temp repository and metadata directories. - repo_dir = self.make_temp_directory() - meta_dir = self.make_temp_directory(repo_dir) - - # Create a directory containing target files. - targets_dir, targets_paths = \ - self.make_temp_directory_with_data_files(directory=repo_dir) - - # Patch signercli._get_metadata_directory(). - self.mock_get_metadata_directory(directory=meta_dir) - - # Patch signercli._get_password(). Used in _get_role_config_keyids(). - self.get_passwords() - - # Create keystore directory. - keystore_dir = self.create_temp_keystore_directory() - - # Mock method for signercli._prompt(). - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - - # TESTS - # Test: no root.txt in the metadata dir. - signercli.make_targets_metadata(keystore_dir) - - # Verify if the targets metadata file was created. - keystore.clear_keystore() - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt'))) - self.assertRaises(tuf.RepositoryError, signercli.make_timestamp_metadata, - keystore_dir) - os.remove(os.path.join(meta_dir,'targets.txt')) - keystore.clear_keystore() - - # Test: no targets.txt in the metadatadir. - signercli.make_root_metadata(keystore_dir) - - # Verify if the root metadata file was created. - keystore.clear_keystore() - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt'))) - self.assertRaises(tuf.RepositoryError, signercli.make_timestamp_metadata, - keystore_dir) - os.remove(os.path.join(meta_dir,'root.txt')) - keystore.clear_keystore() - - # Test: no release.txt in the metadatadir. - signercli.make_root_metadata(keystore_dir) - keystore.clear_keystore() - signercli.make_targets_metadata(keystore_dir) - keystore.clear_keystore() - - # Verify that 'tuf.Repository' is raised due to a missing release.txt. - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt'))) - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt'))) - self.assertRaises(tuf.RepositoryError, signercli.make_timestamp_metadata, - keystore_dir) - os.remove(os.path.join(meta_dir,'root.txt')) - os.remove(os.path.join(meta_dir,'targets.txt')) - keystore.clear_keystore() - - # Test: normal case. - signercli.make_root_metadata(keystore_dir) - keystore.clear_keystore() - signercli.make_targets_metadata(keystore_dir) - keystore.clear_keystore() - signercli.make_release_metadata(keystore_dir) - keystore.clear_keystore() - signercli.make_timestamp_metadata(keystore_dir) - keystore.clear_keystore() - - # Verify if the root, targets and release metadata files were created. - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'root.txt'))) - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'targets.txt'))) - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'release.txt'))) - self.assertTrue(os.path.exists(os.path.join(meta_dir, 'timestamp.txt'))) - - # Test: invalid config path. - # Supply a non-existing config file path. - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=self.random_path(), - expiration=expiration_date) - self.assertRaises(tuf.RepositoryError, - signercli.make_release_metadata, keystore_dir) - - # Restore the config file path. - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - # Test: incorrect 'release' passwords. - - # Clear keystore's dictionaries. - keystore.clear_keystore() - - keyids = self.top_level_role_info['release']['keyids'] - for keyid in keyids: - saved_pw = self.rsa_passwords[keyid] - self.rsa_passwords[keyid] = self.random_string() - self.assertRaises(tuf.RepositoryError, - signercli.make_release_metadata, keystore_dir) - self.rsa_passwords[keyid] = saved_pw - - # RESTORE - signercli._get_password = original_get_password - signercli._get_metadata_directory = original_get_metadata_directory - - - - - def test_6_sign_metadata_file(self): - - # SETUP - original_get_metadata_directory = signercli._get_metadata_directory - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Creating the top-level metadata requires an expiration date to be set. - # Expiration date set to expires 100 seconds from the current time. - expiration_date = tuf.formats.format_time(time.time()+100) - expiration_date = expiration_date[0:expiration_date.rfind(' UTC')] - - # To test this method, an RSA key will be created with - # a password in addition to the existing RSA keys. - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build a config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Create a temp repository and metadata directories. - repo_dir = self.make_temp_directory() - meta_dir = self.make_temp_directory(repo_dir) - - # Create a directory containing target files. - targets_dir, targets_paths = \ - self.make_temp_directory_with_data_files(directory=repo_dir) - - # Patch signercli._get_metadata_directory(). - self.mock_get_metadata_directory(directory=meta_dir) - - # Patch signercli._get_password(). Used in _get_role_config_keyids(). - self.get_passwords() - - # Create keystore directory. - keystore_dir = self.create_temp_keystore_directory() - - # Mock method for signercli._prompt(). - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - # Create metadata files. - signercli.make_root_metadata(keystore_dir) - keystore.clear_keystore() - signercli.make_targets_metadata(keystore_dir) - keystore.clear_keystore() - signercli.make_release_metadata(keystore_dir) - keystore.clear_keystore() - signercli.make_timestamp_metadata(keystore_dir) - keystore.clear_keystore() - - # Verify if the root, targets and release meta files were created. - root_meta_filepath = os.path.join(meta_dir, 'root.txt') - targets_meta_filepath = os.path.join(meta_dir, 'targets.txt') - release_meta_filepath = os.path.join(meta_dir, 'release.txt') - timestamp_meta_filepath = os.path.join(meta_dir, 'timestamp.txt') - - self.assertTrue(os.path.exists(root_meta_filepath)) - self.assertTrue(os.path.exists(targets_meta_filepath)) - self.assertTrue(os.path.exists(release_meta_filepath)) - self.assertTrue(os.path.exists(timestamp_meta_filepath)) - - - # Create a new RSA key, indicate metadata filename. - new_keyid = self.generate_rsakey() - meta_filename = targets_meta_filepath - - # Create keystore directory. New key is untouched. - keystore_dir = self.create_temp_keystore_directory(keystore_dicts=True) - - # List of keyids to be returned by _get_keyids() - signing_keyids = [] - - # Method to patch signercli._get_keyids() - def _mock_get_keyids(junk): - return signing_keyids - - # Method to patch signercli._prompt(). - def _mock_prompt(msg, junk): - return meta_filename - - # Patch signercli._get_keyids() - signercli._get_keyids = _mock_get_keyids - - # Patch signercli._prompt(). - signercli._prompt = _mock_prompt - - - # TESTS - # Test: no loaded keyids. - self.assertRaises(tuf.RepositoryError, - signercli.sign_metadata_file, keystore_dir) - - # Load new keyid. - signing_keyids = [new_keyid] - - # Test: normal case. - signercli.sign_metadata_file(keystore_dir) - - # Verify the change. - self.assertTrue(os.path.exists(targets_meta_filepath)) - - # Load targets metadata from the file ('targets.txt'). - targets_metadata = tuf.util.load_json_file(targets_meta_filepath) - keyid_exists = False - for signature in targets_metadata['signatures']: - if new_keyid == signature['keyid']: - keyid_exists = True - break - - self.assertTrue(keyid_exists) - - # RESTORE - signercli._get_password = original_get_password - signercli._prompt = original_prompt - signercli._get_metadata_directory = original_get_metadata_directory - - - - - def test_7_make_delegation(self): - - # SETUP - original_get_metadata_directory = signercli._get_metadata_directory - original_prompt = signercli._prompt - original_get_password = signercli._get_password - - # Creating the top-level metadata requires an expiration date to be set. - # Expiration date set to expires 100 seconds from the current time. - expiration_date = tuf.formats.format_time(time.time()+100) - expiration_date = expiration_date[0:expiration_date.rfind(' UTC')] - - # Create a temp repository and metadata directories. - repo_dir = self.make_temp_directory() - meta_dir = self.make_temp_directory(directory=repo_dir) - - # Create targets directories. - targets_dir, targets_paths =\ - self.make_temp_directory_with_data_files(directory=repo_dir) - delegated_targets_dir = os.path.join(targets_dir,'targets', - 'delegated_level1') - - # Assign parent role and name of the delegated role. - parent_role = 'targets' - delegated_role = 'delegated_role_1' - - # Create couple new RSA keys for delegation levels 1 and 2. - new_keyid_1 = self.generate_rsakey() - new_keyid_2 = self.generate_rsakey() - - # Create temp directory for config file. - config_dir = self.make_temp_directory() - - # Build a config file. - config_filepath = signerlib.build_config_file(config_dir, 365, - self.top_level_role_info) - - # Patch signercli._get_metadata_directory(). - self.mock_get_metadata_directory(directory=meta_dir) - - # Patch signercli._get_password(). Get passwords for parent's keyids. - self.get_passwords() - - # Create keystore directory. - keystore_dir = self.create_temp_keystore_directory() - - # Mock method for signercli._prompt() to generate targets.txt file. - self.make_metadata_mock_prompts(targ_dir=targets_dir, - conf_path=config_filepath, - expiration=expiration_date) - - # List of keyids to be returned by _get_keyids() - signing_keyids = [new_keyid_1] - - # Load keystore. - load_keystore = keystore.load_keystore_from_keyfiles - - # Build the root metadata file (root.txt). - signercli.make_root_metadata(keystore_dir) - - # Build targets metadata file (targets.txt). - signercli.make_targets_metadata(keystore_dir) - - # Clear kestore's dictionaries. - keystore.clear_keystore() - - # Mock method for signercli._prompt(). - def _mock_prompt(msg, junk): - if msg.startswith('\nThe paths entered'): - return delegated_targets_dir - elif msg.startswith('\nChoose and enter the parent'): - return parent_role - elif msg.startswith('\nEnter the delegated role\'s name: '): - return delegated_role - elif msg.startswith('\nCurrent time:'): - return expiration_date - else: - error_msg = ('Prompt: '+'\''+msg+'\''+ - ' did not match any predefined mock prompts.') - self.fail(error_msg) - - # Mock method for signercli._get_password(). - def _mock_get_password(msg): - for keyid in self.rsa_keyids: - if msg.endswith('('+keyid+'): '): - return self.rsa_passwords[keyid] - - # Method to patch signercli._get_keyids() - def _mock_get_keyids(junk): - if signing_keyids: - for keyid in signing_keyids: - password = self.rsa_passwords[keyid] - # Load the keyfile. - load_keystore(keystore_dir, [keyid], [password]) - return signing_keyids - - # Patch signercli._prompt(). - signercli._prompt = _mock_prompt - - # Patch signercli._get_password(). - signercli._get_password = _mock_get_password - - # Patch signercli._get_keyids(). - signercli._get_keyids = _mock_get_keyids - - - # TESTS - # Test: invalid parent role. - # Assign a non-existing parent role. - parent_role = self.random_string() - self.assertRaises(tuf.RepositoryError, signercli.make_delegation, - keystore_dir) - - # Restore parent role. - parent_role = 'targets' - - # Test: invalid password(s) for parent's keyids. - keystore.clear_keystore() - parent_keyids = self.top_level_role_info[parent_role]['keyids'] - for keyid in parent_keyids: - saved_pw = self.rsa_passwords[keyid] - self.rsa_passwords[keyid] = self.random_string() - self.assertRaises(tuf.RepositoryError, signercli.make_delegation, - keystore_dir) - self.rsa_passwords[keyid] = saved_pw - - # Test: delegated_keyids == 0. - keystore.clear_keystore() - - # Load 0 keyids (== 0). - signing_keyids = [] - self.assertRaises(tuf.RepositoryError, signercli.make_delegation, - keystore_dir) - keystore.clear_keystore() - - # Restore signing_keyids (== 1). - signing_keyids = [new_keyid_1] - - # Test: normal case 1. - # Testing first level delegation. - signercli.make_delegation(keystore_dir) - - # Verify delegated metadata file exists. - delegated_meta_file = os.path.join(meta_dir, parent_role, - delegated_role+'.txt') - self.assertTrue(os.path.exists(delegated_meta_file)) - - # Test: normal case 2. - # Testing second level delegation. - keystore.clear_keystore() - - # Make necessary adjustments for the test. - signing_keyids = [new_keyid_2] - delegated_targets_dir = os.path.join(delegated_targets_dir, - 'delegated_level2') - parent_role = os.path.join(parent_role, delegated_role) - delegated_role = 'delegated_role_2' - - signercli.make_delegation(keystore_dir) - - # Verify delegated metadata file exists. - delegated_meta_file = os.path.join(meta_dir, parent_role, - delegated_role+'.txt') - self.assertTrue(os.path.exists(delegated_meta_file)) - - # Test: normal case 3. - # Testing delegated_keyids > 1. - # Ensure make_delegation() sets 'threshold' = 2 for the delegated role. - keystore.clear_keystore() - - # Populate 'signing_keyids' with multiple keys, so the - # the delegated metadata is set to a threshold > 1. - signing_keyids = [new_keyid_1, new_keyid_2] - parent_role = 'targets' - delegated_role = 'delegated_role_1' - - signercli.make_delegation(keystore_dir) - - # Verify delegated metadata file exists. - delegated_meta_file = os.path.join(meta_dir, parent_role, - delegated_role+'.txt') - self.assertTrue(os.path.exists(delegated_meta_file)) - - # Verify the threshold value of the delegated metadata file - # by inspecting the parent role's 'delegations' field. - parent_role_file = os.path.join(meta_dir, parent_role+'.txt') - signable = signerlib.read_metadata_file(parent_role_file) - delegated_rolename = parent_role+'/'+delegated_role - - roles = signable['signed']['delegations']['roles'] - role_index = signerlib.find_delegated_role(roles, delegated_rolename) - self.assertIsNotNone(role_index) - role = roles[role_index] - - threshold = role['threshold'] - self.assertTrue(threshold == 2) - - # RESTORE - signercli._get_password = original_get_password - signercli._prompt = original_prompt - signercli._get_metadata_directory = original_get_metadata_directory - - -def setUpModule(): - # setUpModule() is called before any test cases run. - # Populating 'rsa_keystore' and 'rsa_passwords' dictionaries. - # We will need them when creating keystore directories. - unittest_toolbox.Modified_TestCase.bind_keys_to_roles() - - -def tearDownModule(): - # tearDownModule() is called after all the test cases have run. - unittest_toolbox.Modified_TestCase.clear_toolbox() - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/unit/deprecated/test_signerlib.py b/tests/unit/deprecated/test_signerlib.py deleted file mode 100755 index a09f78fa..00000000 --- a/tests/unit/deprecated/test_signerlib.py +++ /dev/null @@ -1,986 +0,0 @@ -""" - - test_signerlib.py - - - Konstantin Andrianov - - - September 6, 2012 - - - See LICENSE for licensing information. - - - 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. - - - - 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. - - - directory: - Directory of a config file. - - - 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() diff --git a/tests/unit/simple_server.py b/tests/unit/simple_server.py deleted file mode 100755 index 217bdeed..00000000 --- a/tests/unit/simple_server.py +++ /dev/null @@ -1,48 +0,0 @@ -""" - - simple_server.py - - - Konstantin Andrianov - - - February 15, 2012 - - - See LICENSE for licensing information. - - - This is a basic server that was designed to be used in conjunction with - test_download.py to test download.py module. - - - 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() diff --git a/tests/unit/statement_coverage.py b/tests/unit/statement_coverage.py deleted file mode 100755 index 6c40b0d5..00000000 --- a/tests/unit/statement_coverage.py +++ /dev/null @@ -1,86 +0,0 @@ -""" - - statement_coverage.py - - - Konstantin Andrianov - - - March 20, 2013. - - - See LICENSE for licensing information. - - - 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) \ No newline at end of file diff --git a/tests/unit/test_util_test_tools.py b/tests/unit/test_util_test_tools.py deleted file mode 100755 index bfd86d7f..00000000 --- a/tests/unit/test_util_test_tools.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env python - -""" - - test_util_test_tools.py - - - Konstantin Andrianov - - - February 26, 2012 - - - See LICENSE for licensing information. - - - 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() diff --git a/tuf/tests/unittest_toolbox.py b/tests/unittest_toolbox.py old mode 100644 new mode 100755 similarity index 99% rename from tuf/tests/unittest_toolbox.py rename to tests/unittest_toolbox.py index d425fe76..ee0ac170 --- a/tuf/tests/unittest_toolbox.py +++ b/tests/unittest_toolbox.py @@ -27,11 +27,11 @@ import ConfigParser import tuf.keys -import tuf.repo.keystore as keystore +#import tuf.repo.keystore as keystore # Modify the number of iterations (from the higher default count) so the unit # tests run faster. -keystore._PBKDF2_ITERATIONS = 1000 +#keystore._PBKDF2_ITERATIONS = 1000 class Modified_TestCase(unittest.TestCase): diff --git a/tuf/README.md b/tuf/README.md index 52f9214c..404438e5 100644 --- a/tuf/README.md +++ b/tuf/README.md @@ -170,6 +170,7 @@ Not enough signatures for 'path/to/repository/metadata.staged/targets.json' ```python # Continuing from the previous section . . . +import datetime # Generate keys for the remaining top-level roles. The root keys have been set above. # The password argument may be omitted if a password prompt is needed. @@ -200,7 +201,7 @@ repository.timestamp.load_signing_key(private_timestamp_key) # Optionally set the expiration date of the timestamp role. By default, roles are set to expire # as follows: root(1 year), targets(3 months), snapshot(1 week), timestamp(1 day). -repository.timestamp.expiration = "2014-10-28 12:08:00" +repository.timestamp.expiration = datetime.datetime(2014, 10, 28, 12, 08) # Metadata files may also be compressed. Only "gz" is currently supported. repository.targets.compressions = ["gz"] diff --git a/tuf/__init__.py b/tuf/__init__.py index 14a61f6c..eefde2d8 100755 --- a/tuf/__init__.py +++ b/tuf/__init__.py @@ -22,6 +22,7 @@ import urlparse + # Import 'tuf.formats' if a module tries to import the # entire tuf package (i.e., from tuf import *). __all__ = ['formats'] @@ -134,12 +135,7 @@ class ForbiddenTargetError(RepositoryError): class ExpiredMetadataError(Error): """Indicate that a TUF Metadata file has expired.""" - - def __init__(self, expiry_time): - self.expiry_time = expiry_time # UTC - - def __str__(self): - return 'Metadata expired on '+str(self.expiry_time)+'.' + pass diff --git a/tuf/_vendor/__init__.py b/tuf/_vendor/__init__.py old mode 100644 new mode 100755 diff --git a/tuf/_vendor/iso8601/LICENSE b/tuf/_vendor/iso8601/LICENSE new file mode 100644 index 00000000..471acb7b --- /dev/null +++ b/tuf/_vendor/iso8601/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2007 - 2013 Michael Twomey + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/tuf/_vendor/iso8601/README.rst b/tuf/_vendor/iso8601/README.rst new file mode 100644 index 00000000..e854dee9 --- /dev/null +++ b/tuf/_vendor/iso8601/README.rst @@ -0,0 +1,170 @@ +Simple module to parse ISO 8601 dates + +This module parses the most common forms of ISO 8601 date strings (e.g. +2007-01-14T20:34:22+00:00) into datetime objects. + +>>> import iso8601 +>>> iso8601.parse_date("2007-01-25T12:00:00Z") +datetime.datetime(2007, 1, 25, 12, 0, tzinfo=) +>>> + +See the LICENSE file for the license this package is released under. + +If you want more full featured parsing look at: + +- http://labix.org/python-dateutil - python-dateutil + +Parsed Formats +============== + +You can parse full date + times, or just the date. In both cases a datetime instance is returned but with missing times defaulting to 0, and missing days / months defaulting to 1. + +Dates +----- + +- YYYY-MM-DD +- YYYYMMDD +- YYYY-MM (defaults to 1 for the day) +- YYYY (defaults to 1 for month and day) + +Times +----- + +- hh:mm:ss.nn +- hhmmss.nn +- hh:mm (defaults to 0 for seconds) +- hhmm (defaults to 0 for seconds) +- hh (defaults to 0 for minutes and seconds) + +Time Zones +---------- + +- Nothing uses the default timezone given (UTC). +- Z (UTC) +- +/-hh:mm +- +/-hhmm +- +/-hh + +Where it Differs From ISO 8601 +============================== + +Known differences from the ISO 8601 spec: + +- You can use a " " (space) instead of T for separating date from time. +- Days and months without a leading 0 (2 vs 02) will be parsed. +- If time zone information is omitted the default time zone given is used (which in turn defaults to UTC). Use a default of None to yield naive datetime instances. + +Homepage +======== + +- https://bitbucket.org/micktwomey/pyiso8601/ + +This was originally hosted at https://code.google.com/p/pyiso8601/ + +References +========== + +- http://en.wikipedia.org/wiki/ISO_8601 + +- http://www.cl.cam.ac.uk/~mgk25/iso-time.html - simple overview + +- http://hydracen.com/dx/iso8601.htm - more detailed enumeration of valid formats. + +Testing +======= + +1. pip install -r dev-requirements.txt +2. tox + +Note that you need all the pythons installed to perform a tox run (see below). Homebrew helps a lot on the mac, however you wind up having to add cellars to your PATH or symlinking the pythonX.Y executables. + +Alternatively, to test only with your current python: + +1. pip install -r dev-requirements.txt +2. py.test --verbose iso8601 + +Supported Python Versions +========================= + +Tested against: + +- Python 2.6 +- Python 2.7 +- Python 3.2 +- Python 3.3 +- PyPy + +Python 3.0 and 3.1 are untested but should work (tests didn't run under them when last tried). + +Jython is untested but should work (tests failed to run). + +Python 2.5 is not supported (too old for the tests for the most part). It could work with some small changes but I'm not supporting it. + +Changes +======= + +0.1.10 +------ + +* Fixes https://bitbucket.org/micktwomey/pyiso8601/issue/14/regression-yyyy-mm-no-longer-parses (thanks to Kevin Gill for reporting) +* Adds YYYY as a valid date (uses 1 for both month and day) +* Woo, semantic versioning, .10 at last. + +0.1.9 +----- + +* Lots of fixes tightening up parsing from jdanjou. In particular more invalid cases are treated as errors. Also includes fixes for tests (which is how these invalid cases got in in the first place). +* Release addresses https://bitbucket.org/micktwomey/pyiso8601/issue/13/new-release-based-on-critical-bug-fix + +0.1.8 +----- + +* Remove +/- chars from README.rst and ensure tox tests run using LC_ALL=C. The setup.py egg_info command was failing in python 3.* on some setups (basically any where the system encoding wasn't UTF-8). (https://bitbucket.org/micktwomey/pyiso8601/issue/10/setuppy-broken-for-python-33) (thanks to klmitch) + +0.1.7 +----- + +* Fix parsing of microseconds (https://bitbucket.org/micktwomey/pyiso8601/issue/9/regression-parsing-microseconds) (Thanks to dims and bnemec) + +0.1.6 +----- + +* Correct negative timezone offsets (https://bitbucket.org/micktwomey/pyiso8601/issue/8/015-parses-negative-timezones-incorrectly) (thanks to Jonathan Lange) + +0.1.5 +----- + +* Wow, it's alive! First update since 2007 +* Moved over to https://bitbucket.org/micktwomey/pyiso8601 +* Add support for python 3. https://code.google.com/p/pyiso8601/issues/detail?id=23 (thanks to zefciu) +* Switched to py.test and tox for testing +* Make seconds optional in date format ("1997-07-16T19:20+01:00" now valid). https://bitbucket.org/micktwomey/pyiso8601/pull-request/1/make-the-inclusion-of-seconds-optional-in/diff (thanks to Chris Down) +* Correctly raise ParseError for more invalid inputs (https://bitbucket.org/micktwomey/pyiso8601/issue/1/raise-parseerror-for-invalid-input) (thanks to manish.tomar) +* Support more variations of ISO 8601 dates, times and time zone specs. +* Fix microsecond rounding issues (https://bitbucket.org/micktwomey/pyiso8601/issue/2/roundoff-issues-when-parsing-decimal) (thanks to nielsenb@jetfuse.net) +* Fix pickling and deepcopy of returned datetime objects (https://bitbucket.org/micktwomey/pyiso8601/issue/3/dates-returned-by-parse_date-do-not) (thanks to fogathmann and john@openlearning.com) +* Fix timezone offsets without a separator (https://bitbucket.org/micktwomey/pyiso8601/issue/4/support-offsets-without-a-separator) (thanks to joe.walton.gglcd) +* "Z" produces default timezone if one is specified (https://bitbucket.org/micktwomey/pyiso8601/issue/5/z-produces-default-timezone-if-one-is) (thanks to vfaronov). This one may cause problems if you've been relying on default_timezone to use that timezone instead of UTC. Strictly speaking that was wrong but this is potentially backwards incompatible. +* Handle compact date format (https://bitbucket.org/micktwomey/pyiso8601/issue/6/handle-compact-date-format) (thanks to rvandolson@esri.com) + +0.1.4 +----- + +* The default_timezone argument wasn't being passed through correctly, UTC was being used in every case. Fixes issue 10. + +0.1.3 +----- + +* Fixed the microsecond handling, the generated microsecond values were way too small. Fixes issue 9. + +0.1.2 +----- + +* Adding ParseError to __all__ in iso8601 module, allows people to import it. Addresses issue 7. +* Be a little more flexible when dealing with dates without leading zeroes. This violates the spec a little, but handles more dates as seen in the field. Addresses issue 6. +* Allow date/time separators other than T. + +0.1.1 +----- + +* When parsing dates without a timezone the specified default is used. If no default is specified then UTC is used. Addresses issue 4. diff --git a/tuf/_vendor/iso8601/__init__.py b/tuf/_vendor/iso8601/__init__.py new file mode 100644 index 00000000..11b1adcb --- /dev/null +++ b/tuf/_vendor/iso8601/__init__.py @@ -0,0 +1 @@ +from .iso8601 import * diff --git a/tuf/_vendor/iso8601/iso8601.py b/tuf/_vendor/iso8601/iso8601.py new file mode 100644 index 00000000..becdd958 --- /dev/null +++ b/tuf/_vendor/iso8601/iso8601.py @@ -0,0 +1,202 @@ +"""ISO 8601 date time string parsing + +Basic usage: +>>> import iso8601 +>>> iso8601.parse_date("2007-01-25T12:00:00Z") +datetime.datetime(2007, 1, 25, 12, 0, tzinfo=) +>>> + +""" + +from datetime import ( + datetime, + timedelta, + tzinfo +) +from decimal import Decimal +import logging +import sys +import re + +__all__ = ["parse_date", "ParseError"] + +LOG = logging.getLogger(__name__) + +if sys.version_info >= (3, 0, 0): + _basestring = str +else: + _basestring = basestring + + +# Adapted from http://delete.me.uk/2005/03/iso8601.html +ISO8601_REGEX = re.compile( + r""" + (?P[0-9]{4}) + ( + ( + (-(?P[0-9]{1,2})) + | + (?P[0-9]{2}) + (?!$) # Don't allow YYYYMM + ) + ( + ( + (-(?P[0-9]{1,2})) + | + (?P[0-9]{2}) + ) + ( + ( + (?P[ T]) + (?P[0-9]{2}) + (:{0,1}(?P[0-9]{2})){0,1} + ( + :{0,1}(?P[0-9]{1,2}) + (\.(?P[0-9]+)){0,1} + ){0,1} + (?P + Z + | + ( + (?P[-+]) + (?P[0-9]{2}) + :{0,1} + (?P[0-9]{2}){0,1} + ) + ){0,1} + ){0,1} + ) + ){0,1} # YYYY-MM + ){0,1} # YYYY only + $ + """, + re.VERBOSE +) + +class ParseError(Exception): + """Raised when there is a problem parsing a date string""" + +# Yoinked from python docs +ZERO = timedelta(0) +class Utc(tzinfo): + """UTC + + """ + def utcoffset(self, dt): + return ZERO + + def tzname(self, dt): + return "UTC" + + def dst(self, dt): + return ZERO + +UTC = Utc() + +class FixedOffset(tzinfo): + """Fixed offset in hours and minutes from UTC + + """ + def __init__(self, offset_hours, offset_minutes, name): + self.__offset_hours = offset_hours # Keep for later __getinitargs__ + self.__offset_minutes = offset_minutes # Keep for later __getinitargs__ + self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes) + self.__name = name + + def __eq__(self, other): + if isinstance(other, FixedOffset): + return ( + (other.__offset == self.__offset) + and + (other.__name == self.__name) + ) + if isinstance(other, tzinfo): + return other == self + return False + + def __getinitargs__(self): + return (self.__offset_hours, self.__offset_minutes, self.__name) + + def utcoffset(self, dt): + return self.__offset + + def tzname(self, dt): + return self.__name + + def dst(self, dt): + return ZERO + + def __repr__(self): + return "" % (self.__name, self.__offset) + +def to_int(d, key, default_to_zero=False, default=None, required=True): + """Pull a value from the dict and convert to int + + :param default_to_zero: If the value is None or empty, treat it as zero + :param default: If the value is missing in the dict use this default + + """ + value = d.get(key) or default + LOG.debug("Got %r for %r with default %r", value, key, default) + if (value in ["", None]) and default_to_zero: + return 0 + if value is None: + if required: + raise ParseError("Unable to read %s from %s" % (key, d)) + else: + return int(value) + +def parse_timezone(matches, default_timezone=UTC): + """Parses ISO 8601 time zone specs into tzinfo offsets + + """ + + if matches["timezone"] == "Z": + return UTC + # This isn't strictly correct, but it's common to encounter dates without + # timezones so I'll assume the default (which defaults to UTC). + # Addresses issue 4. + if matches["timezone"] is None: + return default_timezone + sign = matches["tz_sign"] + hours = to_int(matches, "tz_hour") + minutes = to_int(matches, "tz_minute", default_to_zero=True) + description = "%s%02d:%02d" % (sign, hours, minutes) + if sign == "-": + hours = -hours + minutes = -minutes + return FixedOffset(hours, minutes, description) + +def parse_date(datestring, default_timezone=UTC): + """Parses ISO 8601 dates into datetime objects + + The timezone is parsed from the date string. However it is quite common to + have dates without a timezone (not strictly correct). In this case the + default timezone specified in default_timezone is used. This is UTC by + default. + """ + if not isinstance(datestring, _basestring): + raise ParseError("Expecting a string %r" % datestring) + m = ISO8601_REGEX.match(datestring) + if not m: + raise ParseError("Unable to parse date string %r" % datestring) + groups = m.groupdict() + LOG.debug("Parsed %s into %s with default timezone %s", datestring, groups, default_timezone) + + tz = parse_timezone(groups, default_timezone=default_timezone) + + groups["second_fraction"] = int(Decimal("0.%s" % (groups["second_fraction"] or 0)) * Decimal("1000000.0")) + + try: + return datetime( + year=to_int(groups, "year"), + month=to_int(groups, "month", default=to_int(groups, "monthdash", required=False, default=1)), + day=to_int(groups, "day", default=to_int(groups, "daydash", required=False, default=1)), + hour=to_int(groups, "hour", default_to_zero=True), + minute=to_int(groups, "minute", default_to_zero=True), + second=to_int(groups, "second", default_to_zero=True), + microsecond=groups["second_fraction"], + tzinfo=tz, + ) + except Exception as e: + raise ParseError(e) diff --git a/tuf/_vendor/iso8601/test_iso8601.py b/tuf/_vendor/iso8601/test_iso8601.py new file mode 100644 index 00000000..ed2d45a0 --- /dev/null +++ b/tuf/_vendor/iso8601/test_iso8601.py @@ -0,0 +1,97 @@ +# coding=UTF-8 +from __future__ import absolute_import + +import copy +import datetime +import pickle + +import pytest + +from iso8601 import iso8601 + +def test_iso8601_regex(): + assert iso8601.ISO8601_REGEX.match("2006-10-11T00:14:33Z") + +def test_parse_no_timezone_different_default(): + tz = iso8601.FixedOffset(2, 0, "test offset") + d = iso8601.parse_date("2007-01-01T08:00:00", default_timezone=tz) + assert d == datetime.datetime(2007, 1, 1, 8, 0, 0, 0, tz) + assert d.tzinfo == tz + +def test_parse_utc_different_default(): + """Z should mean 'UTC', not 'default'. + + """ + tz = iso8601.FixedOffset(2, 0, "test offset") + d = iso8601.parse_date("2007-01-01T08:00:00Z", default_timezone=tz) + assert d == datetime.datetime(2007, 1, 1, 8, 0, 0, 0, iso8601.UTC) + +@pytest.mark.parametrize("invalid_date, error_string", [ + ("2013-10-", "Unable to parse date string"), + ("2013-", "Unable to parse date string"), + ("", "Unable to parse date string"), + (None, "Expecting a string"), + ("wibble", "Unable to parse date string"), + ("23", "Unable to parse date string"), + ("131015T142533Z", "Unable to parse date string"), + ("131015", "Unable to parse date string"), + ("20141", "Unable to parse date string"), + ("201402", "Unable to parse date string"), + ("2007-06-23X06:40:34.00Z", "Unable to parse date string"), # https://code.google.com/p/pyiso8601/issues/detail?id=14 + ("2007-06-23 06:40:34.00Zrubbish", "Unable to parse date string"), # https://code.google.com/p/pyiso8601/issues/detail?id=14 + ("20114-01-03T01:45:49", "Unable to parse date string"), +]) +def test_parse_invalid_date(invalid_date, error_string): + assert isinstance(invalid_date, str) or invalid_date is None # Why? 'cos I've screwed up the parametrize before :) + with pytest.raises(iso8601.ParseError) as exc: + iso8601.parse_date(invalid_date) + assert exc.errisinstance(iso8601.ParseError) + assert str(exc.value).startswith(error_string) + +@pytest.mark.parametrize("valid_date,expected_datetime,isoformat", [ + ("2007-06-23 06:40:34.00Z", datetime.datetime(2007, 6, 23, 6, 40, 34, 0, iso8601.UTC), "2007-06-23T06:40:34+00:00"), # Handle a separator other than T + ("1997-07-16T19:20+01:00", datetime.datetime(1997, 7, 16, 19, 20, 0, 0, iso8601.FixedOffset(1, 0, "+01:00")), "1997-07-16T19:20:00+01:00"), # Parse with no seconds + ("2007-01-01T08:00:00", datetime.datetime(2007, 1, 1, 8, 0, 0, 0, iso8601.UTC), "2007-01-01T08:00:00+00:00"), # Handle timezone-less dates. Assumes UTC. http://code.google.com/p/pyiso8601/issues/detail?id=4 + ("2006-10-20T15:34:56.123+02:30", datetime.datetime(2006, 10, 20, 15, 34, 56, 123000, iso8601.FixedOffset(2, 30, "+02:30")), None), + ("2006-10-20T15:34:56Z", datetime.datetime(2006, 10, 20, 15, 34, 56, 0, iso8601.UTC), "2006-10-20T15:34:56+00:00"), + ("2007-5-7T11:43:55.328Z", datetime.datetime(2007, 5, 7, 11, 43, 55, 328000, iso8601.UTC), "2007-05-07T11:43:55.328000+00:00"), # http://code.google.com/p/pyiso8601/issues/detail?id=6 + ("2006-10-20T15:34:56.123Z", datetime.datetime(2006, 10, 20, 15, 34, 56, 123000, iso8601.UTC), "2006-10-20T15:34:56.123000+00:00"), + ("2013-10-15T18:30Z", datetime.datetime(2013, 10, 15, 18, 30, 0, 0, iso8601.UTC), "2013-10-15T18:30:00+00:00"), + ("2013-10-15T22:30+04", datetime.datetime(2013, 10, 15, 22, 30, 0, 0, iso8601.FixedOffset(4, 0, "+04:00")), "2013-10-15T22:30:00+04:00"), #