Esempio n. 1
0
def import_image(operation_id, account,
                 import_manifest: InternalImportManifest):
    """
    The main thread of exec for importing an image

    :param operation_id:
    :param account:
    :param import_manifest:
    :return:
    """
    timer = int(time.time())
    analysis_events = []

    config = localconfig.get_config()
    all_content_types = config.get("image_content_types", []) + config.get(
        "image_metadata_types", [])
    image_digest = import_manifest.digest

    try:
        catalog_client = internal_client_for(CatalogClient, account)

        # check to make sure image is still in DB
        catalog_client = internal_client_for(CatalogClient, account)
        try:
            image_record = catalog_client.get_image(image_digest)
            if not image_record:
                raise Exception("empty image record from catalog")
        except Exception as err:
            logger.debug_exception("Could not get image record")
            logger.warn(
                "dequeued image cannot be fetched from catalog - skipping analysis ("
                + str(image_digest) + ") - exception: " + str(err))
            return True

        if image_record["analysis_status"] != taskstate.base_state("analyze"):
            logger.info(
                "dequeued image to import is not in base 'not_analyzed' state - skipping import"
            )
            return True

        try:
            last_analysis_status = image_record["analysis_status"]
            image_record = update_analysis_started(catalog_client,
                                                   image_digest, image_record)

            logger.info("Loading content from import")
            sbom_map = get_content(import_manifest, catalog_client)

            manifest = sbom_map.get("manifest")

            try:
                logger.info("processing image import data")
                image_data, analysis_manifest = process_import(
                    image_record, sbom_map, import_manifest)
            except AnchoreException as e:
                event = events.ImageAnalysisFailed(user_id=account,
                                                   image_digest=image_digest,
                                                   error=e.to_dict())
                analysis_events.append(event)
                raise

            # Store the manifest in the object store
            logger.info("storing image manifest")
            catalog_client.put_document(bucket="manifest_data",
                                        name=image_digest,
                                        inobj=json.dumps(manifest))

            # Save the results to the upstream components and data stores
            logger.info("storing import result")
            store_analysis_results(
                account,
                image_digest,
                image_record,
                image_data,
                manifest,
                analysis_events,
                all_content_types,
            )

            logger.info("updating image catalog record analysis_status")
            last_analysis_status = image_record["analysis_status"]
            image_record = update_analysis_complete(catalog_client,
                                                    image_digest, image_record)
            try:
                analysis_events.extend(
                    notify_analysis_complete(image_record,
                                             last_analysis_status))
            except Exception as err:
                logger.warn(
                    "failed to enqueue notification on image analysis state update - exception: "
                    + str(err))

            logger.info("analysis complete: " + str(account) + " : " +
                        str(image_digest))

            try:
                catalog_client.update_image_import_status(operation_id,
                                                          status="complete")
            except Exception as err:
                logger.debug_exception(
                    "failed updating import status success, will continue and rely on expiration for GC later"
                )

            try:
                metrics.counter_inc(name="anchore_import_success")
                run_time = float(time.time() - timer)

                metrics.histogram_observe(
                    "anchore_import_time_seconds",
                    run_time,
                    buckets=IMPORT_TIME_SECONDS_BUCKETS,
                    status="success",
                )

            except Exception as err:
                logger.warn(str(err))

        except Exception as err:
            run_time = float(time.time() - timer)
            logger.exception("problem importing image - exception: " +
                             str(err))
            analysis_failed_metrics(run_time)

            # Transition the image record to failure status
            image_record = update_analysis_failed(catalog_client, image_digest,
                                                  image_record)

            try:
                catalog_client.update_image_import_status(operation_id,
                                                          status="failed")
            except Exception as err:
                logger.debug_exception(
                    "failed updating import status failure, will continue and rely on expiration for GC later"
                )

            if account and image_digest:
                for image_detail in image_record["image_detail"]:
                    fulltag = (image_detail["registry"] + "/" +
                               image_detail["repo"] + ":" +
                               image_detail["tag"])
                    event = events.UserAnalyzeImageFailed(user_id=account,
                                                          full_tag=fulltag,
                                                          error=str(err))
                    analysis_events.append(event)
        finally:
            if analysis_events:
                emit_events(catalog_client, analysis_events)

    except Exception as err:
        logger.debug_exception("Could not import image")
        logger.warn("job processing bailed - exception: " + str(err))
        raise err

    return True
Esempio n. 2
0
def process_analyzer_job(request: AnalysisQueueMessage, layer_cache_enable):
    """
    Core logic of the analysis process

    :param request:
    :param layer_cache_enable:
    :return:
    """

    timer = int(time.time())
    analysis_events = []

    loaded_config = get_config()
    all_content_types = loaded_config.get("image_content_types",
                                          []) + loaded_config.get(
                                              "image_metadata_types", [])

    try:
        account = request.account
        image_digest = request.image_digest
        manifest = request.manifest
        parent_manifest = request.parent_manifest

        # check to make sure image is still in DB
        catalog_client = internal_client_for(CatalogClient, account)
        try:
            image_record = catalog_client.get_image(image_digest)
            if not image_record:
                raise Exception("empty image record from catalog")
        except Exception as err:
            logger.warn(
                "dequeued image cannot be fetched from catalog - skipping analysis ("
                + str(image_digest) + ") - exception: " + str(err))
            return True

        logger.info("image dequeued for analysis: " + str(account) + " : " +
                    str(image_digest))
        if image_record[
                "analysis_status"] != anchore_engine.subsys.taskstate.base_state(
                    "analyze"):
            logger.debug(
                "dequeued image is not in base state - skipping analysis")
            return True

        try:
            logger.spew("TIMING MARK0: " + str(int(time.time()) - timer))

            last_analysis_status = image_record["analysis_status"]
            image_record = update_analysis_started(catalog_client,
                                                   image_digest, image_record)

            # actually do analysis
            registry_creds = catalog_client.get_registry()
            try:
                image_data = perform_analyze(
                    account,
                    manifest,
                    image_record,
                    registry_creds,
                    layer_cache_enable=layer_cache_enable,
                    parent_manifest=parent_manifest,
                )
            except AnchoreException as e:
                event = events.ImageAnalysisFailed(user_id=account,
                                                   image_digest=image_digest,
                                                   error=e.to_dict())
                analysis_events.append(event)
                raise

            # Save the results to the upstream components and data stores
            store_analysis_results(
                account,
                image_digest,
                image_record,
                image_data,
                manifest,
                analysis_events,
                all_content_types,
            )

            logger.debug("updating image catalog record analysis_status")
            last_analysis_status = image_record["analysis_status"]
            image_record = update_analysis_complete(catalog_client,
                                                    image_digest, image_record)

            try:
                notify_analysis_complete(image_record, last_analysis_status)
            except Exception as err:
                logger.warn(
                    "failed to enqueue notification on image analysis state update - exception: "
                    + str(err))

            logger.info("analysis complete: " + str(account) + " : " +
                        str(image_digest))
            logger.spew("TIMING MARK1: " + str(int(time.time()) - timer))

            try:
                anchore_engine.subsys.metrics.counter_inc(
                    name="anchore_analysis_success")
                run_time = float(time.time() - timer)

                anchore_engine.subsys.metrics.histogram_observe(
                    "anchore_analysis_time_seconds",
                    run_time,
                    buckets=ANALYSIS_TIME_SECONDS_BUCKETS,
                    status="success",
                )

            except Exception as err:
                logger.warn(str(err))
                pass

        except Exception as err:
            run_time = float(time.time() - timer)
            logger.exception("problem analyzing image - exception: " +
                             str(err))
            analysis_failed_metrics(run_time)

            # Transition the image record to failure status
            image_record = update_analysis_failed(catalog_client, image_digest,
                                                  image_record)

            if account and image_digest:
                for image_detail in image_record["image_detail"]:
                    fulltag = (image_detail["registry"] + "/" +
                               image_detail["repo"] + ":" +
                               image_detail["tag"])
                    event = events.UserAnalyzeImageFailed(user_id=account,
                                                          full_tag=fulltag,
                                                          error=str(err))
                    analysis_events.append(event)
        finally:
            if analysis_events:
                emit_events(catalog_client, analysis_events)

    except Exception as err:
        logger.warn("job processing bailed - exception: " + str(err))
        raise err

    return True