From db430d87f3dc61d8130650dee79f488f705b4d14 Mon Sep 17 00:00:00 2001 From: Kon Date: Thu, 21 Feb 2013 16:16:51 -0500 Subject: [PATCH] Added few more methods to test_system_setup.py and some stylistic changes to signercli.py. --- tuf/repo/signercli.py | 4 +- tuf/tests/system_test/test_system_setup.py | 177 ++++++++++++++++++--- 2 files changed, 158 insertions(+), 23 deletions(-) diff --git a/tuf/repo/signercli.py b/tuf/repo/signercli.py index 89a81411..56bc504a 100755 --- a/tuf/repo/signercli.py +++ b/tuf/repo/signercli.py @@ -731,7 +731,7 @@ def make_release_metadata(keystore_directory): try: release_keyids = _get_role_config_keyids(config_filepath, keystore_directory, 'release') - # Generate the root metadata and write it to 'release.txt' + # Generate the release metadata and write it to 'release.txt' tuf.repo.signerlib.build_release_file(release_keyids, metadata_directory) except (tuf.FormatError, tuf.Error), e: message = str(e)+'\n' @@ -785,7 +785,7 @@ def make_timestamp_metadata(keystore_directory): try: timestamp_keyids = _get_role_config_keyids(config_filepath, keystore_directory, 'timestamp') - # Generate the root metadata and write it to 'timestamp.txt' + # Generate the timestamp metadata and write it to 'timestamp.txt' tuf.repo.signerlib.build_timestamp_file(timestamp_keyids, metadata_directory) except (tuf.FormatError, tuf.Error), e: diff --git a/tuf/tests/system_test/test_system_setup.py b/tuf/tests/system_test/test_system_setup.py index 15a160f4..318aa261 100644 --- a/tuf/tests/system_test/test_system_setup.py +++ b/tuf/tests/system_test/test_system_setup.py @@ -13,20 +13,28 @@ Provide automatic setup and clean-up functionality. This module is based on - python's unittest. In fact the main class TestCase inherits from + python's unittest, the main class 'TestCase' inherits from unittest.TestCase. -simple server --> repository_dir - | - -------------------------- - | | - filename1 filename2 + Initial repository looks like this: + simple server --> repository_dir + | + -------------------------- + | | + filename1 filename2 This modules uses unittest module to provide easy setup and tear down capability. -Repository + Server <---------------> Client -Repository + TUF + Server <---------> TUF + Client + Essentially there are two choices: either a system that simply performs + update downloads without any protections or a system that utilizes TUF to + perform secure update downloads. + + A structure that does NOT implementing TUF. A direct download over http. + Repository + Server <---------------> Client + + The TUF structure is described bellow in the class and tuf_tearDown() docs. + Repository + TUF + Server <---------> TUF + Client """ @@ -53,11 +61,21 @@ class TestCase(unittest.TestCase): """ + + TestCase inherits from unittest.TestCase class. + + client_download(filename): + Downloads a file ('filename') from 'url' (described bellow). + + + The contents of the file. + TUF: - Indicates whether or not TUF structure should be implemented. + Indicates whether or not TUF is implemented. + Boolean values that implements TUF if True. Otherwise TUF is skipped. - + repository_dir: Repository directory, where updates are located. @@ -68,7 +86,8 @@ class TestCase(unittest.TestCase): A subprocess object. url: - URL pointing to the repository directory ('repository_dir'). + A loopback address pointing to the repository directory + ('repository_dir'). TUF related instance variables. Refer to the diagram in tuf_setUp(). @@ -100,7 +119,8 @@ class TestCase(unittest.TestCase): Note: metadata files are root.txt, targets.txt, release.txt and timestamp.txt. There could be more metadata files such us mirrors.txt. The metadata files are signed by their corresponding roles i.e. root, - targets etc. + targets etc. + """ @@ -153,6 +173,60 @@ def tearDown(self): self.tuf_tearDown() + + def add_or_change_file_at_repository(self, filename=None, data=None): + """ + + Adds or changes a file named 'filename' at the repository + 'repository_dir'. + + + filename: + Name of the file located on the repository 'repository_dir'. + Ex: file1.txt + + data: + A string to write to the indicated file. If None, 'test' string is + used. + + """ + + if filename is not None and isinstance(filename, basestring): + filepath = os.path.join(self.repository_dir, filename) + if not os.path.isfile(filepath): + print 'There is no filepath ' + repr(filepath)+' does not exit.\n' + sys.exit(1) + fileobj = open(filepath, 'wb') + else: + junk, filepath = tempfile.mkstemp(dir=self.repository_dir) + filename = os.path.basename(filepath) + fileobj = open(filepath, 'wb') + + if data is None or not isinstance(data, basestring): + data = 'test' + + fileobj.write(data) + fileobj.close() + return filepath + + + def delete_file_at_repository(self, filename): + """ + + Attempt to delete a file named 'filename' at the repository. + """ + if isinstance(filename, basestring): + filepath = os.path.join(self.repository_dir, filename) + if os.path.isfile(filepath): + os.remove(filepath) + else: + print 'There is no filepath ' + repr(filepath) + ' does not exit.\n' + sys.exit(1) + else: + print 'Wrong type: ' + repr(filepath) + '\n' + sys.exit(1) + + @staticmethod def _open_connection(url): @@ -167,6 +241,9 @@ def _open_connection(url): def client_download(self, filename): + if not isinstance(filename, basestring): + print 'Wrong type: ' + repr(filepath) + '\n' + sys.exit(1) connection = self._open_connection(self.url+filename) return connection.read() @@ -220,7 +297,7 @@ def tuf_setUp(self): # Set some role info. info = {'keyids': [key['keyid']], 'threshold': threshold} - # Setup keystore. 'role_info' dictionary looks like this: + # 'role_info' dictionary looks like this: # {'keyids : [keyid1, ...] , 'threshold' : 2} # In our case 'role_info[keyids]' will only have on entry since only one # is being used. @@ -233,20 +310,21 @@ def tuf_setUp(self): # and metadata files. # Build the configuration file. - conf_filepath = signerlib.build_config_file(self.repository_dir, 365, role_info) + self._conf_filepath = signerlib.build_config_file(self.repository_dir, + 365, role_info) # Generate the 'root.txt' metadata file. - keyid = [key['keyid']] - signerlib.build_root_file(conf_filepath, keyid, self.tuf_metadata_dir) + self._keyid = [key['keyid']] + signerlib.build_root_file(self._conf_filepath, self._keyid, self.tuf_metadata_dir) # Generate the 'targets.txt' metadata file. - signerlib.build_targets_file(self.tuf_targets_dir, keyid, self.tuf_metadata_dir) + signerlib.build_targets_file(self.tuf_targets_dir, self._keyid, self.tuf_metadata_dir) # Generate the 'release.txt' metadata file. - signerlib.build_release_file(keyid, self.tuf_metadata_dir) + signerlib.build_release_file(self._keyid, self.tuf_metadata_dir) # Generate the 'timestamp.txt' metadata file. - signerlib.build_timestamp_file(keyid, self.tuf_metadata_dir) + signerlib.build_timestamp_file(self._keyid, self.tuf_metadata_dir) # Setting up client's TUF directory structure. # 'tuf.client.updater.py' expects the 'current' and 'previous' @@ -272,13 +350,38 @@ def tuf_tearDown(self): shutil.rmtree(self.tuf_client_dir) + def tuf_refresh(self): + """ + + Update TUF metadata files. Call this method whenever targets files have + changed in the 'repository_dir'. - # Quick internal test to see if everything runs smoothly. + """ + + shutil.rmtree(self.tuf_targets_dir) + shutil.copytree(self.repository_dir, self.tuf_targets_dir) + + # Regenerate the 'targets.txt' metadata file. + signerlib.build_targets_file(self.tuf_targets_dir, self._keyid, + self.tuf_metadata_dir) + + # Regenerate the 'release.txt' metadata file. + signerlib.build_release_file(self._keyid, self.tuf_metadata_dir) + + # Regenerate the 'timestamp.txt' metadata file. + signerlib.build_timestamp_file(self._keyid, self.tuf_metadata_dir) + + + + # A few quick internal tests to see if everything runs smoothly. def test_client_download(self): data = self.client_download(self.filename1) self.assertEquals(data, 'System Test File 1') - # Verify that all necessary paths exist. + + + def test_tuf_setup(self): + # Verify that all necessary TUF-paths exist. for role in ['root', 'targets', 'release', 'timestamp']: # Repository side. role_file = os.path.join(self.tuf_metadata_dir, role+'.txt') @@ -293,7 +396,39 @@ def test_client_download(self): self.assertTrue(os.path.isfile(target1)) self.assertTrue(os.path.isfile(target2)) + self.tuf_refresh() + def test_methods(self): + """ + Making sure following methods work as intended: + - add_or_change_file_at_repository() + - delete_file_at_repository() + - tuf_refresh() + """ + new_file = self.add_or_change_file_at_repository() + fileobj = open(new_file, 'rb') + self.assertTrue(os.path.exists(new_file)) + self.assertEquals('test', fileobj.read()) + + old_file = self.add_or_change_file_at_repository(filename=self.filename1) + fileobj = open(new_file, 'rb') + self.assertTrue(os.path.exists(new_file)) + self.assertEquals('test', fileobj.read()) + + old_file = self.add_or_change_file_at_repository(filename=self.filename1, + data='1234') + fileobj = open(old_file, 'rb') + self.assertTrue(os.path.exists(old_file)) + self.assertEquals('1234', fileobj.read()) + + self.tuf_refresh() + new_target = os.path.join(self.tuf_targets_dir, os.path.basename(new_file)) + self.assertTrue(os.path.exists(new_target)) + # Here it is assumed that all relevant metadata has been updated + # successfully. This is tested in signerlib and other unit tests. + + self.delete_file_at_repository(os.path.basename(new_file)) + self.assertFalse(os.path.exists(new_file))