def test_register_on_operation_failure(self): """ Test that a KmipOperationFailure exception is raised when the backend fails to register a key. """ status = enums.ResultStatus.OPERATION_FAILED reason = enums.ResultReason.GENERAL_FAILURE message = "Test failure message" result = results.OperationResult(contents.ResultStatus(status), contents.ResultReason(reason), contents.ResultMessage(message)) error_msg = str(KmipOperationFailure(status, reason, message)) # Key encoding obtained from Section 14.2 of the KMIP 1.1 test # documentation. key_value = ( b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E' b'\x0F') key = objects.SymmetricKey(enums.CryptographicAlgorithm.AES, 128, key_value) client = ProxyKmipClient() client.open() client.proxy.register.return_value = result args = [key] self.assertRaisesRegexp(KmipOperationFailure, error_msg, client.register, *args)
def test_mac_on_operation_failure(self): """ Test that a KmipOperationFailure exception is raised when the backend fails to generate MAC. """ uuid = 'aaaaaaaa-1111-2222-3333-ffffffffffff' algorithm = enums.CryptographicAlgorithm.HMAC_SHA256 data = (b'\x00\x01\x02\x03\x04') status = enums.ResultStatus.OPERATION_FAILED reason = enums.ResultReason.GENERAL_FAILURE message = "Test failure message" result = results.OperationResult(contents.ResultStatus(status), contents.ResultReason(reason), contents.ResultMessage(message)) error_msg = str(KmipOperationFailure(status, reason, message)) client = ProxyKmipClient() client.open() client.proxy.mac.return_value = result args = [uuid, algorithm, data] self.assertRaisesRegexp(KmipOperationFailure, error_msg, client.mac, *args)
def test_handle_message_loop(self, request_mock): """ Test that the correct logging and error handling occurs during the message handling loop. """ data = utils.BytearrayStream() # Build a response and use it as a dummy processing result. batch_item = messages.ResponseBatchItem( result_status=contents.ResultStatus(enums.ResultStatus.SUCCESS), result_reason=contents.ResultReason( enums.ResultReason.OBJECT_ARCHIVED), result_message=contents.ResultMessage("Test message.")) batch_items = [batch_item] header = messages.ResponseHeader( protocol_version=contents.ProtocolVersion(1, 0), time_stamp=contents.TimeStamp(int(time.time())), batch_count=contents.BatchCount(len(batch_items))) message = messages.ResponseMessage(response_header=header, batch_items=batch_items) kmip_engine = engine.KmipEngine() kmip_engine._logger = mock.MagicMock() kmip_session = session.KmipSession(kmip_engine, None, 'name') kmip_session._engine = mock.MagicMock() kmip_session._get_client_identity = mock.MagicMock() kmip_session._get_client_identity.return_value = 'test' kmip_session._engine.process_request = mock.MagicMock( return_value=(message, kmip_session._max_response_size)) kmip_session._logger = mock.MagicMock() kmip_session._connection = mock.MagicMock() kmip_session._connection.shared_ciphers = mock.MagicMock( return_value=[('AES128-SHA256', 'TLSv1/SSLv3', 128), ('AES256-SHA256', 'TLSv1/SSLv3', 256)]) kmip_session._connection.cipher = mock.MagicMock( return_value=('AES128-SHA256', 'TLSv1/SSLv3', 128)) kmip_session._receive_request = mock.MagicMock(return_value=data) kmip_session._send_response = mock.MagicMock() kmip_session._handle_message_loop() kmip_session._receive_request.assert_called_once_with() kmip_session._logger.info.assert_not_called() kmip_session._logger.debug.assert_any_call( "Possible session ciphers: 2") kmip_session._logger.debug.assert_any_call( ('AES128-SHA256', 'TLSv1/SSLv3', 128)) kmip_session._logger.debug.assert_any_call( ('AES256-SHA256', 'TLSv1/SSLv3', 256)) kmip_session._logger.debug.assert_any_call( "Session cipher selected: {0}".format( ('AES128-SHA256', 'TLSv1/SSLv3', 128))) kmip_session._logger.warning.assert_not_called() kmip_session._logger.exception.assert_not_called() self.assertTrue(kmip_session._send_response.called)
def read(self, istream, kmip_version=enums.KMIPVersion.KMIP_1_0): super(ResponseBatchItem, self).read( istream, kmip_version=kmip_version ) tstream = BytearrayStream(istream.read(self.length)) # Read the batch item operation if it is present if self.is_tag_next(Tags.OPERATION, tstream): self.operation = contents.Operation() self.operation.read(tstream, kmip_version=kmip_version) # Read the unique batch item ID if it is present if self.is_tag_next(Tags.UNIQUE_BATCH_ITEM_ID, tstream): self.unique_batch_item_id = contents.UniqueBatchItemID() self.unique_batch_item_id.read(tstream, kmip_version=kmip_version) # Read the batch item result status self.result_status = contents.ResultStatus() self.result_status.read(tstream, kmip_version=kmip_version) # Read the batch item result reason if it is present if self.is_tag_next(Tags.RESULT_REASON, tstream): self.result_reason = contents.ResultReason() self.result_reason.read(tstream, kmip_version=kmip_version) # Read the batch item result message if it is present if self.is_tag_next(Tags.RESULT_MESSAGE, tstream): self.result_message = contents.ResultMessage() self.result_message.read(tstream, kmip_version=kmip_version) # Read the batch item asynchronous correlation value if it is present if self.is_tag_next(Tags.ASYNCHRONOUS_CORRELATION_VALUE, tstream): self.async_correlation_value = AsynchronousCorrelationValue() self.async_correlation_value.read( tstream, kmip_version=kmip_version ) if (self.operation is not None): # Dynamically create the response payload class that belongs to the # operation expected = self.payload_factory.create(self.operation.value) if self.is_tag_next(expected.tag, tstream): self.response_payload = expected self.response_payload.read(tstream, kmip_version=kmip_version) # Read the message extension if it is present if self.is_tag_next(Tags.MESSAGE_EXTENSION, tstream): self.message_extension = contents.MessageExtension() self.message_extension.read(tstream, kmip_version=kmip_version) self.is_oversized(tstream) self.validate()
def test_destroy_on_operation_failure(self): """ Test that a KmipOperationFailure exception is raised when the backend fails to destroy a secret. """ status = enums.ResultStatus.OPERATION_FAILED reason = enums.ResultReason.GENERAL_FAILURE message = "Test failure message" result = results.OperationResult(contents.ResultStatus(status), contents.ResultReason(reason), contents.ResultMessage(message)) error_msg = str(KmipOperationFailure(status, reason, message)) client = ProxyKmipClient() client.open() client.proxy.destroy.return_value = result args = ['id'] self.assertRaisesRegexp(KmipOperationFailure, error_msg, client.destroy, *args)
def test_get_attribute_list_on_operation_failure(self): """ Test that a KmipOperationFailure exception is raised when the backend fails to retrieve the attribute names of a managed object. """ status = enums.ResultStatus.OPERATION_FAILED reason = enums.ResultReason.GENERAL_FAILURE message = "Test failure message" result = results.OperationResult(contents.ResultStatus(status), contents.ResultReason(reason), contents.ResultMessage(message)) error_msg = str(KmipOperationFailure(status, reason, message)) client = ProxyKmipClient() client.open() client.proxy.get_attribute_list.return_value = result args = ['id'] self.assertRaisesRegexp(KmipOperationFailure, error_msg, client.get_attribute_list, *args)
def test_create_key_pair_on_operation_failure(self): """ Test that a KmipOperationFailure exception is raised when the backend fails to create an asymmetric key pair. """ status = enums.ResultStatus.OPERATION_FAILED reason = enums.ResultReason.GENERAL_FAILURE message = "Test failure message" result = results.OperationResult(contents.ResultStatus(status), contents.ResultReason(reason), contents.ResultMessage(message)) error_msg = str(KmipOperationFailure(status, reason, message)) client = ProxyKmipClient() client.open() client.proxy.create_key_pair.return_value = result args = [enums.CryptographicAlgorithm.RSA, 2048] self.assertRaisesRegexp(KmipOperationFailure, error_msg, client.create_key_pair, *args)
def test_handle_message_loop(self, request_mock): """ Test that the correct logging and error handling occurs during the message handling loop. """ data = utils.BytearrayStream() # Build a response and use it as a dummy processing result. batch_item = messages.ResponseBatchItem( result_status=contents.ResultStatus(enums.ResultStatus.SUCCESS), result_reason=contents.ResultReason( enums.ResultReason.OBJECT_ARCHIVED), result_message=contents.ResultMessage("Test message.")) batch_items = [batch_item] header = messages.ResponseHeader( protocol_version=contents.ProtocolVersion.create(1, 0), time_stamp=contents.TimeStamp(int(time.time())), batch_count=contents.BatchCount(len(batch_items))) message = messages.ResponseMessage(response_header=header, batch_items=batch_items) kmip_engine = engine.KmipEngine() kmip_engine._logger = mock.MagicMock() kmip_session = session.KmipSession(kmip_engine, None, 'name') kmip_session._engine = mock.MagicMock() kmip_session._engine.process_request = mock.MagicMock( return_value=(message, kmip_session._max_response_size)) kmip_session._logger = mock.MagicMock() kmip_session._connection = mock.MagicMock() kmip_session._receive_request = mock.MagicMock(return_value=data) kmip_session._send_response = mock.MagicMock() kmip_session._handle_message_loop() kmip_session._receive_request.assert_called_once_with() kmip_session._logger.info.assert_not_called() kmip_session._logger.warning.assert_not_called() kmip_session._logger.exception.assert_not_called() self.assertTrue(kmip_session._send_response.called)
def build_error_response(self, version, reason, message): """ Build a simple ResponseMessage with a single error result. Args: version (ProtocolVersion): The protocol version the response should be addressed with. reason (ResultReason): An enumeration classifying the type of error occurred. message (str): A string providing additional information about the error. Returns: ResponseMessage: The simple ResponseMessage containing a single error result. """ batch_item = messages.ResponseBatchItem( result_status=contents.ResultStatus( enums.ResultStatus.OPERATION_FAILED), result_reason=contents.ResultReason(reason), result_message=contents.ResultMessage(message)) return self._build_response(version, [batch_item])
def _process_batch(self, request_batch, batch_handling, batch_order): response_batch = list() self._data_session = self._data_store_session_factory() for batch_item in request_batch: error_occurred = False response_payload = None result_status = None result_reason = None result_message = None operation = batch_item.operation request_payload = batch_item.request_payload # Process batch item ID. if len(request_batch) > 1: if not batch_item.unique_batch_item_id: raise exceptions.InvalidMessage( "Batch item ID is undefined.") # Process batch message extension. # TODO (peterhamilton) Add support for message extension handling. # 1. Extract the vendor identification and criticality indicator. # 2. If the indicator is True, raise an error. # 3. If the indicator is False, ignore the extension. # Process batch payload. try: response_payload = self._process_operation( operation.value, request_payload) result_status = enums.ResultStatus.SUCCESS except exceptions.KmipError as e: error_occurred = True result_status = e.status result_reason = e.reason result_message = str(e) except Exception as e: self._logger.warning( "Error occurred while processing operation.") self._logger.exception(e) error_occurred = True result_status = enums.ResultStatus.OPERATION_FAILED result_reason = enums.ResultReason.GENERAL_FAILURE result_message = ( "Operation failed. See the server logs for more " "information.") # Compose operation result. result_status = contents.ResultStatus(result_status) if result_reason: result_reason = contents.ResultReason(result_reason) if result_message: result_message = contents.ResultMessage(result_message) batch_item = messages.ResponseBatchItem( operation=batch_item.operation, unique_batch_item_id=batch_item.unique_batch_item_id, result_status=result_status, result_reason=result_reason, result_message=result_message, response_payload=response_payload) response_batch.append(batch_item) # Handle batch error if necessary. if error_occurred: if batch_handling == enums.BatchErrorContinuationOption.STOP: break return response_batch