@@ -25,6 +25,7 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:
25
25
test file: https://github.com/DefectDojo/django-DefectDojo/blob/master/unittests/scans/wiz/multiple_findings.csv
26
26
"""
27
27
findings = []
28
+
28
29
description_fields = [
29
30
"Description" ,
30
31
"Resource Type" ,
@@ -51,42 +52,34 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:
51
52
"Kubernetes Cluster" ,
52
53
"Kubernetes Namespace" ,
53
54
"Container Service" ,
55
+ "Provider ID" ,
56
+ "Risks" ,
57
+ "Threats"
58
+ "Created At" ,
59
+ "Status Changed At" ,
60
+ "Updated At" ,
54
61
]
62
+
55
63
# Iterate over the objects to create findings
56
64
for row in reader :
57
65
title = row .get ("Title" )
66
+ issue_id = row .get ("Issue ID" )
58
67
severity = row .get ("Severity" )
59
68
mitigation = row .get ("Remediation Recommendation" )
69
+
70
+ if row .get ("Resolution" ):
71
+ mitigation += "\n Resolution: " + row .get ("Resolution" )
72
+
60
73
description = ""
61
74
status_dict = WizcliParsers .convert_status (row .get ("Status" , None ))
75
+ date = parse_wiz_datetime (row , "Created At" )
62
76
if status_dict .get ("is_mitigated" , False ):
63
77
# If the finding is mitigated, set the date to the mitigation date
64
78
mitigated_timestamp = None
65
79
66
80
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
90
83
91
84
# Iterate over the description fields to create the description
92
85
for field in description_fields :
@@ -96,10 +89,12 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]:
96
89
findings .append (
97
90
Finding (
98
91
title = title ,
92
+ date = date ,
99
93
description = description ,
100
94
severity = severity .lower ().capitalize (),
101
95
static_finding = False ,
102
96
dynamic_finding = True ,
97
+ unique_id_from_tool = issue_id ,
103
98
mitigation = mitigation ,
104
99
test = test ,
105
100
** status_dict ,
@@ -232,3 +227,39 @@ def get_findings(self, filename, test):
232
227
return WizParserByDetailedName ().parse_findings (test , reader )
233
228
msg = "This CSV format of Wiz is not supported"
234
229
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