Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def analyze_first_layer(image_obj, master_list, redo):
# find the binary and shell by mounting the base layer
target = rootfs.mount_base_layer(image_obj.layers[0].tar_file)
binary = common.get_base_bin()
shell = get_shell(image_obj, binary)
# set up a notice origin for the first layer
origin_first_layer = 'Layer: ' + image_obj.layers[0].fs_hash[:10]
# only extract packages if there is a known binary and the layer is not
# cached
if binary:
if not common.load_from_cache(image_obj.layers[0], redo):
# Determine pacakge/os style from binary in the image layer
common.get_os_style(image_obj.layers[0], binary)
# get the packages of the first layer
try:
rootfs.prep_rootfs(target)
common.add_base_packages(image_obj.layers[0], binary, shell)
except KeyboardInterrupt:
logger.critical(errors.keyboard_interrupt)
abort_analysis()
if not common.load_from_cache(image_obj.layers[curr_layer], redo):
# get commands that created the layer
# for docker images this is retrieved from the image history
command_list = dhelper.get_commands_from_history(
image_obj.layers[curr_layer])
if command_list:
# mount diff layers from 0 till the current layer
target = mount_overlay_fs(image_obj, curr_layer)
# mount dev, sys and proc after mounting diff layers
rootfs.prep_rootfs(target)
# for each command look up the snippet library
for command in command_list:
pkg_listing = command_lib.get_package_listing(command.name)
if isinstance(pkg_listing, str):
try:
common.add_base_packages(
image_obj.layers[curr_layer], pkg_listing, shell)
except KeyboardInterrupt:
logger.critical(errors.keyboard_interrupt)
abort_analysis()
else:
try:
common.add_snippet_packages(
image_obj.layers[curr_layer], command, pkg_listing,
shell)
except KeyboardInterrupt:
logger.critical(errors.keyboard_interrupt)
abort_analysis()
if command_list:
rootfs.undo_mount()
rootfs.unmount_rootfs()
# update the master list
def analyze_first_layer(image_obj, master_list, redo):
# find the binary and shell by mounting the base layer
target = rootfs.mount_base_layer(image_obj.layers[0].tar_file)
binary = common.get_base_bin()
shell = get_shell(image_obj, binary)
# set up a notice origin for the first layer
origin_first_layer = 'Layer: ' + image_obj.layers[0].fs_hash[:10]
# only extract packages if there is a known binary and the layer is not
# cached
if binary:
if not common.load_from_cache(image_obj.layers[0], redo):
# Determine pacakge/os style from binary in the image layer
common.get_os_style(image_obj.layers[0], binary)
# get the packages of the first layer
try:
rootfs.prep_rootfs(target)
common.add_base_packages(image_obj.layers[0], binary, shell)
except KeyboardInterrupt:
logger.critical(errors.keyboard_interrupt)
abort_analysis()
# unmount proc, sys and dev
rootfs.undo_mount()
else:
logger.warning(errors.no_package_manager)
# /etc/os-release may still be present even if binary is not
common.get_os_style(image_obj.layers[0], None)
image_obj.layers[0].origins.add_notice_to_origins(
if not common.load_from_cache(image_obj.layers[0], redo):
# Determine pacakge/os style from binary in the image layer
common.get_os_style(image_obj.layers[0], binary)
# get the packages of the first layer
try:
rootfs.prep_rootfs(target)
common.add_base_packages(image_obj.layers[0], binary, shell)
except KeyboardInterrupt:
logger.critical(errors.keyboard_interrupt)
abort_analysis()
# unmount proc, sys and dev
rootfs.undo_mount()
else:
logger.warning(errors.no_package_manager)
# /etc/os-release may still be present even if binary is not
common.get_os_style(image_obj.layers[0], None)
image_obj.layers[0].origins.add_notice_to_origins(
origin_first_layer, Notice(errors.no_package_manager, 'warning'))
# no binary means there is no shell so set to default shell
logger.warning('Unknown filesystem. Using default shell')
shell = constants.shell
# unmount the first layer
rootfs.unmount_rootfs()
# populate the master list with all packages found in the first layer
for p in image_obj.layers[0].packages:
master_list.append(p)
return shell
target = mount_overlay_fs(image_obj, curr_layer)
# mount dev, sys and proc after mounting diff layers
rootfs.prep_rootfs(target)
# for each command look up the snippet library
for command in command_list:
pkg_listing = command_lib.get_package_listing(command.name)
if isinstance(pkg_listing, str):
try:
common.add_base_packages(
image_obj.layers[curr_layer], pkg_listing, shell)
except KeyboardInterrupt:
logger.critical(errors.keyboard_interrupt)
abort_analysis()
else:
try:
common.add_snippet_packages(
image_obj.layers[curr_layer], command, pkg_listing,
shell)
except KeyboardInterrupt:
logger.critical(errors.keyboard_interrupt)
abort_analysis()
if command_list:
rootfs.undo_mount()
rootfs.unmount_rootfs()
# update the master list
common.update_master_list(master_list, image_obj.layers[curr_layer])
curr_layer = curr_layer + 1
def get_dockerfile_packages():
'''Given a Dockerfile return an approximate image object. This is mosty
guess work and shouldn't be relied on for accurate information. Add
Notice messages indicating as such:
1. Create an image with a placeholder repotag
2. For each RUN command, create a package list
3. Create layer objects with incremental integers and add the package
list to that layer with a Notice about parsing
4. Return stub image'''
stub_image = Image('easteregg:cookie')
layer_count = 0
for inst in dhelper.docker_commands:
if inst[0] == 'RUN':
layer_count = layer_count + 1
layer = ImageLayer(layer_count)
install_commands, msg = common.filter_install_commands(inst[1])
if msg:
layer.origins.add_notice_to_origins(
inst[1], Notice(msg, 'info'))
pkg_names = []
for command in install_commands:
pkg_names.append(common.get_installed_package_names(command))
for pkg_name in pkg_names:
pkg = Package(pkg_name)
# shell parser does not parse version pins yet
# when that is enabled, Notices for no versions need to be
# added here
layer.add_package(pkg)
return stub_image
def extract_image_metadata(image_tag_string):
'''Run docker save and extract the files in a temporary directory'''
temp_path = rootfs.get_working_dir()
placeholder = os.path.join(general.get_top_dir(), temp_tarfile)
try:
if common.check_tar(image_tag_string) is True:
# image_tag_string is the path to the tar file for raw images
rootfs.extract_tarfile(image_tag_string, temp_path)
else:
image = client.images.get(image_tag_string)
result = image.save(chunk_size=2097152, named=True)
# write all of the tar byte stream into temporary tar file
with open(placeholder, 'wb') as f:
for chunk in result:
f.write(chunk)
# extract tarfile into folder
rootfs.extract_tarfile(placeholder, temp_path)
# remove temporary tar file
os.remove(placeholder)
if not os.listdir(temp_path):
raise IOError('Unable to untar Docker image')
except docker.errors.APIError: # pylint: disable=try-except-raise
# create working directory
create_top_dir()
if args.log_stream:
# set up console logs
global logger
global console
logger.addHandler(console)
logger.debug('Starting...')
if args.clear_cache:
logger.debug('Clearing cache...')
cache.clear()
if hasattr(args, 'name') and args.name == 'report':
if args.dockerfile:
run.execute_dockerfile(args)
if args.docker_image:
if common.check_tar(args.docker_image):
logger.error("%s", errors.incorrect_raw_option)
else:
run.execute_docker_image(args)
logger.debug('Report completed.')
if args.raw_image:
if not common.check_tar(args.raw_image):
logger.error("%s", errors.invalid_raw_image.format(
image=args.raw_image))
else:
run.execute_docker_image(args)
logger.debug('Report completed.')
logger.debug('Finished')
# find the binary and shell by mounting the base layer
target = rootfs.mount_base_layer(image_obj.layers[0].tar_file)
binary = common.get_base_bin()
shell = get_shell(image_obj, binary)
# set up a notice origin for the first layer
origin_first_layer = 'Layer: ' + image_obj.layers[0].fs_hash[:10]
# only extract packages if there is a known binary and the layer is not
# cached
if binary:
if not common.load_from_cache(image_obj.layers[0], redo):
# Determine pacakge/os style from binary in the image layer
common.get_os_style(image_obj.layers[0], binary)
# get the packages of the first layer
try:
rootfs.prep_rootfs(target)
common.add_base_packages(image_obj.layers[0], binary, shell)
except KeyboardInterrupt:
logger.critical(errors.keyboard_interrupt)
abort_analysis()
# unmount proc, sys and dev
rootfs.undo_mount()
else:
logger.warning(errors.no_package_manager)
# /etc/os-release may still be present even if binary is not
common.get_os_style(image_obj.layers[0], None)
image_obj.layers[0].origins.add_notice_to_origins(
origin_first_layer, Notice(errors.no_package_manager, 'warning'))
# no binary means there is no shell so set to default shell
logger.warning('Unknown filesystem. Using default shell')
shell = constants.shell
# unmount the first layer
rootfs.unmount_rootfs()
3. Create layer objects with incremental integers and add the package
list to that layer with a Notice about parsing
4. Return stub image'''
stub_image = Image('easteregg:cookie')
layer_count = 0
for inst in dhelper.docker_commands:
if inst[0] == 'RUN':
layer_count = layer_count + 1
layer = ImageLayer(layer_count)
install_commands, msg = common.filter_install_commands(inst[1])
if msg:
layer.origins.add_notice_to_origins(
inst[1], Notice(msg, 'info'))
pkg_names = []
for command in install_commands:
pkg_names.append(common.get_installed_package_names(command))
for pkg_name in pkg_names:
pkg = Package(pkg_name)
# shell parser does not parse version pins yet
# when that is enabled, Notices for no versions need to be
# added here
layer.add_package(pkg)
return stub_image