Skip to content

Commit a748a91

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 5abf96e commit a748a91

File tree

2 files changed

+63
-22
lines changed

2 files changed

+63
-22
lines changed

securesystemslib/interface.py

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ def generate_and_write_rsa_keypair(filepath=None, bits=DEFAULT_RSA_KEY_BITS,
242242

243243

244244
def import_rsa_privatekey_from_file(filepath, password=None,
245-
scheme='rsassa-pss-sha256', prompt=False):
245+
scheme='rsassa-pss-sha256', prompt=False,
246+
storage_backend=None):
246247
"""
247248
<Purpose>
248249
Import the PEM file in 'filepath' containing the private key.
@@ -272,6 +273,11 @@ def import_rsa_privatekey_from_file(filepath, password=None,
272273
If True the user is prompted for a passphrase to decrypt 'filepath'.
273274
Default is False.
274275
276+
storage_backend:
277+
An object which implements
278+
securesystemslib.storage.StorageBackendInterface. When no object is
279+
passed a FilesystemBackend will be instantiated and used.
280+
275281
<Exceptions>
276282
ValueError, if 'password' is passed and 'prompt' is True.
277283
@@ -344,9 +350,13 @@ def import_rsa_privatekey_from_file(filepath, password=None,
344350
logger.debug('No password was given. Attempting to import an'
345351
' unencrypted file.')
346352

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

351361
# Convert 'pem_key' to 'securesystemslib.formats.RSAKEY_SCHEMA' format.
352362
# Raise 'securesystemslib.exceptions.CryptoError' if 'pem_key' is invalid.
@@ -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,10 +413,14 @@ 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:
403-
rsa_pubkey_pem = file_object.read().decode('utf-8')
421+
file_object = storage_backend.get(filepath)
422+
rsa_pubkey_pem = file_object.read().decode('utf-8')
423+
file_object.close()
404424

405425
# Convert 'rsa_pubkey_pem' to 'securesystemslib.formats.RSAKEY_SCHEMA' format.
406426
try:
@@ -587,7 +607,8 @@ def import_ed25519_publickey_from_file(filepath):
587607

588608

589609

590-
def import_ed25519_privatekey_from_file(filepath, password=None, prompt=False):
610+
def import_ed25519_privatekey_from_file(filepath, password=None, prompt=False,
611+
storage_backend=None):
591612
"""
592613
<Purpose>
593614
Import the encrypted ed25519 key file in 'filepath', decrypt it, and return
@@ -610,6 +631,11 @@ def import_ed25519_privatekey_from_file(filepath, password=None, prompt=False):
610631
If True the user is prompted for a passphrase to decrypt 'filepath'.
611632
Default is False.
612633
634+
storage_backend:
635+
An object which implements
636+
securesystemslib.storage.StorageBackendInterface. When no object is
637+
passed a FilesystemBackend will be instantiated and used.
638+
613639
<Exceptions>
614640
securesystemslib.exceptions.FormatError, if the arguments are improperly
615641
formatted or the imported key object contains an invalid key type (i.e.,
@@ -634,6 +660,9 @@ def import_ed25519_privatekey_from_file(filepath, password=None, prompt=False):
634660
if password and prompt:
635661
raise ValueError("Passing 'password' and 'prompt' True is not allowed.")
636662

663+
if storage_backend is None:
664+
storage_backend = securesystemslib.storage.FilesystemBackend()
665+
637666
# If 'password' was passed check format and that it is not empty.
638667
if password is not None:
639668
securesystemslib.formats.PASSWORD_SCHEMA.check_match(password)
@@ -664,10 +693,11 @@ def import_ed25519_privatekey_from_file(filepath, password=None, prompt=False):
664693

665694
# Finally, regardless of password, try decrypting the key, if necessary.
666695
# Otherwise, load it straight from the disk.
667-
with open(filepath, 'rb') as file_object:
668-
json_str = file_object.read()
669-
return securesystemslib.keys.\
670-
import_ed25519key_from_private_json(json_str, password=password)
696+
file_object = storage_backend.get(filepath)
697+
json_str = file_object.read()
698+
file_object.close()
699+
return securesystemslib.keys.\
700+
import_ed25519key_from_private_json(json_str, password=password)
671701

672702

673703

@@ -832,7 +862,8 @@ def import_ecdsa_publickey_from_file(filepath):
832862

833863

834864

835-
def import_ecdsa_privatekey_from_file(filepath, password=None):
865+
def import_ecdsa_privatekey_from_file(filepath, password=None,
866+
storage_backend=None):
836867
"""
837868
<Purpose>
838869
Import the encrypted ECDSA key file in 'filepath', decrypt it, and return
@@ -850,6 +881,11 @@ def import_ecdsa_privatekey_from_file(filepath, password=None):
850881
encrypted key file 'filepath' must be decrypted before the ECDSA key
851882
object can be returned.
852883
884+
storage_backend:
885+
An object which implements
886+
securesystemslib.storage.StorageBackendInterface. When no object is
887+
passed a FilesystemBackend will be instantiated and used.
888+
853889
<Exceptions>
854890
securesystemslib.exceptions.FormatError, if the arguments are improperly
855891
formatted or the imported key object contains an invalid key type (i.e.,
@@ -886,12 +922,16 @@ def import_ecdsa_privatekey_from_file(filepath, password=None):
886922
# Does 'password' have the correct format?
887923
securesystemslib.formats.PASSWORD_SCHEMA.check_match(password)
888924

925+
if storage_backend is None:
926+
storage_backend = securesystemslib.storage.FilesystemBackend()
927+
889928
# Store the encrypted contents of 'filepath' prior to calling the decryption
890929
# routine.
891930
encrypted_key = None
892931

893-
with open(filepath, 'rb') as file_object:
894-
encrypted_key = file_object.read()
932+
file_object = storage_backend.get(filepath)
933+
encrypted_key = file_object.read()
934+
file_object.close()
895935

896936
# Decrypt the loaded key file, calling the 'cryptography' library to generate
897937
# the derived encryption key from 'password'. Raise

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)