Add asymmetric key generation in dogtag plugin
This patch adds methods to support asymmetric key generation using the dogtag plugin. The supported algorithms are RSA and DSA. Corresponding tests have been added to test_dogtag.py. Change-Id: Ic8a7635ce98f3220f85740085072d73f66282cd1
This commit is contained in:
parent
2683630098
commit
6084017bc1
@ -335,7 +335,6 @@ class TypeOrderValidator(ValidatorBase):
|
||||
self._assert_validity(asymmetric_meta is not None,
|
||||
schema_name,
|
||||
u._("'meta' attributes is required"), "meta")
|
||||
self._raise_feature_not_implemented('asymmetric', schema_name)
|
||||
|
||||
def _validate_certificate_meta(self, certificate_meta, schema_name):
|
||||
"""Validation specific to meta for certificate type order."""
|
||||
|
@ -16,7 +16,10 @@
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Util import asn1
|
||||
from oslo.config import cfg
|
||||
|
||||
import pki
|
||||
import pki.cert
|
||||
import pki.client
|
||||
@ -27,11 +30,13 @@ import pki.profile
|
||||
from requests import exceptions as request_exceptions
|
||||
|
||||
from barbican.common import exception
|
||||
from barbican.common import utils
|
||||
from barbican.openstack.common import gettextutils as u
|
||||
import barbican.plugin.interface.certificate_manager as cm
|
||||
import barbican.plugin.interface.secret_store as sstore
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = utils.getLogger(__name__)
|
||||
|
||||
dogtag_plugin_group = cfg.OptGroup(name='dogtag_plugin',
|
||||
title="Dogtag Plugin Options")
|
||||
@ -90,18 +95,41 @@ class DogtagPluginAlgorithmException(exception.BarbicanException):
|
||||
message = u._("Invalid algorithm passed in")
|
||||
|
||||
|
||||
class DogtagPluginNotSupportedException(exception.NotSupported):
|
||||
message = u._("Operation not supported by Dogtag Plugin")
|
||||
|
||||
def __init__(self, msg=None):
|
||||
if not msg:
|
||||
message = self.message
|
||||
else:
|
||||
message = msg
|
||||
|
||||
super(DogtagPluginNotSupportedException, self).__init__(message)
|
||||
|
||||
|
||||
class DogtagKRAPlugin(sstore.SecretStoreBase):
|
||||
"""Implementation of the secret store plugin with KRA as the backend."""
|
||||
|
||||
TRANSPORT_NICK = "KRA transport cert"
|
||||
|
||||
# metadata constants
|
||||
ALG = "alg"
|
||||
BIT_LENGTH = "bit_length"
|
||||
KEY_ID = "key_id"
|
||||
SECRET_TYPE = "secret_type"
|
||||
SECRET_KEYSPEC = "secret_keyspec"
|
||||
SECRET_MODE = "secret_mode"
|
||||
PASSPHRASE_KEY_ID = "passphrase_key_id"
|
||||
CONVERT_TO_PEM = "convert_to_pem"
|
||||
|
||||
# string constants
|
||||
DSA_PRIVATE_KEY_HEADER = '-----BEGIN DSA PRIVATE KEY-----'
|
||||
DSA_PRIVATE_KEY_FOOTER = '-----END DSA PRIVATE KEY-----'
|
||||
DSA_PUBLIC_KEY_HEADER = '-----BEGIN DSA PUBLIC KEY-----'
|
||||
DSA_PUBLIC_KEY_FOOTER = '-----END DSA PUBLIC KEY-----'
|
||||
|
||||
def __init__(self, conf=CONF):
|
||||
"""Constructor - create the keyclient."""
|
||||
LOG.debug("starting DogtagKRAPlugin init")
|
||||
crypto, create_nss_db = setup_nss_db(conf)
|
||||
connection = create_connection(conf, 'kra')
|
||||
|
||||
@ -118,6 +146,8 @@ class DogtagKRAPlugin(sstore.SecretStoreBase):
|
||||
self.keyclient.set_transport_cert(
|
||||
DogtagKRAPlugin.TRANSPORT_NICK)
|
||||
|
||||
LOG.debug("completed DogtagKRAPlugin init")
|
||||
|
||||
def import_transport_cert(self, crypto):
|
||||
# Get transport cert and insert in the certdb
|
||||
transport_cert = self.systemcert_client.get_transport_cert()
|
||||
@ -163,9 +193,10 @@ class DogtagKRAPlugin(sstore.SecretStoreBase):
|
||||
key_algorithm=None,
|
||||
key_size=None)
|
||||
|
||||
return {DogtagKRAPlugin.SECRET_TYPE: secret_dto.type,
|
||||
DogtagKRAPlugin.SECRET_KEYSPEC: secret_dto.key_spec,
|
||||
DogtagKRAPlugin.KEY_ID: response.get_key_id()}
|
||||
meta_dict = {DogtagKRAPlugin.KEY_ID: response.get_key_id()}
|
||||
|
||||
self._store_secret_attributes(meta_dict, secret_dto)
|
||||
return meta_dict
|
||||
|
||||
def get_secret(self, secret_metadata):
|
||||
"""Retrieve a secret from the KRA
|
||||
@ -185,22 +216,111 @@ class DogtagKRAPlugin(sstore.SecretStoreBase):
|
||||
on the barbican client. That way only the client will be
|
||||
able to unwrap the secret. This wrapping key is provided in the
|
||||
secret_metadata by Barbican core.
|
||||
|
||||
Format/Type of the secret returned in the SecretDTO object.
|
||||
-----------------------------------------------------------
|
||||
The type of the secret returned is always dependent on the way it is
|
||||
stored using the store_secret method.
|
||||
|
||||
In case of strings - like passphrase/PEM strings, the return will be a
|
||||
string.
|
||||
|
||||
In case of binary data - the return will be the actual binary data.
|
||||
|
||||
In case of retrieving an asymmetric key that is generated using the
|
||||
dogtag plugin, then the binary representation of, the asymmetric key in
|
||||
PEM format, is returned
|
||||
"""
|
||||
key_id = secret_metadata[DogtagKRAPlugin.KEY_ID]
|
||||
twsk = None
|
||||
if 'trans_wrapped_session_key' in secret_metadata:
|
||||
twsk = secret_metadata['trans_wrapped_session_key']
|
||||
secret_type = secret_metadata.get(DogtagKRAPlugin.SECRET_TYPE, None)
|
||||
|
||||
# TODO(alee-3) send transport key as well when dogtag client API
|
||||
# changes in case the transport key has changed.
|
||||
recovered_key = self.keyclient.retrieve_key(key_id, twsk)
|
||||
key_spec = sstore.KeySpec(
|
||||
alg=secret_metadata.get(DogtagKRAPlugin.ALG, None),
|
||||
bit_length=secret_metadata.get(DogtagKRAPlugin.BIT_LENGTH, None),
|
||||
mode=secret_metadata.get(DogtagKRAPlugin.SECRET_MODE, None),
|
||||
passphrase=None
|
||||
)
|
||||
|
||||
passphrase = self._get_passphrase_for_a_private_key(
|
||||
secret_metadata, key_spec)
|
||||
|
||||
recovered_key = None
|
||||
twsk = DogtagKRAPlugin._get_trans_wrapped_session_key(secret_metadata)
|
||||
|
||||
if DogtagKRAPlugin.CONVERT_TO_PEM in secret_metadata:
|
||||
# Case for returning the asymmetric keys generated in KRA.
|
||||
# Asymmetric keys generated in KRA are not generated in PEM format.
|
||||
# This marker DogtagKRAPlugin.CONVERT_TO_PEM is set in the
|
||||
# secret_metadata for asymmetric keys generated in KRA to
|
||||
# help convert the returned private/public keys to PEM format and
|
||||
# eventually return the binary data of the keys in PEM format.
|
||||
|
||||
if secret_type == sstore.SecretType.PUBLIC:
|
||||
# Public key should be retrieved using the get_key_info method
|
||||
# as it is treated as an attribute of the asymmetric key pair
|
||||
# stored in the KRA database.
|
||||
|
||||
if key_spec.alg is None:
|
||||
raise sstore.SecretAlgorithmNotSupportedException('None')
|
||||
|
||||
key_info = self.keyclient.get_key_info(key_id)
|
||||
if key_spec.alg.upper() == key.KeyClient.RSA_ALGORITHM:
|
||||
recovered_key = (RSA.importKey(key_info.public_key)
|
||||
.publickey()
|
||||
.exportKey('PEM')).encode('utf-8')
|
||||
elif key_spec.alg.upper() == key.KeyClient.DSA_ALGORITHM:
|
||||
pub_seq = asn1.DerSequence()
|
||||
pub_seq[:] = key_info.public_key
|
||||
recovered_key = (
|
||||
("%s\n%s%s" %
|
||||
(DogtagKRAPlugin.DSA_PUBLIC_KEY_HEADER,
|
||||
pub_seq.encode().encode("base64"),
|
||||
DogtagKRAPlugin.DSA_PUBLIC_KEY_FOOTER)
|
||||
).encode('utf-8')
|
||||
)
|
||||
else:
|
||||
raise sstore.SecretAlgorithmNotSupportedException(
|
||||
key_spec.alg.upper()
|
||||
)
|
||||
|
||||
elif secret_type == sstore.SecretType.PRIVATE:
|
||||
key_data = self.keyclient.retrieve_key(key_id)
|
||||
if key_spec.alg.upper() == key.KeyClient.RSA_ALGORITHM:
|
||||
recovered_key = (
|
||||
(RSA.importKey(key_data.data)
|
||||
.exportKey('PEM', passphrase))
|
||||
.encode('utf-8')
|
||||
)
|
||||
elif key_spec.alg.upper() == key.KeyClient.DSA_ALGORITHM:
|
||||
pub_seq = asn1.DerSequence()
|
||||
pub_seq[:] = key_data.data
|
||||
recovered_key = (
|
||||
("%s\n%s%s" %
|
||||
(DogtagKRAPlugin.DSA_PRIVATE_KEY_HEADER,
|
||||
pub_seq.encode().encode("base64"),
|
||||
DogtagKRAPlugin.DSA_PRIVATE_KEY_FOOTER)
|
||||
).encode('utf-8')
|
||||
)
|
||||
else:
|
||||
raise sstore.SecretAlgorithmNotSupportedException(
|
||||
key_spec.alg.upper()
|
||||
)
|
||||
else:
|
||||
# TODO(alee-3) send transport key as well when dogtag client API
|
||||
# changes in case the transport key has changed.
|
||||
key_data = self.keyclient.retrieve_key(key_id, twsk)
|
||||
if twsk:
|
||||
# The data returned is a byte array.
|
||||
recovered_key = key_data.encrypted_data
|
||||
else:
|
||||
recovered_key = key_data.data
|
||||
|
||||
# TODO(alee) remove final field when content_type is removed
|
||||
# from secret_dto
|
||||
ret = sstore.SecretDTO(
|
||||
type=secret_metadata[DogtagKRAPlugin.SECRET_TYPE],
|
||||
type=secret_type,
|
||||
secret=recovered_key,
|
||||
key_spec=secret_metadata[DogtagKRAPlugin.SECRET_KEYSPEC],
|
||||
key_spec=key_spec,
|
||||
content_type=None,
|
||||
transport_key=None)
|
||||
|
||||
@ -232,20 +352,84 @@ class DogtagKRAPlugin(sstore.SecretStoreBase):
|
||||
|
||||
if algorithm is None:
|
||||
raise DogtagPluginAlgorithmException
|
||||
passphrase = key_spec.passphrase
|
||||
if passphrase:
|
||||
raise DogtagPluginNotSupportedException(
|
||||
"Passphrase encryption is not supported for symmetric"
|
||||
" key generating algorithms.")
|
||||
|
||||
response = self.keyclient.generate_symmetric_key(
|
||||
client_key_id,
|
||||
algorithm,
|
||||
key_spec.bit_length,
|
||||
usages)
|
||||
return {DogtagKRAPlugin.SECRET_KEYSPEC: key_spec,
|
||||
return {DogtagKRAPlugin.ALG: key_spec.alg,
|
||||
DogtagKRAPlugin.BIT_LENGTH: key_spec.bit_length,
|
||||
DogtagKRAPlugin.SECRET_MODE: key_spec.mode,
|
||||
DogtagKRAPlugin.SECRET_TYPE: sstore.SecretType.SYMMETRIC,
|
||||
DogtagKRAPlugin.KEY_ID: response.get_key_id()}
|
||||
|
||||
def generate_asymmetric_key(self, key_spec):
|
||||
"""Generate an asymmetric key."""
|
||||
raise NotImplementedError(
|
||||
"Feature not yet implemented by dogtag plugin")
|
||||
|
||||
usages = [key.AsymKeyGenerationRequest.DECRYPT_USAGE,
|
||||
key.AsymKeyGenerationRequest.ENCRYPT_USAGE]
|
||||
|
||||
client_key_id = uuid.uuid4().hex
|
||||
algorithm = self._map_algorithm(key_spec.alg.lower())
|
||||
passphrase = key_spec.passphrase
|
||||
|
||||
if algorithm is None:
|
||||
raise DogtagPluginAlgorithmException
|
||||
|
||||
passphrase_key_id = None
|
||||
passphrase_metadata = None
|
||||
if passphrase:
|
||||
if algorithm == key.KeyClient.DSA_ALGORITHM:
|
||||
raise DogtagPluginNotSupportedException("Passphrase encryption"
|
||||
" is not supported for"
|
||||
" DSA algorithm")
|
||||
|
||||
stored_passphrase_info = self.keyclient.archive_key(
|
||||
uuid.uuid4().hex,
|
||||
self.keyclient.PASS_PHRASE_TYPE,
|
||||
passphrase)
|
||||
|
||||
passphrase_key_id = stored_passphrase_info.get_key_id()
|
||||
passphrase_metadata = {
|
||||
DogtagKRAPlugin.KEY_ID: passphrase_key_id
|
||||
}
|
||||
|
||||
response = self.keyclient.generate_asymmetric_key(
|
||||
client_key_id,
|
||||
algorithm,
|
||||
key_spec.bit_length,
|
||||
usages)
|
||||
|
||||
public_key_metadata = {
|
||||
DogtagKRAPlugin.ALG: key_spec.alg,
|
||||
DogtagKRAPlugin.BIT_LENGTH: key_spec.bit_length,
|
||||
DogtagKRAPlugin.SECRET_TYPE: sstore.SecretType.PUBLIC,
|
||||
DogtagKRAPlugin.KEY_ID: response.get_key_id(),
|
||||
DogtagKRAPlugin.CONVERT_TO_PEM: "true"
|
||||
}
|
||||
|
||||
private_key_metadata = {
|
||||
DogtagKRAPlugin.ALG: key_spec.alg,
|
||||
DogtagKRAPlugin.BIT_LENGTH: key_spec.bit_length,
|
||||
DogtagKRAPlugin.SECRET_TYPE: sstore.SecretType.PRIVATE,
|
||||
DogtagKRAPlugin.KEY_ID: response.get_key_id(),
|
||||
DogtagKRAPlugin.CONVERT_TO_PEM: "true"
|
||||
}
|
||||
|
||||
if passphrase_key_id:
|
||||
private_key_metadata[DogtagKRAPlugin.PASSPHRASE_KEY_ID] = (
|
||||
passphrase_key_id
|
||||
)
|
||||
|
||||
return sstore.AsymmetricKeyMetadataDTO(private_key_metadata,
|
||||
public_key_metadata,
|
||||
passphrase_metadata)
|
||||
|
||||
def generate_supports(self, key_spec):
|
||||
"""Key generation supported?
|
||||
@ -279,21 +463,74 @@ class DogtagKRAPlugin(sstore.SecretStoreBase):
|
||||
return key.KeyClient.DES_ALGORITHM
|
||||
elif algorithm == sstore.KeyAlgorithm.DESEDE:
|
||||
return key.KeyClient.DES3_ALGORITHM
|
||||
elif algorithm == sstore.KeyAlgorithm.DIFFIE_HELLMAN:
|
||||
# may be supported, needs to be tested
|
||||
return None
|
||||
elif algorithm == sstore.KeyAlgorithm.DSA:
|
||||
return key.KeyClient.DSA_ALGORITHM
|
||||
elif algorithm == sstore.KeyAlgorithm.RSA:
|
||||
return key.KeyClient.RSA_ALGORITHM
|
||||
elif algorithm == sstore.KeyAlgorithm.DIFFIE_HELLMAN:
|
||||
# may be supported, needs to be tested
|
||||
return None
|
||||
elif algorithm == sstore.KeyAlgorithm.EC:
|
||||
# asymmetric keys not yet supported
|
||||
return None
|
||||
elif algorithm == sstore.KeyAlgorithm.RSA:
|
||||
# asymmetric keys not yet supported
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _store_secret_attributes(meta_dict, secret_dto):
|
||||
# store the following attributes for retrieval
|
||||
key_spec = secret_dto.key_spec
|
||||
if key_spec.alg is not None:
|
||||
meta_dict[DogtagKRAPlugin.ALG] = key_spec.alg
|
||||
if key_spec.bit_length is not None:
|
||||
meta_dict[DogtagKRAPlugin.BIT_LENGTH] = key_spec.bit_length
|
||||
if key_spec.mode is not None:
|
||||
meta_dict[DogtagKRAPlugin.SECRET_MODE] = key_spec.mode
|
||||
if secret_dto.type is not None:
|
||||
meta_dict[DogtagKRAPlugin.SECRET_TYPE] = secret_dto, type
|
||||
|
||||
def _get_passphrase_for_a_private_key(self, secret_metadata, key_spec):
|
||||
"""Retrieve the passphrase for the private key which is stored
|
||||
in the KRA.
|
||||
"""
|
||||
secret_type = secret_metadata.get(DogtagKRAPlugin.SECRET_TYPE, None)
|
||||
if secret_type is None:
|
||||
return None
|
||||
if key_spec.alg is None:
|
||||
return None
|
||||
|
||||
passphrase = None
|
||||
if DogtagKRAPlugin.PASSPHRASE_KEY_ID in secret_metadata:
|
||||
if key_spec.alg.upper() == key.KeyClient.RSA_ALGORITHM:
|
||||
passphrase = self.keyclient.retrieve_key(
|
||||
secret_metadata.get(DogtagKRAPlugin.PASSPHRASE_KEY_ID)
|
||||
).data
|
||||
else:
|
||||
if key_spec.alg.upper() == key.KeyClient.DSA_ALGORITHM:
|
||||
raise sstore.SecretGeneralException(
|
||||
"DSA keys should not have a passphrase in the"
|
||||
" database, for being used during retrieval."
|
||||
)
|
||||
raise sstore.SecretGeneralException(
|
||||
"Secrets of type " + secret_type +
|
||||
" should not have a passphrase in the database, "
|
||||
"for being used during retrieval."
|
||||
)
|
||||
return passphrase
|
||||
|
||||
@staticmethod
|
||||
def _get_trans_wrapped_session_key(secret_metadata):
|
||||
twsk = secret_metadata.get('trans_wrapped_session_key', None)
|
||||
secret_type = secret_metadata.get(DogtagKRAPlugin.SECRET_TYPE, None)
|
||||
if secret_type in [sstore.SecretType.PUBLIC,
|
||||
sstore.SecretType.PRIVATE]:
|
||||
if twsk:
|
||||
raise DogtagPluginNotSupportedException(
|
||||
"Encryption using session key is not supported when "
|
||||
"retrieving a " + secret_type + " key.")
|
||||
|
||||
return twsk
|
||||
|
||||
|
||||
def _catch_request_exception(ca_related_function):
|
||||
def _catch_ca_unavailable(self, *args, **kwargs):
|
||||
@ -302,6 +539,7 @@ def _catch_request_exception(ca_related_function):
|
||||
except request_exceptions.RequestException:
|
||||
return cm.ResultDTO(
|
||||
cm.CertificateStatus.CA_UNAVAILABLE_FOR_REQUEST)
|
||||
|
||||
return _catch_ca_unavailable
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
import mock
|
||||
from requests import exceptions as request_exceptions
|
||||
import testtools
|
||||
@ -29,6 +30,7 @@ try:
|
||||
|
||||
import pki
|
||||
import pki.cert as dogtag_cert
|
||||
import pki.key as dogtag_key
|
||||
imports_ok = True
|
||||
except ImportError:
|
||||
# dogtag imports probably not available
|
||||
@ -58,10 +60,9 @@ class WhenTestingDogtagKRAPlugin(utils.BaseTestCase):
|
||||
self.patcher.stop()
|
||||
os.rmdir(self.nss_dir)
|
||||
|
||||
def test_generate(self):
|
||||
def test_generate_symmetric_key(self):
|
||||
key_spec = sstore.KeySpec(sstore.KeyAlgorithm.AES, 128)
|
||||
context = mock.MagicMock()
|
||||
self.plugin.generate_symmetric_key(key_spec, context)
|
||||
self.plugin.generate_symmetric_key(key_spec)
|
||||
|
||||
self.keyclient_mock.generate_symmetric_key.assert_called_once_with(
|
||||
mock.ANY,
|
||||
@ -69,14 +70,22 @@ class WhenTestingDogtagKRAPlugin(utils.BaseTestCase):
|
||||
128,
|
||||
mock.ANY)
|
||||
|
||||
def test_generate_asymmetric_key(self):
|
||||
key_spec = sstore.KeySpec(sstore.KeyAlgorithm.RSA, 2048)
|
||||
self.plugin.generate_asymmetric_key(key_spec)
|
||||
|
||||
self.keyclient_mock.generate_asymmetric_key.assert_called_once_with(
|
||||
mock.ANY,
|
||||
sstore.KeyAlgorithm.RSA.upper(),
|
||||
2048,
|
||||
mock.ANY)
|
||||
|
||||
def test_generate_non_supported_algorithm(self):
|
||||
key_spec = sstore.KeySpec(sstore.KeyAlgorithm.EC, 192)
|
||||
context = mock.MagicMock()
|
||||
self.assertRaises(
|
||||
dogtag_import.DogtagPluginAlgorithmException,
|
||||
self.plugin.generate_symmetric_key,
|
||||
key_spec,
|
||||
context
|
||||
key_spec
|
||||
)
|
||||
|
||||
def test_raises_error_with_no_pem_path(self):
|
||||
@ -101,14 +110,13 @@ class WhenTestingDogtagKRAPlugin(utils.BaseTestCase):
|
||||
payload = 'encrypt me!!'
|
||||
key_spec = mock.MagicMock()
|
||||
content_type = mock.MagicMock()
|
||||
context = mock.MagicMock()
|
||||
transport_key = None
|
||||
secret_dto = sstore.SecretDTO(sstore.SecretType.SYMMETRIC,
|
||||
payload,
|
||||
key_spec,
|
||||
content_type,
|
||||
transport_key)
|
||||
self.plugin.store_secret(secret_dto, context)
|
||||
self.plugin.store_secret(secret_dto)
|
||||
self.keyclient_mock.archive_key.assert_called_once_with(
|
||||
mock.ANY,
|
||||
"passPhrase",
|
||||
@ -120,14 +128,13 @@ class WhenTestingDogtagKRAPlugin(utils.BaseTestCase):
|
||||
payload = 'data wrapped in PKIArchiveOptions object'
|
||||
key_spec = mock.MagicMock()
|
||||
content_type = mock.MagicMock()
|
||||
context = mock.MagicMock()
|
||||
transport_key = mock.MagicMock()
|
||||
secret_dto = sstore.SecretDTO(sstore.SecretType.SYMMETRIC,
|
||||
payload,
|
||||
key_spec,
|
||||
content_type,
|
||||
transport_key)
|
||||
self.plugin.store_secret(secret_dto, context)
|
||||
self.plugin.store_secret(secret_dto)
|
||||
self.keyclient_mock.archive_pki_options.assert_called_once_with(
|
||||
mock.ANY,
|
||||
"passPhrase",
|
||||
@ -136,39 +143,102 @@ class WhenTestingDogtagKRAPlugin(utils.BaseTestCase):
|
||||
key_size=None)
|
||||
|
||||
def test_get_secret(self):
|
||||
key_spec = mock.MagicMock()
|
||||
context = mock.MagicMock()
|
||||
secret_metadata = {
|
||||
dogtag_import.DogtagKRAPlugin.SECRET_TYPE:
|
||||
sstore.SecretType.SYMMETRIC,
|
||||
dogtag_import.DogtagKRAPlugin.SECRET_KEYSPEC: key_spec,
|
||||
dogtag_import.DogtagKRAPlugin.ALG: sstore.KeyAlgorithm.AES,
|
||||
dogtag_import.DogtagKRAPlugin.BIT_LENGTH: 256,
|
||||
dogtag_import.DogtagKRAPlugin.KEY_ID: 'key1'
|
||||
}
|
||||
self.plugin.get_secret(secret_metadata, context)
|
||||
self.plugin.get_secret(secret_metadata)
|
||||
|
||||
self.keyclient_mock.retrieve_key.assert_called_once_with('key1', None)
|
||||
|
||||
def test_get_secret_with_twsk(self):
|
||||
key_spec = mock.MagicMock()
|
||||
context = mock.MagicMock()
|
||||
twsk = mock.MagicMock()
|
||||
secret_metadata = {
|
||||
dogtag_import.DogtagKRAPlugin.SECRET_TYPE:
|
||||
sstore.SecretType.SYMMETRIC,
|
||||
dogtag_import.DogtagKRAPlugin.SECRET_KEYSPEC: key_spec,
|
||||
dogtag_import.DogtagKRAPlugin.ALG: sstore.KeyAlgorithm.AES,
|
||||
dogtag_import.DogtagKRAPlugin.BIT_LENGTH: 256,
|
||||
dogtag_import.DogtagKRAPlugin.KEY_ID: 'key1',
|
||||
'trans_wrapped_session_key': twsk
|
||||
}
|
||||
self.plugin.get_secret(secret_metadata, context)
|
||||
self.plugin.get_secret(secret_metadata)
|
||||
|
||||
self.keyclient_mock.retrieve_key.assert_called_once_with('key1', twsk)
|
||||
|
||||
def test_get_private_key(self):
|
||||
test_key = RSA.generate(2048)
|
||||
key_data = dogtag_key.KeyData()
|
||||
key_data.data = test_key.exportKey('DER')
|
||||
self.keyclient_mock.retrieve_key.return_value = key_data
|
||||
secret_metadata = {
|
||||
dogtag_import.DogtagKRAPlugin.SECRET_TYPE:
|
||||
sstore.SecretType.PRIVATE,
|
||||
dogtag_import.DogtagKRAPlugin.ALG: sstore.KeyAlgorithm.RSA,
|
||||
dogtag_import.DogtagKRAPlugin.BIT_LENGTH: 2048,
|
||||
dogtag_import.DogtagKRAPlugin.KEY_ID: 'key1',
|
||||
dogtag_import.DogtagKRAPlugin.CONVERT_TO_PEM: 'true'
|
||||
}
|
||||
result = self.plugin.get_secret(secret_metadata)
|
||||
|
||||
assert result.secret == test_key.exportKey('PEM').encode('utf-8')
|
||||
|
||||
def test_get_public_key(self):
|
||||
test_public_key = RSA.generate(2048).publickey()
|
||||
key_info = dogtag_key.KeyInfo()
|
||||
key_info.public_key = test_public_key.exportKey('DER')
|
||||
self.keyclient_mock.get_key_info.return_value = key_info
|
||||
secret_metadata = {
|
||||
dogtag_import.DogtagKRAPlugin.SECRET_TYPE:
|
||||
sstore.SecretType.PUBLIC,
|
||||
dogtag_import.DogtagKRAPlugin.ALG: sstore.KeyAlgorithm.RSA,
|
||||
dogtag_import.DogtagKRAPlugin.BIT_LENGTH: 2048,
|
||||
dogtag_import.DogtagKRAPlugin.KEY_ID: 'key1',
|
||||
dogtag_import.DogtagKRAPlugin.CONVERT_TO_PEM: 'true'
|
||||
}
|
||||
result = self.plugin.get_secret(secret_metadata)
|
||||
|
||||
assert result.secret == (test_public_key.exportKey('PEM')
|
||||
.encode('utf-8'))
|
||||
|
||||
def test_store_passphrase_for_using_in_private_key_retrieval(self):
|
||||
|
||||
key_spec = sstore.KeySpec(sstore.KeyAlgorithm.RSA, 2048,
|
||||
passphrase="password123")
|
||||
|
||||
# Mock the response for passphrase archival
|
||||
request_response = dogtag_key.KeyRequestResponse()
|
||||
request_info = dogtag_key.KeyRequestInfo()
|
||||
request_info.key_url = "https://example_url/1"
|
||||
request_response.request_info = request_info
|
||||
self.keyclient_mock.archive_key.return_value = request_response
|
||||
|
||||
asym_key_DTO = self.plugin.generate_asymmetric_key(key_spec)
|
||||
|
||||
assert asym_key_DTO.private_key_meta[
|
||||
dogtag_import.DogtagKRAPlugin.PASSPHRASE_KEY_ID
|
||||
] == '1'
|
||||
|
||||
self.keyclient_mock.generate_asymmetric_key.assert_called_once_with(
|
||||
mock.ANY,
|
||||
sstore.KeyAlgorithm.RSA.upper(),
|
||||
2048,
|
||||
mock.ANY)
|
||||
|
||||
def test_supports_symmetric_aes_key_generation(self):
|
||||
key_spec = sstore.KeySpec(sstore.KeyAlgorithm.AES, 256)
|
||||
self.assertTrue(
|
||||
self.plugin.generate_supports(key_spec)
|
||||
)
|
||||
|
||||
def test_supports_asymmetric_rsa_key_generation(self):
|
||||
key_spec = sstore.KeySpec(sstore.KeyAlgorithm.RSA, 2048)
|
||||
self.assertTrue(
|
||||
self.plugin.generate_supports(key_spec)
|
||||
)
|
||||
|
||||
def test_supports_asymmetric_ec_key_generation(self):
|
||||
key_spec = sstore.KeySpec(sstore.KeyAlgorithm.EC, 156)
|
||||
self.assertFalse(
|
||||
|
Loading…
Reference in New Issue
Block a user