diff --git a/openscap_report/report_generators/html_templates/rule_detail.html b/openscap_report/report_generators/html_templates/rule_detail.html
index a774103e..3ae5087e 100644
--- a/openscap_report/report_generators/html_templates/rule_detail.html
+++ b/openscap_report/report_generators/html_templates/rule_detail.html
@@ -136,20 +136,21 @@
References: |
-
-
-
+
{%- for reference in rule.references -%}
- {%- if reference.href -%}
- {{ reference.text }}
- {%- else -%}
- {{ reference.text }}
- {%- endif -%}
- {{- ", " if not loop.last else "" -}}
+
+
+ {{ reference.name }}:
+ |
+
+ {%- for ref_id in reference.ref_ids -%}
+ {{ ref_id }}
+ {{- ", " if not loop.last else "" -}}
+ {%- endfor -%}
+ |
+
{%- endfor -%}
-
-
-
+
|
{% endif %}
diff --git a/openscap_report/scap_results_parser/data_structures/reference.py b/openscap_report/scap_results_parser/data_structures/reference.py
index 64952b54..7419216d 100644
--- a/openscap_report/scap_results_parser/data_structures/reference.py
+++ b/openscap_report/scap_results_parser/data_structures/reference.py
@@ -11,8 +11,9 @@
@dataclass
class Reference:
+ name: str
href: str
- text: str
+ ref_ids: list[str]
def as_dict(self):
return asdict(self)
diff --git a/openscap_report/scap_results_parser/parsers/rule_parser.py b/openscap_report/scap_results_parser/parsers/rule_parser.py
index 05a031b7..2677d3c9 100644
--- a/openscap_report/scap_results_parser/parsers/rule_parser.py
+++ b/openscap_report/scap_results_parser/parsers/rule_parser.py
@@ -1,6 +1,8 @@
# Copyright 2022, Red Hat, Inc.
# SPDX-License-Identifier: LGPL-2.1-or-later
+import collections
+
from dataclasses import replace
from ..data_structures import Identifier, Reference, Rule, RuleWarning
@@ -8,6 +10,33 @@
from .full_text_parser import FullTextParser
from .remediation_parser import RemediationParser
+KNOWN_REFERENCES = {
+ "http://www.ssi.gouv.fr/administration/bonnes-pratiques/" : "ANSSI",
+ "https://public.cyber.mil/stigs/cci/": "CCI",
+ "https://www.ccn-cert.cni.es/pdf/guias/series-ccn-stic/guias-de-acceso-publico-ccn-stic/6768-ccn-stic-610a22-perfilado-de-seguridad-red-hat-enterprise-linux-9-0/file.html": "CCN for RHEL 9",
+ "https://www.cisecurity.org/controls/": "CIS",
+ "https://www.cisecurity.org/benchmark/red_hat_linux/": "CIS for RHEL",
+ "https://www.fbi.gov/file-repository/cjis-security-policy-v5_5_20160601-2-1.pdf": "CJIS",
+ "http://www.cnss.gov/Assets/pdf/CNSSI-1253.pdf": "CNSS",
+ "https://www.isaca.org/resources/cobit": "COBIT",
+ "http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-171.pdf": "CUI",
+ "https://www.gpo.gov/fdsys/pkg/CFR-2007-title45-vol1/pdf/CFR-2007-title45-vol1-chapA-subchapC.pdf": "HIPAA",
+ "https://www.isa.org/products/ansi-isa-62443-3-3-99-03-03-2013-security-for-indu": "ISA-62443-2013",
+ "https://www.isa.org/products/isa-62443-2-1-2009-security-for-industrial-automat": "ISA-62443-2009",
+ "https://www.cyber.gov.au/acsc/view-all-content/ism": "ISM",
+ "https://www.iso.org/standard/54534.html": "ISO 27001-2013",
+ "https://www.nerc.com/pa/Stand/Standard%20Purpose%20Statement%20DL/US_Standard_One-Stop-Shop.xlsx": "NERC-CIP",
+ "http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf": "NIST 800-53",
+ "https://nvlpubs.nist.gov/nistpubs/CSWP/NIST.CSWP.04162018.pdf": "NIST CSF",
+ "https://www.niap-ccevs.org/Profile/PP.cfm": "OSPP",
+ "https://www.pcisecuritystandards.org/documents/PCI_DSS_v3-2-1.pdf": "PCI-DSS v3",
+ "https://docs-prv.pcisecuritystandards.org/PCI%20DSS/Standard/PCI-DSS-v4_0.pdf": "PCI-DSS v4",
+ "https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=application-servers": "SRG-APP",
+ "https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=operating-systems%2Cgeneral-purpose-os": "SRG-OS",
+ "https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=operating-systems%2Cunix-linux": "STIG ID",
+ "https://public.cyber.mil/stigs/srg-stig-tools/": "STIG ref",
+}
+
class RuleParser():
def __init__(self, root, test_results, ref_values):
@@ -20,10 +49,16 @@ def __init__(self, root, test_results, ref_values):
@staticmethod
def _get_references(rule):
+ url_to_ref_ids = collections.defaultdict(list)
+ for reference_el in rule.findall(".//xccdf:reference", NAMESPACES):
+ url = reference_el.get("href")
+ ref_id = reference_el.text
+ url_to_ref_ids[url].append(ref_id)
references = []
- for referenc in rule.findall(".//xccdf:reference", NAMESPACES):
- references.append(Reference(referenc.get("href"), referenc.text))
- return references
+ for url, ref_ids in url_to_ref_ids.items():
+ name = KNOWN_REFERENCES.get(url, url)
+ references.append(Reference(name, url, sorted(ref_ids)))
+ return sorted(references, key=lambda x: x.name)
@staticmethod
def _get_identifiers(rule):