コード例 #1
0
ファイル: driver.py プロジェクト: airshipit/deckhand
    def _base64_encode_payload(self, secret_doc):
        """Ensures secret document payload is compatible with Barbican."""

        payload = secret_doc.data
        secret_type = None
        # Explicitly list the "empty" payloads we are refusing to store.
        # We don't use ``if not payload`` because that would not encrypt
        # and store something like ``data: !!int 0``
        if payload in ('', {}, [], None):
            # There is no point in even bothering to encrypt an empty
            # body, which just leads to needless overhead, so return
            # early.
            LOG.info('Barbican does not accept empty payloads so '
                     'Deckhand will not encrypt document [%s, %s] %s.',
                     secret_doc.schema, secret_doc.layer, secret_doc.name)
            secret_doc.storage_policy = types.CLEARTEXT
        else:
            LOG.debug('Setting secret_type=opaque and '
                      'base64-encoding payload of type %s for '
                      'document [%s, %s] %s.', type(payload),
                      secret_doc.schema, secret_doc.layer, secret_doc.name)
            secret_type = 'opaque'  # nosec  # not a hardcoded password
            try:
                payload = base64.encode_as_text(repr(payload))
            except Exception:
                message = ('Failed to base64-encode payload of type %s '
                           'for Barbican storage.', type(payload))
                LOG.error(message)
                raise errors.UnknownSubstitutionError(
                    src_schema=secret_doc.schema,
                    src_layer=secret_doc.layer, src_name=secret_doc.name,
                    schema='N/A', layer='N/A', name='N/A', details=message)
        return secret_type, payload
コード例 #2
0
ファイル: secrets_manager.py プロジェクト: airshipit/deckhand
 def _handle_unknown_substitution_exc(self, exc_message, src_doc, dest_doc):
     if self._fail_on_missing_sub_src:
         LOG.error(exc_message)
         raise errors.UnknownSubstitutionError(
             src_schema=src_doc.schema, src_layer=src_doc.layer,
             src_name=src_doc.name, schema=dest_doc.schema,
             layer=dest_doc.layer, name=dest_doc.name, details=exc_message)
     else:
         LOG.warning(exc_message)
コード例 #3
0
ファイル: driver.py プロジェクト: daaser/deckhand
    def _base64_encode_payload(self, secret_doc):
        """Ensures secret document payload is compatible with Barbican."""

        payload = secret_doc.data
        secret_type = self._get_secret_type(secret_doc.schema)

        # NOTE(felipemonteiro): The logic for the 2 conditions below is
        # enforced from Barbican's Python client. Some pre-processing and
        # transformation is needed to make Barbican work with non-compatible
        # formats.
        if not payload and payload is not False:
            # There is no point in even bothering to encrypt an empty
            # body, which just leads to needless overhead, so return
            # early.
            LOG.info(
                'Barbican does not accept empty payloads so '
                'Deckhand will not encrypt document [%s, %s] %s.',
                secret_doc.schema, secret_doc.layer, secret_doc.name)
            secret_doc.storage_policy = types.CLEARTEXT
        elif not isinstance(payload, (six.text_type, six.binary_type)):
            LOG.debug(
                'Forcibly setting secret_type=opaque and '
                'base64-encoding non-string payload for '
                'document [%s, %s] %s.', secret_doc.schema, secret_doc.layer,
                secret_doc.name)
            # NOTE(felipemonteiro): base64-encoding the non-string payload is
            # done for serialization purposes, not for security purposes.
            # 'opaque' is used to avoid Barbican doing any further
            # serialization server-side.
            secret_type = 'opaque'
            try:
                payload = base64.encode_as_text(six.text_type(payload))
            except Exception:
                message = ('Failed to base64-encode payload of type %s '
                           'for Barbican storage.', type(payload))
                LOG.error(message)
                raise errors.UnknownSubstitutionError(
                    src_schema=secret_doc.schema,
                    src_layer=secret_doc.layer,
                    src_name=secret_doc.name,
                    schema='N/A',
                    layer='N/A',
                    name='N/A',
                    details=message)
        return secret_type, payload
コード例 #4
0
    def substitute_all(self, documents):
        """Substitute all documents that have a `metadata.substitutions` field.

        Concrete (non-abstract) documents can be used as a source of
        substitution into other documents. This substitution is
        layer-independent, a document in the region layer could insert data
        from a document in the site layer.

        :param documents: List of documents that are candidates for
            substitution.
        :type documents: dict or List[dict]
        :returns: List of fully substituted documents.
        :rtype: Generator[:class:`DocumentDict`]
        :raises SubstitutionSourceNotFound: If a substitution source document
            is referenced by another document but wasn't found.
        :raises UnknownSubstitutionError: If an unknown error occurred during
            substitution.
        """

        documents_to_substitute = []
        if not isinstance(documents, list):
            documents = [documents]

        for document in documents:
            if not isinstance(document, document_wrapper.DocumentDict):
                document = document_wrapper.DocumentDict(document)
            # If the document has substitutions include it.
            if document.substitutions:
                documents_to_substitute.append(document)

        LOG.debug(
            'Performing substitution on following documents: %s', ', '.join([
                '[%s] %s' % (d.schema, d.name) for d in documents_to_substitute
            ]))

        for document in documents_to_substitute:
            LOG.debug('Checking for substitutions for document [%s] %s.',
                      document.schema, document.name)
            for sub in document.substitutions:
                src_schema = sub['src']['schema']
                src_name = sub['src']['name']
                src_path = sub['src']['path']

                if (src_schema, src_name) in self._substitution_sources:
                    src_doc = self._substitution_sources[(src_schema,
                                                          src_name)]
                else:
                    message = ('Could not find substitution source document '
                               '[%s] %s among the provided '
                               '`substitution_sources`.', src_schema, src_name)
                    LOG.error(message)
                    raise errors.SubstitutionSourceNotFound(
                        src_schema=src_schema,
                        src_name=src_name,
                        document_schema=document.schema,
                        document_name=document.name)

                # If the data is a dictionary, retrieve the nested secret
                # via jsonpath_parse, else the secret is the primitive/string
                # stored in the data section itself.
                if isinstance(src_doc.get('data'), dict):
                    src_secret = utils.jsonpath_parse(src_doc.get('data', {}),
                                                      src_path)
                else:
                    src_secret = src_doc.get('data')

                dest_path = sub['dest']['path']
                dest_pattern = sub['dest'].get('pattern', None)

                LOG.debug(
                    'Substituting from schema=%s name=%s src_path=%s '
                    'into dest_path=%s, dest_pattern=%s', src_schema, src_name,
                    src_path, dest_path, dest_pattern)
                try:
                    substituted_data = utils.jsonpath_replace(
                        document['data'], src_secret, dest_path, dest_pattern)
                    sub_source = self._substitution_sources.get(
                        (document.schema, document.name))
                    if (isinstance(document['data'], dict)
                            and isinstance(substituted_data, dict)):
                        document['data'].update(substituted_data)
                        if sub_source:
                            sub_source['data'].update(substituted_data)
                    elif substituted_data:
                        document['data'] = substituted_data
                        if sub_source:
                            sub_source['data'] = substituted_data
                    else:
                        message = ('Failed to create JSON path "%s" in the '
                                   'destination document [%s] %s. No data was '
                                   'substituted.', dest_path, document.schema,
                                   document.name)
                        LOG.error(message)
                        raise errors.UnknownSubstitutionError(details=message)
                except Exception as e:
                    LOG.error(
                        'Unexpected exception occurred while attempting '
                        'secret substitution. %s', six.text_type(e))
                    raise errors.UnknownSubstitutionError(
                        details=six.text_type(e))

        yield document