Esempio n. 1
0
def get_services_by_name(servicename):
    """
    GET /system/services/<servicename>

    :param request_inputs:
    :param servicename:
    :param hostid:
    :return:
    """
    request_inputs = anchore_engine.apis.do_request_prep(request,
                                                         default_params={})
    user_auth = request_inputs['auth']
    params = request_inputs['params']

    return_object = []
    httpcode = 500
    try:
        client = CatalogClient(user=user_auth[0], password=user_auth[1])
        service_records = client.get_service(servicename=servicename)
        for service_record in service_records:
            return_object.append(
                make_response_service(user_auth, service_record, params))

        httpcode = 200
    except Exception as err:
        return_object = anchore_engine.common.helpers.make_response_error(
            err, in_httpcode=httpcode)
        httpcode = return_object['httpcode']

    return (return_object, httpcode)
Esempio n. 2
0
    def run_feeds_update(cls, json_obj=None, force_flush=False):
        """
        Creates a task and runs it, optionally with a thread if locking is enabled.

        :return:
        """
        error = None
        feeds = None

        with session_scope() as session:
            mgr = identities.manager_factory.for_session(session)
            system_user = mgr.get_system_credentials()

        catalog_client = CatalogClient(user=system_user[0], password=system_user[1])

        try:

            feeds = get_selected_feeds_to_sync(localconfig.get_config())
            if json_obj:
                task = cls.from_json(json_obj)
                if not task:
                    return None
                task.feeds = feeds
            else:
                task = FeedsUpdateTask(feeds_to_sync=feeds, flush=force_flush)

            # Create feed task begin event
            try:
                catalog_client.add_event(FeedSyncStart(groups=feeds if feeds else 'all'))
            except:
                log.exception('Ignoring event generation error before feed sync')

            result = []
            if cls.locking_enabled:
                # system_user = get_system_user_auth()
                run_target_with_lease(user_auth=system_user, lease_id='feed_sync', ttl=90, target=lambda: result.append(task.execute()))
                # A bit of work-around for the lambda def to get result from thread execution
                if result:
                    result = result[0]
            else:
                result = task.execute()

            return result
        except LeaseAcquisitionFailedError as ex:
            error = ex
            log.exception('Could not acquire lock on feed sync, likely another sync already in progress')
            raise Exception('Cannot execute feed sync, lock is held by another feed sync in progress')
        except Exception as e:
            error = e
            log.exception('Error executing feeds update')
            raise e
        finally:
            # log feed sync event
            try:
                if error:
                    catalog_client.add_event(FeedSyncFail(groups=feeds if feeds else 'all', error=error))
                else:
                    catalog_client.add_event(FeedSyncComplete(groups=feeds if feeds else 'all'))
            except:
                log.exception('Ignoring event generation error after feed sync')
Esempio n. 3
0
def notify_event(event: EventBase, client: CatalogClient, operation_id=None):
    """
    Send an event or just log it if client is None
    Always log the event to info level
    """

    if client:
        try:
            client.add_event(event)
        except Exception as e:
            logger.warn("Error adding feed start event: {}".format(e))

    try:
        logger.info("Event: {} (operation_id={})".format(event.to_json(), operation_id))
    except:
        logger.exception("Error logging event")
Esempio n. 4
0
def update_catalog_image_status(
    client: CatalogClient,
    image_digest: str,
    image_record: dict,
    new_analysis_status=None,
    new_image_status=None,
) -> dict:
    """
    Update the analysis and/or image status for the record, one of new_analysis_status and new_image_status must be non-None

    :param client:
    :param image_digest:
    :param image_record:
    :param new_analysis_status: str new analysis_status value, options
    :param new_image_status: str new image status value, optional
    :return:
    """

    if not (new_analysis_status or new_image_status):
        raise ValueError(
            "one of new_analysis_status or new_image_status must be non None")

    if new_analysis_status:
        image_record["analysis_status"] = new_analysis_status

    if new_image_status:
        image_record["image_status"] = new_image_status

    rc = client.update_image(image_digest, image_record)
    return image_record
Esempio n. 5
0
def get_content(
    manifest: InternalImportManifest,
    client: CatalogClient,
) -> dict:

    content_map = {}
    for content_ref in manifest.contents:
        logger.info(
            "loading import content type %s from %s/%s",
            content_ref.content_type,
            content_ref.bucket,
            content_ref.key,
        )
        raw = client.get_document(content_ref.bucket, content_ref.key)
        if content_ref.content_type in JSON_CONTENT_TYPES:
            content_map[content_ref.content_type] = json.loads(raw)
        else:
            content_map[content_ref.content_type] = raw

    return content_map
Esempio n. 6
0
def imagepolicywebhook(bodycontent):

    # TODO - while the image policy webhook feature is in k8s beta, we've decided to make any errors that occur during check still respond with 'allowed: True'.  This should be reverted to default to 'False' on any error, once the k8s feature is further along

    return_object = {
        "apiVersion": "imagepolicy.k8s.io/v1alpha1",
        "kind": "ImageReview",
        "status": {
            "allowed": True,
            "reason": "all images passed anchore policy evaluation"
        }
    }
    httpcode = 200

    try:
        request_inputs = anchore_engine.apis.do_request_prep(connexion.request,
                                                             default_params={})

        user_auth = request_inputs['auth']
        method = request_inputs['method']
        params = request_inputs['params']
        userId = request_inputs['userId']

        try:

            final_allowed = True
            reason = "unset"

            try:
                try:
                    #incoming = json.loads(bodycontent)
                    incoming = bodycontent
                    logger.debug("incoming post data: " +
                                 json.dumps(incoming, indent=4))
                except Exception as err:
                    raise Exception("could not load post data as json: " +
                                    str(err))

                try:
                    requestUserId = None
                    requestPolicyId = None
                    # see if the request from k8s contains an anchore policy and/or whitelist name
                    if 'annotations' in incoming['spec']:
                        logger.debug(
                            "incoming request contains annotations: " +
                            json.dumps(incoming['spec']['annotations'],
                                       indent=4))
                        requestUserId = incoming['spec']['annotations'].pop(
                            "anchore.image-policy.k8s.io/userId", None)
                        requestPolicyId = incoming['spec']['annotations'].pop(
                            "anchore.image-policy.k8s.io/policyBundleId", None)
                except Exception as err:
                    raise Exception("could not parse out annotations: " +
                                    str(err))

                if not requestUserId:
                    raise Exception(
                        "need to specify an anchore.image-policy.k8s.io/userId annotation with a valid anchore service username as a value"
                    )

                # TODO - get anchore system uber cred to access
                # this data on behalf of user?  tough...maybe see
                # if kuber can make request as anchore-system so
                # that we can switch roles?
                localconfig = anchore_engine.configuration.localconfig.get_config(
                )
                system_user_auth = localconfig['system_user_auth']

                # TODO: zhill This is bad, this is identity switching, need to resolve (this is not a change to previous behavior, but that behavior was bad)
                with session_scope() as dbsession:
                    mgr = manager_factory.for_session(dbsession)
                    request_user_auth = mgr.get_credentials_for_userid(
                        requestUserId)

                catalog = CatalogClient(
                    user=request_user_auth[0],
                    password=request_user_auth[1],
                    as_account=requestUserId if requestUserId else
                    ApiRequestContextProxy.effective_account())

                reason = "all images passed anchore policy checks"
                final_action = False
                for el in incoming['spec']['containers']:
                    image = el['image']
                    logger.debug("found image in request: " + str(image))
                    image_records = catalog.get_image(tag=image)
                    if not image_records:
                        raise Exception("could not find requested image (" +
                                        str(image) + ") in anchore service DB")

                    for image_record in image_records:
                        imageDigest = image_record['imageDigest']

                        for image_detail in image_record['image_detail']:
                            fulltag = image_detail[
                                'registry'] + "/" + image_detail[
                                    'repo'] + ':' + image_detail['tag']
                            result = catalog.get_eval_latest(
                                tag=fulltag,
                                imageDigest=imageDigest,
                                policyId=requestPolicyId)
                            if result:
                                httpcode = 200
                                if result['final_action'].upper() not in [
                                        'GO', 'WARN'
                                ]:
                                    final_action = False
                                    raise Exception(
                                        "image failed anchore policy check: " +
                                        json.dumps(result, indent=4))
                                else:
                                    final_action = True

                            else:
                                httpcode = 404
                                final_action = False
                                raise Exception(
                                    "no anchore evaluation available for image: "
                                    + str(image))

                final_allowed = final_action

            except Exception as err:
                reason = str(err)
                final_allowed = False
                httpcode = 200

            return_object['status']['allowed'] = final_allowed
            return_object['status']['reason'] = reason

            anchore_engine.subsys.metrics.counter_inc(
                "anchore_image_policy_webhooks_evaluation_total",
                allowed=final_allowed)

            #logger.debug("final return: " + json.dumps(return_object, indent=4))
            httpcode = 200
        except Exception as err:
            return_object['reason'] = str(err)
            httpcode = 500

    except Exception as err:
        return_object['reason'] = str(err)
        httpcode = 500

    return (return_object, httpcode)
Esempio n. 7
0
def emit_events(client: CatalogClient, analysis_events: list):
    for event in analysis_events:
        try:
            client.add_event(event)
        except:
            logger.error("Ignoring error sending event")