diff --git a/dojo/settings/.settings.dist.py.sha256sum b/dojo/settings/.settings.dist.py.sha256sum index 220f2b35098..6e1a934f57d 100644 --- a/dojo/settings/.settings.dist.py.sha256sum +++ b/dojo/settings/.settings.dist.py.sha256sum @@ -1 +1 @@ -f09caa2d4e41f44b7cd6ecf2f1400817d4776e703bd039c8d857f1356382e1f3 +f85484f23e59aabe591b30db10e0de05aaeeb9d8979d236d565dc8279e03e116 diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index e9100b681b5..c5453c018de 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1760,6 +1760,7 @@ def saml2_attrib_map_format(dict): "ELSA": "https://linux.oracle.com/errata/&&.html", # e.g. https://linux.oracle.com/errata/ELSA-2024-12714.html "ELBA": "https://linux.oracle.com/errata/&&.html", # e.g. https://linux.oracle.com/errata/ELBA-2024-7457.html "RXSA": "https://errata.rockylinux.org/", # e.g. https://errata.rockylinux.org/RXSA-2024:4928 + "C-": "https://hub.armosec.io/docs/", # e.g. https://hub.armosec.io/docs/c-0085 "AVD": "https://avd.aquasec.com/misconfig/", # e.g. https://avd.aquasec.com/misconfig/avd-ksv-01010 "KHV": "https://avd.aquasec.com/misconfig/kubernetes/", # e.g. https://avd.aquasec.com/misconfig/kubernetes/khv045 "CAPEC": "https://capec.mitre.org/data/definitions/&&.html", # e.g. https://capec.mitre.org/data/definitions/157.html diff --git a/dojo/templatetags/display_tags.py b/dojo/templatetags/display_tags.py index feeb8f8d6c4..cd3627d41bf 100644 --- a/dojo/templatetags/display_tags.py +++ b/dojo/templatetags/display_tags.py @@ -780,7 +780,7 @@ def vulnerability_url(vulnerability_id): for key in settings.VULNERABILITY_URLS: if vulnerability_id.upper().startswith(key): - if key in ["AVD", "KHV"]: + if key in ["AVD", "KHV", "C-"]: return settings.VULNERABILITY_URLS[key] + str(vulnerability_id.lower()) if "&&" in settings.VULNERABILITY_URLS[key]: # Process specific keys specially if need diff --git a/dojo/tools/kubescape/parser.py b/dojo/tools/kubescape/parser.py index c371f477901..0f472a902ef 100644 --- a/dojo/tools/kubescape/parser.py +++ b/dojo/tools/kubescape/parser.py @@ -59,65 +59,65 @@ def get_findings(self, filename, test): controls = results[0].get("controls", []) for control in controls: - # This condition is true if the result doesn't contain the status for each control (old format) - retrocompatibility_condition = "status" not in control or "status" not in control["status"] - if retrocompatibility_condition or control["status"]["status"] == "failed": - control_name = control["name"] - if resource_type and resource_name and control_name: - title = f"{control_name} - {resource_type} {resource_name}" - else: - title = f"{control_name} - {resourceid}" - controlID = control["controlID"] - - # Find control details - controlSummary = self.find_control_summary_by_id(data, controlID) - if controlSummary is None: - severity = "Info" - mitigation = "" - else: - severity = self.severity_mapper(controlSummary.get("scoreFactor", 0)) - # Define mitigation if available - if "mitigation" in controlSummary: - mitigation = controlSummary["mitigation"] + for rule in control["rules"]: + if rule["status"] == "passed": + continue + # This condition is true if the result doesn't contain the status for each control (old format) + retrocompatibility_condition = "status" not in control or "status" not in control["status"] + if retrocompatibility_condition or control["status"]["status"] == "failed": + control_name = control["name"] + if resource_type and resource_name and control_name: + title = f"{control_name} - {resource_type} {resource_name}" else: - mitigation = "" + title = f"{control_name} - {resourceid}" + controlID = control["controlID"] - armoLink = f"https://hub.armosec.io/docs/{controlID.lower()}" - description = "**Summary:** " + f"The ressource '{resourceid}' has failed the control '{control_name}'." + "\n" - if controlSummary is not None and "description" in controlSummary: - description += "**Description:** " + controlSummary["description"] + "\n" - - # Define category if available - if controlSummary is not None and "category" in controlSummary and "subCategory" in controlSummary["category"]: - category_name = controlSummary["category"]["name"] - category_subname = controlSummary["category"]["subCategory"]["name"] - category = f"{category_name} > {category_subname}" - description += "**Category:** " + category + "\n" - elif controlSummary is not None and "category" in controlSummary and "name" in controlSummary["category"]: - category = controlSummary["category"]["name"] - description += "**Category:** " + category + "\n" - - description += "View control details here: " + self.__hyperlink(armoLink) - - steps_to_reproduce = "The following rules have failed :" + "\n" - steps_to_reproduce += "\t**Rules:** " + str(json.dumps(control["rules"], indent=4)) + "\n" - - steps_to_reproduce += "Resource object may contain evidence:" + "\n" - steps_to_reproduce += "\t**Resource object:** " + str(json.dumps(resource["object"], indent=4)) - - references = armoLink - - find = Finding( - title=textwrap.shorten(title, 150), - test=test, - description=description, - mitigation=mitigation, - steps_to_reproduce=steps_to_reproduce, - references=references, - severity=severity, - component_name=resourceid, - static_finding=True, - dynamic_finding=False, - ) - findings.append(find) + # Find control details + controlSummary = self.find_control_summary_by_id(data, controlID) + if controlSummary is None: + severity = "Info" + mitigation = "" + else: + severity = self.severity_mapper(controlSummary.get("scoreFactor", 0)) + # Define mitigation if available + if "mitigation" in controlSummary: + mitigation = controlSummary["mitigation"] + else: + mitigation = "" + + description = "**Summary:** " + f"The ressource '{resourceid}' has failed the control '{control_name}'." + "\n" + if controlSummary is not None and "description" in controlSummary: + description += "**Description:** " + controlSummary["description"] + "\n" + + # Define category if available + if controlSummary is not None and "category" in controlSummary and "subCategory" in controlSummary["category"]: + category_name = controlSummary["category"]["name"] + category_subname = controlSummary["category"]["subCategory"]["name"] + category = f"{category_name} > {category_subname}" + description += "**Category:** " + category + "\n" + elif controlSummary is not None and "category" in controlSummary and "name" in controlSummary["category"]: + category = controlSummary["category"]["name"] + description += "**Category:** " + category + "\n" + + steps_to_reproduce = "The following rules have failed :" + "\n" + steps_to_reproduce += "\t**Rules:** " + str(json.dumps(control["rules"], indent=4)) + "\n" + steps_to_reproduce += "Resource object may contain evidence:" + "\n" + steps_to_reproduce += "\t**Resource object:** " + str(json.dumps(resource["object"], indent=4)) + + find = Finding( + title=textwrap.shorten(title, 150), + test=test, + description=description, + mitigation=mitigation, + steps_to_reproduce=steps_to_reproduce, + references=f"https://hub.armosec.io/docs/{controlID.lower()}", + severity=severity, + component_name=resourceid, + static_finding=True, + dynamic_finding=False, + ) + if controlID is not None: + find.unsaved_vulnerability_ids = [] + find.unsaved_vulnerability_ids.append(controlID) + findings.append(find) return findings diff --git a/unittests/tools/test_kubescape_parser.py b/unittests/tools/test_kubescape_parser.py index caacd8fe85b..346cda04019 100644 --- a/unittests/tools/test_kubescape_parser.py +++ b/unittests/tools/test_kubescape_parser.py @@ -8,7 +8,7 @@ def test_parse_file_has_many_findings(self): with open(get_unit_tests_path() + "/scans/kubescape/many_findings.json", encoding="utf-8") as testfile: parser = KubescapeParser() findings = parser.get_findings(testfile, Test()) - self.assertEqual(710, len(findings)) + self.assertEqual(349, len(findings)) def test_parse_file_has_many_results(self): with open(get_unit_tests_path() + "/scans/kubescape/results.json", encoding="utf-8") as testfile: