mirror of
https://github.com/theupdateframework/python-tuf
synced 2026-05-24 10:08:28 +00:00
test_system_setup.py is complete. Few minor stylistic changes were made to download.py and signercli.py.
This commit is contained in:
parent
4bf56c8fa1
commit
bebdab3cb5
3 changed files with 205 additions and 17 deletions
|
|
@ -175,7 +175,7 @@ def download_url_to_tempfileobj(url, required_hashes=None, required_length=None)
|
|||
# might put back-slashes in place of forward-slashes. This converts it to the
|
||||
# common format.
|
||||
url = url.replace('\\','/')
|
||||
logger.info('Downloading '+url)
|
||||
logger.info('Downloading: '+url)
|
||||
connection = _open_connection(url)
|
||||
temp_file = tuf.util.TempFile()
|
||||
|
||||
|
|
|
|||
|
|
@ -1226,43 +1226,43 @@ def parse_options():
|
|||
|
||||
# Add the options supported by 'signercli' to the option parser.
|
||||
option_parser.add_option('--genrsakey', action='store', type='string',
|
||||
help='Generate an RSA key and save it to '
|
||||
help='Generate an RSA key and save it to '\
|
||||
'the keystore.')
|
||||
|
||||
option_parser.add_option('--listkeys', action='store', type='string',
|
||||
help='List the key IDs of the signing '
|
||||
help='List the key IDs of the signing '\
|
||||
'keys located in the keystore.')
|
||||
|
||||
option_parser.add_option('--changepass', action='store', type='string',
|
||||
help='Change the password for one of '
|
||||
help='Change the password for one of '\
|
||||
'the signing keys.')
|
||||
|
||||
option_parser.add_option('--dumpkey', action='store', type='string',
|
||||
help='Dump the contents of an encrypted '
|
||||
help='Dump the contents of an encrypted '\
|
||||
'key file.')
|
||||
|
||||
option_parser.add_option('--makeroot', action='store', type='string',
|
||||
help='Create the Root metadata file '
|
||||
help='Create the Root metadata file '\
|
||||
'(root.txt).')
|
||||
|
||||
option_parser.add_option('--maketargets', action='store', type='string',
|
||||
help='Create the Targets metadata file '
|
||||
help='Create the Targets metadata file '\
|
||||
'(targets.txt).')
|
||||
|
||||
option_parser.add_option('--makerelease', action='store', type='string',
|
||||
help='Create the Release metadata file '
|
||||
help='Create the Release metadata file '\
|
||||
'(release.txt).')
|
||||
|
||||
option_parser.add_option('--maketimestamp', action='store', type='string',
|
||||
help='Create the Timestamp metadata file '
|
||||
help='Create the Timestamp metadata file '\
|
||||
'(timestamp.txt).')
|
||||
|
||||
option_parser.add_option('--sign', action='store', type='string',
|
||||
help='Sign a metadata file.')
|
||||
|
||||
option_parser.add_option('--makedelegation', action='store', type='string',
|
||||
help='Create a delegated role by creating '
|
||||
'its metadata file and updating the parent '
|
||||
help='Create a delegated role by creating '\
|
||||
'its metadata file and updating the parent '\
|
||||
'role\'s metadata file.')
|
||||
|
||||
(options, remaining_arguments) = option_parser.parse_args()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"""
|
||||
<Program Name>
|
||||
repository_setup.py
|
||||
test_system_setup.py
|
||||
|
||||
<Author>
|
||||
Konstantin Andrianov
|
||||
|
|
@ -12,13 +12,15 @@
|
|||
See LICENSE for licensing information.
|
||||
|
||||
<Purpose>
|
||||
Setup a repository structure.
|
||||
Provide automatic setup and clean-up functionality. This module is based on
|
||||
python's unittest. In fact the main class TestCase inherits from
|
||||
unittest.TestCase.
|
||||
|
||||
simple server --> repository_dir
|
||||
|
|
||||
--------------------------
|
||||
| |
|
||||
repository_file1path repository_file2path
|
||||
filename1 filename2
|
||||
|
||||
This modules uses unittest module to provide easy setup and tear down
|
||||
capability.
|
||||
|
|
@ -37,12 +39,73 @@
|
|||
import shutil
|
||||
import random
|
||||
import urllib2
|
||||
import logging
|
||||
import tempfile
|
||||
import unittest
|
||||
import subprocess
|
||||
|
||||
import tuf.repo.signerlib as signerlib
|
||||
|
||||
# Disable/Enable logging. Comment-out to Enable logging.
|
||||
logging.getLogger('tuf')
|
||||
logging.disable(logging.CRITICAL)
|
||||
|
||||
|
||||
class TestCase(unittest.TestCase):
|
||||
"""
|
||||
<Class Variables>
|
||||
TUF:
|
||||
Indicates whether or not TUF structure should be implemented.
|
||||
|
||||
<Instance Variables>
|
||||
repository_dir:
|
||||
Repository directory, where updates are located.
|
||||
|
||||
filename#:
|
||||
Name of the update, which is located in the repository directory.
|
||||
|
||||
server_process:
|
||||
A subprocess object.
|
||||
|
||||
url:
|
||||
URL pointing to the repository directory ('repository_dir').
|
||||
|
||||
|
||||
TUF related instance variables. Refer to the diagram in tuf_setUp().
|
||||
|
||||
tuf_repository_dir:
|
||||
A tuf repository that contains all tuf related directories, such as
|
||||
metadata, targets, and keystore. (Read docs on how to handle keys!)
|
||||
|
||||
tuf_metadata_dir:
|
||||
Metadata directory that contains metadata files and is located in the
|
||||
tuf repository directory ('tuf_repository_dir').
|
||||
|
||||
tuf_keystore_dir:
|
||||
Contains all tuf keys, i.e. keys that are used to sign metadata roles.
|
||||
It's located in the tuf repository directory ('tuf_repository_dir').
|
||||
|
||||
tuf_targets_dir:
|
||||
All target files (updates) are stored in tuf targets directory.
|
||||
It's populated using the content 'repository_dir' (devel's repository).
|
||||
It's located in the tuf repository directory ('tuf_repository_dir').
|
||||
|
||||
tuf_client_dir:
|
||||
Client side tuf directory. It contains current and previous metadata
|
||||
files.
|
||||
|
||||
tuf_client_metadata_dir:
|
||||
Contains current and previous versions of metadata files.
|
||||
|
||||
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.
|
||||
|
||||
"""
|
||||
|
||||
TUF = True
|
||||
|
||||
def setUp(self):
|
||||
unittest.TestCase.setUp(self)
|
||||
|
||||
|
|
@ -50,8 +113,8 @@ def setUp(self):
|
|||
self.repository_dir = tempfile.mkdtemp(dir=os.getcwd())
|
||||
repository_file1 = tempfile.mkstemp(dir=self.repository_dir)
|
||||
repository_file2 = tempfile.mkstemp(dir=self.repository_dir)
|
||||
self.repository_file1path = os.path.basename(repository_file1[1])
|
||||
self.repository_file2path = os.path.basename(repository_file2[1])
|
||||
self.filename1 = os.path.basename(repository_file1[1])
|
||||
self.filename2 = os.path.basename(repository_file2[1])
|
||||
fileobj = open(repository_file1[1], 'wb')
|
||||
fileobj.write('System Test File 1')
|
||||
fileobj.close()
|
||||
|
|
@ -71,17 +134,24 @@ def setUp(self):
|
|||
# <urlopen error [Errno 111] Connection refused>
|
||||
time.sleep(.1)
|
||||
|
||||
if self.TUF is True:
|
||||
self.tuf_setUp()
|
||||
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
unittest.TestCase.tearDown(self)
|
||||
|
||||
if self.server_process.returncode is None:
|
||||
print 'Server terminated.'
|
||||
self.server_process.kill()
|
||||
|
||||
# Removing repository directory.
|
||||
shutil.rmtree(self.repository_dir)
|
||||
|
||||
if self.TUF is True:
|
||||
self.tuf_tearDown()
|
||||
|
||||
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -102,11 +172,129 @@ def client_download(self, filename):
|
|||
|
||||
|
||||
|
||||
def tuf_setUp(self):
|
||||
"""
|
||||
<Purpose>
|
||||
Setup TUF directory structure and populated it with TUF metadata and
|
||||
congfiguration files.
|
||||
|
||||
tuf_repository_dir
|
||||
|
|
||||
--------------------------------------------
|
||||
| | |
|
||||
keystore metadata targets
|
||||
| | |
|
||||
key.key files role.txt files targets (updates)
|
||||
... ... ...
|
||||
|
||||
|
||||
tuf_client_dir
|
||||
|
|
||||
metadata
|
||||
|
|
||||
---------------------------
|
||||
| |
|
||||
current previous
|
||||
| |
|
||||
role.txt files role.txt files
|
||||
... ...
|
||||
|
||||
"""
|
||||
|
||||
passwd = 'test'
|
||||
threshold = 1
|
||||
|
||||
# Setup TUF directory structure.
|
||||
self.tuf_repository_dir = tempfile.mkdtemp(suffix='tuf_r', dir=os.getcwd())
|
||||
self.tuf_client_dir = tempfile.mkdtemp(suffix='tuf_c', dir=os.getcwd())
|
||||
self.tuf_keystore_dir = os.path.join(self.tuf_repository_dir, 'keystore')
|
||||
self.tuf_metadata_dir = os.path.join(self.tuf_repository_dir, 'metadata')
|
||||
os.mkdir(self.tuf_keystore_dir)
|
||||
os.mkdir(self.tuf_metadata_dir)
|
||||
self.tuf_targets_dir = os.path.join(self.tuf_repository_dir, 'targets')
|
||||
shutil.copytree(self.repository_dir, self.tuf_targets_dir)
|
||||
|
||||
# Generate at least one rsa key.
|
||||
key = signerlib.generate_and_save_rsa_key(self.tuf_keystore_dir, passwd)
|
||||
|
||||
# Set some role info.
|
||||
info = {'keyids': [key['keyid']], 'threshold': threshold}
|
||||
|
||||
# Setup keystore. '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.
|
||||
role_info = {}
|
||||
role_list = ['root', 'targets', 'release', 'timestamp']
|
||||
for role in role_list:
|
||||
role_info[role] = info
|
||||
|
||||
# At this point there is enough information to create TUF configuration
|
||||
# and metadata files.
|
||||
|
||||
# Build the configuration file.
|
||||
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)
|
||||
|
||||
# Generate the 'targets.txt' metadata file.
|
||||
signerlib.build_targets_file(self.tuf_targets_dir, keyid, self.tuf_metadata_dir)
|
||||
|
||||
# Generate the 'release.txt' metadata file.
|
||||
signerlib.build_release_file(keyid, self.tuf_metadata_dir)
|
||||
|
||||
# Generate the 'timestamp.txt' metadata file.
|
||||
signerlib.build_timestamp_file(keyid, self.tuf_metadata_dir)
|
||||
|
||||
# Setting up client's TUF directory structure.
|
||||
# 'tuf.client.updater.py' expects the 'current' and 'previous'
|
||||
# directories to exist under client's 'metadata' directory.
|
||||
self.tuf_client_metadata_dir = os.path.join(self.tuf_client_dir, 'metadata')
|
||||
os.mkdir(self.tuf_client_metadata_dir)
|
||||
|
||||
# Move the metadata to the client's 'current' and 'previous' directories.
|
||||
self.client_current = os.path.join(self.tuf_client_metadata_dir, 'current')
|
||||
self.client_previous = os.path.join(self.tuf_client_metadata_dir, 'previous')
|
||||
shutil.copytree(self.tuf_metadata_dir, self.client_current)
|
||||
shutil.copytree(self.tuf_metadata_dir, self.client_previous)
|
||||
|
||||
|
||||
|
||||
def tuf_tearDown(self):
|
||||
"""
|
||||
<Purpose>
|
||||
The clean-up method, removes all TUF directories created using
|
||||
tuf_setUp().
|
||||
"""
|
||||
shutil.rmtree(self.tuf_repository_dir)
|
||||
shutil.rmtree(self.tuf_client_dir)
|
||||
|
||||
|
||||
|
||||
# Quick internal test to see if everything runs smoothly.
|
||||
def test_client_download(self):
|
||||
data = self.client_download(self.repository_file1path)
|
||||
data = self.client_download(self.filename1)
|
||||
self.assertEquals(data, 'System Test File 1')
|
||||
|
||||
# Verify that all necessary paths exist.
|
||||
for role in ['root', 'targets', 'release', 'timestamp']:
|
||||
# Repository side.
|
||||
role_file = os.path.join(self.tuf_metadata_dir, role+'.txt')
|
||||
self.assertTrue(os.path.isfile(role_file))
|
||||
|
||||
# Client side.
|
||||
role_file = os.path.join(self.client_current, role+'.txt')
|
||||
self.assertTrue(os.path.isfile(role_file))
|
||||
|
||||
target1 = os.path.join(self.tuf_targets_dir, self.filename1)
|
||||
target2 = os.path.join(self.tuf_targets_dir, self.filename2)
|
||||
self.assertTrue(os.path.isfile(target1))
|
||||
self.assertTrue(os.path.isfile(target2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__=='__main__':
|
||||
|
|
|
|||
Loading…
Reference in a new issue