Beispiel #1
0
def get_trusted_digest(host: str, image: Image, policy_rule: dict):
    """
    Searches in given notary server(`host`) for trust data, that belongs to the
    given `image`, by using the notary API. Also checks whether the given
    `policy_rule` complies.

    Returns the signed digest, belonging to the `image` or throws if validation fails.
    """
    # prepend `targets/` to the required delegation roles, if not already present
    req_delegations = list(
        map(normalize_delegation, policy_rule.get("delegations", []))
    )

    # get list of targets fields, containing tag to signed digest mapping from
    # `targets.json` and all potential delegation roles
    signed_image_targets = process_chain_of_trust(host, image, req_delegations)

    # search for digests or tag, depending on given image
    search_image_targets = (
        search_image_targets_for_digest
        if image.has_digest()
        else search_image_targets_for_tag
    )

    # filter out the searched for digests, if present
    digests = list(map(lambda x: search_image_targets(x, image), signed_image_targets))

    # in case certain delegations are needed, `signed_image_targets` should only
    # consist of delegation role targets. if searched for the signed digest, none of
    # them should be empty
    if req_delegations and not all(digests):
        raise NotFoundException(
            'not all required delegations have trust data for image "{}".'.format(
                str(image)
            )
        )

    # filter out empty results and squash same elements
    digests = set(filter(None, digests))

    # no digests could be found
    if not digests:
        raise NotFoundException(
            'could not find signed digest for image "{}" in trust data.'.format(
                str(image)
            )
        )

    # if there is more than one valid digest in the set, no decision can be made, which
    # to chose
    if len(digests) > 1:
        raise AmbiguousDigestError("found multiple signed digests for the same image.")

    return digests.pop()
    async def validate(self,
                       image: Image,
                       trust_root: str = None,
                       delegations: list = None,
                       **kwargs):  # pylint: disable=arguments-differ
        if delegations is None:
            delegations = []
        # get the public root key
        pub_key = self.notary.get_key(trust_root)
        # prepend `targets/` to the required delegation roles, if not already present
        req_delegations = list(
            map(NotaryV1Validator.__normalize_delegation, delegations))

        # get list of targets fields, containing tag to signed digest mapping from
        # `targets.json` and all potential delegation roles
        signed_image_targets = await self.__process_chain_of_trust(
            image, req_delegations, pub_key)

        # search for digests or tag, depending on given image
        search_image_targets = (
            NotaryV1Validator.__search_image_targets_for_digest
            if image.has_digest() else
            NotaryV1Validator.__search_image_targets_for_tag)
        # filter out the searched for digests, if present
        digests = list(
            map(lambda x: search_image_targets(x, image),
                signed_image_targets))

        # in case certain delegations are needed, `signed_image_targets` should only
        # consist of delegation role targets. if searched for the signed digest, none of
        # them should be empty
        if req_delegations and not all(digests):
            msg = "Not all required delegations have trust data for image {image_name}."
            raise InsufficientTrustDataError(message=msg,
                                             image_name=str(image))

        # filter out empty results and squash same elements
        digests = set(filter(None, digests))

        # no digests could be found
        if not digests:
            msg = "Unable to find signed digest for image {image_name}."
            raise NotFoundException(message=msg, image_name=str(image))

        # if there is more than one valid digest in the set, no decision can be made,
        # which to chose
        if len(digests) > 1:
            msg = "Found multiple signed digests for image {image_name}."
            raise AmbiguousDigestError(message=msg, image_name=str(image))

        return digests.pop()