def __buildah_import_image_from_tar(image_tar_file, container_name):
        """Import a container image using buildah form a TAR file.

        Parameters
        ----------
        image_tar_file : str
            Path to TAR file to import as a container image.
        container_name : str
            name for the working container.

        Returns
        -------
        str
            Name of the imported container.
        """
        # import image tar file to vfs file system
        try:
            sh.buildah(  # pylint: disable=no-member
                'from',
                '--storage-driver',
                'vfs',
                '--name',
                container_name,
                f"docker-archive:{image_tar_file}",
                _out=sys.stdout,
                _err=sys.stderr,
                _tee='err')
        except sh.ErrorReturnCode as error:
            raise RuntimeError(
                f'Unexpected runtime error importing the image ({image_tar_file}): {error}'
            ) from error

        return container_name
Example #2
0
def create_container_from_image(
    image_address,
    repository_type='container-storage:'
):
    """Import a container image using buildah form a TAR file.

    Parameters
    ----------
    image_address : str
        Image tag to create a container from.
        ex:
        * localhost/my-app:latest
        * quay.io/my-org/my-app:latest
        * docker-archive:/local/path/to/my-app-container-image.tar
    container_name : str
        name for the working container.
    repository_type : str
        The type of repository to mount the given image tag from.
        See https://github.com/containers/skopeo for details on different repository types.

    Returns
    -------
    str
        Name of the imported container.

    Raises
    ------
    RuntimeError
        If error importing image.
    """
    container_name = None
    try:
        buildah_from_out_buff = StringIO()
        buildah_from_out_callback = create_sh_redirect_to_multiple_streams_fn_callback([
            sys.stdout,
            buildah_from_out_buff
        ])
        sh.buildah(  # pylint: disable=no-member
            'from',
            f"{repository_type}{image_address}",
            _out=buildah_from_out_callback,
            _err=sys.stderr,
            _tee='err'
        )
        container_name = buildah_from_out_buff.getvalue().rstrip()
    except sh.ErrorReturnCode as error:
        raise RuntimeError(
            f'Error creating container from image ({image_address}): {error}'
        ) from error

    return container_name
    def _run_step(self):  # pylint: disable=too-many-locals
        """Runs the TSSC step implemented by this StepImplementer.

        Returns
        -------
        dict
            Results of running this step.
        """

        image_tar_file = ''
        if(self.get_step_results(DefaultSteps.CREATE_CONTAINER_IMAGE) and \
          self.get_step_results(DefaultSteps.CREATE_CONTAINER_IMAGE).get('image-tar-file')):
            image_tar_file = self.\
            get_step_results(DefaultSteps.CREATE_CONTAINER_IMAGE)['image-tar-file']
        else:
            raise RuntimeError('Missing image tar file from ' +
                               DefaultSteps.CREATE_CONTAINER_IMAGE)

        log_level = 'info'
        if self.get_config_value('log-level'):
            log_level = self.get_config_value('log-level')

        buildah_containers_pre_import_result = sh.buildah(  # pylint: disable=no-member
            '--storage-driver',
            'vfs',
            'containers',
            '-q',
            _out=sys.stdout,
            _err=sys.stderr,
            _tee=True)
        num_containers = buildah_containers_pre_import_result.stdout.count(
            b'\n')
        if num_containers > 0:
            raise ValueError('Zero vfs base containers should be running')

        try:
            # import image tar file to vfs file system
            sh.buildah(  # pylint: disable=no-member
                'from',
                '--storage-driver',
                'vfs',
                '--log-level',
                log_level,
                f"docker-archive:{image_tar_file}",
                _out=sys.stdout,
                _err=sys.stderr)

            # get container id
            buildah_containers_result = sh.buildah(  # pylint: disable=no-member
                '--storage-driver',
                'vfs',
                'containers',
                '-q',
                _out=sys.stdout,
                _err=sys.stderr,
                _tee=True)
            container_id = buildah_containers_result.stdout.rstrip()
            print(f"container_id to scan = {container_id}")

            # baking `buildah unshare` command to wrap other buildah commands with
            # so that container does not need to be running in a privilaged mode to be able
            # to function
            buildah_unshare_comand = sh.buildah.bake('unshare')  # pylint: disable=no-member

            # mount the container filesystem and get mount path
            #
            # NOTE: run in the context of `buildah unshare` so that container does not
            #       need to be run in a privilaged mode
            buildah_mount_command = buildah_unshare_comand.bake(
                "buildah", "mount")
            buildah_mount_result = buildah_mount_command('--storage-driver',
                                                         'vfs',
                                                         container_id,
                                                         _out=sys.stdout,
                                                         _err=sys.stderr,
                                                         _tee=True)
            mount_path = buildah_mount_result.stdout.rstrip()
            print(f"mount_path to scan = {mount_path}")

            # Execute scan in the context of buildah unshare
            #
            # NOTE: run in the context of `buildah unshare` so that container does not
            #       need to be run in a privilaged mode
            scan_input_file = self.get_config_value('scap-input-file').rstrip()
            scan_output_absolute_path = self.write_working_file(
                'scap-compliance-output.txt', b'')
            scan_report_absolute_path = self.write_working_file(
                'scap-compliance-report.html', b'')
            oscap_chroot_command = buildah_unshare_comand.bake("oscap-chroot")
            oscap_result = oscap_chroot_command(mount_path,
                                                'oval',
                                                'eval',
                                                '--report',
                                                scan_report_absolute_path,
                                                scan_input_file,
                                                _out=sys.stdout,
                                                _err=sys.stderr,
                                                _tee=True)

            oscap_result_file = open(scan_output_absolute_path, "w+")
            oscap_result_file.write(oscap_result.stdout.decode("utf-8"))
            oscap_result_file.close()
            print(
                "Compliance Scan Completed.  Report found at following path: "
                + scan_report_absolute_path)

        except sh.ErrorReturnCode as error:
            raise RuntimeError('Unexpected runtime error') from error

        results = {
            'result': {
                'success': True,
                'message':
                'container-image-static-compliance-scan step completed',
            },
            'report-artifacts': [{
                'name': 'container-image-static-compliance-scan result set',
                'path': 'file://' + scan_report_absolute_path
            }]
        }
        return results