Example #1
0
def perform_analyze_nodocker(userId, manifest, image_record, registry_creds):
    ret_analyze = {}
    ret_query = {}

    localconfig = anchore_engine.configuration.localconfig.get_config()
    try:
        tmpdir = localconfig['tmp_dir']
    except Exception as err:
        logger.warn("could not get tmp_dir from localconfig - exception: " + str(err))
        tmpdir = "/tmp"

    # choose the first TODO possible more complex selection here
    try:
        image_detail = image_record['image_detail'][0]
        registry_manifest = manifest
        pullstring = image_detail['registry'] + "/" + image_detail['repo'] + "@" + image_detail['imageDigest']
        fulltag = image_detail['registry'] + "/" + image_detail['repo'] + ":" + image_detail['tag']
        logger.debug("using pullstring ("+str(pullstring)+") and fulltag ("+str(fulltag)+") to pull image data")
    except Exception as err:
        image_detail = pullstring = fulltag = None
        raise Exception("failed to extract requisite information from image_record - exception: " + str(err))
        
    timer = int(time.time())
    logger.spew("TIMING MARK0: " + str(int(time.time()) - timer))
    logger.info("performing analysis on image: " + str([userId, pullstring, fulltag]))

    logger.debug("obtaining anchorelock..." + str(pullstring))
    with localanchore.get_anchorelock(lockId=pullstring):
        logger.debug("obtaining anchorelock successful: " + str(pullstring))
        analyzed_image_report = localanchore_standalone.analyze_image(userId, registry_manifest, image_record, tmpdir, registry_creds=registry_creds)
        ret_analyze = analyzed_image_report

    logger.info("performing analysis on image complete: " + str(pullstring))

    return (ret_analyze)
def analyze(registry, manifest, repo, digest, tag, work_dir):
    userId = None  # Not used at all in analyze_image
    image_record = {
        'dockerfile_mode': 'actual',  # XXX no idea
        'image_detail': [{  # always picks the first one
            'registry': registry,
            'repo': repo,
            'imageDigest': digest,
            'tag': tag,
            'imageId': 'XXX',  # XXX no idea
            'dockerfile': None,
        }],
        'imageDigest': 'some sha256 - this seems repeated?',  # XXX
    }
    localconfig = {'service_dir': join(work_dir, 'service_dir')}

    click.echo('Starting the analyze process...')
    image_report, manifest = analyze_image(userId,
                                           manifest,
                                           image_record,
                                           work_dir,
                                           localconfig,
                                           use_cache_dir=join(
                                               work_dir, 'cache_dir'))
    click.echo('Completed analyze process. Saving results...')
    result_python = join(work_dir, 'result.py')
    with open(result_python, 'w') as python_file:
        python_file.write('result = ')
        python_file.write(pprint.pformat(image_report))
    click.echo('Saved the results of the analyzer to %s' % result_python)
Example #3
0
def perform_analyze(
    account,
    manifest,
    image_record,
    registry_creds,
    layer_cache_enable=False,
    parent_manifest=None,
):
    ret_analyze = {}

    loaded_config = get_config()
    tmpdir = get_tempdir(loaded_config)

    use_cache_dir = None
    if layer_cache_enable:
        use_cache_dir = os.path.join(tmpdir, "anchore_layercache")

    # choose the first TODO possible more complex selection here
    try:
        image_detail = image_record["image_detail"][0]
        registry_manifest = manifest
        registry_parent_manifest = parent_manifest
        pullstring = (image_detail["registry"] + "/" + image_detail["repo"] +
                      "@" + image_detail["imageDigest"])
        fulltag = (image_detail["registry"] + "/" + image_detail["repo"] +
                   ":" + image_detail["tag"])
        logger.debug("using pullstring (" + str(pullstring) +
                     ") and fulltag (" + str(fulltag) + ") to pull image data")
    except Exception as err:
        image_detail = pullstring = fulltag = None
        raise Exception(
            "failed to extract requisite information from image_record - exception: "
            + str(err))

    timer = int(time.time())
    logger.spew("timing: analyze start: " + str(int(time.time()) - timer))
    logger.info("performing analysis on image: " +
                str([account, pullstring, fulltag]))

    logger.debug("obtaining anchorelock..." + str(pullstring))
    with anchore_engine.clients.localanchore_standalone.get_anchorelock(
            lockId=pullstring, driver="nodocker"):
        logger.debug("obtaining anchorelock successful: " + str(pullstring))
        logger.info("analyzing image: %s", pullstring)
        analyzed_image_report, manifest_raw = localanchore_standalone.analyze_image(
            account,
            registry_manifest,
            image_record,
            tmpdir,
            loaded_config,
            registry_creds=registry_creds,
            use_cache_dir=use_cache_dir,
            parent_manifest=registry_parent_manifest,
        )
        ret_analyze = analyzed_image_report

    logger.info("performing analysis on image complete: " + str(pullstring))

    return ret_analyze
Example #4
0
def exec(tag, tmpdir):
    """
    Run analyzer(s) against the local tagged image and write the result in a local fs
    :param tag: str tag name to analyze on local host (e.g. alpine:latest)
    :param tmpdir: valid and existing file path
    :return:
    """
    global config
    click.echo('Getting tag manifest for: {}'.format(tag))
    registry, rest = tag.split('/', 1)
    repo, tag = rest.split(':', 1)
    click.echo('Registry: {}, Repository: {}, Tag: {}'.format(
        registry, repo, tag))
    manifest, digest, parentdigest = get_image_manifest_skopeo(None,
                                                               registry,
                                                               repo,
                                                               intag=tag)
    img_record = {
        'imageDigest':
        digest,
        'parentDigest':
        parentdigest,
        'dockerfile_mode':
        'guessed',
        'image_detail': [{
            'dockerfile': '',
            'imageId': digest,
            'imageDigest': digest,
            'tag': tag,
            'registry': registry,
            'repo': repo
        }]
    }
    click.echo('Got digest: {}'.format(digest))
    click.echo('Got parentdigest: {}'.format(parentdigest))
    click.echo('Config: {}'.format(config))
    click.echo('Running analyzers')

    image_report = localanchore_standalone.analyze_image(
        userId='cli_test',
        manifest=json.dumps(manifest),
        image_record=img_record,
        tmprootdir=tmpdir,
        localconfig=config,
        registry_creds=None,
        use_cache_dir=False)
    click.echo('complete!')
    with open(digest + '.report.json', 'w') as f:
        json.dump(image_report, f)
Example #5
0
def perform_analyze_nodocker(userId, manifest, image_record, registry_creds, layer_cache_enable=False, parent_manifest=None):
    ret_analyze = {}
    ret_query = {}

    localconfig = anchore_engine.configuration.localconfig.get_config()
    try:
        tmpdir = localconfig['tmp_dir']
    except Exception as err:
        logger.warn("could not get tmp_dir from localconfig - exception: " + str(err))
        tmpdir = "/tmp"

    use_cache_dir=None
    if layer_cache_enable:
        use_cache_dir = os.path.join(tmpdir, "anchore_layercache")

    # choose the first TODO possible more complex selection here
    try:
        image_detail = image_record['image_detail'][0]
        registry_manifest = manifest
        registry_parent_manifest = parent_manifest
        pullstring = image_detail['registry'] + "/" + image_detail['repo'] + "@" + image_detail['imageDigest']
        fulltag = image_detail['registry'] + "/" + image_detail['repo'] + ":" + image_detail['tag']
        logger.debug("using pullstring ("+str(pullstring)+") and fulltag ("+str(fulltag)+") to pull image data")
    except Exception as err:
        image_detail = pullstring = fulltag = None
        raise Exception("failed to extract requisite information from image_record - exception: " + str(err))

    timer = int(time.time())
    logger.spew("timing: analyze start: " + str(int(time.time()) - timer))
    logger.info("performing analysis on image: " + str([userId, pullstring, fulltag]))

    logger.debug("obtaining anchorelock..." + str(pullstring))
    with anchore_engine.clients.localanchore_standalone.get_anchorelock(lockId=pullstring, driver='nodocker'):
        logger.debug("obtaining anchorelock successful: " + str(pullstring))
        analyzed_image_report, manifest_raw = localanchore_standalone.analyze_image(userId, registry_manifest, image_record, tmpdir, localconfig, registry_creds=registry_creds, use_cache_dir=use_cache_dir, parent_manifest=registry_parent_manifest)
        ret_analyze = analyzed_image_report

    logger.info("performing analysis on image complete: " + str(pullstring))

    return ret_analyze
Example #6
0
def analyze(registry, manifest, repo, digest, tag, work_dir, localconfig):
    userId = None  # Not used at all in analyze_image
    image_record = {
        "dockerfile_mode": "actual",  # XXX no idea
        "image_detail": [
            {  # always picks the first one
                "registry": registry,
                "repo": repo,
                "imageDigest": digest,
                "tag": tag,
                "imageId": "XXX",  # XXX no idea
                "dockerfile": None,
            }
        ],
        "imageDigest": "some sha256 - this seems repeated?",  # XXX
    }
    _localconfig = {"service_dir": join(work_dir, "service_dir")}
    if localconfig:
        _localconfig.update(localconfig)

    localconfig = _localconfig

    click.echo("Starting the analyze process...")

    image_report, manifest = analyze_image(
        userId,
        manifest,
        image_record,
        work_dir,
        localconfig,
        use_cache_dir=join(work_dir, "cache_dir"),
    )
    click.echo("Completed analyze process. Saving results...")
    result_python = join(work_dir, "result.py")
    with open(result_python, "w") as python_file:
        python_file.write("result = ")
        python_file.write(pprint.pformat(image_report))
    click.echo("Saved the results of the analyzer to %s" % result_python)
Example #7
0
def exec(docker_archive, anchore_archive, digest, parent_digest, image_id, tag,
         account_id, manifest, dockerfile, created_at, annotation):
    """
    Analyze a local image stored as a docker archive (output result of 'docker save'), and generate an anchore image archive tarball ready for import into an anchore engine.

    DOCKER_ARCHIVE : Location of input docker archive tarfile to analyze
    ANCHORE_ARCHIVE : Location of output anchore image archive to write

    """

    global config

    # this could be improved to allow use to input timestamps (created_at, analyzed_at, etc)
    now = int(time.time())
    try:
        try:
            imageDigest = None
            input_manifest_data = None
            rawmanifest = None

            if (not manifest and not digest) or (manifest and digest):
                raise Exception(
                    "must supply either an image digest or a valid manifest, but not both"
                )

            if os.path.exists(anchore_archive):
                raise Exception(
                    "the supplied anchore archive file ({}) already exists, please remove and try again"
                    .format(anchore_archive))

            if manifest:
                try:
                    with open(manifest, 'r') as FH:
                        # TODO implement manifest validator for anchore requirements, specifically
                        rawmanifest = FH.read()
                        input_manifest_data = json.loads(rawmanifest)
                        imageDigest = manifest_to_digest(rawmanifest)
                except Exception as err:
                    raise ValueError(
                        "cannot calculate digest from supplied manifest - exception: {}"
                        .format(err))

            if digest:
                if re.match("^sha256:[\d|a-f]{64}$", digest):
                    imageDigest = digest
                else:
                    raise ValueError(
                        "input digest does not validate - must be sha256:<64 hex characters>"
                    )

            if parent_digest:
                if re.match("^sha256:[\d|a-f]{64}$", parent_digest):
                    parentDigest = parent_digest
                else:
                    raise ValueError(
                        "input parent_digest does not validate - must be sha256:<64 hex characters>"
                    )
            else:
                parentDigest = imageDigest

            if image_id:
                if re.match("^[\d|a-f]{64}$", image_id):
                    imageId = image_id
                else:
                    raise ValueError("input image_id does not validate")
            else:
                # TODO this could be improved to generate imageId from configuration hash
                imageId = "{}".format(''.join(
                    [random.choice('0123456789abcdef') for x in range(0, 64)]))

            if account_id:
                userId = account_id
            else:
                userId = 'admin'

            if created_at:
                try:
                    if int(created_at) < 0 or int(created_at) > now + 1:
                        raise Exception()
                except Exception as err:
                    raise ValueError(
                        "created_at must by a unix timestamp between 0 and now ({})"
                        .format(now))
            else:
                created_at = now

            try:
                inputTag = tag
                image_info = parse_dockerimage_string(inputTag)
                fulltag = "{}/{}:{}".format(image_info['registry'],
                                            image_info['repo'],
                                            image_info['tag'])
                fulldigest = "{}/{}@{}".format(image_info['registry'],
                                               image_info['repo'], imageDigest)
            except Exception as err:
                raise ValueError(
                    "input tag does not validate - exception: {}".format(err))

            dockerfile_mode = "Guessed"
            dockerfile_contents = None
            if dockerfile:
                with open(dockerfile, 'r') as FH:
                    dockerfile_contents = ensure_str(
                        base64.b64encode(ensure_bytes(FH.read())))
                    dockerfile_mode = "Actual"

            annotations = {}
            if annotation:
                for a in annotation:
                    try:
                        (k, v) = a.split('=', 1)
                        if k and v:
                            annotations[k] = v
                        else:
                            raise Exception("found null in key or value")
                    except Exception as err:
                        raise ValueError(
                            "annotation format error - annotations must be of the form (--annotation key=value), found: {}"
                            .format(a))

            workspace_root = config['tmp_dir']
        except Exception as err:
            # input setup/validation failure
            raise err

        logger.debug(
            "input has been prepared: imageDigest={} parentDigest={} imageId={} inputTag={} fulltag={} fulldigest={} userId={} annotations={} created_at={}"
            .format(imageDigest, parentDigest, imageId, inputTag, fulltag,
                    fulldigest, userId, annotations, created_at))

        # create an image record
        try:
            image_record = make_image_record(userId,
                                             'docker',
                                             None,
                                             image_metadata={
                                                 'tag': fulltag,
                                                 'digest': fulldigest,
                                                 'imageId': imageId,
                                                 'parentdigest': parentDigest,
                                                 'created_at': created_at,
                                                 'dockerfile':
                                                 dockerfile_contents,
                                                 'dockerfile_mode':
                                                 dockerfile_mode,
                                                 'annotations': annotations
                                             },
                                             registry_lookup=False,
                                             registry_creds=(None, None))
            image_record['created_at'] = created_at
            image_record['last_updated'] = created_at
            image_record['analyzed_at'] = now
            image_record['analysis_status'] = 'analyzed'
            image_record['image_status'] = 'active'
            image_record['record_state_key'] = 'active'
            for image_detail in image_record['image_detail']:
                image_detail['created_at'] = created_at
                image_detail['last_updated'] = created_at
                image_detail['tag_detected_at'] = created_at
                image_detail['record_state_key'] = 'active'
        except Exception as err:
            # image record setup fail
            raise err

        # perform analysis
        try:
            image_data, analyzed_manifest_data = analyze_image(
                userId,
                rawmanifest,
                image_record,
                workspace_root,
                config,
                registry_creds=[],
                use_cache_dir=None,
                image_source='docker-archive',
                image_source_meta=docker_archive)

            image_content_data = {}
            for content_type in anchore_engine.common.image_content_types + anchore_engine.common.image_metadata_types:
                try:
                    image_content_data[
                        content_type] = anchore_engine.common.helpers.extract_analyzer_content(
                            image_data,
                            content_type,
                            manifest=input_manifest_data)
                except:
                    image_content_data[content_type] = {}

            anchore_engine.common.helpers.update_image_record_with_analysis_data(
                image_record, image_data)
            image_record['image_size'] = int(image_record['image_size'])
        except Exception as err:
            # image analysis fail
            raise err

        # generate an output image archive tarball
        archive_file = anchore_archive
        try:
            with ImageArchive.for_writing(archive_file) as img_archive:

                img_archive.account = userId
                img_archive.image_digest = imageDigest
                img_archive.manifest.metadata = {
                    'versions': localconfig.get_versions(),
                    'image_id': imageId,
                    'image_record': json.dumps(image_record, sort_keys=True)
                }

                pack_data = {'document': image_data}
                data = ensure_bytes(json.dumps(pack_data, sort_keys=True))
                img_archive.add_artifact('analysis',
                                         source=ObjectStoreLocation(
                                             bucket='analysis_data',
                                             key=imageDigest),
                                         data=data,
                                         metadata=None)

                pack_data = {'document': image_content_data}
                data = ensure_bytes(json.dumps(pack_data, sort_keys=True))
                img_archive.add_artifact('image_content',
                                         source=ObjectStoreLocation(
                                             bucket='image_content_data',
                                             key=imageDigest),
                                         data=data,
                                         metadata=None)

                pack_data = {'document': input_manifest_data}
                data = ensure_bytes(json.dumps(pack_data, sort_keys=True))
                img_archive.add_artifact('image_manifest',
                                         source=ObjectStoreLocation(
                                             bucket='manifest_data',
                                             key=imageDigest),
                                         data=data,
                                         metadata=None)
        except Exception as err:
            # archive tarball generate fail
            raise err

    except Exception as err:
        logger.error(
            anchore_manager.cli.utils.format_error_output(
                click_config, 'db', {}, err))
        sys.exit(2)

    click.echo(
        "Analysis complete for image {} - archive file is located at {}".
        format(imageDigest, archive_file))