Beispiel #1
0
def execute_step(image_obj, args):
    """Execution path for looking at a container image filesystem at a
    specific layer. This is an interactive debugging option and should not be
    used in production."""
    print()
    print("*************************************************************")
    print("          Container Image Interactive Debug Mode             ")
    print("*************************************************************")
    print()
    for layer in image_obj.layers:
        created_by = layer.created_by if layer.created_by else 'unknown'
        print("[{}] {}".format(image_obj.layers.index(layer), created_by))
    try:
        while True:
            try:
                # input is safe in Python3
                top_layer = int(input("\nPick a layer to debug: "))  # nosec
            except ValueError:
                print("Not an integer")
                continue
            if not 0 <= top_layer < len(image_obj.layers):
                print("Not a valid layer number")
                continue
            drop_into_layer(image_obj, top_layer)
    except KeyboardInterrupt:
        print("Exiting...")
        rootfs.clean_up()
    if not args.keep_wd:
        prep.clean_image_tars(image_obj)
Beispiel #2
0
def execute_image(args):
    """Execution path for container images"""
    logger.debug('Starting analysis...')
    image_type, image_string = extract_image(args)
    # If the image has been extracted, load the metadata
    if image_type and image_string:
        full_image = cimage.load_full_image(
            image_string, image_type, args.load_until_layer)
        # check if the image was loaded successfully
        if full_image.origins.is_empty():
            # Add an image origin here
            full_image.origins.add_notice_origin(
                formats.docker_image.format(imagetag=image_string))
            # Set up for analysis
            setup(full_image)
            # analyze image
            cimage.default_analyze(full_image, args)
            # report out
            report.report_out(args, full_image)
            # clean up
            teardown(full_image)
        else:
            # we cannot load the full image
            logger.error('Cannot retrieve full image metadata')
        if not args.keep_wd:
            prep.clean_image_tars(full_image)
Beispiel #3
0
def execute_invoke(image_obj, args):
    """Execution path for checking command library scripts"""
    # we set up the image for analysis
    run.setup(image_obj)
    # we now mount the whole container image
    mount_container_image(image_obj, args.driver)
    # invoke commands in chroot
    invoke_script(args)
    # undo the mounts
    if args.driver in ('fuse', 'overlay2'):
        rootfs.unmount_rootfs()
    # cleanup
    rootfs.clean_up()
    if not args.keep_wd:
        prep.clean_image_tars(image_obj)
Beispiel #4
0
def full_image_analysis(dfile, options):
    """This subroutine is executed when a Dockerfile is successfully built"""
    image_list = []
    # attempt to load the built image metadata
    full_image = cimage.load_full_image(dfile)
    if full_image.origins.is_empty():
        # Add an image origin here
        full_image.origins.add_notice_origin(
            formats.dockerfile_image.format(dockerfile=dfile))
        image_list = analyze_full_image(full_image, options)
    else:
        # we cannot analyze the full image, but maybe we can
        # analyze the base image
        logger.error('Cannot retrieve full image metadata')
    # cleanup for full images
    if not options.keep_wd:
        prep.clean_image_tars(full_image)
    return image_list
Beispiel #5
0
def execute_docker_image(args):  # pylint: disable=too-many-branches
    '''Execution path if given a Docker image'''
    logger.debug('Starting analysis...')
    image_string = ''
    image_digest = ''
    if args.docker_image:
        # extract the docker image
        image_attrs = docker_api.dump_docker_image(args.docker_image)
        if image_attrs:
            if image_attrs['RepoTags']:
                image_string = image_attrs['RepoTags'][0]
            if image_attrs['RepoDigests']:
                image_digest = image_attrs['RepoDigests'][0]
        else:
            logger.critical("Cannot extract Docker image")
    elif args.raw_image:
        # for now we assume that the raw image tarball is always
        # the product of "docker save", hence it will be in
        # the docker style layout
        if rootfs.extract_tarfile(args.raw_image, rootfs.get_working_dir()):
            image_string = args.raw_image
        else:
            logger.critical("Cannot extract raw image")
    # If the image has been extracted, load the metadata
    if image_string:
        full_image = report.load_full_image(image_string, image_digest)
        # check if the image was loaded successfully
        if full_image.origins.is_empty():
            # Add an image origin here
            full_image.origins.add_notice_origin(
                formats.docker_image.format(imagetag=image_string))
            # analyze image
            analyze(full_image, args)
            # report out
            report.report_out(args, full_image)
        else:
            # we cannot load the full image
            logger.error('Cannot retrieve full image metadata')
    # cleanup
    if not args.keep_wd:
        prep.clean_image_tars(full_image)
Beispiel #6
0
def base_and_run_analysis(dfile, options):
    """This subroutine is executed when a Dockerfile fails build. It returns
    a base image and any RUN commands in the Dockerfile."""
    image_list = []
    # Try to analyze the base image
    logger.debug('Analyzing base image...')
    # this will pull, dump and load the base image
    base_image = load_base_image()
    if base_image:
        if base_image.origins.is_empty():
            # add a notice stating failure to build image
            base_image.origins.add_notice_to_origins(
                dfile, Notice(formats.image_build_failure, 'warning'))
            image_list = analyze_base_image(base_image, options)
        else:
            # we cannot load the base image
            logger.warning('Cannot retrieve base image metadata')
        # cleanup for base images
        if not options.keep_wd:
            prep.clean_image_tars(base_image)
    else:
        logger.error('Cannot analyze base image')
    return image_list
Beispiel #7
0
def execute_dockerfile(args):  # noqa C901,R0912
    '''Execution path if given a dockerfile'''
    dfile = ''
    dfile_lock = False
    if args.name == 'report':
        dfile = args.dockerfile
    else:
        dfile = args.lock
        dfile_lock = True
    logger.debug("Parsing Dockerfile...")
    dfobj = dockerfile.get_dockerfile_obj(dfile)
    # expand potential ARG values so base image tag is correct
    dockerfile.expand_arg(dfobj)
    dockerfile.expand_vars(dfobj)
    # Store dockerfile path and commands so we can access it during execution
    dhelper.load_docker_commands(dfobj)
    # attempt to build the image
    logger.debug('Building Docker image...')
    image_info = docker_api.build_and_dump(dfile)
    if image_info:
        # attempt to load the built image metadata
        full_image = report.load_full_image(dfile, '')
        if full_image.origins.is_empty():
            # image loading was successful
            # Add an image origin here
            full_image.origins.add_notice_origin(
                formats.dockerfile_image.format(dockerfile=dfile))
            # analyze image
            analyze(full_image, args, dfile_lock, dfobj)
            completed = True
        else:
            # we cannot analyze the full image, but maybe we can
            # analyze the base image
            logger.warning('Cannot retrieve full image metadata')
        # clean up image tarballs
        if not args.keep_wd:
            prep.clean_image_tars(full_image)
    else:
        # cannot build the image
        logger.warning('Cannot build image')
    # check if we have analyzed the full image or not
    if not completed:
        # Try to analyze the base image
        logger.debug('Analyzing base image...')
        base_image = report.load_base_image()
        if base_image.origins.is_empty():
            # image loading was successful
            # add a notice stating failure to build image
            base_image.origins.add_notice_to_origins(
                dfile, Notice(
                    formats.image_build_failure, 'warning'))
            # analyze image
            analyze(base_image, args, dfile_lock, dfobj)
        else:
            # we cannot load the base image
            logger.warning('Cannot retrieve base image metadata')
        stub_image = get_dockerfile_packages()
        if args.name == 'report':
            if not args.keep_wd:
                report.clean_image_tars(base_image)
    # generate report based on what images were created
    if not dfile_lock:
        if completed:
            report.report_out(args, full_image)
        else:
            report.report_out(args, base_image, stub_image)
    else:
        logger.debug('Parsing Dockerfile to generate report...')
        output = dockerfile.create_locked_dockerfile(dfobj)
        dockerfile.write_locked_dockerfile(output, args.output_file)
    # cleanup
    if not args.keep_wd:
        prep.clean_image_tars(full_image)