Skip to content

Commit

Permalink
Adapt the mapping of OVAL definitions to the new OVAL definition anal…
Browse files Browse the repository at this point in the history
…ysis system and specify which OVAL result report is for CPE
  • Loading branch information
Honny1 committed Mar 24, 2023
1 parent 5543bcc commit c105d74
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 36 deletions.
112 changes: 82 additions & 30 deletions openscap_report/scap_results_parser/oval_and_cpe_tree_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,53 +9,89 @@


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.dict_of_oval_cpe_definitions = {}
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.dict_of_oval_cpe_definitions = self._get_dict_of_oval_cpe_definitions()
self.cpe_al_parser = CPEApplicabilityLanguageParser(
self.root, self.dict_of_oval_cpe_definitions
)
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 len(source_id) == 1:
self.cpe_source = source_id.pop()

def _get_dict_of_oval_cpe_definitions(self):
if self.cpe_source in self.reports_with_oval_definitions:
return self.reports_with_oval_definitions[self.cpe_source]
logging.warning((
"The given input does not contain a clear mapping of the OVAL definition used"
" for CPE checks. The results of the OVAL definition in the CPE checks could "
"be biased."
))
all_oval_definition = {}
for report in self.reports_with_oval_definitions.values():
for id_definition, definition in report.items():
if id_definition not in all_oval_definition:
all_oval_definition[id_definition] = definition
else:
if definition.oval_tree.evaluate_tree() != "not evaluated":
all_oval_definition[id_definition] = definition
return all_oval_definition

def _get_oval_definition_of_cpe(self, platform):
cpe_oval_id = self.platform_to_oval_cpe_id.get(platform)
return self.dict_of_oval_cpe_definitions.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
Expand All @@ -69,8 +105,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.dict_of_oval_cpe_definitions:
return self.dict_of_oval_cpe_definitions[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)
Expand Down Expand Up @@ -98,13 +134,29 @@ def _remove_double_cpe_requirement(rule, group_platforms):
if platform in group_platforms:
group_platforms.remove(platform)

def get_oval_definition(self, rule):
report = self.reports_with_oval_definitions.get(rule.oval_reference, None)
if report is not None:
return report.get(rule.oval_definition_id)
oval_def = None
for report in self.reports_with_oval_definitions.values():
if oval_def is not None and rule.oval_definition_id in report:
logging.warning(
("The given input contains the duplicate results of"
" the OVAL definition (\"%s\")."),
rule.oval_definition_id
)
if rule.oval_definition_id in report:
oval_def = report[rule.oval_definition_id]
return oval_def

def insert_oval_and_cpe_trees_to_rules(self, rules):
if self.missing_oval_results:
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.get_oval_definition(rule)

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)
Expand Down
7 changes: 3 additions & 4 deletions openscap_report/scap_results_parser/parsers/cpe_al_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 = ""
Expand Down
13 changes: 11 additions & 2 deletions openscap_report/scap_results_parser/scap_results_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)

Expand Down

0 comments on commit c105d74

Please sign in to comment.