Skip to content

Commit 32f3394

Browse files
committed
Add StorageBackendInterface to interface funcs
Add storage_backend as an optional parameter to functions in the interface module which read files from the disk. When no argument is provided and the default value of None is used, instantiate a FilesystemBackend and use that to access files on the local filesystem. Signed-off-by: Joshua Lock <[email protected]>
1 parent 8deb29f commit 32f3394

File tree

2 files changed

+58
-19
lines changed

2 files changed

+58
-19
lines changed

securesystemslib/interface.py

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343

4444
import securesystemslib.formats
4545
import securesystemslib.settings
46+
import securesystemslib.storage
4647
import securesystemslib.util
4748
import securesystemslib.keys
4849

@@ -242,7 +243,8 @@ def generate_and_write_rsa_keypair(filepath=None, bits=DEFAULT_RSA_KEY_BITS,
242243

243244

244245
def import_rsa_privatekey_from_file(filepath, password=None,
245-
scheme='rsassa-pss-sha256', prompt=False):
246+
scheme='rsassa-pss-sha256', prompt=False,
247+
storage_backend=None):
246248
"""
247249
<Purpose>
248250
Import the PEM file in 'filepath' containing the private key.
@@ -272,6 +274,11 @@ def import_rsa_privatekey_from_file(filepath, password=None,
272274
If True the user is prompted for a passphrase to decrypt 'filepath'.
273275
Default is False.
274276
277+
storage_backend:
278+
An object which implements
279+
securesystemslib.storage.StorageBackendInterface. When no object is
280+
passed a FilesystemBackend will be instantiated and used.
281+
275282
<Exceptions>
276283
ValueError, if 'password' is passed and 'prompt' is True.
277284
@@ -344,8 +351,11 @@ def import_rsa_privatekey_from_file(filepath, password=None,
344351
logger.debug('No password was given. Attempting to import an'
345352
' unencrypted file.')
346353

354+
if storage_backend is None:
355+
storage_backend = securesystemslib.storage.FilesystemBackend()
356+
347357
# Read the contents of 'filepath' that should be a PEM formatted private key.
348-
with open(filepath, 'rb') as file_object:
358+
with storage_backend.get(filepath) as file_object:
349359
pem_key = file_object.read().decode('utf-8')
350360

351361
# Convert 'pem_key' to 'securesystemslib.formats.RSAKEY_SCHEMA' format.
@@ -360,7 +370,8 @@ def import_rsa_privatekey_from_file(filepath, password=None,
360370

361371

362372

363-
def import_rsa_publickey_from_file(filepath, scheme='rsassa-pss-sha256'):
373+
def import_rsa_publickey_from_file(filepath, scheme='rsassa-pss-sha256',
374+
storage_backend=None):
364375
"""
365376
<Purpose>
366377
Import the RSA key stored in 'filepath'. The key object returned is in the
@@ -374,6 +385,11 @@ def import_rsa_publickey_from_file(filepath, scheme='rsassa-pss-sha256'):
374385
scheme:
375386
The signature scheme used by the imported key.
376387
388+
storage_backend:
389+
An object which implements
390+
securesystemslib.storage.StorageBackendInterface. When no object is
391+
passed a FilesystemBackend will be instantiated and used.
392+
377393
<Exceptions>
378394
securesystemslib.exceptions.FormatError, if 'filepath' is improperly
379395
formatted.
@@ -397,9 +413,12 @@ def import_rsa_publickey_from_file(filepath, scheme='rsassa-pss-sha256'):
397413
# Is 'scheme' properly formatted?
398414
securesystemslib.formats.RSA_SCHEME_SCHEMA.check_match(scheme)
399415

416+
if storage_backend is None:
417+
storage_backend = securesystemslib.storage.FilesystemBackend()
418+
400419
# Read the contents of the key file that should be in PEM format and contains
401420
# the public portion of the RSA key.
402-
with open(filepath, 'rb') as file_object:
421+
with storage_backend.get(filepath) as file_object:
403422
rsa_pubkey_pem = file_object.read().decode('utf-8')
404423

405424
# Convert 'rsa_pubkey_pem' to 'securesystemslib.formats.RSAKEY_SCHEMA' format.
@@ -587,7 +606,8 @@ def import_ed25519_publickey_from_file(filepath):
587606

588607

589608

590-
def import_ed25519_privatekey_from_file(filepath, password=None, prompt=False):
609+
def import_ed25519_privatekey_from_file(filepath, password=None, prompt=False,
610+
storage_backend=None):
591611
"""
592612
<Purpose>
593613
Import the encrypted ed25519 key file in 'filepath', decrypt it, and return
@@ -610,6 +630,11 @@ def import_ed25519_privatekey_from_file(filepath, password=None, prompt=False):
610630
If True the user is prompted for a passphrase to decrypt 'filepath'.
611631
Default is False.
612632
633+
storage_backend:
634+
An object which implements
635+
securesystemslib.storage.StorageBackendInterface. When no object is
636+
passed a FilesystemBackend will be instantiated and used.
637+
613638
<Exceptions>
614639
securesystemslib.exceptions.FormatError, if the arguments are improperly
615640
formatted or the imported key object contains an invalid key type (i.e.,
@@ -634,6 +659,9 @@ def import_ed25519_privatekey_from_file(filepath, password=None, prompt=False):
634659
if password and prompt:
635660
raise ValueError("Passing 'password' and 'prompt' True is not allowed.")
636661

662+
if storage_backend is None:
663+
storage_backend = securesystemslib.storage.FilesystemBackend()
664+
637665
# If 'password' was passed check format and that it is not empty.
638666
if password is not None:
639667
securesystemslib.formats.PASSWORD_SCHEMA.check_match(password)
@@ -663,11 +691,12 @@ def import_ed25519_privatekey_from_file(filepath, password=None, prompt=False):
663691
password = None
664692

665693
# Finally, regardless of password, try decrypting the key, if necessary.
666-
# Otherwise, load it straight from the disk.
667-
with open(filepath, 'rb') as file_object:
694+
# Otherwise, load it straight from storage.
695+
with storage_backend.get(filepath) as file_object:
668696
json_str = file_object.read()
669-
return securesystemslib.keys.\
670-
import_ed25519key_from_private_json(json_str, password=password)
697+
698+
return securesystemslib.keys.\
699+
import_ed25519key_from_private_json(json_str, password=password)
671700

672701

673702

@@ -832,7 +861,8 @@ def import_ecdsa_publickey_from_file(filepath):
832861

833862

834863

835-
def import_ecdsa_privatekey_from_file(filepath, password=None):
864+
def import_ecdsa_privatekey_from_file(filepath, password=None,
865+
storage_backend=None):
836866
"""
837867
<Purpose>
838868
Import the encrypted ECDSA key file in 'filepath', decrypt it, and return
@@ -850,6 +880,11 @@ def import_ecdsa_privatekey_from_file(filepath, password=None):
850880
encrypted key file 'filepath' must be decrypted before the ECDSA key
851881
object can be returned.
852882
883+
storage_backend:
884+
An object which implements
885+
securesystemslib.storage.StorageBackendInterface. When no object is
886+
passed a FilesystemBackend will be instantiated and used.
887+
853888
<Exceptions>
854889
securesystemslib.exceptions.FormatError, if the arguments are improperly
855890
formatted or the imported key object contains an invalid key type (i.e.,
@@ -886,11 +921,14 @@ def import_ecdsa_privatekey_from_file(filepath, password=None):
886921
# Does 'password' have the correct format?
887922
securesystemslib.formats.PASSWORD_SCHEMA.check_match(password)
888923

924+
if storage_backend is None:
925+
storage_backend = securesystemslib.storage.FilesystemBackend()
926+
889927
# Store the encrypted contents of 'filepath' prior to calling the decryption
890928
# routine.
891929
encrypted_key = None
892930

893-
with open(filepath, 'rb') as file_object:
931+
with storage_backend.get(filepath) as file_object:
894932
encrypted_key = file_object.read()
895933

896934
# Decrypt the loaded key file, calling the 'cryptography' library to generate

tests/test_interface.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,8 @@ def test_import_rsa_privatekey_from_file(self):
218218
# Non-existent key file.
219219
nonexistent_keypath = os.path.join(temporary_directory,
220220
'nonexistent_keypath')
221-
self.assertRaises(IOError, interface.import_rsa_privatekey_from_file,
222-
nonexistent_keypath, 'pw')
221+
self.assertRaises(securesystemslib.exceptions.StorageError,
222+
interface.import_rsa_privatekey_from_file, nonexistent_keypath, 'pw')
223223

224224
# Invalid key file argument.
225225
invalid_keyfile = os.path.join(temporary_directory, 'invalid_keyfile')
@@ -252,8 +252,8 @@ def test_import_rsa_publickey_from_file(self):
252252
# Non-existent key file.
253253
nonexistent_keypath = os.path.join(temporary_directory,
254254
'nonexistent_keypath')
255-
self.assertRaises(IOError, interface.import_rsa_publickey_from_file,
256-
nonexistent_keypath)
255+
self.assertRaises(securesystemslib.exceptions.StorageError,
256+
interface.import_rsa_publickey_from_file, nonexistent_keypath)
257257

258258
# Invalid key file argument.
259259
invalid_keyfile = os.path.join(temporary_directory, 'invalid_keyfile')
@@ -426,8 +426,9 @@ def test_import_ed25519_privatekey_from_file(self):
426426
# Non-existent key file.
427427
nonexistent_keypath = os.path.join(temporary_directory,
428428
'nonexistent_keypath')
429-
self.assertRaises(IOError, interface.import_ed25519_privatekey_from_file,
430-
nonexistent_keypath, 'pw')
429+
self.assertRaises(securesystemslib.exceptions.StorageError,
430+
interface.import_ed25519_privatekey_from_file, nonexistent_keypath,
431+
'pw')
431432

432433
# Invalid key file argument.
433434
invalid_keyfile = os.path.join(temporary_directory, 'invalid_keyfile')
@@ -576,8 +577,8 @@ def test_import_ecdsa_privatekey_from_file(self):
576577
# Test invalid argument.
577578
# Non-existent key file.
578579
nonexistent_keypath = os.path.join(temporary_directory, 'nonexistent_keypath')
579-
self.assertRaises(IOError, interface.import_ecdsa_privatekey_from_file,
580-
nonexistent_keypath, 'pw')
580+
self.assertRaises(securesystemslib.exceptions.StorageError,
581+
interface.import_ecdsa_privatekey_from_file, nonexistent_keypath, 'pw')
581582

582583
# Invalid key file argument.
583584
invalid_keyfile = os.path.join(temporary_directory, 'invalid_keyfile')

0 commit comments

Comments
 (0)