diff --git a/openscap_report/report_generators/html_templates/evaluation_characteristics.html b/openscap_report/report_generators/html_templates/evaluation_characteristics.html index 47e8510f..6adf8e04 100644 --- a/openscap_report/report_generators/html_templates/evaluation_characteristics.html +++ b/openscap_report/report_generators/html_templates/evaluation_characteristics.html @@ -155,6 +155,20 @@

+ + {%- for type, addresses in report.scan_result.target_addresses.items() -%} +
  • +
    +
    +
    Target {{ type }} addresses:
    +
    + {{- ", ".join(addresses) -}} +
    +
    +
    +
  • + {%- endfor -%} + diff --git a/openscap_report/scap_results_parser/data_structures/result_of_scan.py b/openscap_report/scap_results_parser/data_structures/result_of_scan.py index 0b2aa35d..e65daee4 100644 --- a/openscap_report/scap_results_parser/data_structures/result_of_scan.py +++ b/openscap_report/scap_results_parser/data_structures/result_of_scan.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: LGPL-2.1-or-later from dataclasses import asdict, dataclass, field -from typing import List +from typing import Dict, List SCAN_JSON_KEYS = [ "title", @@ -21,6 +21,7 @@ "score_system", "score", "score_max", + "target_addresses", ] SCORE_COMPUTATION_EXPLANATIONS = { @@ -68,6 +69,7 @@ class ResultOfScan: # pylint: disable=R0902 score_system: str = "" score: float = 0.0 score_max: float = 0.0 + target_addresses: Dict[str, list] = field(default_factory=dict) def as_dict(self): return asdict(self) diff --git a/openscap_report/scap_results_parser/parsers/scan_result_parser.py b/openscap_report/scap_results_parser/parsers/scan_result_parser.py index aeb78b11..58028bbf 100644 --- a/openscap_report/scap_results_parser/parsers/scan_result_parser.py +++ b/openscap_report/scap_results_parser/parsers/scan_result_parser.py @@ -23,6 +23,16 @@ def _get_text_of_element(self, element_path): return "" return element.text + def _get_list_of_addresses(self, type_): + out = [] + path = ( + ".//xccdf:target-facts/xccdf:fact" + f"[@name='urn:xccdf:fact:asset:identifier:{type_.lower()}']" + ) + for address in self.test_results_el.findall(path, NAMESPACES): + out.append(address.text) + return out + def get_test_result(self): score_el = self.test_results_el.find(".//xccdf:score", NAMESPACES) @@ -50,4 +60,9 @@ def get_test_result(self): if profile_name is not None: scan_result_dict["profile_id"] = profile_name.get("idref") + target_addresses = {} + for type_ in ["MAC", "IPv4", "IPv6"]: + target_addresses[type_] = self._get_list_of_addresses(type_) + + scan_result_dict["target_addresses"] = target_addresses return ResultOfScan(**scan_result_dict) diff --git a/tests/json_schema_of_report.json b/tests/json_schema_of_report.json index 7fd86766..61078112 100644 --- a/tests/json_schema_of_report.json +++ b/tests/json_schema_of_report.json @@ -112,7 +112,31 @@ "title": "Score Max", "default": 0.0, "type": "number" - } + }, + "target_addresses": { + "title": "Target addresses", + "type": "object", + "properties": { + "IPv4": { + "type": "array", + "items": { + "type": "string" + } + }, + "IPv6": { + "type": "array", + "items": { + "type": "string" + } + }, + "MAC": { + "type": "array", + "items": { + "type": "string" + } + } + } + } }, "required": [ "title", @@ -128,7 +152,8 @@ "end_time", "test_system", "score", - "score_max" + "score_max", + "target_addresses" ] }, "rules": {