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()