diff --git a/dojo/tools/wiz/parser.py b/dojo/tools/wiz/parser.py index 219cf715149..06808e863b0 100644 --- a/dojo/tools/wiz/parser.py +++ b/dojo/tools/wiz/parser.py @@ -7,6 +7,7 @@ from dateutil import parser as date_parser from dojo.models import SEVERITIES, Finding, Test +from dojo.tools.wizcli_common_parsers.parsers import WizcliParsers logger = logging.getLogger(__name__) @@ -51,27 +52,28 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]: ] # Iterate over the objects to create findings for row in reader: - if row.get("Status").lower() == "open": - title = row.get("Title") - severity = row.get("Severity") - mitigation = row.get("Remediation Recommendation") - description = "" - # Iterate over the description fields to create the description - for field in description_fields: - if (field_value := row.get(field)) is not None and len(field_value) > 0: - description += f"**{field}**: {field_value}\n" - # Create the finding object - findings.append( - Finding( - title=title, - description=description, - severity=severity.lower().capitalize(), - static_finding=False, - dynamic_finding=True, - mitigation=mitigation, - test=test, - ), - ) + title = row.get("Title") + severity = row.get("Severity") + mitigation = row.get("Remediation Recommendation") + description = "" + status_dict = WizcliParsers.convert_status(row.get("Status", None)) + # Iterate over the description fields to create the description + for field in description_fields: + if (field_value := row.get(field)) is not None and len(field_value) > 0: + description += f"**{field}**: {field_value}\n" + # Create the finding object + findings.append( + Finding( + title=title, + description=description, + severity=severity.lower().capitalize(), + static_finding=False, + dynamic_finding=True, + mitigation=mitigation, + test=test, + **status_dict, + ), + ) return findings @@ -126,7 +128,7 @@ def parse_findings(self, test: Test, reader: csv.DictReader) -> list[Finding]: description = self._construct_string_field(description_fields, row) mitigation = self._construct_string_field(mitigation_fields, row) - status_dict = self._convert_status(row) + status_dict = WizcliParsers.convert_status(row.get("FindingStatus", None)) # Create the finding object finding = Finding( title=f"{package_name}: {vulnerability_id}", @@ -156,7 +158,7 @@ def _construct_string_field(self, fields: dict[str, str], row: dict) -> str: def _parse_tags(self, tags: str) -> list[str]: """ - parse the Tag string dict, and convert to a list of strings. + Parse the Tag string dict, and convert to a list of strings. The format of the tags is is "{""key"":""value""}" format """ @@ -172,19 +174,6 @@ def _validate_severities(self, severity: str) -> str: return "Info" return severity - def _convert_status(self, row: dict) -> dict: - """ - Convert the "FindingStatus" column to a dict of Finding statuses. - - - Open-> Active = True - - Other statuses that may exist... - """ - if (status := row.get("FindingStatus")) is not None: - if status == "Open": - return {"active": True} - # Return the default status of active - return {"active": True} - class WizParser( WizParserByTitle, diff --git a/dojo/tools/wizcli_common_parsers/parsers.py b/dojo/tools/wizcli_common_parsers/parsers.py index dbd9583b598..38c1ae2e2d4 100644 --- a/dojo/tools/wizcli_common_parsers/parsers.py +++ b/dojo/tools/wizcli_common_parsers/parsers.py @@ -176,3 +176,23 @@ def parse_os_packages(osPackages, test): ) findings.append(finding) return findings + + @staticmethod + def convert_status(wiz_status) -> dict: + """ + Convert the Wiz Status to a dict of Finding status flags. + + - Open-> Active = True + - Other statuses that may exist... + """ + if (status := wiz_status) is not None: + if status.upper() == "OPEN": + return {"active": True} + if status.upper() == "RESOLVED": + return {"active": False, "is_mitigated": True} + if status.upper() == "IGNORED": + return {"active": False, "out_of_scope": True} + if status.upper() == "IN_PROGRESS": + return {"active": True} + # Return the default status of active + return {"active": True} diff --git a/unittests/scans/wiz/multiple_findings.csv b/unittests/scans/wiz/multiple_findings.csv index 1fb6eb6fbb1..fffc62733c5 100644 --- a/unittests/scans/wiz/multiple_findings.csv +++ b/unittests/scans/wiz/multiple_findings.csv @@ -51,7 +51,7 @@ An attacker that manages to execute code on the resource can use the publicly kn * For private images, check the Finding for detailed information regarding the vulnerability. * Build a new image with the fixed vulnerability and replace it in the resource. * If you cannot use the latest version, prioritize patching resources in your environment according to the attack surface they are exposed to and the potential impact of this resource’s compromise (based on the Issue severity).",Wiz - Demo-Scenarios,https://demo.wiz.io/issues#~(issue~'027155e3-56a2-4916-9697-0c2202b9f5d1),https://portal.azure.com/#@wizsectest.onmicrosoft.com/resource//subscriptions/fee3535b-9616-486f-a476-6a500a08a02b/resourcegroups/us2eastrg/providers/microsoft.compute/virtualmachines/ms2012datacenterv001,{},,, -2023-01-25T00:19:57Z,AKS user/service accounts with the privileges to create pods,INFORMATIONAL,OPEN,"#### Description +2023-01-25T00:19:57Z,AKS user/service accounts with the privileges to create pods,INFORMATIONAL,IN_PROGRESS,"#### Description This account is assigned the permission to create new pods. #### Potential impact @@ -73,7 +73,7 @@ Publicly exposed resources are more easily accessible for an attacker than inter * Sensitive information should not be directly accessible from the internet, or accessible by easily-compromised principals. * Limit the data access to only those who need it. Minimize the attack surface of users with access to sensitive data to protect from breaches. * Make sure that the data is encrypted at rest.",Wiz - Demo-Scenarios,https://demo.wiz.io/issues#~(issue~'02ab10b7-e431-4349-b1ea-96db0aece24d),,{},,, -2024-01-24T11:02:11Z,AKS cluster contains a pod running containers with added capabilities,INFORMATIONAL,OPEN,"#### Description +2024-01-24T11:02:11Z,AKS cluster contains a pod running containers with added capabilities,INFORMATIONAL,RESOLVED,"#### Description This cluster contains a pod running containers with added capabilities. #### Potential impact @@ -87,7 +87,7 @@ Containers run with a default set of capabilities as assigned by the Container R * Avoid running privileged containers. * Avoid sharing namespaces from the host to the container. * Assign a network policy to namespaces so proper network segmentation is in place in case of a compromised container.",Wiz - Demo-Scenarios,https://demo.wiz.io/issues#~(issue~'02fd8a0d-16fa-4da0-aa49-a99694365d41),https://portal.azure.com/#@wizsectest.onmicrosoft.com/resource//subscriptions/fee3535b-9616-486f-a476-6a500a08a02b/resourcegroups/laliv_rg/providers/microsoft.containerservice/managedclusters/lalivaks,{},,, -2023-08-30T18:52:52Z,Container using an image with high/critical severity network vulnerabilities with a known exploit,LOW,OPEN,"#### Description +2023-08-30T18:52:52Z,Container using an image with high/critical severity network vulnerabilities with a known exploit,LOW,IGNORED,"#### Description This container has a critical/high severity network vulnerability [based on CVSS](https://docs.wiz.io/wiz-docs/docs/controls-issues#control-severity) with a known exploit in the wild. #### Potential impact @@ -97,7 +97,7 @@ An attacker that manages to execute code on the public container can exploit the * For private images, check the Finding for detailed information regarding the vulnerability. * Build a new image with the fixed vulnerability and replace it in the resource. * If you cannot use the latest version, prioritize patching resources in your environment according to the attack surface they are exposed to and the potential impact of this resource’s compromise (based on the Issue severity).",Wiz - Demo-Scenarios,https://demo.wiz.io/issues#~(issue~'030c78d3-0509-4565-8083-d83cd8c0dc96),,"{""app.kubernetes.io/instance"": ""sb-nginx-aks""}",,, -2023-01-24T22:09:36Z,Container using an image with high/critical severity network vulnerabilities with a known exploit,LOW,OPEN,"#### Description +2023-01-24T22:09:36Z,Container using an image with high/critical severity network vulnerabilities with a known exploit,LOW,IGNORED,"#### Description This container has a critical/high severity network vulnerability [based on CVSS](https://docs.wiz.io/wiz-docs/docs/controls-issues#control-severity) with a known exploit in the wild. #### Potential impact diff --git a/unittests/tools/test_wiz_parser.py b/unittests/tools/test_wiz_parser.py index a2d3975e4e9..19d8c7bd234 100644 --- a/unittests/tools/test_wiz_parser.py +++ b/unittests/tools/test_wiz_parser.py @@ -39,6 +39,25 @@ def test_multiple_findings(self): finding = findings[1] self.assertEqual("Unusual activity by a principal from previously unseen country", finding.title) self.assertEqual("High", finding.severity) + + finding = findings[7] + self.assertEqual("AKS user/service accounts with the privileges to create pods", finding.title) + self.assertEqual(True, finding.active) + self.assertEqual(False, finding.is_mitigated) + self.assertEqual(False, finding.out_of_scope) + + finding = findings[9] + self.assertEqual("AKS cluster contains a pod running containers with added capabilities", finding.title) + self.assertEqual(False, finding.active) + self.assertEqual(True, finding.is_mitigated) + self.assertEqual(False, finding.out_of_scope) + + finding = findings[11] + self.assertEqual("Container using an image with high/critical severity network vulnerabilities with a known exploit", finding.title) + self.assertEqual(False, finding.active) + self.assertEqual(False, finding.is_mitigated) + self.assertEqual(True, finding.out_of_scope) + finding = findings[20] self.assertEqual( "User/service account with get/list/watch permissions on secrets in an AKS cluster", finding.title,