Skip to content

Commit 540377e

Browse files
authored
Merge pull request #1024 from joshuagl/joshuagl/abstract-filesystem
Port to securesystemslib with abstract files and directories (securesystemslib PR 232)
2 parents d7aec6a + be3c541 commit 540377e

13 files changed

+278
-418
lines changed

requirements-pinned.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pycparser==2.20 # via cffi
1111
pynacl==1.3.0 # via securesystemslib
1212
python-dateutil==2.8.1 # via securesystemslib
1313
requests==2.23.0
14-
securesystemslib[colors,crypto,pynacl]==0.14.2
14+
securesystemslib[colors,crypto,pynacl]==0.15.0
1515
six==1.14.0
1616
subprocess32==3.5.4 ; python_version < '3' # via securesystemslib
1717
urllib3==1.25.9 # via requests

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
'iso8601>=0.1.12',
117117
'requests>=2.19.1',
118118
'six>=1.11.0',
119-
'securesystemslib>=0.12.0'
119+
'securesystemslib>=0.15.0'
120120
],
121121
tests_require = [
122122
'mock; python_version < "3.3"'

tests/repository_data/generate_project_data.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,6 @@
104104
project.expiration = datetime.datetime(2030, 1, 1, 0, 0)
105105
project('role1').expiration = datetime.datetime(2030, 1, 1, 0, 0)
106106

107-
# Compress the project role metadata so that the unit tests have a pre-generated
108-
# example of compressed metadata.
109-
project.compressions = ['gz']
110-
111107
# Create the actual metadata files, which are saved to 'metadata.staged'.
112108
if not options.dry_run:
113109
project.write()

tests/test_developer_tool.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import tuf.exceptions
3939

4040
import securesystemslib
41+
import securesystemslib.exceptions
4142

4243
from tuf.developer_tool import METADATA_DIRECTORY_NAME
4344
from tuf.developer_tool import TARGETS_DIRECTORY_NAME
@@ -188,7 +189,8 @@ def test_load_project(self):
188189

189190
# Test non-existent project filepath.
190191
nonexistent_path = os.path.join(local_tmp, 'nonexistent')
191-
self.assertRaises(IOError, developer_tool.load_project, nonexistent_path)
192+
self.assertRaises(securesystemslib.exceptions.StorageError,
193+
developer_tool.load_project, nonexistent_path)
192194

193195
# Copy the pregenerated metadata.
194196
project_data_filepath = os.path.join('repository_data', 'project')

tests/test_repository_lib.py

Lines changed: 50 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@
5252
import tuf.repository_tool as repo_tool
5353

5454
import securesystemslib
55+
import securesystemslib.exceptions
5556
import securesystemslib.rsa_keys
5657
import securesystemslib.interface
58+
import securesystemslib.storage
5759
import six
5860

5961
logger = logging.getLogger(__name__)
@@ -126,8 +128,9 @@ def test_import_rsa_privatekey_from_file(self):
126128
# Non-existent key file.
127129
nonexistent_keypath = os.path.join(temporary_directory,
128130
'nonexistent_keypath')
129-
self.assertRaises(IOError, repo_lib.import_rsa_privatekey_from_file,
130-
nonexistent_keypath, 'pw')
131+
self.assertRaises(securesystemslib.exceptions.StorageError,
132+
repo_lib.import_rsa_privatekey_from_file,
133+
nonexistent_keypath, 'pw')
131134

132135
# Invalid key file argument.
133136
invalid_keyfile = os.path.join(temporary_directory, 'invalid_keyfile')
@@ -160,7 +163,8 @@ def test_import_ed25519_privatekey_from_file(self):
160163
# Non-existent key file.
161164
nonexistent_keypath = os.path.join(temporary_directory,
162165
'nonexistent_keypath')
163-
self.assertRaises(IOError, repo_lib.import_ed25519_privatekey_from_file,
166+
self.assertRaises(securesystemslib.exceptions.StorageError,
167+
repo_lib.import_ed25519_privatekey_from_file,
164168
nonexistent_keypath, 'pw')
165169

166170
# Invalid key file argument.
@@ -215,7 +219,7 @@ def test_get_metadata_filenames(self):
215219
'targets.json': os.path.join(metadata_directory, 'targets.json'),
216220
'snapshot.json': os.path.join(metadata_directory, 'snapshot.json'),
217221
'timestamp.json': os.path.join(metadata_directory, 'timestamp.json')}
218-
self.assertEqual(filenames, repo_lib.get_metadata_filenames())
222+
self.assertEqual(filenames, repo_lib.get_metadata_filenames(metadata_directory))
219223

220224

221225
# Test improperly formatted argument.
@@ -241,17 +245,23 @@ def test_get_metadata_fileinfo(self):
241245
fileinfo = {'length': file_length, 'hashes': file_hashes}
242246
self.assertTrue(tuf.formats.FILEINFO_SCHEMA.matches(fileinfo))
243247

244-
self.assertEqual(fileinfo, repo_lib.get_metadata_fileinfo(test_filepath))
248+
storage_backend = securesystemslib.storage.FilesystemBackend()
249+
250+
self.assertEqual(fileinfo, repo_lib.get_metadata_fileinfo(test_filepath,
251+
storage_backend))
245252

246253

247254
# Test improperly formatted argument.
248-
self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.get_metadata_fileinfo, 3)
255+
self.assertRaises(securesystemslib.exceptions.FormatError,
256+
repo_lib.get_metadata_fileinfo, 3,
257+
storage_backend)
249258

250259

251260
# Test non-existent file.
252261
nonexistent_filepath = os.path.join(temporary_directory, 'oops.txt')
253-
self.assertRaises(securesystemslib.exceptions.Error, repo_lib.get_metadata_fileinfo,
254-
nonexistent_filepath)
262+
self.assertRaises(securesystemslib.exceptions.Error,
263+
repo_lib.get_metadata_fileinfo,
264+
nonexistent_filepath, storage_backend)
255265

256266

257267

@@ -440,8 +450,9 @@ def test_generate_snapshot_metadata(self):
440450

441451
# Load a valid repository so that top-level roles exist in roledb and
442452
# generate_snapshot_metadata() has roles to specify in snapshot metadata.
453+
storage_backend = securesystemslib.storage.FilesystemBackend()
443454
repository = repo_tool.Repository(repository_directory, metadata_directory,
444-
targets_directory)
455+
targets_directory, storage_backend)
445456

446457
repository_junk = repo_tool.load_repository(repository_directory)
447458

@@ -458,26 +469,27 @@ def test_generate_snapshot_metadata(self):
458469
repo_lib.generate_snapshot_metadata(metadata_directory, version,
459470
expiration_date,
460471
targets_filename,
472+
storage_backend,
461473
consistent_snapshot=False)
462474
self.assertTrue(tuf.formats.SNAPSHOT_SCHEMA.matches(snapshot_metadata))
463475

464476

465477
# Test improperly formatted arguments.
466478
self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.generate_snapshot_metadata,
467479
3, version, expiration_date,
468-
targets_filename, consistent_snapshot=False)
480+
targets_filename, consistent_snapshot=False, storage_backend=storage_backend)
469481
self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.generate_snapshot_metadata,
470482
metadata_directory, '3', expiration_date,
471-
targets_filename, consistent_snapshot=False)
483+
targets_filename, storage_backend, consistent_snapshot=False)
472484
self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.generate_snapshot_metadata,
473485
metadata_directory, version, '3',
474-
targets_filename, consistent_snapshot=False)
486+
targets_filename, storage_backend, consistent_snapshot=False)
475487
self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.generate_snapshot_metadata,
476488
metadata_directory, version, expiration_date,
477-
3, consistent_snapshot=False)
489+
3, storage_backend, consistent_snapshot=False)
478490
self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.generate_snapshot_metadata,
479491
metadata_directory, version, expiration_date,
480-
targets_filename, 3)
492+
targets_filename, 3, storage_backend)
481493

482494

483495

@@ -599,85 +611,25 @@ def test_write_metadata_file(self):
599611
version_number = root_signable['signed']['version'] + 1
600612

601613
self.assertFalse(os.path.exists(output_filename))
614+
storage_backend = securesystemslib.storage.FilesystemBackend()
602615
repo_lib.write_metadata_file(root_signable, output_filename, version_number,
603-
consistent_snapshot=False)
616+
consistent_snapshot=False, storage_backend=storage_backend)
604617
self.assertTrue(os.path.exists(output_filename))
605618

606619
# Attempt to over-write the previously written metadata file. An exception
607620
# is not raised in this case, only a debug message is logged.
608621
repo_lib.write_metadata_file(root_signable, output_filename, version_number,
609-
consistent_snapshot=False)
610-
611-
# Try to write a consistent metadate file. An exception is not raised in
612-
# this case. For testing purposes, root.json should be a hard link to the
613-
# consistent metadata file. We should verify that root.json points to
614-
# the latest consistent files.
615-
tuf.settings.CONSISTENT_METHOD = 'hard_link'
616-
repo_lib.write_metadata_file(root_signable, output_filename, version_number,
617-
consistent_snapshot=True)
618-
619-
# Test if the consistent files are properly named
620-
# Filename format of a consistent file: <version number>.rolename.json
621-
version_and_filename = str(version_number) + '.' + 'root.json'
622-
first_version_output_file = os.path.join(temporary_directory, version_and_filename)
623-
self.assertTrue(os.path.exists(first_version_output_file))
624-
625-
# Verify that the consistent file content is equal to 'output_filename'.
626-
self.assertEqual(
627-
securesystemslib.util.get_file_details(output_filename),
628-
securesystemslib.util.get_file_details(first_version_output_file))
629-
630-
# Try to add more consistent metadata files.
631-
version_number += 1
632-
root_signable['signed']['version'] = version_number
633-
repo_lib.write_metadata_file(root_signable, output_filename,
634-
version_number, consistent_snapshot=True)
635-
636-
# Test if the latest root.json points to the expected consistent file
637-
# and consistent metadata do not all point to the same root.json
638-
version_and_filename = str(version_number) + '.' + 'root.json'
639-
second_version_output_file = os.path.join(temporary_directory, version_and_filename)
640-
self.assertTrue(os.path.exists(second_version_output_file))
641-
642-
# Verify that the second version is equal to the second output file, and
643-
# that the second output filename differs from the first.
644-
self.assertEqual(securesystemslib.util.get_file_details(output_filename),
645-
securesystemslib.util.get_file_details(second_version_output_file))
646-
self.assertNotEqual(securesystemslib.util.get_file_details(output_filename),
647-
securesystemslib.util.get_file_details(first_version_output_file))
648-
649-
# Test for an improper settings.CONSISTENT_METHOD string value.
650-
tuf.settings.CONSISTENT_METHOD = 'somebadidea'
651-
652-
# Test for invalid consistent methods on systems other than Windows,
653-
# which always uses the copy method.
654-
if platform.system() == 'Windows':
655-
pass
656-
657-
else:
658-
self.assertRaises(securesystemslib.exceptions.InvalidConfigurationError,
659-
repo_lib.write_metadata_file, root_signable, output_filename,
660-
version_number, consistent_snapshot=True)
661-
662-
# Try to create a link to root.json when root.json doesn't exist locally.
663-
# repository_lib should log a message if this is the case.
664-
tuf.settings.CONSISTENT_METHOD = 'hard_link'
665-
os.remove(output_filename)
666-
repo_lib.write_metadata_file(root_signable, output_filename, version_number,
667-
consistent_snapshot=True)
668-
669-
# Reset CONSISTENT_METHOD so that subsequent tests work as expected.
670-
tuf.settings.CONSISTENT_METHOD = 'copy'
622+
consistent_snapshot=False, storage_backend=storage_backend)
671623

672624
# Test improperly formatted arguments.
673625
self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.write_metadata_file,
674-
3, output_filename, version_number, False)
626+
3, output_filename, version_number, False, storage_backend)
675627
self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.write_metadata_file,
676-
root_signable, 3, version_number, False)
628+
root_signable, 3, version_number, False, storage_backend)
677629
self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.write_metadata_file,
678-
root_signable, output_filename, '3', False)
630+
root_signable, output_filename, '3', False, storage_backend)
679631
self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.write_metadata_file,
680-
root_signable, output_filename, version_number, 3)
632+
root_signable, output_filename, storage_backend, version_number, 3)
681633

682634

683635

@@ -731,13 +683,6 @@ def test_create_tuf_client_directory(self):
731683

732684

733685

734-
def test__check_directory(self):
735-
# Test for non-existent directory.
736-
self.assertRaises(securesystemslib.exceptions.Error,
737-
repo_lib._check_directory, 'non-existent')
738-
739-
740-
741686
def test__generate_and_write_metadata(self):
742687
# Test for invalid, or unsupported, rolename.
743688
# Load the root metadata provided in 'tuf/tests/repository_data/'.
@@ -774,9 +719,11 @@ def test__generate_and_write_metadata(self):
774719
tuf.roledb.add_role('obsolete_role', targets_roleinfo,
775720
repository_name=repository_name)
776721

722+
storage_backend = securesystemslib.storage.FilesystemBackend()
777723
repo_lib._generate_and_write_metadata('obsolete_role', obsolete_metadata,
778-
targets_directory, metadata_directory, consistent_snapshot=False,
779-
filenames=None, repository_name=repository_name)
724+
targets_directory, metadata_directory, storage_backend,
725+
consistent_snapshot=False, filenames=None,
726+
repository_name=repository_name)
780727

781728
snapshot_filepath = os.path.join('repository_data', 'repository',
782729
'metadata', 'snapshot.json')
@@ -785,7 +732,8 @@ def test__generate_and_write_metadata(self):
785732
self.assertTrue(os.path.exists(os.path.join(metadata_directory,
786733
'obsolete_role.json')))
787734
tuf.repository_lib._delete_obsolete_metadata(metadata_directory,
788-
snapshot_signable['signed'], False, repository_name)
735+
snapshot_signable['signed'], False, repository_name,
736+
storage_backend)
789737
self.assertFalse(os.path.exists(metadata_directory + 'obsolete_role.json'))
790738
shutil.copyfile(targets_metadata, obsolete_metadata)
791739

@@ -801,27 +749,29 @@ def test__delete_obsolete_metadata(self):
801749
snapshot_filepath = os.path.join('repository_data', 'repository',
802750
'metadata', 'snapshot.json')
803751
snapshot_signable = securesystemslib.util.load_json_file(snapshot_filepath)
752+
storage_backend = securesystemslib.storage.FilesystemBackend()
804753

805754
# Create role metadata that should not exist in snapshot.json.
806755
role1_filepath = os.path.join('repository_data', 'repository', 'metadata',
807756
'role1.json')
808757
shutil.copyfile(role1_filepath, os.path.join(metadata_directory, 'role2.json'))
809758

810759
repo_lib._delete_obsolete_metadata(metadata_directory,
811-
snapshot_signable['signed'], True, repository_name)
760+
snapshot_signable['signed'], True, repository_name, storage_backend)
812761

813762
# _delete_obsolete_metadata should never delete root.json.
814763
root_filepath = os.path.join('repository_data', 'repository', 'metadata',
815764
'root.json')
816765
shutil.copyfile(root_filepath, os.path.join(metadata_directory, 'root.json'))
817766
repo_lib._delete_obsolete_metadata(metadata_directory,
818-
snapshot_signable['signed'], True, repository_name)
767+
snapshot_signable['signed'], True, repository_name, storage_backend)
819768
self.assertTrue(os.path.exists(os.path.join(metadata_directory, 'root.json')))
820769

821770
# Verify what happens for a non-existent metadata directory (a debug
822771
# message is logged).
823-
repo_lib._delete_obsolete_metadata('non-existent',
824-
snapshot_signable['signed'], True, repository_name)
772+
self.assertRaises(securesystemslib.exceptions.StorageError,
773+
repo_lib._delete_obsolete_metadata, 'non-existent',
774+
snapshot_signable['signed'], True, repository_name, storage_backend)
825775

826776

827777
def test__load_top_level_metadata(self):
@@ -843,12 +793,8 @@ def test__load_top_level_metadata(self):
843793
signable = securesystemslib.util.load_json_file(os.path.join(metadata_directory, 'root.json'))
844794
signable['signatures'].append(signable['signatures'][0])
845795

846-
repo_lib.write_metadata_file(signable, root_file, 8, False)
847-
848-
# Attempt to load a repository that contains a compressed Root file.
849-
repository = repo_tool.create_new_repository(repository_directory, repository_name)
850-
filenames = repo_lib.get_metadata_filenames(metadata_directory)
851-
repo_lib._load_top_level_metadata(repository, filenames, repository_name)
796+
storage_backend = securesystemslib.storage.FilesystemBackend()
797+
repo_lib.write_metadata_file(signable, root_file, 8, False, storage_backend)
852798

853799
filenames = repo_lib.get_metadata_filenames(metadata_directory)
854800
repository = repo_tool.create_new_repository(repository_directory, repository_name)
@@ -872,7 +818,9 @@ def test__load_top_level_metadata(self):
872818
if role_file.endswith('.json') and not role_file.startswith('root'):
873819
role_filename = os.path.join(metadata_directory, role_file)
874820
os.remove(role_filename)
875-
repo_lib._load_top_level_metadata(repository, filenames, repository_name)
821+
self.assertRaises(tuf.exceptions.RepositoryError,
822+
repo_lib._load_top_level_metadata, repository, filenames,
823+
repository_name)
876824

877825
# Remove the required Root file and verify that an exception is raised.
878826
os.remove(os.path.join(metadata_directory, 'root.json'))

0 commit comments

Comments
 (0)