Skip to content

Commit 331e69b

Browse files
valentijnscholtenMaffooch
authored andcommitted
wiz scan: handle more fields and unique_id_from_tool (#12198)
* wiz scan: handle more fields * wiz scan: handle more fields
1 parent 06f63d7 commit 331e69b

File tree

3 files changed

+84
-39
lines changed

3 files changed

+84
-39
lines changed

dojo/tools/wiz/parser.py

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:
2525
test file: https://github.com/DefectDojo/django-DefectDojo/blob/master/unittests/scans/wiz/multiple_findings.csv
2626
"""
2727
findings = []
28+
2829
description_fields = [
2930
"Description",
3031
"Resource Type",
@@ -51,42 +52,34 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:
5152
"Kubernetes Cluster",
5253
"Kubernetes Namespace",
5354
"Container Service",
55+
"Provider ID",
56+
"Risks",
57+
"Threats"
58+
"Created At",
59+
"Status Changed At",
60+
"Updated At",
5461
]
62+
5563
# Iterate over the objects to create findings
5664
for row in reader:
5765
title = row.get("Title")
66+
issue_id = row.get("Issue ID")
5867
severity = row.get("Severity")
5968
mitigation = row.get("Remediation Recommendation")
69+
70+
if row.get("Resolution"):
71+
mitigation += "\nResolution: " + row.get("Resolution")
72+
6073
description = ""
6174
status_dict = WizcliParsers.convert_status(row.get("Status", None))
75+
date = parse_wiz_datetime(row, "Created At")
6276
if status_dict.get("is_mitigated", False):
6377
# If the finding is mitigated, set the date to the mitigation date
6478
mitigated_timestamp = None
6579

6680
if row.get("Resolved Time", None):
67-
with contextlib.suppress(ValueError):
68-
mitigated_timestamp = date_parser.parse(row.get("Resolved Time"))
69-
70-
if not mitigated_timestamp:
71-
# other timestamps in the wiz scans are ISO8601
72-
# but the Resolved Time is in a different format based on data we've seen
73-
# example value: 2025-04-03 20:20:00.43042 +0000 UTC
74-
75-
resolved_time_string = row.get("Resolved Time")
76-
# need to use suppress as try-except ValueError doesn't work here for some reason
77-
78-
# File "/usr/local/lib/python3.11/_strptime.py", line 352, in _strptime
79-
# raise ValueError("unconverted data remains: %s" %
80-
# ValueError: unconverted data remains: CET
81-
with contextlib.suppress(ValueError):
82-
mitigated_timestamp = datetime.strptime(
83-
resolved_time_string, "%Y-%m-%d %H:%M:%S.%f %z %Z",
84-
)
85-
86-
if not mitigated_timestamp:
87-
logger.warning(f"Unable to parse Resolved Time: {resolved_time_string}")
88-
89-
status_dict["mitigated"] = mitigated_timestamp
81+
mitigated_timestamp = parse_wiz_datetime(row, "Resolved Time")
82+
status_dict["mitigated"] = mitigated_timestamp or None
9083

9184
# Iterate over the description fields to create the description
9285
for field in description_fields:
@@ -96,10 +89,12 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:
9689
findings.append(
9790
Finding(
9891
title=title,
92+
date=date,
9993
description=description,
10094
severity=severity.lower().capitalize(),
10195
static_finding=False,
10296
dynamic_finding=True,
97+
unique_id_from_tool=issue_id,
10398
mitigation=mitigation,
10499
test=test,
105100
**status_dict,
@@ -232,3 +227,39 @@ def get_findings(self, filename, test):
232227
return WizParserByDetailedName().parse_findings(test, reader)
233228
msg = "This CSV format of Wiz is not supported"
234229
raise ValueError(msg)
230+
231+
232+
def parse_wiz_datetime(row: dict, column: str) -> datetime:
233+
"""
234+
Parse the Wiz datetime string to a datetime object.
235+
236+
The format of the date is "2025-04-03 20:20:00.43042 +0000 UTC"
237+
"""
238+
value = row.get(column)
239+
if value is None:
240+
return None
241+
242+
parsed_value = None
243+
244+
# Try default parser first
245+
with contextlib.suppress(ValueError):
246+
parsed_value = date_parser.parse(value)
247+
248+
# other timestamps in the wiz scans are ISO8601
249+
# but the Resolved Time is in a different format based on data we've seen
250+
# example value: 2025-04-03 20:20:00.43042 +0000 UTC
251+
252+
# need to use suppress as try-except ValueError doesn't work here for some reason
253+
# File "/usr/local/lib/python3.11/_strptime.py", line 352, in _strptime
254+
# raise ValueError("unconverted data remains: %s" %
255+
# ValueError: unconverted data remains: CET
256+
if not parsed_value:
257+
with contextlib.suppress(ValueError):
258+
parsed_value = datetime.strptime(
259+
value, "%Y-%m-%d %H:%M:%S.%f %z %Z",
260+
)
261+
262+
if not parsed_value:
263+
logger.warning(f"Unable to parse Resolved Time: {value}")
264+
265+
return parsed_value

0 commit comments

Comments
 (0)