Exemplo n.º 1
0
def get_public_dto():
    spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048)
    return secret_store.SecretDTO(secret_store.SecretType.PUBLIC,
                                  base64.b64encode(
                                      keys.get_public_key_pem()),
                                  spec,
                                  'application/octet-stream')
Exemplo n.º 2
0
 def update_public_key(self, public_key_secret_ref):
     pem = keys.get_public_key_pem()
     resp = self.secret_behaviors.update_secret_payload(
         public_key_secret_ref,
         pem,
         'application/octet-stream')
     self.assertEqual(204, resp.status_code)
Exemplo n.º 3
0
 def store_public_key(self):
     pem = keys.get_public_key_pem()
     test_model = secret_models.SecretModel(
         **get_public_key_req(base64.b64encode(pem)))
     resp, public_key_secret_ref = self.secret_behaviors.create_secret(
         test_model)
     self.assertEqual(201, resp.status_code)
     return public_key_secret_ref
Exemplo n.º 4
0
def get_public_key_req():
    return {'name': 'mypublickey',
            'payload_content_type': 'application/octet-stream',
            'payload_content_encoding': 'base64',
            'algorithm': 'rsa',
            'bit_length': 2048,
            'secret_type': s.SecretType.PUBLIC,
            'payload': base64.b64encode(keys.get_public_key_pem())}
Exemplo n.º 5
0
def get_public_key_req():
    return {'name': 'mypublickey',
            'payload_content_type': 'application/octet-stream',
            'payload_content_encoding': 'base64',
            'algorithm': 'rsa',
            'bit_length': 2048,
            'secret_type': 'public',
            'payload': base64.b64encode(keys.get_public_key_pem())}
Exemplo n.º 6
0
def get_public_key_req():
    return {
        "name": "mypublickey",
        "payload_content_type": "application/octet-stream",
        "payload_content_encoding": "base64",
        "algorithm": "rsa",
        "bit_length": 2048,
        "secret_type": "public",
        "payload": base64.b64encode(keys.get_public_key_pem()),
    }
Exemplo n.º 7
0
def get_sample_public_key(pkcs1=False):
    if pkcs1:
        public_key_value = kss.get_public_key_der_pkcs1(
            keys.get_public_key_pem())
        key_format_type = enums.KeyFormatType.PKCS_1
    else:
        public_key_value = keys.get_public_key_der()
        key_format_type = enums.KeyFormatType.X_509

    return objects.PublicKey(enums.CryptographicAlgorithm.RSA, 2048,
                             public_key_value, key_format_type)
Exemplo n.º 8
0
 def verify_container_keys_equal(self, secret_dict, with_passphrase=False):
     if with_passphrase:
         passphrase = keys.get_passphrase_txt()
         self.assertEqual(passphrase, secret_dict['private_key_passphrase'])
         private_pem = keys.get_encrypted_private_key_pem()
     else:
         self.assertFalse('private_key_passphrase' in secret_dict)
         private_pem = keys.get_private_key_pem()
     self.assertEqual(private_pem, secret_dict['private_key'])
     public_pem = keys.get_public_key_pem()
     self.assertEqual(public_pem, secret_dict['public_key'])
Exemplo n.º 9
0
class WhenDenormalizingAfterDecryption(utils.BaseTestCase):

    dataset_for_pem_denormalize = {
        'private_key': {
            'encoded_pem': base64.b64encode(keys.get_private_key_pem()),
            'content_type': 'application/octet-stream'
        },
        'public_key': {
            'encoded_pem': base64.b64encode(keys.get_public_key_pem()),
            'content_type': 'application/octet-stream'
        },
        'certificate': {
            'encoded_pem': base64.b64encode(keys.get_certificate_pem()),
            'content_type': 'application/octet-stream'
        }
    }

    def setUp(self):
        super(WhenDenormalizingAfterDecryption, self).setUp()

        # Aliasing to reduce the number of line continuations
        self.denormalize = translations.denormalize_after_decryption

    def test_ascii_characters_to_utf8_with_plain_text(self):
        secret = 'bam'
        normalized_secret = secret.encode('utf-8')
        normalized_secret = base64.b64encode(normalized_secret)
        unencrypted = self.denormalize(normalized_secret, 'text/plain')
        self.assertEqual('bam', unencrypted)

    def test_ascii_characters_to_utf8_with_app_octet_stream(self):
        unencrypted = self.denormalize(base64.b64encode('bam'),
                                       'application/octet-stream')
        self.assertEqual('bam', unencrypted)

    def test_non_ascii_character_with_plain_text_raises_exception(self):
        exception = s.SecretAcceptNotSupportedException
        kwargs = {
            'unencrypted': base64.b64encode('\xff'),
            'content_type': 'text/plain'
        }

        self.assertRaises(exception, self.denormalize, **kwargs)

    def test_content_type_not_text_or_binary_raises_exception(self):
        exception = s.SecretContentTypeNotSupportedException
        kwargs = {'unencrypted': 'bam', 'content_type': 'other_content_type'}

        self.assertRaises(exception, self.denormalize, **kwargs)

    @utils.parameterized_dataset(dataset_for_pem_denormalize)
    def test_denormalize_pem(self, encoded_pem, content_type):
        denorm_secret = self.denormalize(encoded_pem, content_type)
        self.assertEqual(base64.b64decode(encoded_pem), denorm_secret)
Exemplo n.º 10
0
 def verify_container_keys_equal(self,
                                 secret_dict,
                                 with_passphrase=False):
     if with_passphrase:
         passphrase = keys.get_passphrase_txt()
         self.assertEqual(passphrase,
                          secret_dict['private_key_passphrase'])
         private_pem = keys.get_encrypted_private_key_pem()
     else:
         self.assertFalse('private_key_passphrase' in secret_dict)
         private_pem = keys.get_private_key_pem()
     self.assertEqual(private_pem, secret_dict['private_key'])
     public_pem = keys.get_public_key_pem()
     self.assertEqual(public_pem, secret_dict['public_key'])
Exemplo n.º 11
0
    def test_rsa_check_input_keys(self):
        """Verify the input keys for test cases"""

        # prove pyOpenSSL can parse the original private key
        pem = keys.get_private_key_pem()
        crypto.load_privatekey(crypto.FILETYPE_PEM, pem)

        # prove pyCrypto can parse the original public key
        pem = keys.get_public_key_pem()
        RSA.importKey(pem)

        # prove pyOpenSSL can parse the original encrypted private key
        pem = keys.get_encrypted_private_key_pem()
        passphrase = keys.get_passphrase_txt()
        crypto.load_privatekey(crypto.FILETYPE_PEM, pem, passphrase)

        # prove OpenSSL can parse the original certificate
        pem = keys.get_certificate_pem()
        crypto.load_certificate(crypto.FILETYPE_PEM, pem)
Exemplo n.º 12
0
    def test_rsa_check_input_keys(self):
        """Verify the input keys for test cases"""

        # prove pyOpenSSL can parse the original private key
        pem = keys.get_private_key_pem()
        crypto.load_privatekey(crypto.FILETYPE_PEM, pem)

        # prove cryptography can parse the original public key
        serialization.load_pem_public_key(keys.get_public_key_pem(),
                                          backend=default_backend())

        # prove pyOpenSSL can parse the original encrypted private key
        pem = keys.get_encrypted_private_key_pem()
        passphrase = keys.get_passphrase_txt()
        crypto.load_privatekey(crypto.FILETYPE_PEM, pem, passphrase)

        # prove OpenSSL can parse the original certificate
        pem = keys.get_certificate_pem()
        crypto.load_certificate(crypto.FILETYPE_PEM, pem)
Exemplo n.º 13
0
def get_sample_public_key(pkcs1=False):
    if pkcs1:
        public_key = kss.get_public_key_der_pkcs1(keys.get_public_key_pem())
        key_format_type = misc.KeyFormatType(enums.KeyFormatType.PKCS_1)
    else:
        public_key = keys.get_public_key_der()
        key_format_type = misc.KeyFormatType(enums.KeyFormatType.X_509)

    key_material = objects.KeyMaterial(public_key)
    key_value = objects.KeyValue(key_material)
    key_block = objects.KeyBlock(
        key_format_type=key_format_type,
        key_compression_type=None,
        key_value=key_value,
        cryptographic_algorithm=attr.CryptographicAlgorithm(
            enums.CryptographicAlgorithm.RSA),
        cryptographic_length=attr.CryptographicLength(2048),
        key_wrapping_data=None)
    return secrets.PublicKey(key_block)
Exemplo n.º 14
0
    def test_rsa_check_input_keys(self):
        """Verify the input keys for test cases"""

        # prove pyOpenSSL can parse the original private key
        pem = keys.get_private_key_pem()
        crypto.load_privatekey(crypto.FILETYPE_PEM, pem)

        # prove pyCrypto can parse the original public key
        pem = keys.get_public_key_pem()
        RSA.importKey(pem)

        # prove pyOpenSSL can parse the original encrypted private key
        pem = keys.get_encrypted_private_key_pem()
        passphrase = keys.get_passphrase_txt()
        crypto.load_privatekey(crypto.FILETYPE_PEM,
                               pem,
                               passphrase)

        # prove OpenSSL can parse the original certificate
        pem = keys.get_certificate_pem()
        crypto.load_certificate(crypto.FILETYPE_PEM, pem)
Exemplo n.º 15
0
    def test_rsa_check_input_keys(self):
        """Verify the input keys for test cases"""

        # prove pyOpenSSL can parse the original private key
        pem = keys.get_private_key_pem()
        crypto.load_privatekey(crypto.FILETYPE_PEM, pem)

        # prove cryptography can parse the original public key
        serialization.load_pem_public_key(
            keys.get_public_key_pem(),
            backend=default_backend()
        )

        # prove pyOpenSSL can parse the original encrypted private key
        pem = keys.get_encrypted_private_key_pem()
        passphrase = keys.get_passphrase_txt()
        crypto.load_privatekey(crypto.FILETYPE_PEM,
                               pem,
                               passphrase)

        # prove OpenSSL can parse the original certificate
        pem = keys.get_certificate_pem()
        crypto.load_certificate(crypto.FILETYPE_PEM, pem)
Exemplo n.º 16
0
class WhenTestingKMIPSecretStore(utils.BaseTestCase):
    """Test using the KMIP server backend for SecretStore."""
    def setUp(self):
        super(WhenTestingKMIPSecretStore, self).setUp()

        self.expected_username = "******"
        self.expected_password = "******"

        CONF = kss.CONF
        CONF.kmip_plugin.username = self.expected_username
        CONF.kmip_plugin.password = self.expected_password
        CONF.kmip_plugin.keyfile = None
        CONF.kmip_plugin.pkcs1_only = False

        # get the latest protocol that SSL supports
        protocol_dict = ssl.__dict__.get('_PROTOCOL_NAMES')
        latest_protocol = protocol_dict.get(max(protocol_dict.keys()))
        if not latest_protocol.startswith('PROTOCOL_'):
            latest_protocol = 'PROTOCOL_' + latest_protocol
        CONF.kmip_plugin.ssl_version = latest_protocol

        self.secret_store = kss.KMIPSecretStore(CONF)
        self.credential = self.secret_store.credential
        self.symmetric_type = secret_store.SecretType.SYMMETRIC

        self.sample_secret_features = {
            'key_format_type': enums.KeyFormatType.RAW,
            'key_value': {
                'bytes': bytearray(b'\x00\x00\x00')
            },
            'cryptographic_algorithm': enums.CryptographicAlgorithm.AES,
            'cryptographic_length': 128
        }

        self.symmetric_key_uuid = 'dde870ad-cea3-41a3-9bb9-e8ab579a2f91'
        self.public_key_uuid = 'cb908abb-d363-4d9f-8ef2-5e84d27dd25c'
        self.private_key_uuid = '2d4c0544-4ec6-45b7-81cd-b23c75744eac'

        self.sample_secret = get_sample_symmetric_key()

        self.secret_store.client.open = mock.MagicMock(
            spec=client.ProxyKmipClient.open)
        self.secret_store.client.close = mock.MagicMock(
            spec=client.ProxyKmipClient.close)

        self.secret_store.client.create = mock.MagicMock(
            return_value=self.symmetric_key_uuid)

        self.secret_store.client.create_key_pair = mock.MagicMock(
            return_value=(self.public_key_uuid, self.private_key_uuid))

        self.secret_store.client.register = mock.MagicMock(return_value='uuid')

        self.secret_store.client.destroy = mock.MagicMock(return_value=None)

        self.secret_store.client.get = mock.MagicMock(
            return_value=self.sample_secret)

    # --------------- TEST CONFIG OPTIONS ---------------------------------

    def test_enable_pkcs1_only_config_option(self):
        CONF = kss.CONF
        CONF.kmip_plugin.pkcs1_only = True
        secret_store = kss.KMIPSecretStore(CONF)
        self.assertTrue(secret_store.pkcs1_only)

    @testtools.skipIf(not getattr(ssl, "PROTOCOL_TLSv1_2", None),
                      "TLSv1.2 is not available on this system")
    def test_enable_tlsv12_config_option(self):
        ssl_version = "PROTOCOL_TLSv1_2"
        CONF = kss.CONF
        CONF.kmip_plugin.ssl_version = ssl_version
        kss.KMIPSecretStore(CONF)
        self.assertEqual(ssl_version, CONF.kmip_plugin.ssl_version)

    @testtools.skipIf(not getattr(ssl, "PROTOCOL_TLSv1", None),
                      "TLSv1 is not available on this system")
    def test_enable_tlsv1_config_option(self):
        ssl_version = "PROTOCOL_TLSv1"
        CONF = kss.CONF
        CONF.kmip_plugin.ssl_version = ssl_version
        kss.KMIPSecretStore(CONF)
        self.assertEqual(ssl_version, CONF.kmip_plugin.ssl_version)

    # --------------- TEST GENERATE_SUPPORTS ---------------------------------

    def test_generate_supports_aes(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, None,
                                        'mode')
        for x in [128, 192, 256]:
            key_spec.bit_length = x
            self.assertTrue(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_des(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.DES, None,
                                        'mode')
        for x in [56]:
            key_spec.bit_length = x
            self.assertTrue(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_desede(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.DESEDE, None,
                                        'mode')
        for x in [56, 112, 168]:
            key_spec.bit_length = x
            self.assertTrue(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_rsa(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, None,
                                        'mode')
        for x in [2048, 3072, 4096]:
            key_spec.bit_length = x
            self.assertTrue(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_dsa(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.DSA, None,
                                        'mode')
        for x in [2048, 3072]:
            key_spec.bit_length = x
            self.assertTrue(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_with_invalid_alg(self):
        key_spec = secret_store.KeySpec('invalid_alg', 56, 'mode')
        self.assertFalse(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_with_valid_alg_invalid_bit_length(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 56,
                                        'mode')
        self.assertFalse(self.secret_store.generate_supports(key_spec))

    # ------------ TEST GENERATE_SYMMETRIC -----------------------------------

    def test_generate_symmetric_key_assert_called(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128,
                                        'mode')
        self.secret_store.generate_symmetric_key(key_spec)

        self.secret_store.client.create.assert_called_once_with(
            enums.CryptographicAlgorithm.AES, 128)

    def test_generate_symmetric_key_return_value(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128,
                                        'mode')
        return_value = self.secret_store.generate_symmetric_key(key_spec)
        expected = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}

        self.assertEqual(expected, return_value)

    def test_generate_symmetric_key_server_error_occurs(self):
        self.secret_store.client.create.side_effect = Exception

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128,
                                        'mode')
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.generate_symmetric_key, key_spec)

    def test_generate_symmetric_key_invalid_algorithm(self):
        key_spec = secret_store.KeySpec('invalid_algorithm', 128, 'mode')
        self.assertRaises(secret_store.SecretAlgorithmNotSupportedException,
                          self.secret_store.generate_symmetric_key, key_spec)

    def test_generate_symmetric_key_valid_algorithm_invalid_bit_length(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 56,
                                        'mode')
        self.assertRaises(secret_store.SecretAlgorithmNotSupportedException,
                          self.secret_store.generate_symmetric_key, key_spec)

    def test_generate_symmetric_key_not_symmetric_algorithm(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048,
                                        'mode')
        self.assertRaises(kss.KMIPSecretStoreError,
                          self.secret_store.generate_symmetric_key, key_spec)

    def test_generate_symmetric_key_error_opening_connection(self):
        self.secret_store.client.open.side_effect = Exception

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128,
                                        'mode')
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.generate_symmetric_key, key_spec)

    # ---------------- TEST GENERATE_ASYMMETRIC ------------------------------

    def test_generate_asymmetric_key_assert_called(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048,
                                        'mode')
        self.secret_store.generate_asymmetric_key(key_spec)

        self.secret_store.client.create_key_pair.assert_called_once_with(
            enums.CryptographicAlgorithm.RSA, 2048)

    def test_generate_asymmetric_key_return_value(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048,
                                        'mode')
        return_value = self.secret_store.generate_asymmetric_key(key_spec)
        expected_private_key_meta = {
            kss.KMIPSecretStore.KEY_UUID: self.private_key_uuid
        }
        expected_public_key_meta = {
            kss.KMIPSecretStore.KEY_UUID: self.public_key_uuid
        }
        expected_passphrase_meta = None

        self.assertEqual(expected_private_key_meta,
                         return_value.private_key_meta)
        self.assertEqual(expected_public_key_meta,
                         return_value.public_key_meta)
        self.assertEqual(expected_passphrase_meta,
                         return_value.passphrase_meta)

    def test_generate_asymmetric_key_server_error_occurs(self):
        self.secret_store.client.create_key_pair.side_effect = Exception

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048,
                                        'mode')
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.generate_asymmetric_key, key_spec)

    def test_generate_asymmetric_key_invalid_algorithm(self):
        key_spec = secret_store.KeySpec('invalid_algorithm', 160, 'mode')
        self.assertRaises(secret_store.SecretAlgorithmNotSupportedException,
                          self.secret_store.generate_asymmetric_key, key_spec)

    def test_generate_asymmetric_key_valid_algorithm_invalid_bit_length(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 56,
                                        'mode')
        self.assertRaises(secret_store.SecretAlgorithmNotSupportedException,
                          self.secret_store.generate_asymmetric_key, key_spec)

    def test_generate_asymmetric_key_not_asymmetric_algorithm(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128,
                                        'mode')
        self.assertRaises(secret_store.SecretAlgorithmNotSupportedException,
                          self.secret_store.generate_asymmetric_key, key_spec)

    def test_generate_asymmetric_key_check_for_passphrase(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048,
                                        'mode', 'passphrase')
        self.assertRaises(kss.KMIPSecretStoreActionNotSupported,
                          self.secret_store.generate_asymmetric_key, key_spec)

    def test_generate_asymmetric_key_error_opening_connection(self):
        self.secret_store.client.open.side_effect = Exception

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048,
                                        'mode')
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.generate_asymmetric_key, key_spec)

    # ----------------- TEST STORE -------------------------------------------

    def test_store_symmetric_secret_assert_called(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128,
                                        'mode')
        sym_key = utils.get_symmetric_key()
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            sym_key,
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.secret_store.store_secret(secret_dto)
        self.secret_store.client.register.assert_called_once_with(
            objects.SymmetricKey(enums.CryptographicAlgorithm.AES, 128,
                                 base64.b64decode(utils.get_symmetric_key())))

    def test_store_symmetric_secret_return_value(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128,
                                        'mode')
        sym_key = utils.get_symmetric_key()
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            sym_key,
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        return_value = self.secret_store.store_secret(secret_dto)
        expected = {kss.KMIPSecretStore.KEY_UUID: 'uuid'}

        self.assertEqual(expected, return_value)

    def test_store_passphrase_secret_assert_called(self):
        key_spec = secret_store.KeySpec(None, None, None)
        passphrase = base64.b64encode(b"supersecretpassphrase")
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.PASSPHRASE,
                                            passphrase,
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.secret_store.store_secret(secret_dto)
        self.secret_store.client.register.assert_called_once_with(
            objects.SecretData(base64.b64decode(passphrase),
                               enums.SecretDataType.PASSWORD))

    def test_store_passphrase_secret_return_value(self):
        key_spec = secret_store.KeySpec(None, None, None)
        passphrase = b"supersecretpassphrase"
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.PASSPHRASE,
                                            base64.b64encode(passphrase),
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        return_value = self.secret_store.store_secret(secret_dto)
        expected = {kss.KMIPSecretStore.KEY_UUID: 'uuid'}

        self.assertEqual(expected, return_value)

    def test_store_opaque_secret_assert_called(self):
        key_spec = secret_store.KeySpec(None, None, None)
        opaque = base64.b64encode(b'\x00\x01\x02\x03\x04\x05\x06\x07')
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.OPAQUE,
                                            opaque,
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.secret_store.store_secret(secret_dto)
        self.secret_store.client.register.assert_called_once_with(
            objects.OpaqueObject(base64.b64decode(opaque),
                                 enums.OpaqueDataType.NONE))

    def test_store_opaque_secret_return_value(self):
        key_spec = secret_store.KeySpec(None, None, None)
        opaque = b'\x00\x01\x02\x03\x04\x05\x06\x07'
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.OPAQUE,
                                            base64.b64encode(opaque),
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        return_value = self.secret_store.store_secret(secret_dto)
        expected = {kss.KMIPSecretStore.KEY_UUID: 'uuid'}

        self.assertEqual(expected, return_value)

    @utils.parameterized_dataset({
        'private_pkcs8': [
            secret_store.SecretType.PRIVATE,
            keys.get_private_key_pem(), enums.ObjectType.PRIVATE_KEY,
            keys.get_private_key_der(), False
        ],
        'private_pkcs1': [
            secret_store.SecretType.PRIVATE,
            keys.get_private_key_pem(), enums.ObjectType.PRIVATE_KEY,
            kss.get_private_key_der_pkcs1(keys.get_private_key_pem()), True
        ],
        'public_pkcs8': [
            secret_store.SecretType.PUBLIC,
            keys.get_public_key_pem(), enums.ObjectType.PUBLIC_KEY,
            keys.get_public_key_der(), False
        ],
        'public_pkcs1': [
            secret_store.SecretType.PUBLIC,
            keys.get_public_key_pem(), enums.ObjectType.PUBLIC_KEY,
            kss.get_public_key_der_pkcs1(keys.get_public_key_pem()), True
        ],
    })
    def test_store_asymmetric_key_secret_assert_called(self, barbican_type,
                                                       barbican_key, kmip_type,
                                                       kmip_key, pkcs1_only):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048)
        secret_value = base64.b64encode(barbican_key)
        secret_dto = secret_store.SecretDTO(barbican_type, secret_value,
                                            key_spec, 'content_type')
        self.secret_store.pkcs1_only = pkcs1_only
        self.secret_store.store_secret(secret_dto)
        secret_value = base64.b64decode(secret_value)
        if not pkcs1_only:
            secret_value = translations.convert_pem_to_der(
                secret_value, barbican_type)
        if kmip_type == enums.ObjectType.PUBLIC_KEY:
            if pkcs1_only:
                secret_value = kss.get_public_key_der_pkcs1(secret_value)
            secret = objects.PublicKey(enums.CryptographicAlgorithm.RSA, 2048,
                                       secret_value, enums.KeyFormatType.X_509)
        else:
            if pkcs1_only:
                secret_value = kss.get_private_key_der_pkcs1(secret_value)
            secret = objects.PrivateKey(enums.CryptographicAlgorithm.RSA, 2048,
                                        secret_value,
                                        enums.KeyFormatType.PKCS_8)

        self.secret_store.client.register.assert_called_once_with(secret)

    @utils.parameterized_dataset({
        'private_pkcs8':
        [secret_store.SecretType.PRIVATE,
         keys.get_private_key_pem(), False],
        'private_pkcs1':
        [secret_store.SecretType.PRIVATE,
         keys.get_private_key_pem(), True],
        'public_pkcs8':
        [secret_store.SecretType.PUBLIC,
         keys.get_public_key_pem(), False],
        'public_pkcs1':
        [secret_store.SecretType.PUBLIC,
         keys.get_public_key_pem(), True],
    })
    def test_store_asymmetric_key_secret_return_value(self, barbican_type,
                                                      barbican_key,
                                                      pkcs1_only):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048)
        secret_dto = secret_store.SecretDTO(barbican_type,
                                            base64.b64encode(barbican_key),
                                            key_spec, 'content_type')
        self.secret_store.pkcs1_only = pkcs1_only
        return_value = self.secret_store.store_secret(secret_dto)
        expected = {kss.KMIPSecretStore.KEY_UUID: 'uuid'}

        self.assertEqual(expected, return_value)

    @utils.parameterized_dataset({
        'rsa': [secret_store.KeyAlgorithm.RSA, 2048],
        'no_key_spec': [None, None]
    })
    def test_store_certificate_secret_assert_called(self, algorithm,
                                                    bit_length):
        key_spec = secret_store.KeySpec(algorithm, bit_length)
        certificate_value = base64.b64encode(keys.get_certificate_pem())
        secret_dto = secret_store.SecretDTO(
            secret_store.SecretType.CERTIFICATE, certificate_value, key_spec,
            'content_type')
        self.secret_store.store_secret(secret_dto)
        self.secret_store.client.register.assert_called_once_with(
            objects.X509Certificate(
                translations.convert_pem_to_der(
                    base64.b64decode(certificate_value),
                    secret_store.SecretType.CERTIFICATE)))

    def test_store_certificate_secret_return_value(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048)
        secret_dto = secret_store.SecretDTO(
            secret_store.SecretType.CERTIFICATE,
            base64.b64encode(keys.get_certificate_pem()), key_spec,
            'content_type')
        return_value = self.secret_store.store_secret(secret_dto)
        expected = {kss.KMIPSecretStore.KEY_UUID: 'uuid'}

        self.assertEqual(expected, return_value)

    def test_store_secret_server_error_occurs(self):
        self.secret_store.client.register.side_effect = Exception

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128,
                                        'mode')

        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            utils.get_symmetric_key(),
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.store_secret, secret_dto)

    def test_store_secret_invalid_algorithm(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.DSA, 128,
                                        'mode')
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            "AAAA",
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.assertRaises(secret_store.SecretAlgorithmNotSupportedException,
                          self.secret_store.store_secret, secret_dto)

    def test_store_secret_valid_algorithm_invalid_bit_length(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 56,
                                        'mode')
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            "AAAA",
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.assertRaises(secret_store.SecretAlgorithmNotSupportedException,
                          self.secret_store.store_secret, secret_dto)

    def test_store_secret_error_opening_connection(self):
        self.secret_store.client.open.side_effect = Exception

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES, 128,
                                        'mode')

        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            utils.get_symmetric_key(),
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.store_secret, secret_dto)

    # --------------- TEST GET -----------------------------------------------

    @utils.parameterized_dataset({
        'symmetric': [
            get_sample_symmetric_key(), secret_store.SecretType.SYMMETRIC,
            utils.get_symmetric_key(), False
        ],
        'hmac_sha1': [
            get_sample_symmetric_key(
                algorithm=enums.CryptographicAlgorithm.HMAC_SHA1),
            secret_store.SecretType.SYMMETRIC,
            utils.get_symmetric_key(), False
        ],
        'hmac_sha256': [
            get_sample_symmetric_key(
                algorithm=enums.CryptographicAlgorithm.HMAC_SHA256),
            secret_store.SecretType.SYMMETRIC,
            utils.get_symmetric_key(), False
        ],
        'hmac_sha384': [
            get_sample_symmetric_key(
                algorithm=enums.CryptographicAlgorithm.HMAC_SHA384),
            secret_store.SecretType.SYMMETRIC,
            utils.get_symmetric_key(), False
        ],
        'hmac_sha512': [
            get_sample_symmetric_key(
                algorithm=enums.CryptographicAlgorithm.HMAC_SHA512),
            secret_store.SecretType.SYMMETRIC,
            utils.get_symmetric_key(), False
        ],
        'triple_des': [
            get_sample_symmetric_key(
                key_b64=utils.get_triple_des_key(),
                key_length=192,
                algorithm=enums.CryptographicAlgorithm.TRIPLE_DES),
            secret_store.SecretType.SYMMETRIC,
            utils.get_triple_des_key(), False
        ],
        'opaque': [
            get_sample_opaque_secret(), secret_store.SecretType.OPAQUE,
            utils.get_symmetric_key(), False
        ],
        'public_key': [
            get_sample_public_key(), secret_store.SecretType.PUBLIC,
            base64.b64encode(keys.get_public_key_pem()), False
        ],
        'public_key_pkcs1': [
            get_sample_public_key(pkcs1=True), secret_store.SecretType.PUBLIC,
            base64.b64encode(keys.get_public_key_pem()), True
        ],
        'private_key': [
            get_sample_private_key(), secret_store.SecretType.PRIVATE,
            base64.b64encode(keys.get_private_key_pem()), False
        ],
        'private_key_pkcs1': [
            get_sample_private_key(pkcs1=True),
            secret_store.SecretType.PRIVATE,
            base64.b64encode(keys.get_private_key_pem()), True
        ],
        'certificate': [
            get_sample_certificate(), secret_store.SecretType.CERTIFICATE,
            base64.b64encode(keys.get_certificate_pem()), False
        ]
    })
    def test_get_secret(self, kmip_secret, secret_type, expected_secret,
                        pkcs1_only):
        self.secret_store.pkcs1_only = pkcs1_only
        self.secret_store.client.get.return_value = kmip_secret
        uuid = utils.generate_test_uuid(0)
        metadata = {kss.KMIPSecretStore.KEY_UUID: uuid}
        secret_dto = self.secret_store.get_secret(secret_type, metadata)

        self.secret_store.client.get.assert_called_once_with(uuid)
        self.assertEqual(secret_store.SecretDTO, type(secret_dto))
        self.assertEqual(secret_type, secret_dto.type)
        self.assertEqual(expected_secret, secret_dto.secret)

    def test_get_secret_symmetric_return_value_invalid_key_material_type(self):
        invalid_secret = self.sample_secret
        invalid_secret.value = list('invalid')
        self.secret_store.client.get.return_value = invalid_secret

        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.get_secret, self.symmetric_type,
                          metadata)

    def test_get_secret_symmetric_server_error_occurs(self):
        self.secret_store.client.get.side_effect = Exception
        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.get_secret, self.symmetric_type,
                          metadata)

    def test_get_secret_symmetric_error_opening_connection(self):
        self.secret_store.client.open.side_effect = Exception

        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.get_secret, self.symmetric_type,
                          metadata)

    # ---------------- TEST DELETE -------------------------------------------

    def test_delete_with_null_metadata_values(self):
        metadata = {kss.KMIPSecretStore.KEY_UUID: None}
        self.assertIsNone(self.secret_store.delete_secret(metadata))

    def test_delete_secret_assert_called(self):
        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.secret_store.delete_secret(metadata)
        self.secret_store.client.destroy.assert_called_once_with(
            self.symmetric_key_uuid)

    def test_delete_secret_return_value(self):
        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        return_value = self.secret_store.delete_secret(metadata)
        self.assertIsNone(return_value)

    def test_delete_secret_server_error_occurs(self):
        self.secret_store.client.destroy.side_effect = Exception
        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.delete_secret, metadata)

    def test_delete_secret_error_opening_connection(self):
        self.secret_store.client.open.side_effect = Exception
        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.assertRaises(secret_store.SecretGeneralException,
                          self.secret_store.delete_secret, metadata)

    # -------------- TEST HELPER FUNCTIONS -----------------------------------

    def test_credential(self):
        actual_credential = self.secret_store.credential

        self.assertEqual(self.expected_username,
                         actual_credential.credential_value.username)
        self.assertEqual(self.expected_password,
                         actual_credential.credential_value.password)

    def test_credential_None(self):
        CONF = kss.CONF
        CONF.kmip_plugin.username = None
        CONF.kmip_plugin.password = None
        CONF.kmip_plugin.keyfile = None

        secret_store = kss.KMIPSecretStore(CONF)
        self.assertIsNone(secret_store.credential)

    def test_map_type_ss_to_kmip_valid_type(self):
        ss_types = [
            secret_store.SecretType.SYMMETRIC, secret_store.SecretType.PUBLIC,
            secret_store.SecretType.PRIVATE
        ]
        for ss_type in ss_types:
            self.assertIsNotNone(
                self.secret_store._map_type_ss_to_kmip(ss_type))

    def test_map_type_ss_to_kmip_invalid_type(self):
        object_type, key_format_type = (
            self.secret_store._map_type_ss_to_kmip('bad_type'))
        self.assertIsNone(object_type)
        self.assertIsNone(key_format_type)

    def test_validate_keyfile_permissions_good(self):
        config = {'return_value.st_mode': (stat.S_IRUSR | stat.S_IFREG)}

        with mock.patch('os.stat', **config):
            self.assertIsNone(
                self.secret_store._validate_keyfile_permissions('/some/path/'))

    def test_check_keyfile_permissions_bad(self):
        config = {'return_value.st_mode': (stat.S_IWOTH | stat.S_IFREG)}

        with mock.patch('os.stat', **config):
            self.assertRaises(kss.KMIPSecretStoreError,
                              self.secret_store._validate_keyfile_permissions,
                              '/some/path/')

    def test_checks_keyfile_permissions(self):
        config = {'return_value': True}
        func = ("barbican.plugin.kmip_secret_store."
                "KMIPSecretStore._validate_keyfile_permissions")

        with mock.patch(func, **config) as m:
            CONF = kss.CONF
            CONF.kmip_plugin.keyfile = '/some/path'
            kss.KMIPSecretStore(CONF)
            self.assertEqual(1, len(m.mock_calls))

    def test_get_plugin_name(self):
        CONF = kss.CONF
        CONF.kmip_plugin.plugin_name = "Test KMIP Plugin"
        secret_store = kss.KMIPSecretStore(CONF)
        self.assertEqual("Test KMIP Plugin", secret_store.get_plugin_name())
Exemplo n.º 17
0
 def test_passes_convert_public_der_to_pem(self):
     der = keys.get_public_key_der()
     expected_pem = keys.get_public_key_pem()
     pem = translations.convert_der_to_pem(
         der, s.SecretType.PUBLIC)
     self.assertEqual(expected_pem, pem)
Exemplo n.º 18
0
 def test_passes_convert_public_pem_to_der(self):
     pem = keys.get_public_key_pem()
     expected_der = keys.get_public_key_der()
     der = translations.convert_pem_to_der(pem, s.SecretType.PUBLIC)
     self.assertEqual(expected_der, der)
Exemplo n.º 19
0
class WhenNormalizingBeforeEncryption(utils.BaseTestCase):
    dataset_for_raised_exceptions = {
        'non_encrypted_content': {
            'exception': s.SecretNoPayloadProvidedException,
            'unencrypted': None,
            'secret_type': s.SecretType.OPAQUE,
            'content_type': '',
            'content_encoding': ''
        },
        'invalid_content_type': {
            'exception': s.SecretContentTypeNotSupportedException,
            'unencrypted': 'stuff',
            'secret_type': s.SecretType.OPAQUE,
            'content_type': 'nope',
            'content_encoding': ''
        },
        'content_encoding_isnt_base64': {
            'exception': s.SecretContentEncodingMustBeBase64,
            'unencrypted': 'stuff',
            'secret_type': s.SecretType.OPAQUE,
            'content_type': 'application/octet-stream',
            'content_encoding': 'other_stuff',
            'enforce_text_only': True
        },
        'unsupported_content_encoding': {
            'exception': s.SecretContentEncodingNotSupportedException,
            'unencrypted': 'stuff',
            'secret_type': s.SecretType.OPAQUE,
            'content_type': 'application/octet-stream',
            'content_encoding': 'other_stuff'
        }
    }

    dataset_for_normalization = {
        'plain_text': {
            'unencrypted': 'stuff',
            'secret_type': s.SecretType.OPAQUE,
            'content_type': 'text/plain',
            'content_encoding': '',
            'expected': base64.encode_as_bytes('stuff')
        },
        'binary_base64': {
            'unencrypted': base64.encode_as_bytes('stuff'),
            'secret_type': s.SecretType.OPAQUE,
            'content_type': 'application/octet-stream',
            'content_encoding': 'base64',
            'expected': base64.encode_as_bytes('stuff')
        },
        'binary': {
            'unencrypted': 'stuff',
            'secret_type': s.SecretType.OPAQUE,
            'content_type': 'application/octet-stream',
            'content_encoding': None,
            'expected': base64.encode_as_bytes('stuff')
        },
        'symmetric_base64': {
            'unencrypted': base64.encode_as_bytes('stuff'),
            'secret_type': s.SecretType.SYMMETRIC,
            'content_type': 'application/octet-stream',
            'content_encoding': 'base64',
            'expected': base64.encode_as_bytes('stuff')
        },
        'symmetric': {
            'unencrypted': 'stuff',
            'secret_type': s.SecretType.SYMMETRIC,
            'content_type': 'application/octet-stream',
            'content_encoding': None,
            'expected': base64.encode_as_bytes('stuff')
        },
        'private_base64': {
            'unencrypted': base64.encode_as_bytes(keys.get_private_key_pem()),
            'secret_type': s.SecretType.PRIVATE,
            'content_type': 'application/octet-stream',
            'content_encoding': 'base64',
            'expected': base64.encode_as_bytes(keys.get_private_key_pem())
        },
        'private': {
            'unencrypted': keys.get_private_key_pem(),
            'secret_type': s.SecretType.PRIVATE,
            'content_type': 'application/octet-stream',
            'content_encoding': None,
            'expected': base64.encode_as_bytes(keys.get_private_key_pem())
        },
        'public_base64': {
            'unencrypted': base64.encode_as_bytes(keys.get_public_key_pem()),
            'secret_type': s.SecretType.PUBLIC,
            'content_type': 'application/octet-stream',
            'content_encoding': 'base64',
            'expected': base64.encode_as_bytes(keys.get_public_key_pem())
        },
        'public': {
            'unencrypted': keys.get_public_key_pem(),
            'secret_type': s.SecretType.PUBLIC,
            'content_type': 'application/octet-stream',
            'content_encoding': None,
            'expected': base64.encode_as_bytes(keys.get_public_key_pem())
        },
        'certificate_base64': {
            'unencrypted': base64.encode_as_bytes(keys.get_certificate_pem()),
            'secret_type': s.SecretType.CERTIFICATE,
            'content_type': 'application/octet-stream',
            'content_encoding': 'base64',
            'expected': base64.encode_as_bytes(keys.get_certificate_pem())
        },
        'certificate': {
            'unencrypted': keys.get_certificate_pem(),
            'secret_type': s.SecretType.CERTIFICATE,
            'content_type': 'application/octet-stream',
            'content_encoding': None,
            'expected': base64.encode_as_bytes(keys.get_certificate_pem())
        },
    }

    def setUp(self):
        super(WhenNormalizingBeforeEncryption, self).setUp()

        # Aliasing to reduce the number of line continuations
        self.normalize = translations.normalize_before_encryption

    @utils.parameterized_dataset(dataset_for_normalization)
    def test_can_normalize(self, **kwargs):
        unencrypted, content_type = self.normalize(
            unencrypted=kwargs['unencrypted'],
            content_type=kwargs['content_type'],
            content_encoding=kwargs['content_encoding'],
            secret_type=kwargs['secret_type'])
        self.assertEqual(kwargs['expected'], unencrypted)
        self.assertEqual(kwargs['content_type'], content_type)

    def test_can_normalize_tmp_plain_text(self):
        unencrypted, content_type = self.normalize(
            unencrypted='stuff',
            content_type='text/plain',
            content_encoding='',
            secret_type=s.SecretType.OPAQUE)

        self.assertEqual(base64.encode_as_bytes('stuff'), unencrypted)
        self.assertEqual('text/plain', content_type)

    def test_null_content_encoding_gets_passed_through(self):
        unencrypted, content_type = self.normalize(
            unencrypted='bam',
            content_type='application/octet-stream',
            content_encoding=None,
            secret_type=s.SecretType.OPAQUE)

        self.assertEqual(base64.encode_as_bytes('bam'), unencrypted)
        self.assertEqual('application/octet-stream', content_type)

    def test_can_normalize_base64_str(self):
        unencrypted, content_type = self.normalize(
            unencrypted=base64.encode_as_bytes('stuff').decode('utf-8'),
            content_type='application/octet-stream',
            content_encoding='base64',
            secret_type=s.SecretType.OPAQUE)

        self.assertEqual(base64.encode_as_bytes('stuff'), unencrypted)
        self.assertEqual('application/octet-stream', content_type)

    def test_can_normalize_base64_bytes(self):
        unencrypted, content_type = self.normalize(
            unencrypted=base64.encode_as_bytes('stuff'),
            content_type='application/octet-stream',
            content_encoding='base64',
            secret_type=s.SecretType.OPAQUE)

        self.assertEqual(base64.encode_as_bytes('stuff'), unencrypted)
        self.assertEqual('application/octet-stream', content_type)

    @utils.parameterized_dataset(dataset_for_raised_exceptions)
    def test_normalize_raising_exceptions_with(self, exception, **kwargs):
        self.assertRaises(exception, self.normalize, **kwargs)
Exemplo n.º 20
0
 def test_passes_convert_public_der_to_pem(self):
     der = keys.get_public_key_der()
     expected_pem = keys.get_public_key_pem()
     pem = translations.convert_der_to_pem(der, s.SecretType.PUBLIC)
     self.assertEqual(expected_pem, pem)
Exemplo n.º 21
0
 def verify_public_key_equal(self, retrieved_public_key):
     pem = keys.get_public_key_pem()
     self.assertEqual(pem, retrieved_public_key)
Exemplo n.º 22
0
 def test_passes_convert_public_pem_to_der(self):
     pem = keys.get_public_key_pem()
     expected_der = keys.get_public_key_der()
     der = translations.convert_pem_to_der(
         pem, s.SecretType.PUBLIC)
     self.assertEqual(expected_der, der)
Exemplo n.º 23
0
class SecretsTestCase(base.TestCase):
    def setUp(self):
        super(SecretsTestCase, self).setUp()
        self.behaviors = secret_behaviors.SecretBehaviors(self.client)

        # make a local mutable copies of the default data to prevent
        # possible data contamination if (when?) the data contains
        # any nested dicts.
        # TODO(tdink) Move to a config file
        self.default_secret_create_data = get_default_data()

        self.default_secret_create_all_none_data = {
            "name": None,
            "expiration": None,
            "algorithm": None,
            "bit_length": None,
            "mode": None,
            "payload": None,
            "payload_content_type": None,
            "payload_content_encoding": None,
        }

        self.default_secret_create_emptystrings_data = {
            "name": '',
            "expiration": '',
            "algorithm": '',
            "bit_length": '',
            "mode": '',
            "payload": '',
            "payload_content_type": '',
            "payload_content_encoding": '',
        }

        self.default_secret_create_two_phase_data = {
            "name": "AES key",
            "expiration": "2018-02-28T19:14:44.180394",
            "algorithm": "aes",
            "bit_length": 256,
            "mode": "cbc",
        }

    def tearDown(self):
        self.behaviors.delete_all_created_secrets()
        super(SecretsTestCase, self).tearDown()

    @testcase.attr('negative')
    def test_secret_create_with_only_content_type_no_payload(self):
        """Create secret with valid content type but no payload."""

        test_model = secret_models.SecretModel(
            **self.default_secret_create_all_none_data)
        test_model.payload_content_type = 'application/octet-stream'

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)

    @testcase.attr('positive')
    def test_secret_create_then_check_content_types(self):
        """Check that set content-type attribute is retained in metadata."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        resp = self.behaviors.get_secret_metadata(secret_ref)
        self.assertEqual(resp.status_code, 200)
        content_types = resp.model.content_types
        self.assertIsNotNone(content_types)
        self.assertIn('default', content_types)
        self.assertEqual(content_types['default'],
                         test_model.payload_content_type)

    @testcase.attr('positive')
    def test_secret_create_all_none(self):
        """Covers case of a POST request with no JSON data."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_all_none_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

    @testcase.attr('negative')
    def test_secret_get_secret_doesnt_exist(self):
        """GET a non-existent secret.

        Should return a 404.
        """
        resp = self.behaviors.get_secret_metadata('not_a_uuid')
        self.assertEqual(resp.status_code, 404)

    @testcase.attr('positive')
    def test_secret_get_payload_no_accept_header(self):
        """GET a secret payload, do not pass in accept header.

        Should return a 200.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        get_resp = self.behaviors.get_secret(secret_ref,
                                             payload_content_type='')
        self.assertEqual(get_resp.status_code, 200)
        self.assertIn(test_model.payload,
                      binascii.b2a_base64(get_resp.content))

    @testcase.attr('negative')
    def test_secret_delete_doesnt_exist(self):
        """DELETE a non-existent secret.

        Should return a 404.
        """
        resp = self.behaviors.delete_secret('not_a_uuid', expected_fail=True)
        self.assertEqual(resp.status_code, 404)

    @testcase.attr('negative')
    def test_secret_get_invalid_mime_type(self):
        """Covers getting a secret with an invalid mime type."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        resp = self.behaviors.get_secret(secret_ref,
                                         payload_content_type="i/m")
        self.assertEqual(resp.status_code, 406)

    @testcase.attr('negative')
    def test_secret_create_with_expiration_passed(self):
        """Create a secret with an expiration that has already passed.

        Should return a 400.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.expiration = '2000-01-10T14:58:52.546795'

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)

    @testcase.attr('negative')
    def test_secret_create_with_empty_strings(self):
        """Secret create with empty Strings for all attributes.

        Should return a 400.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_emptystrings_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)

    @testcase.attr('negative')
    def test_secret_create_with_invalid_content_type(self):
        """Create secret with an invalid content type in HTTP header.

        Should return a 415.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)

        headers = {"Content-Type": "crypto/boom"}

        resp, secret_ref = self.behaviors.create_secret(test_model, headers)
        self.assertEqual(resp.status_code, 415)

    @testcase.attr('negative')
    def test_secret_create_with_oversized_payload(self):
        """Create a secret that is larger than the max payload size.

        Should return a 413 if the secret size is greater than the
        maximum allowed size.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.payload = str(self.oversized_payload)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 413)

    @testcase.attr('negative')
    def test_secret_put_when_payload_doesnt_exist(self):
        """PUT secret to a non-existent secret.

        Should return 404.
        """
        resp = self.behaviors.update_secret_payload(
            secret_ref='not_a_uuid',
            payload_content_type='application/octet-stream',
            payload_content_encoding='base64',
            payload='testing putting to non-existent secret')

        self.assertEqual(resp.status_code, 404)

    @testcase.attr('negative')
    def test_secret_put_when_payload_already_exists(self):
        """PUT against a secret that already has encrypted data.

        Should return 409.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        resp = self.behaviors.update_secret_payload(
            secret_ref=secret_ref,
            payload_content_type='application/octet-stream',
            payload_content_encoding='base64',
            payload='testing putting data in secret that already has data')
        self.assertEqual(resp.status_code, 409)

    @testcase.attr('negative')
    def test_secret_put_two_phase_empty_payload(self):
        """Covers case of putting empty String to a secret.

        Should return 400.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_two_phase_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        put_resp = self.behaviors.update_secret_payload(
            secret_ref=secret_ref,
            payload_content_type='application/octet-stream',
            payload_content_encoding='base64',
            payload='')
        self.assertEqual(put_resp.status_code, 400)

    @testcase.attr('negative')
    def test_secret_put_two_phase_invalid_content_type(self):
        """PUT with an invalid content type. Should return 415.

        Launchpad bug #1208601
        - Updated in Barbican blueprint barbican-enforce-content-type
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_two_phase_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        put_resp = self.behaviors.update_secret_payload(
            secret_ref=secret_ref,
            payload_content_type='crypto/boom',
            payload_content_encoding='base64',
            payload='invalid content type')
        self.assertEqual(put_resp.status_code, 415)

    @testcase.attr('negative')
    def test_secret_put_two_phase_no_payload(self):
        """Covers case of putting null String to a secret.

        Should return 400.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_two_phase_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        put_resp = self.behaviors.update_secret_payload(
            secret_ref=secret_ref,
            payload_content_type='application/octet-stream',
            payload_content_encoding='base64',
            payload=None)
        self.assertEqual(put_resp.status_code, 400)

    @testcase.attr('negative')
    def test_secret_put_two_phase_w_oversized_binary_data_not_utf8(self):
        """PUT with an oversized binary string that isn't UTF-8.

        Launchpad bug #1315498.
        """
        oversized_payload = bytearray().zfill(self.max_payload_size + 1)

        # put a value in the middle of the data that does not have a UTF-8
        # code point.  Using // to be python3-friendly.
        oversized_payload[self.max_payload_size // 2] = b'\xb0'

        test_model = secret_models.SecretModel(
            **self.default_secret_create_two_phase_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        put_resp = self.behaviors.update_secret_payload(
            secret_ref=secret_ref,
            payload_content_type='application/octet-stream',
            payload_content_encoding='base64',
            payload=str(oversized_payload))
        self.assertEqual(put_resp.status_code, 413)

    @testcase.attr('negative')
    def test_secret_put_two_phase_oversized_payload(self):
        """PUT with oversized payload should return 413.

        Covers the case of putting secret data that is larger than the maximum
        secret size allowed by Barbican. Beyond that it should return 413.
        """
        oversized_payload = self.oversized_payload

        test_model = secret_models.SecretModel(
            **self.default_secret_create_two_phase_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        put_resp = self.behaviors.update_secret_payload(
            secret_ref=secret_ref,
            payload_content_type='application/octet-stream',
            payload_content_encoding='base64',
            payload=oversized_payload)
        self.assertEqual(put_resp.status_code, 413)

    @testcase.attr('positive')
    def test_secret_put_two_phase_valid_binary_data_not_utf8(self):
        """A string with binary data that doesn't contain UTF-8 code points.

        Launchpad bug #1315498.
        """
        # put a value in the data that does not have a UTF-8 code point.
        data = b'\xb0'

        test_model = secret_models.SecretModel(
            **self.default_secret_create_two_phase_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        put_resp = self.behaviors.update_secret_payload(
            secret_ref=secret_ref,
            payload_content_type='application/octet-stream',
            payload_content_encoding='base64',
            payload=str(data))
        self.assertEqual(put_resp.status_code, 204)

    @testcase.attr('positive')
    def test_secret_put_two_phase_high_range_unicode_character(self):
        """Tests a high-range unicode character on a two-step PUT.

        Launchpad bug #1315498
        """
        data = u'\U0001F37A'
        data = data.encode('utf-8')
        test_model = secret_models.SecretModel(
            **self.default_secret_create_two_phase_data)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        put_resp = self.behaviors.update_secret_payload(
            secret_ref=secret_ref,
            payload_content_type='application/octet-stream',
            payload_content_encoding='base64',
            payload=data)
        self.assertEqual(put_resp.status_code, 204)

    @testcase.attr('positive')
    def test_secret_get_nones_payload_with_a_octet_stream(self):
        """Tests getting a secret with octet-stream."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_two_phase_data)
        test_model.payload_content_encoding = 'base64'
        test_model.payload_content_type = 'application/octet-stream'
        test_model.payload = base64.b64encode('abcdef')

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        get_resp = self.behaviors.get_secret(
            secret_ref,
            payload_content_type=test_model.payload_content_type,
            payload_content_encoding=test_model.payload_content_encoding)
        self.assertEqual(get_resp.status_code, 200)
        self.assertIn(test_model.payload,
                      binascii.b2a_base64(get_resp.content))

    @testcase.attr('negative')
    def test_secret_create_defaults_bad_content_type_check_message(self):
        """Verifying the returned error message matches the expected form."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.payload_content_type = 'plain-text'

        resp, secret_ref = self.behaviors.create_secret(test_model)

        # first, ensure that the return code is 400
        self.assertEqual(resp.status_code, 400)

        resp_dict = json.loads(resp.content)

        self.assertIn(
            "Provided object does not match schema 'Secret': "
            "payload_content_type plain-text is not one of ['text/plain', "
            "'text/plain;charset=utf-8', 'text/plain; charset=utf-8', "
            "'application/octet-stream'", resp_dict['description'])
        self.assertIn("Bad Request", resp_dict['title'])

    @testcase.attr('negative')
    def test_secret_create_then_expire_then_check(self):
        """Covers case where you try to retrieve a secret that is expired.

        This test creates a secret that will soon expire.
        After it expires, check it and verify that it is no longer
        a valid secret.
        """

        # create a secret that expires in 5 seconds
        timestamp = utils.create_timestamp_w_tz_and_offset(seconds=5)

        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.expiration = timestamp

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        # now get the secret - will be still valid
        get_resp = self.behaviors.get_secret_metadata(secret_ref)
        self.assertEqual(get_resp.status_code, 200)

        # now wait 10 seconds
        time.sleep(10)

        # now get the secret - should be invalid (expired)
        resp = self.behaviors.get_secret_metadata(secret_ref)
        self.assertEqual(resp.status_code, 404)

    @utils.parameterized_dataset({
        'alphanumeric': ['1f34ds'],
        'punctuation': ['~!@#$%^&*()_+`-={}[]|:;<>,.?'],
        'uuid': ['54262d9d-4bc7-4821-8df0-dc2ca8e112bb'],
        'len_255': [base.TestCase.max_sized_field],
        'empty': [''],
        'null': [None]
    })
    @testcase.attr('positive')
    def test_secret_create_defaults_valid_name(self, name):
        """Covers cases of creating secrets with valid names."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.name = name

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

    @utils.parameterized_dataset({'int': [400]})
    @testcase.attr('negative')
    def test_secret_create_defaults_invalid_name(self, name):
        """Create secrets with various invalid names.

        Should return 400.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.name = name

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)

    @utils.parameterized_dataset({'invalid': ['invalid']})
    @testcase.attr('positive')
    def test_secret_create_valid_algorithms(self, algorithm):
        """Creates secrets with various valid algorithms."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.algorithm = algorithm

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

    @utils.parameterized_dataset({'int': [400]})
    @testcase.attr('negative')
    def test_secret_create_invalid_algorithms(self, algorithm):
        """Creates secrets with various invalid algorithms."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.algorithm = algorithm

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)

    @utils.parameterized_dataset({
        '512': [512],
        'sixteen': [16],
        'fifteen': [15],
        'eight': [8],
        'seven': [7],
        'one': [1],
        'none': [None]
    })
    @testcase.attr('positive')
    def test_secret_create_defaults_valid_bit_length(self, bit_length):
        """Covers cases of creating secrets with valid bit lengths."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.bit_length = bit_length

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

    @utils.parameterized_dataset({
        'str_type': ['not-an-int'],
        'empty': [''],
        'blank': [' '],
        'negative_maxint': [-sys.maxint],
        'negative_one': [-1],
        'zero': [0]
    })
    @testcase.attr('negative')
    def test_secret_create_defaults_invalid_bit_length(self, bit_length):
        """Covers cases of creating secrets with invalid bit lengths."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.bit_length = bit_length

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)

    @utils.parameterized_dataset({
        'cbc': ['cbc'],
        'unknown_positive': ['unknown']
    })
    @testcase.attr('positive')
    def test_secret_create_defaults_valid_mode(self, mode):
        """Covers cases of creating secrets with valid modes."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.mode = mode

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

    @utils.parameterized_dataset({
        'zero': [0],
        'oversized_string': [base.TestCase.oversized_field],
        'int': [400]
    })
    @testcase.attr('negative')
    def test_secret_create_defaults_invalid_mode(self, mode):
        """Covers cases of creating secrets with invalid modes."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.mode = mode

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)

    @utils.parameterized_dataset({
        'text_content_type_none_encoding': {
            'payload_content_type': 'text/plain',
            'payload_content_encoding': None
        },
        'utf8_text_content_type_none_encoding': {
            'payload_content_type': 'text/plain; charset=utf-8',
            'payload_content_encoding': None
        },
        'no_space_utf8_text_content_type_none_encoding': {
            'payload_content_type': 'text/plain;charset=utf-8',
            'payload_content_encoding': None
        },
        'octet_content_type_base64_encoding': {
            'payload_content_type': 'application/octet-stream',
            'payload_content_encoding': 'base64'
        }
    })
    @testcase.attr('positive')
    def test_secret_create_defaults_valid_types_and_encoding(
            self, payload_content_type, payload_content_encoding):
        """Creates secrets with various content types and encodings."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.payload_content_type = payload_content_type
        test_model.payload_content_encoding = payload_content_encoding

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        get_resp = self.behaviors.get_secret(
            secret_ref,
            payload_content_type=payload_content_type,
            payload_content_encoding=payload_content_encoding)
        self.assertEqual(get_resp.status_code, 200)

        if payload_content_encoding == 'base64':
            self.assertIn(test_model.payload,
                          binascii.b2a_base64(get_resp.content))
        else:
            self.assertIn(test_model.payload, get_resp.content)

    @utils.parameterized_dataset({
        'text_content_type_none_encoding': {
            'payload_content_type': 'text/plain',
            'payload_content_encoding': None
        },
        'utf8_text_content_type_none_encoding': {
            'payload_content_type': 'text/plain; charset=utf-8',
            'payload_content_encoding': None
        },
        'no_space_utf8_text_content_type_none_encoding': {
            'payload_content_type': 'text/plain;charset=utf-8',
            'payload_content_encoding': None
        },
        'octet_content_type_base64_encoding': {
            'payload_content_type': 'application/octet-stream',
            'payload_content_encoding': 'base64'
        }
    })
    @testcase.attr('positive', 'deprecated')
    def test_secret_create_defaults_valid_types_and_encoding_old_way(
            self, payload_content_type, payload_content_encoding):
        """Creates secrets with various content types and encodings."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.payload_content_type = payload_content_type
        test_model.payload_content_encoding = payload_content_encoding

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

        get_resp = self.behaviors.get_secret_based_on_content_type(
            secret_ref,
            payload_content_type=payload_content_type,
            payload_content_encoding=payload_content_encoding)
        self.assertEqual(get_resp.status_code, 200)

        if payload_content_encoding == 'base64':
            self.assertIn(test_model.payload,
                          binascii.b2a_base64(get_resp.content))
        else:
            self.assertIn(test_model.payload, get_resp.content)

    @utils.parameterized_dataset({
        'empty_content_type_and_encoding': {
            'payload_content_type': '',
            'payload_content_encoding': ''
        },
        'none_content_type_and_encoding': {
            'payload_content_type': None,
            'payload_content_encoding': None
        },
        'large_string_content_type_and_encoding': {
            'payload_content_type': base.TestCase.oversized_field,
            'payload_content_encoding': base.TestCase.oversized_field
        },
        'int_content_type_and_encoding': {
            'payload_content_type': 123,
            'payload_content_encoding': 123
        },
        'none_content_type_base64_content_encoding': {
            'payload_content_type': None,
            'payload_content_encoding': 'base64'
        },
        'text_content_type_none_content_encoding': {
            'payload_content_type': 'text/plain',
            'payload_content_encoding': ''
        },
        'text_no_subtype_content_type_none_content_encoding': {
            'payload_content_type': 'text',
            'payload_content_encoding': None
        },
        'text_slash_no_subtype_content_type_none_content_encoding': {
            'payload_content_type': 'text/',
            'payload_content_encoding': None
        },
        'text_content_type_empty_content_encoding': {
            'payload_content_type': 'text/plain',
            'payload_content_encoding': ' '
        },
        'text_content_type_spaces_content_encoding': {
            'payload_content_type': 'text/plain',
            'payload_content_encoding': '       '
        },
        'text_content_type_base64_content_encoding': {
            'payload_content_type': 'text/plain',
            'payload_content_encoding': 'base64'
        },
        'text_and_utf88_content_type_none_content_encoding': {
            'payload_content_type': 'text/plain; charset=utf-88',
            'payload_content_encoding': None
        },
        'invalid_content_type_base64_content_encoding': {
            'payload_content_type': 'invalid',
            'payload_content_encoding': 'base64'
        },
        'invalid_content_type_none_content_encoding': {
            'payload_content_type': 'invalid',
            'payload_content_encoding': None
        },
        'octet_content_type_invalid_content_encoding': {
            'payload_content_type': 'application/octet-stream',
            'payload_content_encoding': 'invalid'
        },
        'text_content_type_invalid_content_encoding': {
            'payload_content_type': 'text/plain',
            'payload_content_encoding': 'invalid'
        },
        'none_content_type_invalid_content_encoding': {
            'payload_content_type': None,
            'payload_content_encoding': 'invalid'
        },
    })
    @testcase.attr('negative')
    def test_secret_create_defaults_invalid_types_and_encoding(
            self, payload_content_type, payload_content_encoding):
        """Creating secrets with invalid payload types and encodings."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.payload_content_type = payload_content_type
        test_model.payload_content_encoding = payload_content_encoding

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)

    @utils.parameterized_dataset(
        {'max_payload_string': [base.TestCase.max_sized_payload]})
    @testcase.attr('positive')
    def test_secret_create_defaults_valid_payload(self, payload):
        """Create secrets with a various valid payloads."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        overrides = {"payload": payload}
        test_model.override_values(**overrides)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

    @utils.parameterized_dataset({
        'empty': [''],
        'array': [['boom']],
        'int': [123],
        'none': [None],
        'bad_character': ['\u0080']
    })
    @testcase.attr('negative')
    def test_secret_create_defaults_invalid_payload(self, payload):
        """Covers creating secrets with various invalid payloads."""
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        overrides = {
            "payload_content_type": "application/octet-stream",
            "payload_content_encoding": "base64",
            "payload": payload
        }
        test_model.override_values(**overrides)

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)

    @utils.parameterized_dataset({
        'negative_five_long_expire': {
            'timezone': '-05:00',
            'days': 5
        },
        'positive_five_long_expire': {
            'timezone': '+05:00',
            'days': 5
        },
        'negative_one_short_expire': {
            'timezone': '-01',
            'days': 1
        },
        'positive_one_short_expire': {
            'timezone': '+01',
            'days': 1
        }
    })
    @testcase.attr('positive')
    def test_secret_create_defaults_valid_expiration(self, timezone, days):
        """Create secrets with a various valid expiration data."""
        timestamp = utils.create_timestamp_w_tz_and_offset(timezone=timezone,
                                                           days=days)

        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.expiration = timestamp

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 201)

    @utils.parameterized_dataset(
        {'malformed_timezone': {
            'timezone': '-5:00',
            'days': 0
        }})
    @testcase.attr('negative')
    def test_secret_create_defaults_invalid_expiration(self, timezone, days):
        """Create secrets with various invalid expiration data."""
        timestamp = utils.create_timestamp_w_tz_and_offset(timezone=timezone,
                                                           days=days)

        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.expiration = timestamp

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)

    @testcase.attr('positive')
    def test_secret_create_change_host_header(self, **kwargs):
        """Create a secret with a (possibly) malicious host name in header."""

        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)

        malicious_hostname = 'some.bad.server.com'
        changed_host_header = {'Host': malicious_hostname}

        resp, secret_ref = self.behaviors.create_secret(
            test_model, headers=changed_host_header)

        self.assertEqual(resp.status_code, 201)

        # get Location field from result and assert that it is NOT the
        # malicious one.
        regex = '.*{0}.*'.format(malicious_hostname)
        self.assertNotRegexpMatches(resp.headers['location'], regex)

    @utils.parameterized_dataset({
        'symmetric': [
            'symmetric',
            base64.b64decode(get_default_payload()),
            get_default_data()
        ],
        'private':
        ['private',
         keys.get_private_key_pem(),
         get_private_key_req()],
        'public': ['public',
                   keys.get_public_key_pem(),
                   get_public_key_req()],
        'certificate':
        ['certificate',
         keys.get_certificate_pem(),
         get_certificate_req()],
        'passphrase':
        ['passphrase', 'mysecretpassphrase',
         get_passphrase_req()]
    })
    @testcase.attr('positive')
    def test_secret_create_with_secret_type(self, secret_type, expected, spec):
        """Create secrets with various secret types."""
        test_model = secret_models.SecretModel(**spec)
        test_model.secret_type = secret_type

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(201, resp.status_code)

        resp = self.behaviors.get_secret_metadata(secret_ref)
        secret_type_response = resp.model.secret_type
        self.assertIsNotNone(secret_type_response)
        self.assertEqual(secret_type, secret_type_response)

        content_type = spec['payload_content_type']
        get_resp = self.behaviors.get_secret(secret_ref, content_type)
        self.assertEqual(expected, get_resp.content)

    @utils.parameterized_dataset({
        'invalid_http_content_type_characaters_latin': {
            'http_content_type': u'\u00c4'.encode('utf-8')
        },
        'invalid_http_content_type_characaters_arabic': {
            'http_content_type': u'\u060f'.encode('utf-8')
        },
        'invalid_http_content_type_characaters_cyrillic': {
            'http_content_type': u'\u0416'.encode('utf-8')
        },
        'invalid_http_content_type_characaters_replacement_character': {
            'http_content_type': u'\ufffd'.encode('utf-8')
        },
    })
    @testcase.attr('negative')
    def test_secret_create_with_invalid_http_content_type_characters(
            self, http_content_type):
        """Attempt to create secrets with invalid unicode characters in the

        HTTP request's Content-Type header. Should return a 415.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)

        headers = {"Content-Type": http_content_type}

        resp, secret_ref = self.behaviors.create_secret(test_model, headers)
        self.assertEqual(resp.status_code, 415)

    @utils.parameterized_dataset({
        'invalid_http_content_type_characaters_latin': {
            'payload_content_type': u'\u00c4'.encode('utf-8')
        },
        'invalid_http_content_type_characaters_arabic': {
            'payload_content_type': u'\u060f'.encode('utf-8')
        },
        'invalid_http_content_type_characaters_cyrillic': {
            'payload_content_type': u'\u0416'.encode('utf-8')
        },
        'invalid_http_content_type_characaters_replacement_character': {
            'payload_content_type': u'\ufffd'.encode('utf-8')
        },
    })
    @testcase.attr('negative')
    def test_secret_create_with_invalid_payload_content_type_characters(
            self, payload_content_type):
        """Attempt to create secrets with non-ascii characters in the

        payload's content type attribute. Should return a 400.
        """
        test_model = secret_models.SecretModel(
            **self.default_secret_create_data)
        test_model.payload_content_type = payload_content_type

        resp, secret_ref = self.behaviors.create_secret(test_model)
        self.assertEqual(resp.status_code, 400)
Exemplo n.º 24
0
class WhenTestingKMIPSecretStore(utils.BaseTestCase):
    """Test using the KMIP server backend for SecretStore."""

    def setUp(self):
        super(WhenTestingKMIPSecretStore, self).setUp()

        self.expected_username = "******"
        self.expected_password = "******"

        CONF = kss.CONF
        CONF.kmip_plugin.username = self.expected_username
        CONF.kmip_plugin.password = self.expected_password
        CONF.kmip_plugin.keyfile = None
        CONF.kmip_plugin.pkcs1_only = False

        self.secret_store = kss.KMIPSecretStore(CONF)
        self.credential = self.secret_store.credential
        self.symmetric_type = secret_store.SecretType.SYMMETRIC

        self.sample_secret_features = {
            'key_format_type': enums.KeyFormatType.RAW,
            'key_value': {
                'bytes': bytearray(b'\x00\x00\x00')
            },
            'cryptographic_algorithm': enums.CryptographicAlgorithm.AES,
            'cryptographic_length': 128
        }

        self.symmetric_key_uuid = 'dde870ad-cea3-41a3-9bb9-e8ab579a2f91'
        self.public_key_uuid = 'cb908abb-d363-4d9f-8ef2-5e84d27dd25c'
        self.private_key_uuid = '2d4c0544-4ec6-45b7-81cd-b23c75744eac'

        self.sample_secret = get_sample_symmetric_key()

        self.secret_store.client.proxy.open = mock.MagicMock(
            proxy.KMIPProxy().open)
        self.secret_store.client.proxy.close = mock.MagicMock(
            proxy.KMIPProxy().close)

        self.secret_store.client.proxy.create = mock.MagicMock(
            proxy.KMIPProxy().create, return_value=results.CreateResult(
                contents.ResultStatus(enums.ResultStatus.SUCCESS),
                uuid=attr.UniqueIdentifier(
                    self.symmetric_key_uuid)))

        self.secret_store.client.proxy.create_key_pair = mock.MagicMock(
            proxy.KMIPProxy().create_key_pair,
            return_value=results.CreateKeyPairResult(
                contents.ResultStatus(enums.ResultStatus.SUCCESS),
                private_key_uuid=attr.UniqueIdentifier(self.private_key_uuid),
                public_key_uuid=attr.UniqueIdentifier(self.public_key_uuid)))

        self.secret_store.client.proxy.register = mock.MagicMock(
            proxy.KMIPProxy().register, return_value=results.RegisterResult(
                contents.ResultStatus(enums.ResultStatus.SUCCESS),
                uuid=attr.UniqueIdentifier('uuid')))

        self.secret_store.client.proxy.destroy = mock.MagicMock(
            proxy.KMIPProxy().destroy, return_value=results.DestroyResult(
                contents.ResultStatus(enums.ResultStatus.SUCCESS)))

        self.secret_store.client.proxy.get = mock.MagicMock(
            proxy.KMIPProxy().get, return_value=results.GetResult(
                contents.ResultStatus(enums.ResultStatus.SUCCESS),
                object_type=attr.ObjectType(enums.ObjectType.SYMMETRIC_KEY),
                secret=self.sample_secret))

        self.attribute_factory = attributes.AttributeFactory()

    # --------------- TEST CONFIG OPTIONS ---------------------------------

    def test_enable_pkcs1_only_config_option(self):
        CONF = kss.CONF
        CONF.kmip_plugin.pkcs1_only = True
        secret_store = kss.KMIPSecretStore(CONF)
        self.assertTrue(secret_store.pkcs1_only)

    # --------------- TEST GENERATE_SUPPORTS ---------------------------------

    def test_generate_supports_aes(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        None, 'mode')
        for x in [128, 192, 256]:
            key_spec.bit_length = x
            self.assertTrue(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_des(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.DES,
                                        None, 'mode')
        for x in [56]:
            key_spec.bit_length = x
            self.assertTrue(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_desede(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.DESEDE,
                                        None, 'mode')
        for x in [56, 112, 168]:
            key_spec.bit_length = x
            self.assertTrue(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_rsa(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA,
                                        None, 'mode')
        for x in [2048, 3072, 4096]:
            key_spec.bit_length = x
            self.assertTrue(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_dsa(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.DSA,
                                        None, 'mode')
        for x in [2048, 3072]:
            key_spec.bit_length = x
            self.assertTrue(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_with_invalid_alg(self):
        key_spec = secret_store.KeySpec('invalid_alg', 56, 'mode')
        self.assertFalse(self.secret_store.generate_supports(key_spec))

    def test_generate_supports_with_valid_alg_invalid_bit_length(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        56, 'mode')
        self.assertFalse(self.secret_store.generate_supports(key_spec))

    # ------------ TEST GENERATE_SYMMETRIC -----------------------------------

    def test_generate_symmetric_key_assert_called(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        128, 'mode')
        self.secret_store.generate_symmetric_key(key_spec)

        self.secret_store.client.proxy.create.assert_called_once_with(
            enums.ObjectType.SYMMETRIC_KEY,
            mock.ANY)

    def test_generate_symmetric_key_return_value(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        128, 'mode')
        return_value = self.secret_store.generate_symmetric_key(key_spec)
        expected = {kss.KMIPSecretStore.KEY_UUID:
                    self.symmetric_key_uuid}

        self.assertEqual(expected, return_value)

    def test_generate_symmetric_key_server_error_occurs(self):
        self.secret_store.client.proxy.create = mock.MagicMock(
            proxy.KMIPProxy().create, return_value=results.CreateResult(
                contents.ResultStatus(enums.ResultStatus.OPERATION_FAILED)))

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        128, 'mode')
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.generate_symmetric_key,
            key_spec)

    def test_generate_symmetric_key_invalid_algorithm(self):
        key_spec = secret_store.KeySpec('invalid_algorithm',
                                        128, 'mode')
        self.assertRaises(
            secret_store.SecretAlgorithmNotSupportedException,
            self.secret_store.generate_symmetric_key,
            key_spec)

    def test_generate_symmetric_key_valid_algorithm_invalid_bit_length(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        56, 'mode')
        self.assertRaises(
            secret_store.SecretAlgorithmNotSupportedException,
            self.secret_store.generate_symmetric_key,
            key_spec)

    def test_generate_symmetric_key_not_symmetric_algorithm(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA,
                                        2048, 'mode')
        self.assertRaises(
            kss.KMIPSecretStoreError,
            self.secret_store.generate_symmetric_key,
            key_spec)

    def test_generate_symmetric_key_error_opening_connection(self):
        self.secret_store.client.proxy.open = mock.Mock(
            side_effect=socket.error)

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        128, 'mode')
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.generate_symmetric_key,
            key_spec)

    # ---------------- TEST GENERATE_ASYMMETRIC ------------------------------

    def test_generate_asymmetric_key_assert_called(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA,
                                        2048, 'mode')
        self.secret_store.generate_asymmetric_key(key_spec)

        self.secret_store.client.proxy.create_key_pair.assert_called_once_with(
            common_template_attribute=mock.ANY)

    def test_generate_asymmetric_key_return_value(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA,
                                        2048, 'mode')
        return_value = self.secret_store.generate_asymmetric_key(key_spec)
        expected_private_key_meta = {
            kss.KMIPSecretStore.KEY_UUID:
            self.private_key_uuid}
        expected_public_key_meta = {
            kss.KMIPSecretStore.KEY_UUID:
            self.public_key_uuid}
        expected_passphrase_meta = None

        self.assertEqual(
            expected_private_key_meta, return_value.private_key_meta)
        self.assertEqual(
            expected_public_key_meta, return_value.public_key_meta)
        self.assertEqual(
            expected_passphrase_meta, return_value.passphrase_meta)

    def test_generate_asymmetric_key_server_error_occurs(self):
        self.secret_store.client.proxy.create_key_pair = mock.MagicMock(
            proxy.KMIPProxy().create_key_pair,
            return_value=results.CreateKeyPairResult(
                contents.ResultStatus(enums.ResultStatus.OPERATION_FAILED)))

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA,
                                        2048, 'mode')
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.generate_asymmetric_key,
            key_spec)

    def test_generate_asymmetric_key_invalid_algorithm(self):
        key_spec = secret_store.KeySpec('invalid_algorithm', 160, 'mode')
        self.assertRaises(
            secret_store.SecretAlgorithmNotSupportedException,
            self.secret_store.generate_asymmetric_key,
            key_spec)

    def test_generate_asymmetric_key_valid_algorithm_invalid_bit_length(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA,
                                        56, 'mode')
        self.assertRaises(
            secret_store.SecretAlgorithmNotSupportedException,
            self.secret_store.generate_asymmetric_key,
            key_spec)

    def test_generate_asymmetric_key_not_asymmetric_algorithm(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        128, 'mode')
        self.assertRaises(
            kss.KMIPSecretStoreError,
            self.secret_store.generate_asymmetric_key,
            key_spec)

    def test_generate_asymmetric_key_check_for_passphrase(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA,
                                        2048, 'mode', 'passphrase')
        self.assertRaises(
            kss.KMIPSecretStoreError,
            self.secret_store.generate_asymmetric_key,
            key_spec)

    def test_generate_asymmetric_key_error_opening_connection(self):
        self.secret_store.client.proxy.open = mock.Mock(
            side_effect=socket.error)

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA,
                                        2048, 'mode')
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.generate_asymmetric_key,
            key_spec)

    # ----------------- TEST STORE -------------------------------------------

    def test_store_symmetric_secret_assert_called(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        128, 'mode')
        sym_key = utils.get_symmetric_key()
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            sym_key,
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.secret_store.store_secret(secret_dto)
        self.secret_store.client.proxy.register.assert_called_once_with(
            enums.ObjectType.SYMMETRIC_KEY,
            mock.ANY,
            mock.ANY)
        register_mock = self.secret_store.client.proxy.register
        register_call_args, _ = register_mock.call_args
        actual_secret = register_call_args[2]
        self.assertEqual(
            128,
            actual_secret.key_block.cryptographic_length.value)
        self.assertEqual(
            attr.CryptographicAlgorithm(enums.CryptographicAlgorithm.AES),
            actual_secret.key_block.cryptographic_algorithm)
        self.assertEqual(
            base64.b64decode(sym_key),
            actual_secret.key_block.key_value.key_material.value)

    def test_store_symmetric_secret_return_value(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        128, 'mode')
        sym_key = utils.get_symmetric_key()
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            sym_key,
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        return_value = self.secret_store.store_secret(secret_dto)
        expected = {kss.KMIPSecretStore.KEY_UUID: 'uuid'}

        self.assertEqual(expected, return_value)

    def test_store_passphrase_secret_assert_called(self):
        key_spec = secret_store.KeySpec(None, None, None)
        passphrase = "supersecretpassphrase"
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.PASSPHRASE,
                                            base64.b64encode(passphrase),
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.secret_store.store_secret(secret_dto)
        self.secret_store.client.proxy.register.assert_called_once_with(
            enums.ObjectType.SECRET_DATA,
            mock.ANY,
            mock.ANY)
        proxy = self.secret_store.client.proxy
        register_call_args, _ = proxy.register.call_args
        actual_secret = register_call_args[2]
        self.assertEqual(
            None,
            actual_secret.key_block.cryptographic_length)
        self.assertEqual(
            None,
            actual_secret.key_block.cryptographic_algorithm)
        self.assertEqual(
            passphrase,
            actual_secret.key_block.key_value.key_material.value)

    def test_store_passphrase_secret_return_value(self):
        key_spec = secret_store.KeySpec(None, None, None)
        passphrase = "supersecretpassphrase"
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.PASSPHRASE,
                                            base64.b64encode(passphrase),
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        return_value = self.secret_store.store_secret(secret_dto)
        expected = {kss.KMIPSecretStore.KEY_UUID: 'uuid'}

        self.assertEqual(0, cmp(expected, return_value))

    def test_store_opaque_secret_assert_called(self):
        key_spec = secret_store.KeySpec(None, None, None)
        opaque = ('\x00\x01\x02\x03\x04\x05\x06\x07')
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.OPAQUE,
                                            base64.b64encode(opaque),
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.secret_store.store_secret(secret_dto)
        self.secret_store.client.proxy.register.assert_called_once_with(
            enums.ObjectType.OPAQUE_DATA,
            mock.ANY,
            mock.ANY)
        proxy = self.secret_store.client.proxy
        register_call_args, _ = proxy.register.call_args
        actual_secret = register_call_args[2]
        self.assertEqual(
            Opaque.OpaqueDataType(enums.OpaqueDataType.NONE),
            actual_secret.opaque_data_type)
        self.assertEqual(
            Opaque.OpaqueDataValue(opaque),
            actual_secret.opaque_data_value)

    def test_store_opaque_secret_return_value(self):
        key_spec = secret_store.KeySpec(None, None, None)
        opaque = ('\x00\x01\x02\x03\x04\x05\x06\x07')
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.OPAQUE,
                                            base64.b64encode(opaque),
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        return_value = self.secret_store.store_secret(secret_dto)
        expected = {kss.KMIPSecretStore.KEY_UUID: 'uuid'}

        self.assertEqual(0, cmp(expected, return_value))

    @utils.parameterized_dataset({
        'private_pkcs8': [secret_store.SecretType.PRIVATE,
                          keys.get_private_key_pem(),
                          enums.ObjectType.PRIVATE_KEY,
                          keys.get_private_key_der(),
                          False],
        'private_pkcs1': [secret_store.SecretType.PRIVATE,
                          keys.get_private_key_pem(),
                          enums.ObjectType.PRIVATE_KEY,
                          kss.get_private_key_der_pkcs1(
                              keys.get_private_key_pem()),
                          True],
        'public_pkcs8': [secret_store.SecretType.PUBLIC,
                         keys.get_public_key_pem(),
                         enums.ObjectType.PUBLIC_KEY,
                         keys.get_public_key_der(),
                         False],
        'public_pkcs1': [secret_store.SecretType.PUBLIC,
                         keys.get_public_key_pem(),
                         enums.ObjectType.PUBLIC_KEY,
                         kss.get_public_key_der_pkcs1(
                             keys.get_public_key_pem()),
                         True],
    })
    def test_store_asymmetric_key_secret_assert_called(self,
                                                       barbican_type,
                                                       barbican_key,
                                                       kmip_type,
                                                       kmip_key,
                                                       pkcs1_only):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048)
        secret_dto = secret_store.SecretDTO(barbican_type,
                                            base64.b64encode(barbican_key),
                                            key_spec,
                                            'content_type')
        self.secret_store.pkcs1_only = pkcs1_only
        self.secret_store.store_secret(secret_dto)
        self.secret_store.client.proxy.register.assert_called_once_with(
            kmip_type,
            mock.ANY,
            mock.ANY)
        proxy = self.secret_store.client.proxy
        register_call_args, _ = proxy.register.call_args
        actual_secret = register_call_args[2]
        self.assertEqual(
            2048,
            actual_secret.key_block.cryptographic_length.value)
        self.assertEqual(
            attr.CryptographicAlgorithm(enums.CryptographicAlgorithm.RSA),
            actual_secret.key_block.cryptographic_algorithm)
        self.assertEqual(
            kmip_key,
            actual_secret.key_block.key_value.key_material.value)

    @utils.parameterized_dataset({
        'private_pkcs8': [secret_store.SecretType.PRIVATE,
                          keys.get_private_key_pem(),
                          False],
        'private_pkcs1': [secret_store.SecretType.PRIVATE,
                          keys.get_private_key_pem(),
                          True],
        'public_pkcs8': [secret_store.SecretType.PUBLIC,
                         keys.get_public_key_pem(),
                         False],
        'public_pkcs1': [secret_store.SecretType.PUBLIC,
                         keys.get_public_key_pem(),
                         True],
    })
    def test_store_asymmetric_key_secret_return_value(self,
                                                      barbican_type,
                                                      barbican_key,
                                                      pkcs1_only):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048)
        secret_dto = secret_store.SecretDTO(barbican_type,
                                            base64.b64encode(barbican_key),
                                            key_spec,
                                            'content_type')
        self.secret_store.pkcs1_only = pkcs1_only
        return_value = self.secret_store.store_secret(secret_dto)
        expected = {kss.KMIPSecretStore.KEY_UUID: 'uuid'}

        self.assertEqual(expected, return_value)

    @utils.parameterized_dataset({
        'rsa': [secret_store.KeyAlgorithm.RSA, 2048],
        'no_key_spec': [None, None]
    })
    def test_store_certificate_secret_assert_called(
            self, algorithm, bit_length):
        key_spec = secret_store.KeySpec(algorithm, bit_length)
        secret_dto = secret_store.SecretDTO(
            secret_store.SecretType.CERTIFICATE,
            base64.b64encode(keys.get_certificate_pem()),
            key_spec,
            'content_type')
        self.secret_store.store_secret(secret_dto)
        self.secret_store.client.proxy.register.assert_called_once_with(
            enums.ObjectType.CERTIFICATE,
            mock.ANY,
            mock.ANY)
        proxy = self.secret_store.client.proxy
        register_call_args, _ = proxy.register.call_args
        actual_secret = register_call_args[2]
        self.assertEqual(
            enums.CertificateTypeEnum.X_509.value,
            actual_secret.certificate_type.value)
        self.assertEqual(
            keys.get_certificate_der(),
            actual_secret.certificate_value.value)

    def test_store_certificate_secret_return_value(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048)
        secret_dto = secret_store.SecretDTO(
            secret_store.SecretType.CERTIFICATE,
            base64.b64encode(keys.get_certificate_pem()),
            key_spec,
            'content_type')
        return_value = self.secret_store.store_secret(secret_dto)
        expected = {kss.KMIPSecretStore.KEY_UUID: 'uuid'}

        self.assertEqual(expected, return_value)

    def test_store_secret_server_error_occurs(self):
        self.secret_store.client.proxy.register = mock.MagicMock(
            proxy.KMIPProxy().register, return_value=results.RegisterResult(
                contents.ResultStatus(enums.ResultStatus.OPERATION_FAILED)))

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        128, 'mode')

        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            utils.get_symmetric_key(),
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.store_secret,
            secret_dto)

    def test_store_secret_invalid_algorithm(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.DSA,
                                        128, 'mode')
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            "AAAA",
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.assertRaises(
            secret_store.SecretAlgorithmNotSupportedException,
            self.secret_store.store_secret,
            secret_dto)

    def test_store_secret_valid_algorithm_invalid_bit_length(self):
        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        56, 'mode')
        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            "AAAA",
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.assertRaises(
            secret_store.SecretAlgorithmNotSupportedException,
            self.secret_store.store_secret,
            secret_dto)

    def test_store_secret_error_opening_connection(self):
        self.secret_store.client.proxy.open = mock.Mock(
            side_effect=socket.error)

        key_spec = secret_store.KeySpec(secret_store.KeyAlgorithm.AES,
                                        128, 'mode')

        secret_dto = secret_store.SecretDTO(secret_store.SecretType.SYMMETRIC,
                                            utils.get_symmetric_key(),
                                            key_spec,
                                            'content_type',
                                            transport_key=None)
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.store_secret,
            secret_dto)

    # --------------- TEST GET -----------------------------------------------

    @utils.parameterized_dataset({
        'symmetric': [get_sample_symmetric_key(),
                      secret_store.SecretType.SYMMETRIC,
                      enums.ObjectType.SYMMETRIC_KEY,
                      misc.KeyFormatType(enums.KeyFormatType.RAW),
                      utils.get_symmetric_key(),
                      False],
        'hmac_sha1': [get_sample_symmetric_key(
                      algorithm=enums.CryptographicAlgorithm.HMAC_SHA1),
                      secret_store.SecretType.SYMMETRIC,
                      enums.ObjectType.SYMMETRIC_KEY,
                      misc.KeyFormatType(enums.KeyFormatType.RAW),
                      utils.get_symmetric_key(),
                      False],
        'hmac_sha256': [get_sample_symmetric_key(
                        algorithm=enums.CryptographicAlgorithm.HMAC_SHA256),
                        secret_store.SecretType.SYMMETRIC,
                        enums.ObjectType.SYMMETRIC_KEY,
                        misc.KeyFormatType(enums.KeyFormatType.RAW),
                        utils.get_symmetric_key(),
                        False],
        'hmac_sha384': [get_sample_symmetric_key(
                        algorithm=enums.CryptographicAlgorithm.HMAC_SHA384),
                        secret_store.SecretType.SYMMETRIC,
                        enums.ObjectType.SYMMETRIC_KEY,
                        misc.KeyFormatType(enums.KeyFormatType.RAW),
                        utils.get_symmetric_key(),
                        False],
        'hmac_sha512': [get_sample_symmetric_key(
                        algorithm=enums.CryptographicAlgorithm.HMAC_SHA512),
                        secret_store.SecretType.SYMMETRIC,
                        enums.ObjectType.SYMMETRIC_KEY,
                        misc.KeyFormatType(enums.KeyFormatType.RAW),
                        utils.get_symmetric_key(),
                        False],
        'triple_des': [get_sample_symmetric_key(
                       key_b64=utils.get_triple_des_key(),
                       key_length=192,
                       algorithm=enums.CryptographicAlgorithm.TRIPLE_DES),
                       secret_store.SecretType.SYMMETRIC,
                       enums.ObjectType.SYMMETRIC_KEY,
                       misc.KeyFormatType(enums.KeyFormatType.RAW),
                       utils.get_triple_des_key(),
                       False],
        'opaque': [get_sample_opaque_secret(),
                   secret_store.SecretType.OPAQUE,
                   enums.ObjectType.OPAQUE_DATA,
                   misc.KeyFormatType(enums.KeyFormatType.RAW),
                   utils.get_symmetric_key(),
                   False],
        'public_key': [get_sample_public_key(),
                       secret_store.SecretType.PUBLIC,
                       enums.ObjectType.PUBLIC_KEY,
                       misc.KeyFormatType(enums.KeyFormatType.X_509),
                       base64.b64encode(keys.get_public_key_pem()),
                       False],
        'public_key_pkcs1': [get_sample_public_key(pkcs1=True),
                             secret_store.SecretType.PUBLIC,
                             enums.ObjectType.PUBLIC_KEY,
                             misc.KeyFormatType(enums.KeyFormatType.PKCS_1),
                             base64.b64encode(keys.get_public_key_pem()),
                             True],
        'private_key': [get_sample_private_key(),
                        secret_store.SecretType.PRIVATE,
                        enums.ObjectType.PRIVATE_KEY,
                        misc.KeyFormatType(enums.KeyFormatType.PKCS_8),
                        base64.b64encode(keys.get_private_key_pem()),
                        False],
        'private_key_pkcs1': [get_sample_private_key(pkcs1=True),
                              secret_store.SecretType.PRIVATE,
                              enums.ObjectType.PRIVATE_KEY,
                              misc.KeyFormatType(enums.KeyFormatType.PKCS_1),
                              base64.b64encode(keys.get_private_key_pem()),
                              True],
        'certificate': [get_sample_certificate(),
                        secret_store.SecretType.CERTIFICATE,
                        enums.ObjectType.CERTIFICATE,
                        None,
                        base64.b64encode(keys.get_certificate_pem()),
                        False]
    })
    def test_get_secret(self, kmip_secret, secret_type, kmip_type,
                        key_format_type, expected_secret, pkcs1_only):
        self.secret_store.pkcs1_only = pkcs1_only
        self.secret_store.client.proxy.get = mock.MagicMock(
            proxy.KMIPProxy().get, return_value=results.GetResult(
                contents.ResultStatus(enums.ResultStatus.SUCCESS),
                object_type=attr.ObjectType(kmip_type),
                secret=kmip_secret))
        uuid = utils.generate_test_uuid(0)
        metadata = {kss.KMIPSecretStore.KEY_UUID: uuid}
        secret_dto = self.secret_store.get_secret(secret_type, metadata)

        self.secret_store.client.proxy.get.assert_called_once_with(uuid)
        self.assertEqual(secret_store.SecretDTO, type(secret_dto))
        self.assertEqual(secret_type, secret_dto.type)
        self.assertEqual(expected_secret, secret_dto.secret)

    def test_get_secret_symmetric_return_value_invalid_key_material_type(self):
        sample_secret = self.sample_secret
        sample_secret.key_block.key_value.key_material = 'invalid_type'
        self.secret_store.client.proxy.get = mock.MagicMock(
            proxy.KMIPProxy().get, return_value=results.GetResult(
                contents.ResultStatus(enums.ResultStatus.SUCCESS),
                object_type=attr.ObjectType(enums.ObjectType.SYMMETRIC_KEY),
                secret=sample_secret))

        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.get_secret,
            self.symmetric_type, metadata)

    def test_get_secret_symmetric_server_error_occurs(self):
        self.secret_store.client.proxy.get = mock.MagicMock(
            proxy.KMIPProxy().get, return_value=results.GetResult(
                contents.ResultStatus(enums.ResultStatus.OPERATION_FAILED)))
        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.get_secret,
            self.symmetric_type, metadata)

    def test_get_secret_symmetric_error_opening_connection(self):
        self.secret_store.client.proxy.open = mock.Mock(
            side_effect=socket.error)

        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.get_secret,
            self.symmetric_type, metadata)

    # ---------------- TEST DELETE -------------------------------------------

    def test_delete_with_null_metadata_values(self):
        metadata = {kss.KMIPSecretStore.KEY_UUID: None}
        self.assertIsNone(self.secret_store.delete_secret(metadata))

    def test_delete_secret_assert_called(self):
        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.secret_store.delete_secret(metadata)
        self.secret_store.client.proxy.destroy.assert_called_once_with(
            self.symmetric_key_uuid)

    def test_delete_secret_return_value(self):
        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        return_value = self.secret_store.delete_secret(metadata)
        self.assertIsNone(return_value)

    def test_delete_secret_server_error_occurs(self):
        self.secret_store.client.proxy.destroy = mock.MagicMock(
            proxy.KMIPProxy().destroy, return_value=results.DestroyResult(
                contents.ResultStatus(enums.ResultStatus.OPERATION_FAILED)))
        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.delete_secret,
            metadata)

    def test_delete_secret_error_opening_connection(self):
        self.secret_store.client.proxy.open = mock.Mock(
            side_effect=socket.error)
        metadata = {kss.KMIPSecretStore.KEY_UUID: self.symmetric_key_uuid}
        self.assertRaises(
            secret_store.SecretGeneralException,
            self.secret_store.delete_secret,
            metadata)

    # -------------- TEST HELPER FUNCTIONS -----------------------------------

    def test_credential(self):
        actual_credential = self.secret_store.credential

        self.assertEqual(
            enums.CredentialType.USERNAME_AND_PASSWORD.value,
            actual_credential.credential_type.value)
        self.assertEqual(
            self.expected_username,
            actual_credential.credential_value.username.value)
        self.assertEqual(
            self.expected_password,
            actual_credential.credential_value.password.value)

    def test_credential_None(self):
        CONF = kss.CONF
        CONF.kmip_plugin.username = None
        CONF.kmip_plugin.password = None
        CONF.kmip_plugin.keyfile = None

        secret_store = kss.KMIPSecretStore(CONF)
        self.assertIsNone(secret_store.credential)

    def test_map_type_ss_to_kmip_valid_type(self):
        ss_types = [secret_store.SecretType.SYMMETRIC,
                    secret_store.SecretType.PUBLIC,
                    secret_store.SecretType.PRIVATE]
        for ss_type in ss_types:
            self.assertIsNotNone(
                self.secret_store._map_type_ss_to_kmip(ss_type))

    def test_map_type_ss_to_kmip_invalid_type(self):
        object_type, key_format_type = (
            self.secret_store._map_type_ss_to_kmip('bad_type'))
        self.assertIsNone(object_type)
        self.assertIsNone(key_format_type)

    def test_validate_keyfile_permissions_good(self):
        config = {'return_value.st_mode':
                  (stat.S_IRUSR | stat.S_IFREG)}

        with mock.patch('os.stat', **config):
            self.assertIsNone(
                self.secret_store._validate_keyfile_permissions('/some/path/'))

    def test_check_keyfile_permissions_bad(self):
        config = {'return_value.st_mode':
                  (stat.S_IWOTH | stat.S_IFREG)}

        with mock.patch('os.stat', **config):
            self.assertRaises(
                kss.KMIPSecretStoreError,
                self.secret_store._validate_keyfile_permissions,
                '/some/path/')

    def test_checks_keyfile_permissions(self):
        config = {'return_value': True}
        func = ("barbican.plugin.kmip_secret_store."
                "KMIPSecretStore._validate_keyfile_permissions")

        with mock.patch(func, **config) as m:
            CONF = kss.CONF
            CONF.kmip_plugin.keyfile = '/some/path'
            kss.KMIPSecretStore(CONF)
            self.assertEqual(1, len(m.mock_calls))