From b1f85310de263a9ffad24be7bdda691e7e7260b5 Mon Sep 17 00:00:00 2001 From: dachshund Date: Mon, 5 May 2014 03:22:55 -0400 Subject: [PATCH 1/4] Prototype on removing targets from bins. --- tuf/repository_tool.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tuf/repository_tool.py b/tuf/repository_tool.py index 5c93cab8..0c05c78c 100755 --- a/tuf/repository_tool.py +++ b/tuf/repository_tool.py @@ -2342,8 +2342,18 @@ def delegate_hashed_bins(self, list_of_targets, keys_of_hashed_bins, logger.debug(message) - + # TODO: add docstring def add_target_to_bin(self, target_filepath): + return self.act_on_target_to_bin(target_filepath, 'add_target') + + + # TODO: add docstring + def remove_target_from_bin(self, target_filepath): + return self.act_on_target_to_bin(target_filepath, 'remove_target') + + + # TODO: add docstring about action + def act_on_target_to_bin(self, target_filepath, action): """ Add the fileinfo of 'target_filepath' to the expected hashed bin if @@ -2439,7 +2449,7 @@ def add_target_to_bin(self, target_filepath): # 'hashed_bin_name'. if hashed_bin_name is not None: hashed_bin_name = hashed_bin_name[len(self.rolename)+1:] - self._delegated_roles[hashed_bin_name].add_target(target_filepath) + getattr(self._delegated_roles[hashed_bin_name], action)(target_filepath) else: raise tuf.Error(target_filepath + ' cannot be added to any bins.') From e063447f1e141291032c7c3d6d3d01849f6cfc66 Mon Sep 17 00:00:00 2001 From: dachshund Date: Mon, 5 May 2014 11:50:58 -0400 Subject: [PATCH 2/4] Minor edits. --- tuf/repository_tool.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tuf/repository_tool.py b/tuf/repository_tool.py index 0c05c78c..01e2485d 100755 --- a/tuf/repository_tool.py +++ b/tuf/repository_tool.py @@ -2344,16 +2344,16 @@ def delegate_hashed_bins(self, list_of_targets, keys_of_hashed_bins, # TODO: add docstring def add_target_to_bin(self, target_filepath): - return self.act_on_target_to_bin(target_filepath, 'add_target') + return self.__act_on_target_in_bin(target_filepath, 'add_target') # TODO: add docstring def remove_target_from_bin(self, target_filepath): - return self.act_on_target_to_bin(target_filepath, 'remove_target') + return self.__act_on_target_in_bin(target_filepath, 'remove_target') # TODO: add docstring about action - def act_on_target_to_bin(self, target_filepath, action): + def __act_on_target_in_bin(self, target_filepath, action): """ Add the fileinfo of 'target_filepath' to the expected hashed bin if From 9a90a808e903b06d1ed5123c2780407a33a5fc3b Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Wed, 18 Jun 2014 12:39:01 -0400 Subject: [PATCH 3/4] Update comments and add missing docstrings in PR #216. Update add_target_to_bin() and remove_target_from_bin(). --- tuf/repository_tool.py | 109 +++++++++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 21 deletions(-) diff --git a/tuf/repository_tool.py b/tuf/repository_tool.py index e76bf6b6..6c77b2f4 100755 --- a/tuf/repository_tool.py +++ b/tuf/repository_tool.py @@ -2331,21 +2331,11 @@ def delegate_hashed_bins(self, list_of_targets, keys_of_hashed_bins, logger.debug(message) - # TODO: add docstring + def add_target_to_bin(self, target_filepath): - return self.__act_on_target_in_bin(target_filepath, 'add_target') - - - # TODO: add docstring - def remove_target_from_bin(self, target_filepath): - return self.__act_on_target_in_bin(target_filepath, 'remove_target') - - - # TODO: add docstring about action - def __act_on_target_in_bin(self, target_filepath, action): """ - Add the fileinfo of 'target_filepath' to the expected hashed bin if + Add the fileinfo of 'target_filepath' to the expected hashed bin, if the bin is available. The hashed bin should have been created by {targets_role}.delegate_hashed_bins(). Assuming the target filepath falls under the repository's targets directory, determine the filepath's @@ -2354,10 +2344,6 @@ def __act_on_target_in_bin(self, target_filepath, action): the 'targets/unclaimed/58-5f.json' role's list of targets by calling this method. - >>> - >>> - >>> - target_filepath: The filepath of the target to be added to a hashed bin. The filepath @@ -2383,6 +2369,84 @@ def __act_on_target_in_bin(self, target_filepath, action): # types, and that all dict keys are properly named. # Raise 'tuf.FormatError' if there is a mismatch. tuf.formats.PATH_SCHEMA.check_match(target_filepath) + + return self._locate_and_update_target_in_bin(target_filepath, 'add_target') + + + + def remove_target_from_bin(self, target_filepath): + """ + + Remove the fileinfo of 'target_filepath' from the expected hashed bin, if + the bin is available. The hashed bin should have been created by + {targets_role}.delegate_hashed_bins(). Assuming the target filepath + falls under the repository's targets directory, determine the filepath's + hash prefix, locate the expected bin (if any), and then remove the + fileinfo from the expected bin. Example: 'targets/foo.tar.gz' may be + removed from the 'targets/unclaimed/58-5f.json' role's list of targets by + calling this method. + + + target_filepath: + The filepath of the target to be added to a hashed bin. The filepath + must fall under repository's targets directory. + + + tuf.FormatError, if 'target_filepath' is improperly formatted. + + tuf.Error, if 'target_filepath' cannot be removed from a hashed bin + (e.g., an invalid target filepath, or the expected hashed bin does not + exist.) + + + The fileinfo of 'target_filepath' is removed from a hashed bin of this + Targets object. + + + None. + """ + + # Do the arguments have the correct format? + # Ensure the arguments have the appropriate number of objects and object + # types, and that all dict keys are properly named. + # Raise 'tuf.FormatError' if there is a mismatch. + tuf.formats.PATH_SCHEMA.check_match(target_filepath) + + return self._locate_and_update_target_in_bin(target_filepath, 'remove_target') + + + + def _locate_and_update_target_in_bin(self, target_filepath, method_name): + """ + + Assuming the target filepath falls under the repository's targets + directory, determine the filepath's hash prefix, locate the expected bin + (if any), and then call the 'method_name' method of the expected hashed + bin role. + + + target_filepath: + The filepath of the target that may be specified in one of the hashed + bins. 'target_filepath' must fall under repository's targets directory. + + method_name: + A supported method, in string format, of the Targets() class. For + example, add_target() and remove_target(): + + repository.targets('unclaimed')('58-f7).add_target(target_filepath) + repository.targets('unclaimed')('000-007).remove_target(target_filepath) + + + tuf.Error, if 'target_filepath' cannot be updated (e.g., an invalid target + filepath, or the expected hashed bin does not exist.) + + + The fileinfo of 'target_filepath' is added to a hashed bin of this Targets + object. + + + None. + """ # Determine the prefix length of any one of the hashed bins. The prefix # length is not stored in the roledb, so it must be determined here by @@ -2409,8 +2473,8 @@ def __act_on_target_in_bin(self, target_filepath, action): # Ensure the filepath falls under the repository's targets directory. filepath = os.path.abspath(target_filepath) if not filepath.startswith(self._targets_directory + os.sep): - message = repr(filepath)+' is not under the Repository\'s targets '+\ - 'directory: '+repr(self._targets_directory) + message = repr(filepath) + ' is not under the Repository\'s targets ' +\ + 'directory: ' + repr(self._targets_directory) raise tuf.Error(message) # Determine the hash prefix of 'target_path' by computing the digest of @@ -2437,11 +2501,14 @@ def __act_on_target_in_bin(self, target_filepath, action): # 'self._delegated_roles' is keyed by relative rolenames, so update # 'hashed_bin_name'. if hashed_bin_name is not None: - hashed_bin_name = hashed_bin_name[len(self.rolename)+1:] - getattr(self._delegated_roles[hashed_bin_name], action)(target_filepath) + hashed_bin_name = hashed_bin_name[len(self.rolename) + 1:] + + # 'method_name' should be one of the supported methods of the Targets() + # class. + getattr(self._delegated_roles[hashed_bin_name], method_name)(target_filepath) else: - raise tuf.Error(target_filepath + ' cannot be added to any bins.') + raise tuf.Error(target_filepath + ' not found in any of the bins.') From 882871ccfce635e4c54ce8f1716993387243da6d Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Wed, 18 Jun 2014 12:39:39 -0400 Subject: [PATCH 4/4] Add missing test case for remove_target_from_bin(). --- tests/test_repository_tool.py | 64 +++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 6 deletions(-) diff --git a/tests/test_repository_tool.py b/tests/test_repository_tool.py index 17db845e..06dbac12 100755 --- a/tests/test_repository_tool.py +++ b/tests/test_repository_tool.py @@ -901,8 +901,7 @@ def test_add_target(self): # Test improperly formatted arguments. - self.assertRaises(tuf.FormatError, self.targets_object.add_target, - 3) + self.assertRaises(tuf.FormatError, self.targets_object.add_target, 3) # Test invalid filepath argument (i.e., non-existent or invalid file.) @@ -916,8 +915,7 @@ def test_add_target(self): # Not a file (i.e., a valid path, but a directory.) test_directory = os.path.join(self.targets_directory, 'test_directory') os.mkdir(test_directory) - self.assertRaises(tuf.Error, self.targets_object.add_target, - test_directory) + self.assertRaises(tuf.Error, self.targets_object.add_target, test_directory) @@ -968,8 +966,7 @@ def test_remove_target(self): # Test improperly formatted arguments. - self.assertRaises(tuf.FormatError, self.targets_object.remove_target, - 3) + self.assertRaises(tuf.FormatError, self.targets_object.remove_target, 3) # Test invalid filepath argument (i.e., non-existent or invalid file.) @@ -1167,6 +1164,61 @@ def test_add_target_to_bin(self): # Invalid target file path argument. self.assertRaises(tuf.Error, self.targets_object.add_target_to_bin, '/non-existent') + + + + def test_remove_target_from_bin(self): + # Test normal case. + # Delegate the hashed bins so that add_target_to_bin() can be tested. + keystore_directory = os.path.join('repository_data', 'keystore') + public_keypath = os.path.join(keystore_directory, 'targets_key.pub') + public_key = repo_tool.import_rsa_publickey_from_file(public_keypath) + target1_filepath = os.path.join(self.targets_directory, 'file1.txt') + + # Set needed arguments by delegate_hashed_bins(). + public_keys = [public_key] + list_of_targets = [target1_filepath] + + # Delegate to hashed bins. The target filepath to be tested is expected + # to contain a hash prefix of 'e', so it should be added to the + # 'targets/e' role. + self.targets_object.delegate_hashed_bins(list_of_targets, public_keys, + number_of_bins=16) + + # Ensure each hashed bin initially contains zero targets. + for delegation in self.targets_object.delegations: + self.assertTrue(target1_filepath not in delegation.target_files) + + # Add 'target1_filepath' and verify that the relative path of + # 'target1_filepath' is added to the correct bin. + self.targets_object.add_target_to_bin(target1_filepath) + + for delegation in self.targets_object.delegations: + if delegation.rolename == 'targets/e': + self.assertTrue('/file1.txt' in delegation.target_files) + + else: + self.assertTrue('/file1.txt' not in delegation.target_files) + + # Test the remove_target_from_bin() method. Verify that 'target1_filepath' + # has been removed. + self.targets_object.remove_target_from_bin(target1_filepath) + + for delegation in self.targets_object.delegations: + if delegation.rolename == 'targets/e': + self.assertTrue('/file1.txt' not in delegation.target_files) + + else: + self.assertTrue('/file1.txt' not in delegation.target_files) + + + # Test improperly formatted argument. + self.assertRaises(tuf.FormatError, + self.targets_object.remove_target_from_bin, 3) + + # Invalid target file path argument. + self.assertRaises(tuf.Error, self.targets_object.remove_target_from_bin, + '/non-existent')