示例#1
0
 def test_https_bad_uri(self):
     with TempDirectory() as test_dir:
         with self.assertRaisesRegex(
                 RuntimeError,
                 r"Error downloading file \(.+\): HTTP Error 404: Not Found"
         ):
             download_and_decompress_source_to_destination(
                 source_uri=
                 "https://www.redhat.com/security/data/metrics/ds/v2/RHEL8/does-not-exist.ds.xml.bz2",
                 destination_dir=test_dir.path)
示例#2
0
    def test_bad_protocol(self):
        with TempDirectory() as test_dir:

            with self.assertRaisesRegex(
                    ValueError,
                    r"Unexpected error, should have been caught by step validation."
                    r" Source \(.+\) must start with known protocol \(/|file://\|http://\|https://\)."
            ):
                download_and_decompress_source_to_destination(
                    source_uri=
                    "bad://www.redhat.com/security/data/metrics/ds/v2/RHEL8/rhel-8.ds.xml.bz2",
                    destination_dir=test_dir.path)
    def test_https_xml(self):
        with TempDirectory() as test_dir:

            destination_path = download_and_decompress_source_to_destination(
                source_uri="https://www.redhat.com/security/data/cvrf/2020/cvrf-rhba-2020-0017.xml",
                destination_dir=test_dir.path
            )

            self.assertIsNotNone(destination_path)
            self.assertRegex(destination_path, rf'{test_dir.path}/cvrf-rhba-2020-0017.xml$')
            with open(destination_path) as downloaded_file:
                self.assertTrue(downloaded_file.read())
    def test_https_bz2(self):
        with TempDirectory() as test_dir:

            destination_path = download_and_decompress_source_to_destination(
                source_uri="https://www.redhat.com/security/data/metrics/ds/v2/RHEL8/rhel-8.ds.xml.bz2",
                destination_dir=test_dir.path
            )

            self.assertIsNotNone(destination_path)
            self.assertRegex(destination_path, rf'{test_dir.path}/rhel-8.ds.xml$')
            with open(destination_path) as downloaded_file:
                self.assertTrue(downloaded_file.read())
示例#5
0
    def test_local_file_download_forward_slash_prefix(self):
        sample_file_path = os.path.join(os.path.dirname(__file__), 'files',
                                        'cvrf-rhba-2020-0017.xml')

        with TempDirectory() as test_dir:
            destination_path = download_and_decompress_source_to_destination(
                source_uri=f"{sample_file_path}",
                destination_dir=test_dir.path)

            self.assertIsNotNone(destination_path)
            self.assertRegex(destination_path,
                             rf'{test_dir.path}/cvrf-rhba-2020-0017.xml$')
            with open(destination_path) as downloaded_file, open(
                    sample_file_path) as sample_file:
                downloaded_file_contents = downloaded_file.read()
                self.assertTrue(downloaded_file_contents)
                self.assertEqual(downloaded_file_contents, sample_file.read())
示例#6
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
示例#7
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)

        # get config
        image_address = self.get_value([
            'container-image-build-address', 'container-image-push-address',
            'container-image-pull-address', 'container-image-address',
            'container-image-tag'
        ])
        oscap_profile = self.get_value('oscap-profile')
        oscap_fetch_remote_resources = self.get_value(
            'oscap-fetch-remote-resources')

        oscap_severity_index = OpenSCAPGeneric.__parse_sev_to_int(
            oscap_severity=self.get_value('oscap-severity'))

        pull_repository_type = self.get_value([
            'container-image-pull-registry-type',
            'container-image-registry-type'
        ])

        try:
            # create container from image that can be mounted
            print(f"\nCreate container from image ({image_address})")
            container_name = create_container_from_image(
                image_address=image_address,
                repository_type=pull_repository_type)
            print(
                f"Created container ({container_name}) from image ({image_address})"
            )

            # 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 = 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_uri=oscap_input_definitions_uri,
                    destination_dir=self.work_dir_path)
                print(f"Downloaded input definitions to: {oscap_input_file}")
            except (RuntimeError, ValueError) 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_uri=oscap_tailoring_file_uri,
                        destination_dir=self.work_dir_path)
                    print(
                        f"Download oscap tailoring file to: {oscap_tailoring_file}"
                    )
            except (RuntimeError, ValueError) 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, \
            oscap_failure_met_threshold = 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,
                oscap_severity_index=oscap_severity_index
            )
            print(
                f"OpenSCAP scan completed with eval success: {oscap_eval_success}"
            )

            # save scan results
            # if there were no failure or threshold was met then pass
            step_result.success = oscap_eval_success or not oscap_failure_met_threshold

            # report all issues even if they did not meet threshold
            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, RuntimeError) as error:
            step_result.success = False
            step_result.message = str(error)

        return step_result