def test_create_and_retrieve_base64_encoded_payload(self): # Validate base64-encoded encryption. payload = {'foo': 'bar'} secret_doc = self.factory.gen_test( 'Certificate', 'encrypted', payload) expected_payload = base64.encode_as_text(six.text_type({'foo': 'bar'})) expected_kwargs = { 'name': secret_doc['metadata']['name'], 'secret_type': 'opaque', 'payload': expected_payload } self._mock_barbican_client_call(payload) secret_ref = secrets_manager.SecretsManager.create(secret_doc) self.assertEqual(self.secret_ref, secret_ref) self.assertEqual('encrypted', secret_doc['metadata']['storagePolicy']) self.mock_barbicanclient.call.assert_called_once_with( "secrets.create", **expected_kwargs) # Validate base64-encoded decryption. self.mock_barbicanclient.get_secret.return_value = ( mock.Mock(payload=expected_payload, secret_type='opaque')) dummy_document = document_wrapper.DocumentDict({}) retrieved_payload = secrets_manager.SecretsManager.get( secret_ref, dummy_document) self.assertEqual(payload, retrieved_payload)
def __init__(self, documents, existing_data_schemas=None, pre_validate=True): """Class for document validation logic for documents. This class is responsible for validating documents according to their schema. If ``pre_validate`` is true, then: * the base_schema validates ALL documents * ALL built-in schemas validate the appropriate document given a schema match * NO externally registered DataSchema documents are used for validation Else: * the base_schema validates ALL documents * ALL built-in schemas validate the appropriate document given a schema match * ALL externally registered DataSchema documents are used for validation given a schema match :param documents: Documents to be validated. :type documents: List[dict] :param existing_data_schemas: ``DataSchema`` documents created in prior revisions to be used to validate the "data" section of each document in ``documents``. Additional ``DataSchema`` documents in ``documents`` are combined with these. :type existing_data_schemas: dict or List[dict] :param pre_validate: Whether to pre-validate documents using built-in schema validation. Skips over externally registered ``DataSchema`` documents to avoid false positives. Default is True. :type pre_validate: bool """ self._documents = [] self._current_data_schemas = [ document_wrapper.DocumentDict(d) for d in existing_data_schemas or [] ] data_schema_map = {d.meta: d for d in self._current_data_schemas} raw_properties = ('data', 'metadata', 'schema') if not isinstance(documents, list): documents = [documents] for document in documents: # For post-validation documents are retrieved from the DB so those # DB properties need to be stripped to avoid validation errors. raw_document = {} for prop in raw_properties: raw_document[prop] = document.get(prop) document = document_wrapper.DocumentDict(raw_document) if document.schema.startswith(types.DATA_SCHEMA_SCHEMA): self._current_data_schemas.append(document) # If a newer version of the same DataSchema was passed in, # only use the new one and discard the old one. if document.meta in data_schema_map: self._current_data_schemas.remove( data_schema_map.pop(document.meta)) self._documents.append(document) self._pre_validate = pre_validate self._validators = [ DataSchemaValidator(self._current_data_schemas), ] if self._pre_validate: # Only perform this additional validation "offline". The controller # need not call this as the db module will handle this validation. self._validators.append(DuplicateDocumentValidator())
def test_rendered_documents_validation_message_formatting(self): """Verify formatting for post-validation during rendering revision documents. """ rules = { 'deckhand:create_cleartext_documents': '@', 'deckhand:list_cleartext_documents': '@', 'deckhand:list_encrypted_documents': '@' } self.policy.set_rules(rules) yaml_file = os.path.join(os.getcwd(), 'deckhand', 'tests', 'unit', 'resources', 'sample_layering_policy.yaml') with open(yaml_file) as yaml_stream: payload = yaml_stream.read() resp = self.app.simulate_put( '/api/v1.0/buckets/test/documents', headers={'Content-Type': 'application/x-yaml'}, body=payload) with mock.patch('deckhand.control.revision_documents.db_api' '.revision_documents_get', autospec=True) \ as mock_get_rev_documents: invalid_document = document_wrapper.DocumentDict( yaml.safe_load(payload)) invalid_document.pop('metadata') mock_get_rev_documents.return_value = [invalid_document] resp = self.app.simulate_get( '/api/v1.0/revisions/1/rendered-documents', headers={'Content-Type': 'application/x-yaml'}) expected = { 'status': 'Failure', 'kind': 'Status', 'code': '500 Internal Server Error', 'apiVersion': 'v1.0', 'reason': 'Validation', 'retry': True, 'details': { 'errorType': 'InvalidDocumentFormat', 'errorCount': 1, 'messageList': [{ 'diagnostic': mock.ANY, 'documents': [{ 'layer': '', 'name': '', 'schema': invalid_document['schema'] }], 'error': True, 'kind': 'ValidationMessage', 'level': 'Error', 'message': mock.ANY, # Indicates sanity-check failure post-rendering. 'name': 'D001' }] }, 'message': 'The provided documents failed schema validation.', 'metadata': {} } body = yaml.safe_load(resp.text) self.assertEqual(500, resp.status_code) self.assertEqual(expected, body)