def update_certificate(self, certificate_secret_ref): pem = keys.get_certificate_pem() resp = self.secret_behaviors.update_secret_payload( certificate_secret_ref, pem, 'application/octet-stream') self.assertEqual(204, resp.status_code)
def get_certificate_dto(): spec = secret_store.KeySpec(secret_store.KeyAlgorithm.RSA, 2048) return secret_store.SecretDTO(secret_store.SecretType.CERTIFICATE, base64.b64encode( keys.get_certificate_pem()), spec, 'application/pkix-cert')
def test_passes_certificate_conversion(self): pem = keys.get_certificate_pem() der = translations.convert_pem_to_der( pem, s.SecretType.CERTIFICATE) converted_pem = translations.convert_der_to_pem( der, s.SecretType.CERTIFICATE) self.assertEqual(pem, converted_pem)
def store_certificate(self): pem = keys.get_certificate_pem() test_model = secret_models.SecretModel( **get_certificate_req(base64.b64encode(pem))) resp, certificate_secret_ref = self.secret_behaviors.create_secret( test_model) self.assertEqual(201, resp.status_code) return certificate_secret_ref
def get_certificate_req(): return {'name': 'mycertificate', 'payload_content_type': 'application/pkix-cert', 'payload_content_encoding': 'base64', 'algorithm': 'rsa', 'bit_length': 2048, 'secret_type': 'certificate', 'payload': base64.b64encode(keys.get_certificate_pem())}
def get_certificate_req(): return { "name": "mycertificate", "payload_content_type": "application/octet-stream", "payload_content_encoding": "base64", "algorithm": "rsa", "bit_length": 2048, "secret_type": "certificate", "payload": base64.b64encode(keys.get_certificate_pem()), }
def get_certificate_req(): return { 'name': 'mycertificate', 'payload_content_type': 'application/pkix-cert', 'payload_content_encoding': 'base64', 'algorithm': 'rsa', 'bit_length': 2048, 'secret_type': 'certificate', 'payload': base64.b64encode(keys.get_certificate_pem()) }
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)
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)
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_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(keys.get_certificate_der(), actual_secret.certificate_value.value)
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( keys.get_certificate_der(), actual_secret.certificate_value.value)
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)
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.register.assert_called_once_with( object_type=enums.ObjectType.CERTIFICATE, template_attribute=mock.ANY, secret=mock.ANY, credential=self.credential) _, register_call_kwargs = self.secret_store.client.register.call_args actual_secret = register_call_kwargs.get('secret') 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_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)
def _process_approved_profile_request(self, order_meta, plugin_meta): enrollment_result = dogtag_cert.CertEnrollmentResult( self.request, self.cert) enrollment_results = [enrollment_result] self.certclient_mock.enroll_cert.return_value = enrollment_results result_dto = self.plugin.issue_certificate_request( self.order_id, order_meta, plugin_meta, self.barbican_meta_dto) self.certclient_mock.enroll_cert.assert_called_once_with( self.approved_profile_id, order_meta) self.assertEqual(cm.CertificateStatus.CERTIFICATE_GENERATED, result_dto.status, "result_dto status incorrect") self.assertEqual(base64.b64encode(keys.get_certificate_pem()), result_dto.certificate) self.assertEqual( self.request_id_mock, plugin_meta.get(dogtag_import.DogtagCAPlugin.REQUEST_ID))
def test_check_status(self): order_meta = mock.ANY plugin_meta = { dogtag_import.DogtagCAPlugin.REQUEST_ID: self.request_id_mock } self.certclient_mock.get_request.return_value = self.request self.certclient_mock.get_cert.return_value = self.cert result_dto = self.plugin.check_certificate_status( self.order_id, order_meta, plugin_meta, self.barbican_meta_dto) self.certclient_mock.get_request.assert_called_once_with( self.request_id_mock) self.certclient_mock.get_cert.assert_called_once_with( self.cert_id_mock) self.assertEqual(cm.CertificateStatus.CERTIFICATE_GENERATED, result_dto.status, "result_dto_status incorrect") self.assertEqual(keys.get_certificate_pem(), result_dto.certificate)
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.register.assert_called_once_with( object_type=enums.ObjectType.CERTIFICATE, template_attribute=mock.ANY, secret=mock.ANY, credential=self.credential) _, register_call_kwargs = self.secret_store.client.register.call_args actual_secret = register_call_kwargs.get('secret') 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_check_status(self): order_meta = mock.ANY plugin_meta = {dogtag_import.DogtagCAPlugin.REQUEST_ID: self.request_id_mock} self.certclient_mock.get_request.return_value = self.request self.certclient_mock.get_cert.return_value = self.cert result_dto = self.plugin.check_certificate_status( self.order_id, order_meta, plugin_meta, self.barbican_meta_dto) self.certclient_mock.get_request.assert_called_once_with( self.request_id_mock) self.certclient_mock.get_cert.assert_called_once_with( self.cert_id_mock) self.assertEqual(cm.CertificateStatus.CERTIFICATE_GENERATED, result_dto.status, "result_dto_status incorrect") self.assertEqual(keys.get_certificate_pem(), result_dto.certificate)
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)
def _process_approved_profile_request(self, order_meta, plugin_meta): enrollment_result = dogtag_cert.CertEnrollmentResult( self.request, self.cert) enrollment_results = [enrollment_result] self.certclient_mock.enroll_cert.return_value = enrollment_results result_dto = self.plugin.issue_certificate_request( self.order_id, order_meta, plugin_meta, self.barbican_meta_dto) self.certclient_mock.enroll_cert.assert_called_once_with( self.approved_profile_id, order_meta) self.assertEqual(cm.CertificateStatus.CERTIFICATE_GENERATED, result_dto.status, "result_dto status incorrect") self.assertEqual(base64.b64encode(keys.get_certificate_pem()), result_dto.certificate) self.assertEqual( self.request_id_mock, plugin_meta.get(dogtag_import.DogtagCAPlugin.REQUEST_ID) )
def setUp(self): super(WhenTestingDogtagCAPlugin, self).setUp() self.certclient_mock = mock.MagicMock(name="CertClient mock") self.patcher = mock.patch('pki.crypto.NSSCryptoProvider') self.patcher2 = mock.patch('pki.client.PKIConnection') self.patcher.start() self.patcher2.start() # create nss db for test only self.nss_dir = tempfile.mkdtemp() # create expiration file for test fh, self.expiration_data_path = tempfile.mkstemp() exp_time = datetime.datetime.utcnow() + datetime.timedelta(days=2) os.write(fh, exp_time.strftime( "%Y-%m-%d %H:%M:%S.%f")) os.close(fh) # create host CA file for test fh, self.host_ca_path = tempfile.mkstemp() os.write(fh, "host_ca_aid") os.close(fh) self.approved_profile_id = "caServerCert" CONF = dogtag_import.CONF CONF.dogtag_plugin.nss_db_path = self.nss_dir CONF.dogtag_plugin.ca_expiration_data_path = self.expiration_data_path CONF.dogtag_plugin.ca_host_aid_path = self.host_ca_path CONF.dogtag_plugin.auto_approved_profiles = [self.approved_profile_id] CONF.dogtag_plugin.dogtag_host = "localhost" CONF.dogtag_plugin.dogtag_port = "8443" CONF.dogtag_plugin.simple_cmc_profile = "caOtherCert" self.cfg = CONF self.plugin = dogtag_import.DogtagCAPlugin(CONF) self.plugin.certclient = self.certclient_mock self.order_id = mock.MagicMock() self.profile_id = mock.MagicMock() # request generated self.request_id_mock = mock.MagicMock() self.request = dogtag_cert.CertRequestInfo() self.request.request_id = self.request_id_mock self.request.request_status = dogtag_cert.CertRequestStatus.COMPLETE self.cert_id_mock = mock.MagicMock() self.request.cert_id = self.cert_id_mock # cert generated self.cert = mock.MagicMock() self.cert.encoded = keys.get_certificate_pem() self.cert.pkcs7_cert_chain = keys.get_certificate_der() # for cancel/modify self.review_response = mock.MagicMock() # modified request self.modified_request = mock.MagicMock() self.modified_request_id_mock = mock.MagicMock() self.modified_request.request_id = self.modified_request_id_mock self.modified_request.request_status = ( dogtag_cert.CertRequestStatus.COMPLETE) self.modified_request.cert_id = self.cert_id_mock self.barbican_meta_dto = cm.BarbicanMetaDTO()
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())
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)
def test_passes_convert_certificate_pem_to_der(self): pem = keys.get_certificate_pem() expected_der = keys.get_certificate_der() der = translations.convert_pem_to_der(pem, s.SecretType.CERTIFICATE) self.assertEqual(expected_der, der)
def test_passes_convert_certificate_der_to_pem(self): der = keys.get_certificate_der() expected_pem = keys.get_certificate_pem() pem = translations.convert_der_to_pem(der, s.SecretType.CERTIFICATE) self.assertEqual(expected_pem, pem)
def verify_certificate_equal(self, retrieved_certificate): pem = keys.get_certificate_pem() self.assertEqual(pem, retrieved_certificate)
def test_passes_certificate_conversion(self): pem = keys.get_certificate_pem() der = translations.convert_pem_to_der(pem, s.SecretType.CERTIFICATE) converted_pem = translations.convert_der_to_pem( der, s.SecretType.CERTIFICATE) self.assertEqual(pem, converted_pem)
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)
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))
def test_passes_convert_certificate_der_to_pem(self): der = keys.get_certificate_der() expected_pem = keys.get_certificate_pem() pem = translations.convert_der_to_pem( der, s.SecretType.CERTIFICATE) self.assertEqual(expected_pem, pem)
def test_passes_convert_certificate_pem_to_der(self): pem = keys.get_certificate_pem() expected_der = keys.get_certificate_der() der = translations.convert_pem_to_der( pem, s.SecretType.CERTIFICATE) self.assertEqual(expected_der, der)
def setUp(self): super(WhenTestingDogtagCAPlugin, self).setUp() self.certclient_mock = mock.MagicMock(name="CertClient mock") self.patcher = mock.patch('pki.crypto.NSSCryptoProvider') self.patcher2 = mock.patch('pki.client.PKIConnection') self.patcher.start() self.patcher2.start() # create nss db for test only self.nss_dir = tempfile.mkdtemp() # create expiration file for test fh, self.expiration_data_path = tempfile.mkstemp() exp_time = datetime.datetime.utcnow() + datetime.timedelta(days=2) os.write(fh, exp_time.strftime( "%Y-%m-%d %H:%M:%S.%f")) os.close(fh) # create host CA file for test fh, self.host_ca_path = tempfile.mkstemp() os.write(fh, "host_ca_aid") os.close(fh) self.approved_profile_id = "caServerCert" CONF = dogtag_import.CONF CONF.dogtag_plugin.nss_db_path = self.nss_dir CONF.dogtag_plugin.ca_expiration_data_path = self.expiration_data_path CONF.dogtag_plugin.ca_host_aid_path = self.host_ca_path CONF.dogtag_plugin.auto_approved_profiles = [self.approved_profile_id] CONF.dogtag_plugin.dogtag_host = "localhost" CONF.dogtag_plugin.dogtag_port = 8443 CONF.dogtag_plugin.simple_cmc_profile = "caOtherCert" self.cfg = CONF self.plugin = dogtag_import.DogtagCAPlugin(CONF) self.plugin.certclient = self.certclient_mock self.order_id = mock.MagicMock() self.profile_id = mock.MagicMock() # request generated self.request_id_mock = mock.MagicMock() self.request = dogtag_cert.CertRequestInfo() self.request.request_id = self.request_id_mock self.request.request_status = dogtag_cert.CertRequestStatus.COMPLETE self.cert_id_mock = mock.MagicMock() self.request.cert_id = self.cert_id_mock # cert generated self.cert = mock.MagicMock() self.cert.encoded = keys.get_certificate_pem() self.cert.pkcs7_cert_chain = keys.get_certificate_der() # for cancel/modify self.review_response = mock.MagicMock() # modified request self.modified_request = mock.MagicMock() self.modified_request_id_mock = mock.MagicMock() self.modified_request.request_id = self.modified_request_id_mock self.modified_request.request_status = ( dogtag_cert.CertRequestStatus.COMPLETE) self.modified_request.cert_id = self.cert_id_mock self.barbican_meta_dto = cm.BarbicanMetaDTO()