@@ -15,6 +15,19 @@ class ProwlerParser:
1515 Supports both CSV and OCSF JSON for AWS, Azure, GCP, and Kubernetes.
1616 """
1717
18+ # Severity mapping from Prowler to DefectDojo
19+ SEVERITY_MAP = {
20+ "critical" : "Critical" ,
21+ "high" : "High" ,
22+ "medium" : "Medium" ,
23+ "low" : "Low" ,
24+ "informational" : "Info" ,
25+ "info" : "Info" ,
26+ }
27+
28+ # Statuses that indicate inactive findings
29+ INACTIVE_STATUSES = {"pass" , "manual" , "not_available" , "skipped" }
30+
1831 def get_scan_types (self ):
1932 return ["Prowler Scan" ]
2033
@@ -70,27 +83,16 @@ def _parse_csv(self, content):
7083
7184 def _determine_severity (self , severity_str ):
7285 """Maps Prowler severity to DefectDojo severity"""
73- severity_map = {
74- "critical" : "Critical" ,
75- "high" : "High" ,
76- "medium" : "Medium" ,
77- "low" : "Low" ,
78- "informational" : "Info" ,
79- "info" : "Info" ,
80- }
81-
8286 # Convert to lowercase for case-insensitive matching
8387 severity_str = severity_str .lower () if severity_str else ""
84- return severity_map . get (severity_str , "Medium " )
88+ return self . SEVERITY_MAP . get (severity_str , "Info " )
8589
8690 def _determine_active_status (self , status_code ):
8791 """Determine if the finding is active based on its status"""
8892 if not status_code :
8993 return True
9094
91- # Using a set for O(1) lookup performance
92- inactive_statuses = {"pass" , "manual" , "not_available" , "skipped" }
93- return status_code .lower () not in inactive_statuses
95+ return status_code .lower () not in self .INACTIVE_STATUSES
9496
9597 def _parse_json_findings (self , data , test , * , file_name = "" ):
9698 """Parse findings from the OCSF JSON format"""
@@ -238,19 +240,21 @@ def _parse_json_findings(self, data, test, *, file_name=""):
238240 if check_id :
239241 finding .vuln_id_from_tool = check_id
240242
241- # Add resource information to mitigation if available
242- mitigation_parts = []
243+ # Add resource information to impact field
244+ impact_parts = []
243245 if resource_type :
244- mitigation_parts .append (f"Resource Type: { resource_type } " )
246+ impact_parts .append (f"Resource Type: { resource_type } " )
245247 if resource_name :
246- mitigation_parts .append (f"Resource Name: { resource_name } " )
248+ impact_parts .append (f"Resource Name: { resource_name } " )
247249 if region :
248- mitigation_parts .append (f"Region: { region } " )
249- if remediation :
250- mitigation_parts .append (f"Remediation: { remediation } " )
250+ impact_parts .append (f"Region: { region } " )
251251
252- if mitigation_parts :
253- finding .mitigation = "\n " .join (mitigation_parts )
252+ if impact_parts :
253+ finding .impact = "\n " .join (impact_parts )
254+
255+ # Add remediation information to mitigation field
256+ if remediation :
257+ finding .mitigation = f"Remediation: { remediation } "
254258
255259 findings .append (finding )
256260
@@ -266,23 +270,8 @@ def _parse_csv_findings(self, csv_data, test, *, file_name=""):
266270 check_title = row .get ("CHECK_TITLE" , "" )
267271 provider = row .get ("PROVIDER" , "" ).lower ()
268272
269- # Original check ID before any standardization (for titles)
270- original_check_id = check_id
271-
272- # Standardize check IDs for consistent test results
273- if provider == "gcp" and ("compute_firewall" in check_id .lower () or "rdp" in check_title .lower ()):
274- check_id = "bc_gcp_networking_2"
275- elif provider == "kubernetes" and "alwayspullimages" in check_id .lower ():
276- check_id = "bc_k8s_pod_security_1"
277- # Special handling for AWS Hardware MFA check
278- elif provider == "aws" and "hardware_mfa" in check_id .lower ():
279- check_id = "iam_root_hardware_mfa_enabled"
280- # Special handling for Azure AKS network policy
281- elif provider == "azure" and "aks_network_policy" in check_id .lower ():
282- check_id = "aks_network_policy_enabled"
283-
284273 # Construct title
285- if original_check_id and check_title :
274+ if check_id and check_title :
286275 title = f"{ check_id } : { check_title } "
287276 elif check_id :
288277 title = check_id
@@ -387,16 +376,22 @@ def _parse_csv_findings(self, csv_data, test, *, file_name=""):
387376 if service_name :
388377 finding .unsaved_tags .append (service_name )
389378
390- # Build mitigation from resource info and remediation
391- mitigation_parts = []
379+ # Build impact from resource info
380+ impact_parts = []
392381 if resource_type :
393- mitigation_parts .append (f"Resource Type: { resource_type } " )
382+ impact_parts .append (f"Resource Type: { resource_type } " )
394383 if resource_name :
395- mitigation_parts .append (f"Resource Name: { resource_name } " )
384+ impact_parts .append (f"Resource Name: { resource_name } " )
396385 if resource_uid :
397- mitigation_parts .append (f"Resource ID: { resource_uid } " )
386+ impact_parts .append (f"Resource ID: { resource_uid } " )
398387 if region :
399- mitigation_parts .append (f"Region: { region } " )
388+ impact_parts .append (f"Region: { region } " )
389+
390+ if impact_parts :
391+ finding .impact = "\n " .join (impact_parts )
392+
393+ # Build mitigation from remediation info
394+ mitigation_parts = []
400395 if remediation_text :
401396 mitigation_parts .append (f"Remediation: { remediation_text } " )
402397 if remediation_url :
0 commit comments