diff --git a/openscap_report/scap_results_parser/oval_and_cpe_tree_builder.py b/openscap_report/scap_results_parser/oval_and_cpe_tree_builder.py index 8061b4cd..5c824cb5 100644 --- a/openscap_report/scap_results_parser/oval_and_cpe_tree_builder.py +++ b/openscap_report/scap_results_parser/oval_and_cpe_tree_builder.py @@ -9,53 +9,70 @@ class OVALAndCPETreeBuilder: # pylint: disable=R0902 - def __init__(self, root, group_parser, profile_platforms): + def __init__(self, root, group_parser, profile_platforms, oval_definitions_and_results_sources): self.profile_platforms = profile_platforms self.root = root self.group_parser = group_parser + self.oval_definitions_and_results_sources = oval_definitions_and_results_sources + self.cpe_source = "" self.missing_oval_results = False self.cpe_al = True - self.oval_definitions = {} - self.oval_cpe_definitions = {} + self.reports_with_oval_definitions = None self.platform_to_oval_cpe_id = {} self.cpe_platforms = {} self.load_oval_definitions() def load_oval_definitions(self): try: - self.cpe_al_parser = CPEApplicabilityLanguageParser(self.root) - self.platform_to_oval_cpe_id = self.cpe_al_parser.platform_to_oval_cpe_id self.oval_definition_parser = OVALDefinitionParser(self.root) - self.oval_definitions = self.oval_definition_parser.get_oval_definitions() - self.oval_cpe_definitions = self.oval_definition_parser.get_oval_cpe_definitions() + self.reports_with_oval_definitions = self.oval_definition_parser.get_oval_definitions() + self._determine_cpe_source() + self.cpe_al_parser = CPEApplicabilityLanguageParser( + self.root, + self.reports_with_oval_definitions.get(self.cpe_source, {}) + ) + self.platform_to_oval_cpe_id = self.cpe_al_parser.platform_to_oval_cpe_id self._load_cpe_platforms() except MissingOVALResult as error: logging.warning(( "The given input doesn't contain OVAL results (\"%s\")," " OVAL details won't be shown in the report."), error) - if str(error) != "oval1": - self.missing_oval_results = True + self.missing_oval_results = True + + def _determine_cpe_source(self): + source_id = set(self.reports_with_oval_definitions.keys()).difference( + self.oval_definitions_and_results_sources + ) + if source_id: + self.cpe_source = sorted(source_id, reverse=True).pop() + + def _get_oval_definition_of_cpe(self, platform): + cpe_oval_id = self.platform_to_oval_cpe_id.get(platform) + return self.reports_with_oval_definitions.get(self.cpe_source, {}).get(cpe_oval_id) def _load_cpe_platforms(self): try: - self.cpe_platforms = self.cpe_al_parser.get_cpe_platforms(self.oval_cpe_definitions) + self.cpe_platforms = self.cpe_al_parser.get_cpe_platforms() for platform in self.profile_platforms: - if platform in self.platform_to_oval_cpe_id: - cpe_oval_id = self.platform_to_oval_cpe_id[platform] - if cpe_oval_id in self.oval_cpe_definitions: - oval_tree = self.oval_cpe_definitions[cpe_oval_id].oval_tree - self.cpe_platforms[platform] = Platform( - platform_id=platform, - logical_test=LogicalTest( - node_type="AND", - children=[LogicalTest( - node_type="frac-ref", - value=cpe_oval_id, - oval_tree=oval_tree - )], - ), - title="Profile platform", - ) + oval_definition = self._get_oval_definition_of_cpe(platform) + if oval_definition is None: + logging.warning( + "Platform (\"%s\") doesn't exist, Platform won't be shown in the report.", + platform + ) + continue + self.cpe_platforms[platform] = Platform( + platform_id=platform, + logical_test=LogicalTest( + node_type="AND", + children=[LogicalTest( + node_type="frac-ref", + value=oval_definition.definition_id, + oval_tree=oval_definition.oval_tree + )], + ), + title="Profile platform", + ) self._evaluate_all_cpe_platforms() except ExceptionNoCPEApplicabilityLanguage: self.cpe_al = False @@ -69,8 +86,8 @@ def _get_oval_tree_from_oval_cpe_definition(self, platform): cpe_platform = platform.lstrip("#") if cpe_platform in self.platform_to_oval_cpe_id: cpe_oval_id = self.platform_to_oval_cpe_id[cpe_platform] - if cpe_oval_id in self.oval_cpe_definitions: - return self.oval_cpe_definitions[cpe_oval_id].oval_tree + if cpe_oval_id in self.reports_with_oval_definitions[self.cpe_source]: + return self.reports_with_oval_definitions[self.cpe_source][cpe_oval_id].oval_tree if cpe_platform in self.cpe_platforms: return None logging.warning("There is no CPE check for the platform \"%s\".", platform) @@ -103,8 +120,9 @@ def insert_oval_and_cpe_trees_to_rules(self, rules): return for rule in rules.values(): - if rule.oval_definition_id in self.oval_definitions: - rule.oval_definition = self.oval_definitions[rule.oval_definition_id] + rule.oval_definition = self.reports_with_oval_definitions.get( + rule.oval_reference, {}).get(rule.oval_definition_id) + rule_group = self.group_parser.rule_to_group_id.get(rule.rule_id, "") group_platforms = self.group_parser.group_to_platforms.get(rule_group, []) self._remove_double_cpe_requirement(rule, group_platforms) diff --git a/openscap_report/scap_results_parser/parsers/cpe_al_parser.py b/openscap_report/scap_results_parser/parsers/cpe_al_parser.py index 7dffbcba..5a3ab6c3 100644 --- a/openscap_report/scap_results_parser/parsers/cpe_al_parser.py +++ b/openscap_report/scap_results_parser/parsers/cpe_al_parser.py @@ -7,11 +7,11 @@ class CPEApplicabilityLanguageParser: - def __init__(self, root): + def __init__(self, root, oval_cpe_definitions): self.root = root self.platform_to_oval_cpe_id = self.get_platform_to_oval_cpe_id_dict() self.full_text_parser = FullTextParser({}) - self.oval_cpe_definitions = {} + self.oval_cpe_definitions = oval_cpe_definitions def get_platform_to_oval_cpe_id_dict(self): cpe_list = self.root.find(".//ds:component/cpe-dict:cpe-list", NAMESPACES) @@ -60,9 +60,8 @@ def get_logical_test(self, logical_test_el): logical_test.children.append(self.get_logical_test(child_logical_test_el)) return logical_test - def get_cpe_platforms(self, oval_cpe_definitions): + def get_cpe_platforms(self): out = {} - self.oval_cpe_definitions = oval_cpe_definitions for platform, platform_el in self._get_cpe_platform_elements().items(): title_el = platform_el.find(".//cpe-lang:title", NAMESPACES) title_str = "" diff --git a/openscap_report/scap_results_parser/scap_results_parser.py b/openscap_report/scap_results_parser/scap_results_parser.py index a4458f13..73cfcfa2 100644 --- a/openscap_report/scap_results_parser/scap_results_parser.py +++ b/openscap_report/scap_results_parser/scap_results_parser.py @@ -75,6 +75,14 @@ def _get_benchmark_element(self): benchmark_el = self.root return benchmark_el + @staticmethod + def _get_oval_definition_reference(rules): + references = [] + for rule in rules.values(): + if rule.oval_reference is not None: + references.append(rule.oval_reference) + return set(tuple(references)) + def parse_report(self): test_results_el = self.root.find('.//xccdf:TestResult', NAMESPACES) benchmark_el = self._get_benchmark_element() @@ -88,10 +96,11 @@ def parse_report(self): rule_parser = RuleParser(self.root, test_results_el, self.ref_values) rules = rule_parser.get_rules() - + oval_definitions_and_results_sources = self._get_oval_definition_reference(rules) OVAL_and_CPE_tree_builder = OVALAndCPETreeBuilder( # pylint: disable=C0103 self.root, group_parser, - self._get_applicable_cpe_ids_for_machine(report.profile_info.cpe_platforms_for_profile) + self._get_applicable_cpe_ids_for_machine(report.profile_info.cpe_platforms_for_profile), + oval_definitions_and_results_sources ) OVAL_and_CPE_tree_builder.insert_oval_and_cpe_trees_to_rules(rules)