Example #1
0
    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)
Example #2
0
    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())
Example #3
0
    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)