Skip to content

Commit c4c80e4

Browse files
🔨 rework kubescape parser (#11229)
* 🔨 rework kubescape parser * update * fix unittest, ruff * update * fix * sha sum * retrigger unittest * Update dojo/tools/kubescape/parser.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * review * retrigger unittests --------- Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com>
1 parent 3f2dc20 commit c4c80e4

5 files changed

Lines changed: 63 additions & 62 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f09caa2d4e41f44b7cd6ecf2f1400817d4776e703bd039c8d857f1356382e1f3
1+
f85484f23e59aabe591b30db10e0de05aaeeb9d8979d236d565dc8279e03e116

dojo/settings/settings.dist.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,6 +1760,7 @@ def saml2_attrib_map_format(dict):
17601760
"ELSA": "https://linux.oracle.com/errata/&&.html", # e.g. https://linux.oracle.com/errata/ELSA-2024-12714.html
17611761
"ELBA": "https://linux.oracle.com/errata/&&.html", # e.g. https://linux.oracle.com/errata/ELBA-2024-7457.html
17621762
"RXSA": "https://errata.rockylinux.org/", # e.g. https://errata.rockylinux.org/RXSA-2024:4928
1763+
"C-": "https://hub.armosec.io/docs/", # e.g. https://hub.armosec.io/docs/c-0085
17631764
"AVD": "https://avd.aquasec.com/misconfig/", # e.g. https://avd.aquasec.com/misconfig/avd-ksv-01010
17641765
"KHV": "https://avd.aquasec.com/misconfig/kubernetes/", # e.g. https://avd.aquasec.com/misconfig/kubernetes/khv045
17651766
"CAPEC": "https://capec.mitre.org/data/definitions/&&.html", # e.g. https://capec.mitre.org/data/definitions/157.html

dojo/templatetags/display_tags.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ def vulnerability_url(vulnerability_id):
780780

781781
for key in settings.VULNERABILITY_URLS:
782782
if vulnerability_id.upper().startswith(key):
783-
if key in ["AVD", "KHV"]:
783+
if key in ["AVD", "KHV", "C-"]:
784784
return settings.VULNERABILITY_URLS[key] + str(vulnerability_id.lower())
785785
if "&&" in settings.VULNERABILITY_URLS[key]:
786786
# Process specific keys specially if need

dojo/tools/kubescape/parser.py

Lines changed: 59 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -59,65 +59,65 @@ def get_findings(self, filename, test):
5959
controls = results[0].get("controls", [])
6060

6161
for control in controls:
62-
# This condition is true if the result doesn't contain the status for each control (old format)
63-
retrocompatibility_condition = "status" not in control or "status" not in control["status"]
64-
if retrocompatibility_condition or control["status"]["status"] == "failed":
65-
control_name = control["name"]
66-
if resource_type and resource_name and control_name:
67-
title = f"{control_name} - {resource_type} {resource_name}"
68-
else:
69-
title = f"{control_name} - {resourceid}"
70-
controlID = control["controlID"]
71-
72-
# Find control details
73-
controlSummary = self.find_control_summary_by_id(data, controlID)
74-
if controlSummary is None:
75-
severity = "Info"
76-
mitigation = ""
77-
else:
78-
severity = self.severity_mapper(controlSummary.get("scoreFactor", 0))
79-
# Define mitigation if available
80-
if "mitigation" in controlSummary:
81-
mitigation = controlSummary["mitigation"]
62+
for rule in control["rules"]:
63+
if rule["status"] == "passed":
64+
continue
65+
# This condition is true if the result doesn't contain the status for each control (old format)
66+
retrocompatibility_condition = "status" not in control or "status" not in control["status"]
67+
if retrocompatibility_condition or control["status"]["status"] == "failed":
68+
control_name = control["name"]
69+
if resource_type and resource_name and control_name:
70+
title = f"{control_name} - {resource_type} {resource_name}"
8271
else:
83-
mitigation = ""
72+
title = f"{control_name} - {resourceid}"
73+
controlID = control["controlID"]
8474

85-
armoLink = f"https://hub.armosec.io/docs/{controlID.lower()}"
86-
description = "**Summary:** " + f"The ressource '{resourceid}' has failed the control '{control_name}'." + "\n"
87-
if controlSummary is not None and "description" in controlSummary:
88-
description += "**Description:** " + controlSummary["description"] + "\n"
89-
90-
# Define category if available
91-
if controlSummary is not None and "category" in controlSummary and "subCategory" in controlSummary["category"]:
92-
category_name = controlSummary["category"]["name"]
93-
category_subname = controlSummary["category"]["subCategory"]["name"]
94-
category = f"{category_name} > {category_subname}"
95-
description += "**Category:** " + category + "\n"
96-
elif controlSummary is not None and "category" in controlSummary and "name" in controlSummary["category"]:
97-
category = controlSummary["category"]["name"]
98-
description += "**Category:** " + category + "\n"
99-
100-
description += "View control details here: " + self.__hyperlink(armoLink)
101-
102-
steps_to_reproduce = "The following rules have failed :" + "\n"
103-
steps_to_reproduce += "\t**Rules:** " + str(json.dumps(control["rules"], indent=4)) + "\n"
104-
105-
steps_to_reproduce += "Resource object may contain evidence:" + "\n"
106-
steps_to_reproduce += "\t**Resource object:** " + str(json.dumps(resource["object"], indent=4))
107-
108-
references = armoLink
109-
110-
find = Finding(
111-
title=textwrap.shorten(title, 150),
112-
test=test,
113-
description=description,
114-
mitigation=mitigation,
115-
steps_to_reproduce=steps_to_reproduce,
116-
references=references,
117-
severity=severity,
118-
component_name=resourceid,
119-
static_finding=True,
120-
dynamic_finding=False,
121-
)
122-
findings.append(find)
75+
# Find control details
76+
controlSummary = self.find_control_summary_by_id(data, controlID)
77+
if controlSummary is None:
78+
severity = "Info"
79+
mitigation = ""
80+
else:
81+
severity = self.severity_mapper(controlSummary.get("scoreFactor", 0))
82+
# Define mitigation if available
83+
if "mitigation" in controlSummary:
84+
mitigation = controlSummary["mitigation"]
85+
else:
86+
mitigation = ""
87+
88+
description = "**Summary:** " + f"The ressource '{resourceid}' has failed the control '{control_name}'." + "\n"
89+
if controlSummary is not None and "description" in controlSummary:
90+
description += "**Description:** " + controlSummary["description"] + "\n"
91+
92+
# Define category if available
93+
if controlSummary is not None and "category" in controlSummary and "subCategory" in controlSummary["category"]:
94+
category_name = controlSummary["category"]["name"]
95+
category_subname = controlSummary["category"]["subCategory"]["name"]
96+
category = f"{category_name} > {category_subname}"
97+
description += "**Category:** " + category + "\n"
98+
elif controlSummary is not None and "category" in controlSummary and "name" in controlSummary["category"]:
99+
category = controlSummary["category"]["name"]
100+
description += "**Category:** " + category + "\n"
101+
102+
steps_to_reproduce = "The following rules have failed :" + "\n"
103+
steps_to_reproduce += "\t**Rules:** " + str(json.dumps(control["rules"], indent=4)) + "\n"
104+
steps_to_reproduce += "Resource object may contain evidence:" + "\n"
105+
steps_to_reproduce += "\t**Resource object:** " + str(json.dumps(resource["object"], indent=4))
106+
107+
find = Finding(
108+
title=textwrap.shorten(title, 150),
109+
test=test,
110+
description=description,
111+
mitigation=mitigation,
112+
steps_to_reproduce=steps_to_reproduce,
113+
references=f"https://hub.armosec.io/docs/{controlID.lower()}",
114+
severity=severity,
115+
component_name=resourceid,
116+
static_finding=True,
117+
dynamic_finding=False,
118+
)
119+
if controlID is not None:
120+
find.unsaved_vulnerability_ids = []
121+
find.unsaved_vulnerability_ids.append(controlID)
122+
findings.append(find)
123123
return findings

unittests/tools/test_kubescape_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def test_parse_file_has_many_findings(self):
88
with open(get_unit_tests_path() + "/scans/kubescape/many_findings.json", encoding="utf-8") as testfile:
99
parser = KubescapeParser()
1010
findings = parser.get_findings(testfile, Test())
11-
self.assertEqual(710, len(findings))
11+
self.assertEqual(349, len(findings))
1212

1313
def test_parse_file_has_many_results(self):
1414
with open(get_unit_tests_path() + "/scans/kubescape/results.json", encoding="utf-8") as testfile:

0 commit comments

Comments
 (0)