예제 #1
0
    def merge(self, other):
        """Merge the artifacts and evidence from another StepResult into
        this StepResult. The other StepResult must have the same step name,
        sub step name and environment.

        Parameters
        ----------
        step_result : StepResult
            The second StepResult instance to merge into this one

        Raises
        ------
        StepRunnerException if the StepResult to merge does not have a
        matching step name, sub-step name, or environment.
        """

        if not isinstance(other, StepResult):
            raise StepRunnerException('expect StepResult instance type')

        if other.step_name != self.step_name or \
            other.sub_step_name != self.sub_step_name or \
            other.environment != self.environment:
            raise StepRunnerException(
                    'Other StepResult does not have matching ' \
                    'step name, sub step name, or environment.'
                  )

        for artifact in other.artifacts.values():
            self.add_artifact(artifact.name, artifact.value,
                              artifact.description)

        for evidence in other.evidence.values():
            self.add_evidence(evidence.name, evidence.value,
                              evidence.description)
    def test_fail(self, mock_write_working_file, mock_run_maven_step):
        with TempDirectory() as test_dir:
            parent_work_dir_path = os.path.join(test_dir.path, 'working')

            step_config = {}
            step_implementer = self.create_step_implementer(
                step_config=step_config,
                parent_work_dir_path=parent_work_dir_path,
            )

            # run step with mock failure
            mock_run_maven_step.side_effect = StepRunnerException(
                'Mock error running maven')
            actual_step_result = step_implementer._run_step()

            # create expected step result
            expected_step_result = StepResult(
                step_name='foo',
                sub_step_name='MavenGeneric',
                sub_step_implementer_name='MavenGeneric')
            expected_step_result.add_artifact(
                description="Standard out and standard error from maven.",
                name='maven-output',
                value='/mock/mvn_output.txt')
            expected_step_result.message = "Error running maven. " \
                "More details maybe found in 'maven-output' report artifact: "\
                "Mock error running maven"
            expected_step_result.success = False

            # verify step result
            self.assertEqual(actual_step_result, expected_step_result)

            mock_write_working_file.assert_called_once()
            mock_run_maven_step.assert_called_with(
                mvn_output_file_path='/mock/mvn_output.txt')
예제 #3
0
    def test_dynamically_determined_test_reports_dir_errors(
            self, mock_attempt_get_test_report_directory):
        with TempDirectory() as test_dir:
            # setup test
            parent_work_dir_path = os.path.join(test_dir.path, 'working')
            step_config = {}
            step_implementer = self.create_step_implementer(
                step_config=step_config,
                parent_work_dir_path=parent_work_dir_path,
            )

            # setup mocks
            mock_attempt_get_test_report_directory.side_effect = StepRunnerException(
                'mock error')

            # run test
            actual_test_report_dir = step_implementer._MavenIntegrationTest__get_test_report_dir(
            )

            # verify results
            self.assertEqual(actual_test_report_dir, None)
            mock_attempt_get_test_report_directory.assert_has_calls([
                call(plugin_name='maven-failsafe-plugin',
                     configuration_key='reportsDirectory',
                     default='target/failsafe-reports'),
                call(plugin_name='maven-surefire-plugin',
                     configuration_key='reportsDirectory',
                     default='target/surefire-reports',
                     require_phase_execution_config=True)
            ])
예제 #4
0
    def test_fail_set_version(self, mock_settings_file,
                              mock_write_working_file, mock_run_maven_step,
                              mock_run_maven):
        with TempDirectory() as test_dir:
            parent_work_dir_path = os.path.join(test_dir.path, 'working')

            pom_file = os.path.join(test_dir.path, 'mock-pom.xml')
            maven_push_artifact_repo_id = 'mock-repo-id'
            maven_push_artifact_repo_url = 'https://mock-repo.ploigos.com'
            version = '0.42.0-mock'
            step_config = {
                'pom-file': pom_file,
                'maven-push-artifact-repo-id': maven_push_artifact_repo_id,
                'maven-push-artifact-repo-url': maven_push_artifact_repo_url,
                'version': version
            }
            step_implementer = self.create_step_implementer(
                step_config=step_config,
                parent_work_dir_path=parent_work_dir_path,
            )

            # run step with mvn version:set failure
            mock_run_maven.side_effect = StepRunnerException(
                'mock error setting new pom version')
            actual_step_result = step_implementer._run_step()

            # create expected step result
            expected_step_result = StepResult(
                step_name='deploy',
                sub_step_name='MavenDeploy',
                sub_step_implementer_name='MavenDeploy')
            expected_step_result.success = False
            expected_step_result.message = "Error running 'maven deploy' to push artifacts. " \
                "More details maybe found in 'maven-output' report artifact: " \
                "mock error setting new pom version"
            expected_step_result.add_artifact(
                description=
                "Standard out and standard error from running maven to update version.",
                name='maven-update-version-output',
                value='/mock/mvn_versions_set_output.txt')
            expected_step_result.add_artifact(
                description="Standard out and standard error from running maven to " \
                    "push artifacts to repository.",
                name='maven-push-artifacts-output',
                value='/mock/mvn_deploy_output.txt'
            )

            # verify step result
            self.assertEqual(actual_step_result, expected_step_result)

            mock_write_working_file.assert_called()
            mock_run_maven.assert_called_with(
                mvn_output_file_path='/mock/mvn_versions_set_output.txt',
                settings_file='/fake/settings.xml',
                pom_file=pom_file,
                phases_and_goals=['versions:set'],
                additional_arguments=[f'-DnewVersion={version}'])
            mock_run_maven_step.assert_not_called()
예제 #5
0
    def test_fail_with_report_dir(
        self,
        mock_gather_evidence,
        mock_get_test_report_dir,
        mock_write_working_file,
        mock_run_maven_step
    ):
        with TempDirectory() as test_dir:
            # setup test
            parent_work_dir_path = os.path.join(test_dir.path, 'working')
            pom_file = os.path.join(test_dir.path, 'mock-pom.xml')
            step_config = {
                'pom-file': pom_file
            }
            step_implementer = self.create_step_implementer(
                step_config=step_config,
                parent_work_dir_path=parent_work_dir_path,
            )

            # setup mocks
            mock_run_maven_step.side_effect = StepRunnerException('mock error')

            # run test
            actual_step_result = step_implementer._run_step()

            # verify results
            expected_step_result = StepResult(
                step_name='unit-test',
                sub_step_name='MavenTest',
                sub_step_implementer_name='MavenTest'
            )
            expected_step_result.success = False
            expected_step_result.message = "Error running maven. " \
                "More details maybe found in report artifacts: " \
                "mock error"
            expected_step_result.add_artifact(
                description="Standard out and standard error from maven.",
                name='maven-output',
                value='/mock/mvn_output.txt'
            )
            expected_step_result.add_artifact(
                description="Test report generated when running unit tests.",
                name='test-report',
                value='/mock/test-results-dir'
            )
            self.assertEqual(actual_step_result, expected_step_result)

            mock_run_maven_step.assert_called_once_with(
                mvn_output_file_path='/mock/mvn_output.txt'
            )
            mock_gather_evidence.assert_called_once_with(
                step_result=Any(StepResult),
                test_report_dir='/mock/test-results-dir'
            )
예제 #6
0
    def add_evidence(self, name, value, description=''):
        """Add evidence to this StepResult.

        Parameters
        ----------
        name : str
            Name of the result evidence.
        value : str
            Arbitrary value of the evidence.
        description : str, optional
            Human readable description of the result evidence (defaults to empty).
        """
        if not name:
            raise StepRunnerException('Name is required to add evidence')

        # False can be the value
        if value == '' or value is None:
            raise StepRunnerException('Value is required to add evidence')

        self.__evidence[name] = StepResultEvidence(name=name,
                                                   value=value,
                                                   description=description)
예제 #7
0
    def add_artifact(self, name, value, description=''):
        """Add an artifact to this StepResult.

        Parameters
        ----------
        name : str
            Name of the result artifact.
        value : str
            Arbitrary value of the artifact.
        description : str, optional
            Human readable description of the result artifact (defaults to empty).
        """
        if not name:
            raise StepRunnerException('Name is required to add artifact')

        # False can be the value
        if value == '' or value is None:
            raise StepRunnerException('Value is required to add artifact')

        self.__artifacts[name] = StepResultArtifact(name=name,
                                                    value=value,
                                                    description=description)
예제 #8
0
    def test_fail_no_report_dir(self, mock_gather_evidence,
                                mock_get_test_report_dir,
                                mock_write_working_file, mock_run_maven_step):
        with TempDirectory() as test_dir:
            # setup test
            parent_work_dir_path = os.path.join(test_dir.path, 'working')
            pom_file = os.path.join(test_dir.path, 'mock-pom.xml')
            step_config = {
                'pom-file': pom_file,
                'target-host-url-maven-argument-name':
                'mock.target-host-url-param',
                'deployed-host-urls': ['https://mock.ploigos.org/mock-app-1']
            }
            step_implementer = self.create_step_implementer(
                step_config=step_config,
                parent_work_dir_path=parent_work_dir_path,
            )

            # setup mocks
            mock_run_maven_step.side_effect = StepRunnerException('mock error')
            mock_get_test_report_dir.return_value = None

            # run test
            actual_step_result = step_implementer._run_step()

            # verify results
            expected_step_result = StepResult(
                step_name='unit-test',
                sub_step_name='MavenIntegrationTest',
                sub_step_implementer_name='MavenIntegrationTest')
            expected_step_result.success = False
            expected_step_result.message = "Error running maven. " \
                "More details maybe found in report artifacts: " \
                "mock error"
            expected_step_result.add_artifact(
                description="Standard out and standard error from maven.",
                name='maven-output',
                value='/mock/mvn_output.txt')
            self.assertEqual(actual_step_result, expected_step_result)

            mock_run_maven_step.assert_called_once_with(
                mvn_output_file_path='/mock/mvn_output.txt',
                step_implementer_additional_arguments=[
                    '-Dmock.target-host-url-param=https://mock.ploigos.org/mock-app-1'
                ])
            mock_gather_evidence.assert_not_called()
예제 #9
0
    def test_fail_maven_run(self, mock_effective_pom_element,
                            mock_write_working_file, mock_run_maven_step):
        with TempDirectory() as test_dir:
            parent_work_dir_path = os.path.join(test_dir.path, 'working')

            pom_file = os.path.join(test_dir.path, 'mock-pom.xml')
            step_config = {'pom-file': pom_file}
            step_implementer = self.create_step_implementer(
                step_config=step_config,
                parent_work_dir_path=parent_work_dir_path,
            )

            # run step with mock failure
            mock_run_maven_step.side_effect = StepRunnerException(
                'Mock error running maven')
            actual_step_result = step_implementer._run_step()

            # create expected step result
            surefire_reports_dir = os.path.join(test_dir.path,
                                                'target/surefire-reports')
            expected_step_result = StepResult(
                step_name='unit-test',
                sub_step_name='MavenTest',
                sub_step_implementer_name='MavenTest')
            expected_step_result.success = False
            expected_step_result.message = "Error running 'maven test' to run unit tests. " \
                "More details maybe found in 'maven-output' and `surefire-reports` " \
                f"report artifact: Mock error running maven"
            expected_step_result.add_artifact(
                description="Standard out and standard error from maven.",
                name='maven-output',
                value='/mock/mvn_output.txt')
            expected_step_result.add_artifact(
                description="Surefire reports generated by maven.",
                name='surefire-reports',
                value=surefire_reports_dir)

            # verify step result
            self.assertEqual(actual_step_result, expected_step_result)

            mock_write_working_file.assert_called_once()
            mock_run_maven_step.assert_called_with(
                mvn_output_file_path='/mock/mvn_output.txt')
예제 #10
0
    def __buildah_mount_container(buildah_unshare_command, container_id):
        """Use buildah to mount a container.

        Parameters
        ----------
        buildah_unshare_command : sh.buildah.unshare.bake()
            A baked sh.buildah.unshare command to use to run this command in the context off
            so that this can be done "rootless".
        container_id : str
            ID of the container to mount.

        Returns
        -------
        str
            Absolute path to the mounted container.

        Raises
        ------
        StepRunnerException
            If error mounting the container.
        """
        mount_path = None
        try:
            buildah_mount_out_buff = StringIO()
            buildah_mount_out_callback = create_sh_redirect_to_multiple_streams_fn_callback(
                [sys.stdout, buildah_mount_out_buff])
            buildah_mount_command = buildah_unshare_command.bake(
                "buildah", "mount")
            buildah_mount_command('--storage-driver',
                                  'vfs',
                                  container_id,
                                  _out=buildah_mount_out_callback,
                                  _err=sys.stderr,
                                  _tee='err')
            mount_path = buildah_mount_out_buff.getvalue().rstrip()
        except sh.ErrorReturnCode as error:
            raise StepRunnerException(
                f'Error mounting container ({container_id}): {error}'
            ) from error

        return mount_path
예제 #11
0
    def __get_oscap_document_type(oscap_input_file):
        """Gets the OpenSCAP document type for a given input file.

        Parameters
        ----------
        oscap_input_file : path
            Path to OSCAP file to determine the OpenSCAP document type of.

        Returns
        -------
        str
            OpenSCAP document type. For example:
            * Source Data Stream
            * XCCDF Checklist
            * OVAL Definitions

        Raises
        ------
        StepRunnerException
            If error getting document type of oscap input file.
        """

        oscap_document_type = None
        try:
            oscap_info_out_buff = StringIO()
            sh.oscap.info(  # pylint: disable=no-member
                oscap_input_file,
                _out=oscap_info_out_buff)
            oscap_info_out = oscap_info_out_buff.getvalue().rstrip()
            oscap_document_type_match = OpenSCAPGeneric.OSCAP_INFO_DOC_TYPE_PATTERN.search(
                oscap_info_out)
            oscap_document_type = oscap_document_type_match.groupdict(
            )['doctype']
        except sh.ErrorReturnCode as error:
            raise StepRunnerException(
                f"Error getting document type of oscap input file"
                f" ({oscap_input_file}): {error}") from error

        return oscap_document_type
예제 #12
0
    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.

        Raises
        ------
        StepRunnerException
            If error importing image.
        """
        # 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 StepRunnerException(
                f'Error importing the image ({image_tar_file}): {error}'
            ) from error

        return container_name
def raise_StepRunnerException():
    raise StepRunnerException('test')
예제 #14
0
    def __run_oscap_scan(  # pylint: disable=too-many-arguments,too-many-locals,too-many-branches,too-many-statements
            buildah_unshare_command,
            oscap_eval_type,
            oscap_input_file,
            oscap_out_file_path,
            oscap_xml_results_file_path,
            oscap_html_report_path,
            container_mount_path,
            oscap_profile=None,
            oscap_tailoring_file=None,
            oscap_fetch_remote_resources=True):
        """Run an oscap scan in the context of a buildah unshare to run "rootless".

        Parameters
        ----------
        buildah_unshare_command : sh.buildah.unshare.bake()
            A baked sh.buildah.unshare command to use to run this command in the context off
            so that this can be done "rootless".
        oscap_eval_type : str
            The type of oscap eval to perform. Must be a valid oscap eval type.
            EX: xccdf, oval
        oscap_input_file : str
            Path to rules file passed to the oscap command.
        oscap_out_file_path : str
            Path to write the stdout and stderr of running the oscap command to.
        oscap_xml_results_file_path : str
            Write the scan results into this file.
        oscap_html_report_path : str
            Write the human readable (HTML) report into this file.
        container_mount_path : str
            Path to the mounted container to scan.
        oscap_tailoring_file : str
            XCCF Tailoring file.
            See:
            - https://www.open-scap.org/security-policies/customization/
            - https://www.open-scap.org/resources/documentation/customizing-scap-security-guide-for-your-use-case/ # pylint: disable=line-too-long
            - https://static.open-scap.org/openscap-1.2/oscap_user_manual.html#_how_to_tailor_source_data_stream # pylint: disable=line-too-long
        oscap_profile : str
            OpenSCAP profile to evaluate. Must be a valid profile in the given oscap_input_file.
            EX: if you perform an `oscap info oscap_input_file` the profile must be listed.

        Returns
        -------
        oscap_eval_success : bool
            True if oscap eval passed all rules
            False if oscap eval failed any rules
        oscap_eval_fails : str
            If oscap_eval_success is True then indeterminate.
            If oscap_eval_success is False then string of all of the failed rules.

        Raises
        ------
        StepRunnerException
            If unexpected error running oscap scan.
        """

        oscap_profile_flag = None
        if oscap_profile is not None:
            oscap_profile_flag = f"--profile={oscap_profile}"

        oscap_fetch_remote_resources_flag = None
        if isinstance(oscap_fetch_remote_resources, str):
            oscap_fetch_remote_resources = strtobool(
                oscap_fetch_remote_resources)
        if oscap_fetch_remote_resources:
            oscap_fetch_remote_resources_flag = "--fetch-remote-resources"

        oscap_tailoring_file_flag = None
        if oscap_tailoring_file is not None:
            oscap_tailoring_file_flag = f"--tailoring-file={oscap_tailoring_file}"

        oscap_eval_success = None
        oscap_eval_out_buff = StringIO()
        oscap_eval_out = ""
        oscap_eval_fails = None
        try:
            oscap_chroot_command = buildah_unshare_command.bake("oscap-chroot")
            with open(oscap_out_file_path, 'w') as oscap_out_file:
                out_callback = create_sh_redirect_to_multiple_streams_fn_callback(
                    [oscap_eval_out_buff, oscap_out_file])
                err_callback = create_sh_redirect_to_multiple_streams_fn_callback(
                    [oscap_eval_out_buff, oscap_out_file])
                oscap_chroot_command(
                    container_mount_path,
                    oscap_eval_type,
                    'eval',
                    oscap_profile_flag,
                    oscap_fetch_remote_resources_flag,
                    oscap_tailoring_file_flag,
                    f'--results={oscap_xml_results_file_path}',
                    f'--report={oscap_html_report_path}',
                    oscap_input_file,
                    _out=out_callback,
                    _err=err_callback,
                    _tee='err')
                oscap_eval_success = True
        except sh.ErrorReturnCode_1 as error:  # pylint: disable=no-member
            oscap_eval_success = error
        except sh.ErrorReturnCode_2 as error:  # pylint: disable=no-member
            # XCCDF: If there is at least one rule with either fail or unknown result,
            #           oscap-scan finishes with return code 2.
            # OVAL:  Never returned
            #
            # Source: https://www.systutorials.com/docs/linux/man/8-oscap/
            if oscap_eval_type == 'xccdf':
                oscap_eval_success = False
            else:
                oscap_eval_success = error
        except sh.ErrorReturnCode as error:
            oscap_eval_success = error

        # get the oscap output
        oscap_eval_out = oscap_eval_out_buff.getvalue()

        # parse the oscap output
        # NOTE: oscap is puts carrage returns (\r / ^M) in their output, remove them
        oscap_eval_out = re.sub('\r', '', oscap_eval_out)

        # print the oscap output no matter the results
        print(oscap_eval_out)

        # if unexpected error throw error
        if isinstance(oscap_eval_success, Exception):
            raise StepRunnerException(
                f"Error running 'oscap {oscap_eval_type} eval': {oscap_eval_success} "
            ) from oscap_eval_success

        # NOTE: oscap oval eval returns exit code 0 whether or not any rules failed
        #       need to search output to determine if there were any rule failures
        if oscap_eval_type == 'oval' and oscap_eval_success:
            oscap_eval_fails = ""
            for match in OpenSCAPGeneric.OSCAP_OVAL_STDOUT_PATTERN.finditer(
                    oscap_eval_out):
                # NOTE: need to do regex and not == because may contain xterm color chars
                if OpenSCAPGeneric.OSCAP_OVAL_STDOUT_FAIL_PATTERN.search(
                        match.groupdict()['ruleresult']):
                    oscap_eval_fails += match.groupdict()['ruleblock']
                    oscap_eval_fails += "\n"
                    oscap_eval_success = False

        # if failed xccdf eval then parse out the fails
        if oscap_eval_type == 'xccdf' and not oscap_eval_success:
            oscap_eval_fails = ""
            for match in OpenSCAPGeneric.OSCAP_XCCDF_STDOUT_PATTERN.finditer(
                    oscap_eval_out):
                # NOTE: need to do regex and not == because may contain xterm color chars
                if re.search(r'fail', match.groupdict()['ruleresult']):
                    oscap_eval_fails += "\n"
                    oscap_eval_fails += match.groupdict()['ruleblock']
                    oscap_eval_fails += "\n"

        return oscap_eval_success, oscap_eval_fails
예제 #15
0
    def _run_step(self):  # pylint: disable=too-many-locals,too-many-statements
        """Runs the OpenSCAP eval for a given input file against a given container.
        """
        step_result = StepResult.from_step_implementer(self)

        image_tar_file = self.get_value('image-tar-file')

        oscap_profile = self.get_value('oscap-profile')
        oscap_fetch_remote_resources = self.get_value(
            'oscap-fetch-remote-resources')

        # create a container name from the tar file name, step name, and sub step name
        container_name = os.path.splitext(os.path.basename(image_tar_file))[0]
        container_name += f"-{self.step_name}-{self.sub_step_name}"

        try:
            # import image tar file to vfs file system
            print(f"\nImport image: {image_tar_file}")
            OpenSCAPGeneric.__buildah_import_image_from_tar(
                image_tar_file=image_tar_file, container_name=container_name)
            print(f"Imported image: {image_tar_file}")

            # baking `buildah unshare` command to wrap other buildah commands with
            # so that container does not need to be running in a privileged mode to be able
            # to function
            buildah_unshare_command = 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 privileged mode
            print(f"\nMount container: {container_name}")
            container_mount_path = OpenSCAPGeneric.__buildah_mount_container(
                buildah_unshare_command=buildah_unshare_command,
                container_id=container_name)
            print(
                f"Mounted container ({container_name}) with mount path: '{container_mount_path}'"
            )

            try:
                # download the open scap input file
                oscap_input_definitions_uri = self.get_value(
                    'oscap-input-definitions-uri')
                print(
                    f"\nDownload input definitions: {oscap_input_definitions_uri}"
                )
                oscap_input_file = download_and_decompress_source_to_destination(
                    source_url=oscap_input_definitions_uri,
                    destination_dir=self.work_dir_path_step)
                print(f"Downloaded input definitions to: {oscap_input_file}")
            except (RuntimeError, AssertionError) as error:
                raise StepRunnerException(
                    f"Error downloading OpenSCAP input file: {error}"
                ) from error

            try:
                # if specified download oscap tailoring file
                oscap_tailoring_file = None
                oscap_tailoring_file_uri = self.get_value(
                    'oscap-tailoring-uri')
                if oscap_tailoring_file_uri:
                    print(
                        f"\nDownload oscap tailoring file: {oscap_tailoring_file_uri}"
                    )
                    oscap_tailoring_file = download_and_decompress_source_to_destination(
                        source_url=oscap_tailoring_file_uri,
                        destination_dir=self.work_dir_path_step)
                    print(
                        f"Download oscap tailoring file to: {oscap_tailoring_file}"
                    )
            except (RuntimeError, AssertionError) as error:
                raise StepRunnerException(
                    f"Error downloading OpenSCAP tailoring file: {error}"
                ) from error

            # determine oscap eval type based on document type
            print(
                f"\nDetermine OpenSCAP document type of input file: {oscap_input_file}"
            )
            oscap_document_type = OpenSCAPGeneric.__get_oscap_document_type(
                oscap_input_file=oscap_input_file)
            print("Determined OpenSCAP document type of input file"
                  f" ({oscap_input_file}): {oscap_document_type}")
            print(
                f"\nDetermine OpenSCAP eval type for input file ({oscap_input_file}) "
                f"of document type: {oscap_document_type}")
            oscap_eval_type = OpenSCAPGeneric.__get_oscap_eval_type_based_on_document_type(
                oscap_document_type=oscap_document_type)
            print("Determined OpenSCAP eval type of input file"
                  f" ({oscap_input_file}): {oscap_eval_type}")

            # 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
            oscap_out_file_path = self.write_working_file(
                f'oscap-{oscap_eval_type}-out')
            oscap_xml_results_file_path = self.write_working_file(
                f'oscap-{oscap_eval_type}-results.xml')
            oscap_html_report_path = self.write_working_file(
                f'oscap-{oscap_eval_type}-report.html')
            print("\nRun oscap scan")
            oscap_eval_success, oscap_eval_fails = OpenSCAPGeneric.__run_oscap_scan(
                buildah_unshare_command=buildah_unshare_command,
                oscap_eval_type=oscap_eval_type,
                oscap_input_file=oscap_input_file,
                oscap_out_file_path=oscap_out_file_path,
                oscap_xml_results_file_path=oscap_xml_results_file_path,
                oscap_html_report_path=oscap_html_report_path,
                container_mount_path=container_mount_path,
                oscap_profile=oscap_profile,
                oscap_tailoring_file=oscap_tailoring_file,
                oscap_fetch_remote_resources=oscap_fetch_remote_resources)
            print(
                f"OpenSCAP scan completed with eval success: {oscap_eval_success}"
            )

            # save scan results
            step_result.success = oscap_eval_success
            if not oscap_eval_success:
                step_result.message = f"OSCAP eval found issues:\n{oscap_eval_fails}"

            step_result.add_artifact(name='html-report',
                                     value=oscap_html_report_path)
            step_result.add_artifact(name='xml-report',
                                     value=oscap_xml_results_file_path)
            step_result.add_artifact(name='stdout-report',
                                     value=oscap_out_file_path)
        except StepRunnerException as error:
            step_result.success = False
            step_result.message = str(error)

        return step_result