From 4b46eddd0d0ad7b906fdabc051e06880cbac9526 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Tue, 12 Nov 2024 17:08:25 +0000 Subject: [PATCH 01/14] Update versions in application files --- components/package.json | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/package.json b/components/package.json index 8959190ddf4..82cd7446c69 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.40.1", + "version": "2.41.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index b56712ee075..9d7a99e3609 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.40.1" +appVersion: "2.41.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.159 +version: 1.6.160-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 3f48a942bd736eee7a26cf3abe2aefbe59e143a0 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Tue, 12 Nov 2024 20:47:29 +0100 Subject: [PATCH 02/14] :tada: Make Trivy Operator K8s vulnids consistent (#11188) * :tada: Uniform Trivy Operator K8s vulnids * sha sum * sha sum * bug fix * ruff * fix secretshandler * sha sum * ruff * fix * fix * fix unittests * fix * Update dojo/tools/trivy_operator/uniform_vulnid.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/tools/trivy_operator/compliance_handler.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/tools/trivy_operator/checks_handler.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * Update dojo/tools/trivy_operator/vulnerability_handler.py Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> * update sha sum * update sha sum --------- Co-authored-by: Charles Neill <1749665+cneill@users.noreply.github.com> --- dojo/settings/.settings.dist.py.sha256sum | 2 +- dojo/settings/settings.dist.py | 2 ++ dojo/templatetags/display_tags.py | 2 ++ dojo/tools/trivy_operator/checks_handler.py | 3 ++- .../trivy_operator/compliance_handler.py | 3 ++- dojo/tools/trivy_operator/secrets_handler.py | 3 +-- dojo/tools/trivy_operator/uniform_vulnid.py | 20 +++++++++++++++++++ .../trivy_operator/vulnerability_handler.py | 3 ++- unittests/tools/test_trivy_operator_parser.py | 12 +++-------- 9 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 dojo/tools/trivy_operator/uniform_vulnid.py diff --git a/dojo/settings/.settings.dist.py.sha256sum b/dojo/settings/.settings.dist.py.sha256sum index 59acc056a4b..071a9f0ae26 100644 --- a/dojo/settings/.settings.dist.py.sha256sum +++ b/dojo/settings/.settings.dist.py.sha256sum @@ -1 +1 @@ -58e2f6cb0ed2c041fe2741d955b72cb7540bfb0923f489d6324717fcf00039da +16d7a27d3146421a9aa6a8b1283f3d71b5c41b8bdb7c88ca70b0160e251034d1 diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 2571d99b0cf..426faa6a02c 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1744,6 +1744,8 @@ def saml2_attrib_map_format(dict): "ELSA": "https://linux.oracle.com/errata/&&.html", # e.g. https://linux.oracle.com/errata/ELSA-2024-12714.html "ELBA": "https://linux.oracle.com/errata/&&.html", # e.g. https://linux.oracle.com/errata/ELBA-2024-7457.html "RXSA": "https://errata.rockylinux.org/", # e.g. https://errata.rockylinux.org/RXSA-2024:4928 + "AVD": "https://avd.aquasec.com/misconfig/", # e.g. https://avd.aquasec.com/misconfig/avd-ksv-01010 + "KHV": "https://avd.aquasec.com/misconfig/kubernetes/", # e.g. https://avd.aquasec.com/misconfig/kubernetes/khv045 "CAPEC": "https://capec.mitre.org/data/definitions/&&.html", # e.g. https://capec.mitre.org/data/definitions/157.html "CWE": "https://cwe.mitre.org/data/definitions/&&.html", # e.g. https://cwe.mitre.org/data/definitions/79.html "TEMP": "https://security-tracker.debian.org/tracker/", # e.g. https://security-tracker.debian.org/tracker/TEMP-0841856-B18BAF diff --git a/dojo/templatetags/display_tags.py b/dojo/templatetags/display_tags.py index 3fa030d90a4..feeb8f8d6c4 100644 --- a/dojo/templatetags/display_tags.py +++ b/dojo/templatetags/display_tags.py @@ -780,6 +780,8 @@ def vulnerability_url(vulnerability_id): for key in settings.VULNERABILITY_URLS: if vulnerability_id.upper().startswith(key): + if key in ["AVD", "KHV"]: + return settings.VULNERABILITY_URLS[key] + str(vulnerability_id.lower()) if "&&" in settings.VULNERABILITY_URLS[key]: # Process specific keys specially if need if key in ["CAPEC", "CWE"]: diff --git a/dojo/tools/trivy_operator/checks_handler.py b/dojo/tools/trivy_operator/checks_handler.py index c42eef0fa8a..2a260ff5680 100644 --- a/dojo/tools/trivy_operator/checks_handler.py +++ b/dojo/tools/trivy_operator/checks_handler.py @@ -1,4 +1,5 @@ from dojo.models import Finding +from dojo.tools.trivy_operator.uniform_vulnid import UniformTrivyVulnID TRIVY_SEVERITIES = { "CRITICAL": "Critical", @@ -47,6 +48,6 @@ def handle_checks(self, labels, checks, test): tags=[resource_namespace], ) if check_id: - finding.unsaved_vulnerability_ids = [check_id] + finding.unsaved_vulnerability_ids = [UniformTrivyVulnID().return_uniformed_vulnid(check_id)] findings.append(finding) return findings diff --git a/dojo/tools/trivy_operator/compliance_handler.py b/dojo/tools/trivy_operator/compliance_handler.py index 9e27c56ddf2..62a63929e26 100644 --- a/dojo/tools/trivy_operator/compliance_handler.py +++ b/dojo/tools/trivy_operator/compliance_handler.py @@ -1,4 +1,5 @@ from dojo.models import Finding +from dojo.tools.trivy_operator.uniform_vulnid import UniformTrivyVulnID TRIVY_SEVERITIES = { "CRITICAL": "Critical", @@ -54,6 +55,6 @@ def handle_compliance(self, benchmarkreport, test): dynamic_finding=True, ) if check_checkID: - finding.unsaved_vulnerability_ids = [check_checkID] + finding.unsaved_vulnerability_ids = [UniformTrivyVulnID().return_uniformed_vulnid(check_checkID)] findings.append(finding) return findings diff --git a/dojo/tools/trivy_operator/secrets_handler.py b/dojo/tools/trivy_operator/secrets_handler.py index a00c894a034..6509835b4f1 100644 --- a/dojo/tools/trivy_operator/secrets_handler.py +++ b/dojo/tools/trivy_operator/secrets_handler.py @@ -42,6 +42,7 @@ def handle_secrets(self, labels, secrets, test): secret_description += "\n**resource.kind:** " + resource_kind secret_description += "\n**resource.name:** " + resource_name secret_description += "\n**resource.namespace:** " + resource_namespace + secret_description += "\n**ruleID:** " + secret_rule_id finding = Finding( test=test, title=title, @@ -54,7 +55,5 @@ def handle_secrets(self, labels, secrets, test): service=service, tags=[resource_namespace], ) - if secret_rule_id: - finding.unsaved_vulnerability_ids = [secret_rule_id] findings.append(finding) return findings diff --git a/dojo/tools/trivy_operator/uniform_vulnid.py b/dojo/tools/trivy_operator/uniform_vulnid.py new file mode 100644 index 00000000000..b3aae5055e4 --- /dev/null +++ b/dojo/tools/trivy_operator/uniform_vulnid.py @@ -0,0 +1,20 @@ +import re + + +class UniformTrivyVulnID: + def return_uniformed_vulnid(self, vulnid): + if vulnid is None: + return vulnid + if "cve" in vulnid.lower(): + return vulnid + if "khv" in vulnid.lower(): + temp = re.compile("([a-zA-Z-_]+)([0-9]+)") + number = str(temp.match(vulnid).groups()[1]).zfill(3) + avd_category = str(temp.match(vulnid.lower()).groups()[0]) + return avd_category.upper() + number + if "ksv" in vulnid.lower() or "kcv" in vulnid.lower(): + temp = re.compile("([a-zA-Z-_]+)([0-9]+)") + number = str(temp.match(vulnid).groups()[1]).zfill(4) + avd_category = str(temp.match(vulnid.lower().replace("_", "").replace("-", "")).groups()[0].replace("avd", "")) + return "AVD-" + avd_category.upper() + "-" + number + return vulnid diff --git a/dojo/tools/trivy_operator/vulnerability_handler.py b/dojo/tools/trivy_operator/vulnerability_handler.py index a5a26e1288a..99faa009d1b 100644 --- a/dojo/tools/trivy_operator/vulnerability_handler.py +++ b/dojo/tools/trivy_operator/vulnerability_handler.py @@ -1,4 +1,5 @@ from dojo.models import Finding +from dojo.tools.trivy_operator.uniform_vulnid import UniformTrivyVulnID DESCRIPTION_TEMPLATE = """{title} **Fixed version:** {fixed_version} @@ -85,6 +86,6 @@ def handle_vulns(self, labels, vulnerabilities, test): tags=finding_tags, ) if vuln_id: - finding.unsaved_vulnerability_ids = [vuln_id] + finding.unsaved_vulnerability_ids = [UniformTrivyVulnID().return_uniformed_vulnid(vuln_id)] findings.append(finding) return findings diff --git a/unittests/tools/test_trivy_operator_parser.py b/unittests/tools/test_trivy_operator_parser.py index 5e4a71558da..85ce55bc753 100644 --- a/unittests/tools/test_trivy_operator_parser.py +++ b/unittests/tools/test_trivy_operator_parser.py @@ -25,7 +25,7 @@ def test_configauditreport_single_vulns(self): finding = findings[0] self.assertEqual("Low", finding.severity) self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("KSV014", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("AVD-KSV-0014", finding.unsaved_vulnerability_ids[0]) self.assertEqual("KSV014 - Root file system is not read-only", finding.title) def test_configauditreport_many_vulns(self): @@ -36,12 +36,12 @@ def test_configauditreport_many_vulns(self): finding = findings[0] self.assertEqual("Low", finding.severity) self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("KSV014", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("AVD-KSV-0014", finding.unsaved_vulnerability_ids[0]) self.assertEqual("KSV014 - Root file system is not read-only", finding.title) finding = findings[1] self.assertEqual("Low", finding.severity) self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("KSV016", finding.unsaved_vulnerability_ids[0]) + self.assertEqual("AVD-KSV-0016", finding.unsaved_vulnerability_ids[0]) self.assertEqual("KSV016 - Memory requests not specified", finding.title) def test_vulnerabilityreport_no_vuln(self): @@ -96,8 +96,6 @@ def test_exposedsecretreport_single_vulns(self): self.assertEqual(len(findings), 1) finding = findings[0] self.assertEqual("Critical", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("aws-secret-access-key", finding.unsaved_vulnerability_ids[0]) self.assertEqual("aws-secret-access-key", finding.references) self.assertEqual("root/aws_secret.txt", finding.file_path) self.assertEqual("Secret detected in root/aws_secret.txt - AWS Secret Access Key", finding.title) @@ -109,15 +107,11 @@ def test_exposedsecretreport_many(self): self.assertEqual(len(findings), 2) finding = findings[0] self.assertEqual("Critical", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("aws-secret-access-key", finding.unsaved_vulnerability_ids[0]) self.assertEqual("aws-secret-access-key", finding.references) self.assertEqual("root/aws_secret.txt", finding.file_path) self.assertEqual("Secret detected in root/aws_secret.txt - AWS Secret Access Key", finding.title) finding = findings[1] self.assertEqual("Critical", finding.severity) - self.assertEqual(1, len(finding.unsaved_vulnerability_ids)) - self.assertEqual("github-pat", finding.unsaved_vulnerability_ids[0]) self.assertEqual("github-pat", finding.references) self.assertEqual("root/github_secret.txt", finding.file_path) self.assertEqual("Secret detected in root/github_secret.txt - GitHub Personal Access Token", finding.title) From 7abf3014f0462743d08c3346a574e683954f45f2 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Tue, 12 Nov 2024 21:35:10 +0100 Subject: [PATCH 03/14] :tada: Add DSA vulnid (#11238) * :tada: Add DSA vulnid * update sha sum * retrigger unittest --------- Co-authored-by: Ross E Esposito --- dojo/settings/.settings.dist.py.sha256sum | 2 +- dojo/settings/settings.dist.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dojo/settings/.settings.dist.py.sha256sum b/dojo/settings/.settings.dist.py.sha256sum index 071a9f0ae26..d436cae264c 100644 --- a/dojo/settings/.settings.dist.py.sha256sum +++ b/dojo/settings/.settings.dist.py.sha256sum @@ -1 +1 @@ -16d7a27d3146421a9aa6a8b1283f3d71b5c41b8bdb7c88ca70b0160e251034d1 +7a71516d9e6d3fedd26424517ea2c228ad74b6fee8aaa7d8752b8ea4f228aef3 diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 426faa6a02c..8280884204f 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1749,6 +1749,7 @@ def saml2_attrib_map_format(dict): "CAPEC": "https://capec.mitre.org/data/definitions/&&.html", # e.g. https://capec.mitre.org/data/definitions/157.html "CWE": "https://cwe.mitre.org/data/definitions/&&.html", # e.g. https://cwe.mitre.org/data/definitions/79.html "TEMP": "https://security-tracker.debian.org/tracker/", # e.g. https://security-tracker.debian.org/tracker/TEMP-0841856-B18BAF + "DSA": "https://security-tracker.debian.org/tracker/", # e.g. https://security-tracker.debian.org/tracker/DSA-5791-1 } # List of acceptable file types that can be uploaded to a given object via arbitrary file upload FILE_UPLOAD_TYPES = env("DD_FILE_UPLOAD_TYPES") From e9b1354f295a7f9a46d70737928a29cbe2f85004 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:03:57 +0100 Subject: [PATCH 04/14] :bug: fix bearer_cli #11245 (#11248) * :bug: fix bearer_cli #11245 * ruff --- dojo/tools/bearer_cli/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/tools/bearer_cli/parser.py b/dojo/tools/bearer_cli/parser.py index a7b4eba4f23..0c72db38776 100644 --- a/dojo/tools/bearer_cli/parser.py +++ b/dojo/tools/bearer_cli/parser.py @@ -33,7 +33,7 @@ def get_findings(self, file, test): finding = Finding( title=bearerfinding["title"] + " in " + bearerfinding["filename"] + ":" + str(bearerfinding["line_number"]), test=test, - description=bearerfinding["description"] + "\n Detected code snippet: \n" + bearerfinding["snippet"], + description=bearerfinding["description"] + "\n Detected code snippet: \n" + bearerfinding.get("snippet", bearerfinding.get("code_extract")), severity=severity, cwe=bearerfinding["cwe_ids"][0], static_finding=True, From f71799ed27e930ab377bed2b33ceb8f7d34c1110 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:04:51 +0100 Subject: [PATCH 05/14] add RLSA to vulnid (#11251) --- dojo/settings/.settings.dist.py.sha256sum | 2 +- dojo/settings/settings.dist.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dojo/settings/.settings.dist.py.sha256sum b/dojo/settings/.settings.dist.py.sha256sum index d436cae264c..24fb6aafce2 100644 --- a/dojo/settings/.settings.dist.py.sha256sum +++ b/dojo/settings/.settings.dist.py.sha256sum @@ -1 +1 @@ -7a71516d9e6d3fedd26424517ea2c228ad74b6fee8aaa7d8752b8ea4f228aef3 +09169f6d20ebf2f37347156111c3670a5b207c3530583a53ed9ac59ae4221188 diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index 8280884204f..a0145954308 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1750,6 +1750,7 @@ def saml2_attrib_map_format(dict): "CWE": "https://cwe.mitre.org/data/definitions/&&.html", # e.g. https://cwe.mitre.org/data/definitions/79.html "TEMP": "https://security-tracker.debian.org/tracker/", # e.g. https://security-tracker.debian.org/tracker/TEMP-0841856-B18BAF "DSA": "https://security-tracker.debian.org/tracker/", # e.g. https://security-tracker.debian.org/tracker/DSA-5791-1 + "RLSA": "https://errata.rockylinux.org/", # e.g. https://errata.rockylinux.org/RLSA-2024:7001 } # List of acceptable file types that can be uploaded to a given object via arbitrary file upload FILE_UPLOAD_TYPES = env("DD_FILE_UPLOAD_TYPES") From cdf7b829c6490696f1b491f37a04ca66b6147347 Mon Sep 17 00:00:00 2001 From: kiblik <5609770+kiblik@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:06:30 +0100 Subject: [PATCH 06/14] feat(helm): Allow to keep initializer if requested (#11257) --- helm/defectdojo/templates/initializer-job.yaml | 2 ++ helm/defectdojo/values.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/helm/defectdojo/templates/initializer-job.yaml b/helm/defectdojo/templates/initializer-job.yaml index b078a1fdc64..0f43b32bba3 100644 --- a/helm/defectdojo/templates/initializer-job.yaml +++ b/helm/defectdojo/templates/initializer-job.yaml @@ -15,7 +15,9 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: + {{- if and (int .Values.initializer.keepSeconds) (gt (int .Values.initializer.keepSeconds) 0) }} ttlSecondsAfterFinished: {{ .Values.initializer.keepSeconds }} + {{- end }} template: metadata: labels: diff --git a/helm/defectdojo/values.yaml b/helm/defectdojo/values.yaml index f480810d432..555d66c4757 100644 --- a/helm/defectdojo/values.yaml +++ b/helm/defectdojo/values.yaml @@ -321,7 +321,7 @@ initializer: jobAnnotations: {} annotations: {} labels: {} - keepSeconds: 60 + keepSeconds: 60 # A positive integer will keep this Job and Pod deployed for the specified number of seconds, after which they will be removed. For all other values, the Job and Pod will remain deployed. affinity: {} nodeSelector: {} resources: From 2becdb932409239fb2b517ea4f3ee2ee00ede9e1 Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:35:50 +0100 Subject: [PATCH 07/14] :tada: All Trivy Operator findings in one json (#11252) * :tada: All Trivy Operator findings in one json * ruff * sboms are not covered here * if only sboms are present, skip all --- dojo/tools/trivy_operator/parser.py | 6 +- .../trivy_operator/all_reports_in_dict.json | 674 ++++++++++++++++++ unittests/tools/test_trivy_operator_parser.py | 6 + 3 files changed, 685 insertions(+), 1 deletion(-) create mode 100644 unittests/scans/trivy_operator/all_reports_in_dict.json diff --git a/dojo/tools/trivy_operator/parser.py b/dojo/tools/trivy_operator/parser.py index 8be42e8e31e..ba7cc730a1f 100644 --- a/dojo/tools/trivy_operator/parser.py +++ b/dojo/tools/trivy_operator/parser.py @@ -20,7 +20,6 @@ def get_description_for_scan_types(self, scan_type): def get_findings(self, scan_file, test): scan_data = scan_file.read() - try: data = json.loads(str(scan_data, "utf-8")) except Exception: @@ -29,6 +28,11 @@ def get_findings(self, scan_file, test): if type(data) is list: for listitems in data: findings += self.output_findings(listitems, test) + elif type(data) is dict and bool(set(data.keys()) & {"clustercompliancereports.aquasecurity.github.io", "clusterconfigauditreports.aquasecurity.github.io", "clusterinfraassessmentreports.aquasecurity.github.io", "clusterrbacassessmentreports.aquasecurity.github.io", "configauditreports.aquasecurity.github.io", "exposedsecretreports.aquasecurity.github.io", "infraassessmentreports.aquasecurity.github.io", "rbacassessmentreports.aquasecurity.github.io", "vulnerabilityreports.aquasecurity.github.io"}): + for datakey in list(data.keys()): + if datakey not in ["clustersbomreports.aquasecurity.github.io", "sbomreports.aquasecurity.github.io"]: + for listitems in (data[datakey]): + findings += self.output_findings(listitems, test) else: findings += self.output_findings(data, test) return findings diff --git a/unittests/scans/trivy_operator/all_reports_in_dict.json b/unittests/scans/trivy_operator/all_reports_in_dict.json new file mode 100644 index 00000000000..1ac8c678c38 --- /dev/null +++ b/unittests/scans/trivy_operator/all_reports_in_dict.json @@ -0,0 +1,674 @@ +{ + "clustercompliancereports.aquasecurity.github.io": [], + "clusterconfigauditreports.aquasecurity.github.io": [], + "clusterinfraassessmentreports.aquasecurity.github.io": [], + "clusterrbacassessmentreports.aquasecurity.github.io": [], + "clustersbomreports.aquasecurity.github.io": [], + "configauditreports.aquasecurity.github.io": [ + { + "apiVersion": "aquasecurity.github.io/v1alpha1", + "kind": "ConfigAuditReport", + "metadata": { + "annotations": { + "trivy-operator.aquasecurity.github.io/report-ttl": "24h0m0s" + }, + "creationTimestamp": "2023-03-23T16:22:54Z", + "generation": 1, + "labels": { + "plugin-config-hash": "659b7b9c46", + "resource-spec-hash": "fc85b485f", + "trivy-operator.resource.kind": "ReplicaSet", + "trivy-operator.resource.name": "nginx-deployment-965685897", + "trivy-operator.resource.namespace": "default" + }, + "name": "replicaset-nginx-deployment-965685897", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": false, + "controller": true, + "kind": "ReplicaSet", + "name": "nginx-deployment-965685897", + "uid": "d19c7f74-b4c3-429d-9a45-1b2f5efc3c88" + } + ], + "resourceVersion": "1268", + "uid": "a92e0951-e988-419d-8602-6852f920ce06" + }, + "report": { + "checks": [ + { + "category": "Kubernetes Security Check", + "checkID": "KSV014", + "description": "An immutable root file system prevents applications from writing to their local disk. This can limit intrusions, as attackers will not be able to tamper with the file system or write foreign executables to disk.", + "messages": [ + "Container 'nginx' of ReplicaSet 'nginx-deployment-965685897' should set 'securityContext.readOnlyRootFilesystem' to true" + ], + "severity": "LOW", + "success": false, + "title": "Root file system is not read-only" + } + ], + "scanner": { + "name": "Trivy", + "vendor": "Aqua Security", + "version": "dev" + }, + "summary": { + "criticalCount": 0, + "highCount": 0, + "lowCount": 1, + "mediumCount": 0 + }, + "updateTimestamp": "2023-03-23T16:22:54Z" + } + } + ], + "exposedsecretreports.aquasecurity.github.io": [ + { + "apiVersion": "aquasecurity.github.io/v1alpha1", + "kind": "ExposedSecretReport", + "metadata": { + "annotations": { + "trivy-operator.aquasecurity.github.io/report-ttl": "24h0m0s" + }, + "creationTimestamp": "2023-03-24T08:34:18Z", + "generation": 1, + "labels": { + "resource-spec-hash": "69497b548d", + "trivy-operator.container.name": "nginx", + "trivy-operator.resource.kind": "ReplicaSet", + "trivy-operator.resource.name": "nginx-deployment-c868466d4", + "trivy-operator.resource.namespace": "default" + }, + "name": "replicaset-nginx-deployment-c868466d4-nginx", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": false, + "controller": true, + "kind": "ReplicaSet", + "name": "nginx-deployment-c868466d4", + "uid": "1f07d5aa-f272-4f3d-ada8-a3f80ab8088d" + } + ], + "resourceVersion": "1798", + "uid": "46490b45-f440-446c-9574-efcd3afe3a92" + }, + "report": { + "artifact": { + "repository": "library/secret", + "tag": "latest" + }, + "registry": { + "server": "index.docker.io" + }, + "scanner": { + "name": "Trivy", + "vendor": "Aqua Security", + "version": "0.38.2" + }, + "secrets": [ + { + "category": "AWS", + "match": "AWS_secret_KEY=\"****************************************\"", + "ruleID": "aws-secret-access-key", + "severity": "CRITICAL", + "target": "root/aws_secret.txt", + "title": "AWS Secret Access Key" + } + ], + "summary": { + "criticalCount": 1, + "highCount": 0, + "lowCount": 0, + "mediumCount": 0 + }, + "updateTimestamp": "2023-03-24T08:34:18Z" + } + } + ], + "infraassessmentreports.aquasecurity.github.io": [], + "rbacassessmentreports.aquasecurity.github.io": [], + "sbomreports.aquasecurity.github.io": [], + "vulnerabilityreports.aquasecurity.github.io": [ + { + "apiVersion": "aquasecurity.github.io/v1alpha1", + "kind": "VulnerabilityReport", + "metadata": { + "annotations": { + "trivy-operator.aquasecurity.github.io/report-ttl": "24h0m0s" + }, + "creationTimestamp": "2023-03-23T16:23:01Z", + "generation": 1, + "labels": { + "resource-spec-hash": "fc85b485f", + "trivy-operator.container.name": "nginx", + "trivy-operator.resource.kind": "ReplicaSet", + "trivy-operator.resource.name": "nginx-deployment-965685897", + "trivy-operator.resource.namespace": "default" + }, + "name": "replicaset-nginx-deployment-965685897-nginx", + "namespace": "default", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": false, + "controller": true, + "kind": "ReplicaSet", + "name": "nginx-deployment-965685897", + "uid": "d19c7f74-b4c3-429d-9a45-1b2f5efc3c88" + } + ], + "resourceVersion": "1293", + "uid": "b21503db-3075-4bb5-a259-aa33dbbaef4c" + }, + "report": { + "artifact": { + "repository": "library/nginx", + "tag": "alpine" + }, + "registry": { + "server": "index.docker.io" + }, + "scanner": { + "name": "Trivy", + "vendor": "Aqua Security", + "version": "0.38.2" + }, + "summary": { + "criticalCount": 2, + "highCount": 3, + "lowCount": 11, + "mediumCount": 25, + "noneCount": 0, + "unknownCount": 0 + }, + "updateTimestamp": "2023-03-23T16:23:01Z", + "vulnerabilities": [ + { + "fixedVersion": "7.87.0-r2", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-23914", + "resource": "curl", + "score": 4.2, + "severity": "CRITICAL", + "target": "", + "title": "curl: HSTS ignored on multiple requests", + "vulnerabilityID": "CVE-2023-23914" + }, + { + "fixedVersion": "7.87.0-r2", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-23916", + "resource": "curl", + "score": 6.5, + "severity": "HIGH", + "target": "", + "title": "curl: HTTP multi-header compression denial of service", + "vulnerabilityID": "CVE-2023-23916" + }, + { + "fixedVersion": "7.87.0-r2", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-23915", + "resource": "curl", + "score": 4.2, + "severity": "MEDIUM", + "target": "", + "title": "curl: HSTS amnesia with --parallel", + "vulnerabilityID": "CVE-2023-23915" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27535", + "resource": "curl", + "severity": "MEDIUM", + "target": "", + "title": "curl: FTP too eager connection reuse", + "vulnerabilityID": "CVE-2023-27535" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27533", + "resource": "curl", + "severity": "LOW", + "target": "", + "title": "curl: TELNET option IAC injection", + "vulnerabilityID": "CVE-2023-27533" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27534", + "resource": "curl", + "severity": "LOW", + "target": "", + "title": "curl: SFTP path ~ resolving discrepancy", + "vulnerabilityID": "CVE-2023-27534" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27536", + "resource": "curl", + "severity": "LOW", + "target": "", + "title": "curl: GSS delegation too eager connection re-use", + "vulnerabilityID": "CVE-2023-27536" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27537", + "resource": "curl", + "severity": "LOW", + "target": "", + "title": "curl: HSTS double-free", + "vulnerabilityID": "CVE-2023-27537" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27538", + "resource": "curl", + "severity": "LOW", + "target": "", + "title": "curl: SSH connection too eager reuse still", + "vulnerabilityID": "CVE-2023-27538" + }, + { + "fixedVersion": "3.0.8-r1", + "installedVersion": "3.0.8-r0", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0464", + "resource": "libcrypto3", + "severity": "MEDIUM", + "target": "", + "title": "A security vulnerability has been identified in all supported versions ...", + "vulnerabilityID": "CVE-2023-0464" + }, + { + "fixedVersion": "7.87.0-r2", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-23914", + "resource": "libcurl", + "score": 4.2, + "severity": "CRITICAL", + "target": "", + "title": "curl: HSTS ignored on multiple requests", + "vulnerabilityID": "CVE-2023-23914" + }, + { + "fixedVersion": "7.87.0-r2", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-23916", + "resource": "libcurl", + "score": 6.5, + "severity": "HIGH", + "target": "", + "title": "curl: HTTP multi-header compression denial of service", + "vulnerabilityID": "CVE-2023-23916" + }, + { + "fixedVersion": "7.87.0-r2", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-23915", + "resource": "libcurl", + "score": 4.2, + "severity": "MEDIUM", + "target": "", + "title": "curl: HSTS amnesia with --parallel", + "vulnerabilityID": "CVE-2023-23915" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27535", + "resource": "libcurl", + "severity": "MEDIUM", + "target": "", + "title": "curl: FTP too eager connection reuse", + "vulnerabilityID": "CVE-2023-27535" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27533", + "resource": "libcurl", + "severity": "LOW", + "target": "", + "title": "curl: TELNET option IAC injection", + "vulnerabilityID": "CVE-2023-27533" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27534", + "resource": "libcurl", + "severity": "LOW", + "target": "", + "title": "curl: SFTP path ~ resolving discrepancy", + "vulnerabilityID": "CVE-2023-27534" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27536", + "resource": "libcurl", + "severity": "LOW", + "target": "", + "title": "curl: GSS delegation too eager connection re-use", + "vulnerabilityID": "CVE-2023-27536" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27537", + "resource": "libcurl", + "severity": "LOW", + "target": "", + "title": "curl: HSTS double-free", + "vulnerabilityID": "CVE-2023-27537" + }, + { + "fixedVersion": "7.88.1-r1", + "installedVersion": "7.87.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-27538", + "resource": "libcurl", + "severity": "LOW", + "target": "", + "title": "curl: SSH connection too eager reuse still", + "vulnerabilityID": "CVE-2023-27538" + }, + { + "fixedVersion": "3.0.8-r1", + "installedVersion": "3.0.8-r0", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0464", + "resource": "libssl3", + "severity": "MEDIUM", + "target": "", + "title": "A security vulnerability has been identified in all supported versions ...", + "vulnerabilityID": "CVE-2023-0464" + }, + { + "fixedVersion": "4.4.0-r2", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2022-3970", + "resource": "tiff", + "score": 8.8, + "severity": "HIGH", + "target": "", + "title": "libtiff: integer overflow in function TIFFReadRGBATileExt of the file", + "vulnerabilityID": "CVE-2022-3970" + }, + { + "fixedVersion": "4.4.0-r2", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2022-3570", + "resource": "tiff", + "score": 5.5, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: heap Buffer overflows in tiffcrop.c", + "vulnerabilityID": "CVE-2022-3570" + }, + { + "fixedVersion": "4.4.0-r2", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2022-3597", + "resource": "tiff", + "score": 6.5, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds write in _TIFFmemcpy in libtiff/tif_unix", + "vulnerabilityID": "CVE-2022-3597" + }, + { + "fixedVersion": "4.4.0-r2", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2022-3598", + "resource": "tiff", + "score": 6.5, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds write in extractContigSamplesShifted24bits in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2022-3598" + }, + { + "fixedVersion": "4.4.0-r2", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2022-3599", + "resource": "tiff", + "score": 6.5, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds read in writeSingleSection in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2022-3599" + }, + { + "fixedVersion": "4.4.0-r2", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2022-3626", + "resource": "tiff", + "score": 6.5, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds write in _TIFFmemset in libtiff/tif_unix.c", + "vulnerabilityID": "CVE-2022-3626" + }, + { + "fixedVersion": "4.4.0-r2", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2022-3627", + "resource": "tiff", + "score": 6.5, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds write in _TIFFmemcpy in libtiff/tif_unix.c", + "vulnerabilityID": "CVE-2022-3627" + }, + { + "fixedVersion": "4.4.0-r2", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2022-4645", + "resource": "tiff", + "score": 5.6, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds read in tiffcp in tools/tiffcp.c", + "vulnerabilityID": "CVE-2022-4645" + }, + { + "fixedVersion": "4.4.0-r2", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2022-48281", + "resource": "tiff", + "score": 5.5, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: heap-based buffer overflow in processCropSelections() in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2022-48281" + }, + { + "fixedVersion": "4.4.0-r3", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0795", + "resource": "tiff", + "score": 6.1, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds read in extractContigSamplesShifted16bits() in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2023-0795" + }, + { + "fixedVersion": "4.4.0-r3", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0796", + "resource": "tiff", + "score": 6.1, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds read in extractContigSamplesShifted24bits() in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2023-0796" + }, + { + "fixedVersion": "4.4.0-r3", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0797", + "resource": "tiff", + "score": 6.1, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds read in _TIFFmemcpy() in libtiff/tif_unix.c when called by functions in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2023-0797" + }, + { + "fixedVersion": "4.4.0-r3", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0798", + "resource": "tiff", + "score": 6.1, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds read in extractContigSamplesShifted8bits() in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2023-0798" + }, + { + "fixedVersion": "4.4.0-r3", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0799", + "resource": "tiff", + "score": 5.5, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: use-after-free in extractContigSamplesShifted32bits() in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2023-0799" + }, + { + "fixedVersion": "4.4.0-r3", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0800", + "resource": "tiff", + "score": 6.1, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds write in extractContigSamplesShifted16bits() in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2023-0800" + }, + { + "fixedVersion": "4.4.0-r3", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0801", + "resource": "tiff", + "score": 6.1, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds write in _TIFFmemcpy() in libtiff/tif_unix.c when called by functions in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2023-0801" + }, + { + "fixedVersion": "4.4.0-r3", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0802", + "resource": "tiff", + "score": 6.1, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds write in extractContigSamplesShifted32bits() in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2023-0802" + }, + { + "fixedVersion": "4.4.0-r3", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0803", + "resource": "tiff", + "score": 6.1, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds write in extractContigSamplesShifted16bits() in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2023-0803" + }, + { + "fixedVersion": "4.4.0-r3", + "installedVersion": "4.4.0-r1", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2023-0804", + "resource": "tiff", + "score": 6.1, + "severity": "MEDIUM", + "target": "", + "title": "libtiff: out-of-bounds write in extractContigSamplesShifted24bits() in tools/tiffcrop.c", + "vulnerabilityID": "CVE-2023-0804" + }, + { + "fixedVersion": "", + "installedVersion": "v1.44.212", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2020-8911", + "resource": "github.com/aws/aws-sdk-go", + "score": 5.6, + "severity": "MEDIUM", + "target": "", + "title": "aws/aws-sdk-go: CBC padding oracle issue in AWS S3 Crypto SDK for golang", + "vulnerabilityID": "CVE-2020-8911" + }, + { + "fixedVersion": "", + "installedVersion": "v1.44.212", + "links": [], + "primaryLink": "https://avd.aquasec.com/nvd/cve-2020-8912", + "resource": "github.com/aws/aws-sdk-go", + "score": 2.5, + "severity": "LOW", + "target": "", + "title": "aws-sdk-go: In-band key negotiation issue in AWS S3 Crypto SDK for golang", + "vulnerabilityID": "CVE-2020-8912" + } + ] + } + } + ] + } + \ No newline at end of file diff --git a/unittests/tools/test_trivy_operator_parser.py b/unittests/tools/test_trivy_operator_parser.py index 85ce55bc753..0acf11cb70b 100644 --- a/unittests/tools/test_trivy_operator_parser.py +++ b/unittests/tools/test_trivy_operator_parser.py @@ -157,3 +157,9 @@ def test_findings_in_list(self): parser = TrivyOperatorParser() findings = parser.get_findings(test_file, Test()) self.assertEqual(len(findings), 18) + + def test_findings_all_reports_in_dict(self): + with open(sample_path("all_reports_in_dict.json"), encoding="utf-8") as test_file: + parser = TrivyOperatorParser() + findings = parser.get_findings(test_file, Test()) + self.assertEqual(len(findings), 43) From cf452c80c4504cd215453860125713e4ea4136f3 Mon Sep 17 00:00:00 2001 From: kiblik <5609770+kiblik@users.noreply.github.com> Date: Fri, 15 Nov 2024 19:52:33 +0100 Subject: [PATCH 08/14] feat(DD_DEDUPLICATION_ALGORITHM_PER_PARSER + DD_HASHCODE_FIELDS_PER_SCANNER): Add checker of values (#11244) --- docs/content/en/usage/features.md | 8 ++++---- dojo/settings/.settings.dist.py.sha256sum | 2 +- dojo/settings/settings.dist.py | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/content/en/usage/features.md b/docs/content/en/usage/features.md index 5f99f34023f..7fad563b138 100644 --- a/docs/content/en/usage/features.md +++ b/docs/content/en/usage/features.md @@ -244,7 +244,7 @@ The environment variable will override the settings in `settings.dist.py`, repla The available algorithms are: -DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL +DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL (value for `DD_DEDUPLICATION_ALGORITHM_PER_PARSER`: `unique_id_from_tool`) : The deduplication occurs based on finding.unique_id_from_tool which is a unique technical id existing in the source tool. Few scanners populate this @@ -266,12 +266,12 @@ DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL able to recognise that findings found in previous scans are actually the same as the new findings. -DEDUPE_ALGO_HASH_CODE +DEDUPE_ALGO_HASH_CODE (value for `DD_DEDUPLICATION_ALGORITHM_PER_PARSER`: `hash_code`) : The deduplication occurs based on finding.hash_code. The hash_code itself is configurable for each scanner in parameter `HASHCODE_FIELDS_PER_SCANNER`. -DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL_OR_HASH_CODE +DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL_OR_HASH_CODE (value for `DD_DEDUPLICATION_ALGORITHM_PER_PARSER`: `unique_id_from_tool_or_hash_code`) : A finding is a duplicate with another if they have the same unique_id_from_tool OR the same hash_code. @@ -284,7 +284,7 @@ DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL_OR_HASH_CODE cross-parser deduplication -DEDUPE_ALGO_LEGACY +DEDUPE_ALGO_LEGACY (value for `DD_DEDUPLICATION_ALGORITHM_PER_PARSER`: `legacy`) : This is algorithm that was in place before the configuration per parser was made possible, and also the default one for backward compatibility reasons. diff --git a/dojo/settings/.settings.dist.py.sha256sum b/dojo/settings/.settings.dist.py.sha256sum index 24fb6aafce2..220f2b35098 100644 --- a/dojo/settings/.settings.dist.py.sha256sum +++ b/dojo/settings/.settings.dist.py.sha256sum @@ -1 +1 @@ -09169f6d20ebf2f37347156111c3670a5b207c3530583a53ed9ac59ae4221188 +f09caa2d4e41f44b7cd6ecf2f1400817d4776e703bd039c8d857f1356382e1f3 diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index a0145954308..e9100b681b5 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1296,6 +1296,12 @@ def saml2_attrib_map_format(dict): if len(env("DD_HASHCODE_FIELDS_PER_SCANNER")) > 0: env_hashcode_fields_per_scanner = json.loads(env("DD_HASHCODE_FIELDS_PER_SCANNER")) for key, value in env_hashcode_fields_per_scanner.items(): + if not isinstance(value, list): + msg = f"Fields definition '{value}' for hashcode calculation of '{key}' is not valid. It needs to be list of strings but it is {type(value)}." + raise TypeError(msg) + if not all(isinstance(field, str) for field in value): + msg = f"Fields for hashcode calculation for {key} are not valid. It needs to be list of strings. Some of fields are not string." + raise AttributeError(msg) if key in HASHCODE_FIELDS_PER_SCANNER: logger.info(f"Replacing {key} with value {value} (previously set to {HASHCODE_FIELDS_PER_SCANNER[key]}) from env var DD_HASHCODE_FIELDS_PER_SCANNER") HASHCODE_FIELDS_PER_SCANNER[key] = value @@ -1377,6 +1383,13 @@ def saml2_attrib_map_format(dict): # Makes it possible to deduplicate on a technical id (same parser) and also on some functional fields (cross-parsers deduplication) DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL_OR_HASH_CODE = "unique_id_from_tool_or_hash_code" +DEDUPE_ALGOS = [ + DEDUPE_ALGO_LEGACY, + DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL, + DEDUPE_ALGO_HASH_CODE, + DEDUPE_ALGO_UNIQUE_ID_FROM_TOOL_OR_HASH_CODE, +] + # Allows to deduplicate with endpoints if endpoints is not included in the hashcode. # Possible values are: scheme, host, port, path, query, fragment, userinfo, and user. For a details description see https://hyperlink.readthedocs.io/en/latest/api.html#attributes. # Example: @@ -1526,6 +1539,9 @@ def saml2_attrib_map_format(dict): if len(env("DD_DEDUPLICATION_ALGORITHM_PER_PARSER")) > 0: env_dedup_algorithm_per_parser = json.loads(env("DD_DEDUPLICATION_ALGORITHM_PER_PARSER")) for key, value in env_dedup_algorithm_per_parser.items(): + if value not in DEDUPE_ALGOS: + msg = f"DEDUP algorithm '{value}' for '{key}' is not valid. Use one of following values: {', '.join(DEDUPE_ALGOS)}" + raise AttributeError(msg) if key in DEDUPLICATION_ALGORITHM_PER_PARSER: logger.info(f"Replacing {key} with value {value} (previously set to {DEDUPLICATION_ALGORITHM_PER_PARSER[key]}) from env var DD_DEDUPLICATION_ALGORITHM_PER_PARSER") DEDUPLICATION_ALGORITHM_PER_PARSER[key] = value From 5168154988fec25a29b898012080c083efa75aaf Mon Sep 17 00:00:00 2001 From: manuelsommer <47991713+manuel-sommer@users.noreply.github.com> Date: Sat, 16 Nov 2024 01:02:40 +0100 Subject: [PATCH 09/14] :hammer: rework kubescape parser (#11229) * :hammer: 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> --- dojo/settings/.settings.dist.py.sha256sum | 2 +- dojo/settings/settings.dist.py | 1 + dojo/templatetags/display_tags.py | 2 +- dojo/tools/kubescape/parser.py | 118 +++++++++++----------- unittests/tools/test_kubescape_parser.py | 2 +- 5 files changed, 63 insertions(+), 62 deletions(-) diff --git a/dojo/settings/.settings.dist.py.sha256sum b/dojo/settings/.settings.dist.py.sha256sum index 220f2b35098..6e1a934f57d 100644 --- a/dojo/settings/.settings.dist.py.sha256sum +++ b/dojo/settings/.settings.dist.py.sha256sum @@ -1 +1 @@ -f09caa2d4e41f44b7cd6ecf2f1400817d4776e703bd039c8d857f1356382e1f3 +f85484f23e59aabe591b30db10e0de05aaeeb9d8979d236d565dc8279e03e116 diff --git a/dojo/settings/settings.dist.py b/dojo/settings/settings.dist.py index e9100b681b5..c5453c018de 100644 --- a/dojo/settings/settings.dist.py +++ b/dojo/settings/settings.dist.py @@ -1760,6 +1760,7 @@ def saml2_attrib_map_format(dict): "ELSA": "https://linux.oracle.com/errata/&&.html", # e.g. https://linux.oracle.com/errata/ELSA-2024-12714.html "ELBA": "https://linux.oracle.com/errata/&&.html", # e.g. https://linux.oracle.com/errata/ELBA-2024-7457.html "RXSA": "https://errata.rockylinux.org/", # e.g. https://errata.rockylinux.org/RXSA-2024:4928 + "C-": "https://hub.armosec.io/docs/", # e.g. https://hub.armosec.io/docs/c-0085 "AVD": "https://avd.aquasec.com/misconfig/", # e.g. https://avd.aquasec.com/misconfig/avd-ksv-01010 "KHV": "https://avd.aquasec.com/misconfig/kubernetes/", # e.g. https://avd.aquasec.com/misconfig/kubernetes/khv045 "CAPEC": "https://capec.mitre.org/data/definitions/&&.html", # e.g. https://capec.mitre.org/data/definitions/157.html diff --git a/dojo/templatetags/display_tags.py b/dojo/templatetags/display_tags.py index feeb8f8d6c4..cd3627d41bf 100644 --- a/dojo/templatetags/display_tags.py +++ b/dojo/templatetags/display_tags.py @@ -780,7 +780,7 @@ def vulnerability_url(vulnerability_id): for key in settings.VULNERABILITY_URLS: if vulnerability_id.upper().startswith(key): - if key in ["AVD", "KHV"]: + if key in ["AVD", "KHV", "C-"]: return settings.VULNERABILITY_URLS[key] + str(vulnerability_id.lower()) if "&&" in settings.VULNERABILITY_URLS[key]: # Process specific keys specially if need diff --git a/dojo/tools/kubescape/parser.py b/dojo/tools/kubescape/parser.py index c371f477901..0f472a902ef 100644 --- a/dojo/tools/kubescape/parser.py +++ b/dojo/tools/kubescape/parser.py @@ -59,65 +59,65 @@ def get_findings(self, filename, test): controls = results[0].get("controls", []) for control in controls: - # This condition is true if the result doesn't contain the status for each control (old format) - retrocompatibility_condition = "status" not in control or "status" not in control["status"] - if retrocompatibility_condition or control["status"]["status"] == "failed": - control_name = control["name"] - if resource_type and resource_name and control_name: - title = f"{control_name} - {resource_type} {resource_name}" - else: - title = f"{control_name} - {resourceid}" - controlID = control["controlID"] - - # Find control details - controlSummary = self.find_control_summary_by_id(data, controlID) - if controlSummary is None: - severity = "Info" - mitigation = "" - else: - severity = self.severity_mapper(controlSummary.get("scoreFactor", 0)) - # Define mitigation if available - if "mitigation" in controlSummary: - mitigation = controlSummary["mitigation"] + for rule in control["rules"]: + if rule["status"] == "passed": + continue + # This condition is true if the result doesn't contain the status for each control (old format) + retrocompatibility_condition = "status" not in control or "status" not in control["status"] + if retrocompatibility_condition or control["status"]["status"] == "failed": + control_name = control["name"] + if resource_type and resource_name and control_name: + title = f"{control_name} - {resource_type} {resource_name}" else: - mitigation = "" + title = f"{control_name} - {resourceid}" + controlID = control["controlID"] - armoLink = f"https://hub.armosec.io/docs/{controlID.lower()}" - description = "**Summary:** " + f"The ressource '{resourceid}' has failed the control '{control_name}'." + "\n" - if controlSummary is not None and "description" in controlSummary: - description += "**Description:** " + controlSummary["description"] + "\n" - - # Define category if available - if controlSummary is not None and "category" in controlSummary and "subCategory" in controlSummary["category"]: - category_name = controlSummary["category"]["name"] - category_subname = controlSummary["category"]["subCategory"]["name"] - category = f"{category_name} > {category_subname}" - description += "**Category:** " + category + "\n" - elif controlSummary is not None and "category" in controlSummary and "name" in controlSummary["category"]: - category = controlSummary["category"]["name"] - description += "**Category:** " + category + "\n" - - description += "View control details here: " + self.__hyperlink(armoLink) - - steps_to_reproduce = "The following rules have failed :" + "\n" - steps_to_reproduce += "\t**Rules:** " + str(json.dumps(control["rules"], indent=4)) + "\n" - - steps_to_reproduce += "Resource object may contain evidence:" + "\n" - steps_to_reproduce += "\t**Resource object:** " + str(json.dumps(resource["object"], indent=4)) - - references = armoLink - - find = Finding( - title=textwrap.shorten(title, 150), - test=test, - description=description, - mitigation=mitigation, - steps_to_reproduce=steps_to_reproduce, - references=references, - severity=severity, - component_name=resourceid, - static_finding=True, - dynamic_finding=False, - ) - findings.append(find) + # Find control details + controlSummary = self.find_control_summary_by_id(data, controlID) + if controlSummary is None: + severity = "Info" + mitigation = "" + else: + severity = self.severity_mapper(controlSummary.get("scoreFactor", 0)) + # Define mitigation if available + if "mitigation" in controlSummary: + mitigation = controlSummary["mitigation"] + else: + mitigation = "" + + description = "**Summary:** " + f"The ressource '{resourceid}' has failed the control '{control_name}'." + "\n" + if controlSummary is not None and "description" in controlSummary: + description += "**Description:** " + controlSummary["description"] + "\n" + + # Define category if available + if controlSummary is not None and "category" in controlSummary and "subCategory" in controlSummary["category"]: + category_name = controlSummary["category"]["name"] + category_subname = controlSummary["category"]["subCategory"]["name"] + category = f"{category_name} > {category_subname}" + description += "**Category:** " + category + "\n" + elif controlSummary is not None and "category" in controlSummary and "name" in controlSummary["category"]: + category = controlSummary["category"]["name"] + description += "**Category:** " + category + "\n" + + steps_to_reproduce = "The following rules have failed :" + "\n" + steps_to_reproduce += "\t**Rules:** " + str(json.dumps(control["rules"], indent=4)) + "\n" + steps_to_reproduce += "Resource object may contain evidence:" + "\n" + steps_to_reproduce += "\t**Resource object:** " + str(json.dumps(resource["object"], indent=4)) + + find = Finding( + title=textwrap.shorten(title, 150), + test=test, + description=description, + mitigation=mitigation, + steps_to_reproduce=steps_to_reproduce, + references=f"https://hub.armosec.io/docs/{controlID.lower()}", + severity=severity, + component_name=resourceid, + static_finding=True, + dynamic_finding=False, + ) + if controlID is not None: + find.unsaved_vulnerability_ids = [] + find.unsaved_vulnerability_ids.append(controlID) + findings.append(find) return findings diff --git a/unittests/tools/test_kubescape_parser.py b/unittests/tools/test_kubescape_parser.py index caacd8fe85b..346cda04019 100644 --- a/unittests/tools/test_kubescape_parser.py +++ b/unittests/tools/test_kubescape_parser.py @@ -8,7 +8,7 @@ def test_parse_file_has_many_findings(self): with open(get_unit_tests_path() + "/scans/kubescape/many_findings.json", encoding="utf-8") as testfile: parser = KubescapeParser() findings = parser.get_findings(testfile, Test()) - self.assertEqual(710, len(findings)) + self.assertEqual(349, len(findings)) def test_parse_file_has_many_results(self): with open(get_unit_tests_path() + "/scans/kubescape/results.json", encoding="utf-8") as testfile: From 1a9b08226f76da690f054fb253daa537b442530d Mon Sep 17 00:00:00 2001 From: Ivan Morhun <114015523+ivan-morhun@users.noreply.github.com> Date: Mon, 18 Nov 2024 05:52:03 +0300 Subject: [PATCH 10/14] prowler_v4.py Prowler v4.5.0 changed the 'event_time' key with 'time_dt' (#11213) * #11210 prowler_v4.py Prowler v4.5.0 changed the 'event_time' key in finding with 'time_dt' * #11210 prowler_v4.py Prowler v4.5.0 changed the 'event_time' key in finding with 'time_dt' * Add tesst to support prowler version <4.5.0 * Return new-line * Update tests, clean up scans * Fix ruff * Rename some stuff --------- Co-authored-by: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> --- dojo/tools/aws_prowler_v3plus/prowler_v4.py | 3 +- .../many_vuln_after_4_5_0.ocsf.json | 247 ++++++++++++++++++ .../one_vuln_after_4_5_0.ocsf.json | 80 ++++++ .../tools/test_aws_prowler_v3plus_parser.py | 32 +++ 4 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 unittests/scans/aws_prowler_v3plus/many_vuln_after_4_5_0.ocsf.json create mode 100644 unittests/scans/aws_prowler_v3plus/one_vuln_after_4_5_0.ocsf.json diff --git a/dojo/tools/aws_prowler_v3plus/prowler_v4.py b/dojo/tools/aws_prowler_v3plus/prowler_v4.py index 1b9c155b63a..dd543f27f57 100644 --- a/dojo/tools/aws_prowler_v3plus/prowler_v4.py +++ b/dojo/tools/aws_prowler_v3plus/prowler_v4.py @@ -37,7 +37,8 @@ def process_ocsf_json(self, file, test): documentation = deserialized.get("remediation", {}).get("references", "") documentation = str(documentation) + "\n" + str(deserialized.get("unmapped", {}).get("related_url", "")) security_domain = deserialized.get("resources", [{}])[0].get("type", "") - timestamp = deserialized.get("event_time") + # Prowler v4.5.0 changed 'event_time' key in report with 'time_dt' + timestamp = deserialized.get("time_dt") or deserialized.get("event_time") resource_arn = deserialized.get("resources", [{}])[0].get("uid", "") resource_id = deserialized.get("resources", [{}])[0].get("name", "") unique_id_from_tool = deserialized.get("finding_info", {}).get("uid", "") diff --git a/unittests/scans/aws_prowler_v3plus/many_vuln_after_4_5_0.ocsf.json b/unittests/scans/aws_prowler_v3plus/many_vuln_after_4_5_0.ocsf.json new file mode 100644 index 00000000000..36c0219e396 --- /dev/null +++ b/unittests/scans/aws_prowler_v3plus/many_vuln_after_4_5_0.ocsf.json @@ -0,0 +1,247 @@ +[{ + "metadata": { + "event_code": "iam_role_administratoraccess_policy_permissive_trust_relationship", + "product": { + "name": "Prowler", + "vendor_name": "Prowler", + "version": "4.2.1" + }, + "version": "1.2.0" + }, + "severity_id": 4, + "severity": "High", + "status": "New", + "status_code": "FAIL", + "status_detail": "IAM Role myAdministratorExecutionRole has AdministratorAccess policy attached that has too permissive trust relationship.", + "status_id": 3, + "unmapped": { + "check_type": "", + "related_url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions.html#jf_administrator", + "categories": "trustboundaries", + "depends_on": "", + "related_to": "", + "notes": "CAF Security Epic: IAM", + "compliance": {} + }, + "activity_name": "Create", + "activity_id": 1, + "finding_info": { + "created_time": "2024-06-03T14:15:19.382075", + "desc": "Ensure IAM Roles with attached AdministratorAccess policy have a well defined trust relationship", + "product_uid": "prowler", + "title": "Ensure IAM Roles with attached AdministratorAccess policy have a well defined trust relationship", + "uid": "prowler-aws-iam_role_administratoraccess_policy_permissive_trust_relationship-123456789012-us-east-1-myAdministratorExecutionRole" + }, + "resources": [ + { + "cloud_partition": "aws", + "region": "us-east-1", + "data": { + "details": "" + }, + "group": { + "name": "iam" + }, + "labels": [], + "name": "myAdministratorExecutionRole", + "type": "AwsIamRole", + "uid": "arn:aws:iam::123456789012:role/myAdministratorExecutionRole" + } + ], + "category_name": "Findings", + "category_uid": 2, + "class_name": "DetectionFinding", + "class_uid": 2004, + "cloud": { + "account": { + "name": "", + "type": "AWS_Account", + "type_id": 10, + "uid": "123456789012", + "labels": [] + }, + "org": { + "name": "", + "uid": "" + }, + "provider": "aws", + "region": "us-east-1" + }, + "time_dt": "2024-06-03T14:15:19.382075", + "remediation": { + "desc": "Apply the principle of least privilege. Instead of AdministratorAccess, assign only the permissions necessary for specific roles and tasks. Create custom IAM policies with minimal permissions based on the principle of least privilege. If a role really needs AdministratorAccess, the trust relationship must be well defined to restrict it usage only to the Principal, Action, Audience and Subject intended for it.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege" + ] + }, + "risk_details": "The AWS-managed AdministratorAccess policy grants all actions for all AWS services and for all resources in the account and as such exposes the customer to a significant data leakage threat. It is therefore particularly important that the trust relationship is well defined to restrict it usage only to the Principal, Action, Audience and Subject intended for it.", + "type_uid": 200401, + "type_name": "Create" +},{ + "metadata": { + "event_code": "iam_role_cross_account_readonlyaccess_policy", + "product": { + "name": "Prowler", + "vendor_name": "Prowler", + "version": "4.2.1" + }, + "version": "1.2.0" + }, + "severity_id": 4, + "severity": "High", + "status": "New", + "status_code": "FAIL", + "status_detail": "IAM Role AuditRole gives cross account read-only access.", + "status_id": 3, + "unmapped": { + "check_type": "", + "related_url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions.html#awsmp_readonlyaccess", + "categories": "trustboundaries", + "depends_on": "", + "related_to": "", + "notes": "CAF Security Epic: IAM", + "compliance": { + "MITRE-ATTACK": [ + "T1078" + ], + "AWS-Foundational-Technical-Review": [ + "IAM-0012" + ] + } + }, + "activity_name": "Create", + "activity_id": 1, + "finding_info": { + "created_time": "2024-06-03T14:15:19.382075", + "desc": "Ensure IAM Roles do not have ReadOnlyAccess access for external AWS accounts", + "product_uid": "prowler", + "title": "Ensure IAM Roles do not have ReadOnlyAccess access for external AWS accounts", + "uid": "prowler-aws-iam_role_cross_account_readonlyaccess_policy-123456789012-us-east-1-AuditRole" + }, + "resources": [ + { + "cloud_partition": "aws", + "region": "us-east-1", + "data": { + "details": "" + }, + "group": { + "name": "iam" + }, + "labels": [ + "some-label=some value" + ], + "name": "AuditRole", + "type": "AwsIamRole", + "uid": "arn:aws:iam::123456789012:role/AuditRole" + } + ], + "category_name": "Findings", + "category_uid": 2, + "class_name": "DetectionFinding", + "class_uid": 2004, + "cloud": { + "account": { + "name": "", + "type": "AWS_Account", + "type_id": 10, + "uid": "123456789012", + "labels": [] + }, + "org": { + "name": "", + "uid": "" + }, + "provider": "aws", + "region": "us-east-1" + }, + "time_dt": "2024-06-03T14:15:19.382075", + "remediation": { + "desc": "Remove the AWS-managed ReadOnlyAccess policy from all roles that have a trust policy, including third-party cloud accounts, or remove third-party cloud accounts from the trust policy of all roles that need the ReadOnlyAccess policy.", + "references": [ + "https://docs.securestate.vmware.com/rule-docs/aws-iam-role-cross-account-readonlyaccess-policy" + ] + }, + "risk_details": "The AWS-managed ReadOnlyAccess policy is highly potent and exposes the customer to a significant data leakage threat. It should be granted very conservatively. For granting access to 3rd party vendors, consider using alternative managed policies, such as ViewOnlyAccess or SecurityAudit.", + "type_uid": 200401, + "type_name": "Create" +},{ + "metadata": { + "event_code": "iam_role_permissive_trust_relationship", + "product": { + "name": "Prowler", + "vendor_name": "Prowler", + "version": "4.2.1" + }, + "version": "1.2.0" + }, + "severity_id": 4, + "severity": "High", + "status": "Suppressed", + "status_code": "FAIL", + "status_detail": "IAM Role CrossAccountResourceAccessRole has permissive trust relationship to other accounts", + "status_id": 3, + "unmapped": { + "check_type": "", + "related_url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html#principal-accounts", + "categories": "trustboundaries", + "depends_on": "", + "related_to": "", + "notes": "CAF Security Epic: IAM", + "compliance": {} + }, + "activity_name": "Create", + "activity_id": 1, + "finding_info": { + "created_time": "2024-06-03T14:15:19.382075", + "desc": "Ensure IAM Roles do not allow assume role from any role of a cross account", + "product_uid": "prowler", + "title": "Ensure IAM Roles do not allow assume role from any role of a cross account", + "uid": "prowler-aws-iam_role_permissive_trust_relationship-123456789012-us-east-1-CrossAccountResourceAccessRole" + }, + "resources": [ + { + "cloud_partition": "aws", + "region": "us-east-1", + "data": { + "details": "" + }, + "group": { + "name": "iam" + }, + "labels": [], + "name": "CrossAccountResourceAccessRole", + "type": "AwsIamRole", + "uid": "arn:aws:iam::123456789012:role/CrossAccountResourceAccessRole" + } + ], + "category_name": "Findings", + "category_uid": 2, + "class_name": "DetectionFinding", + "class_uid": 2004, + "cloud": { + "account": { + "name": "", + "type": "AWS_Account", + "type_id": 10, + "uid": "123456789012", + "labels": [] + }, + "org": { + "name": "", + "uid": "" + }, + "provider": "aws", + "region": "us-east-1" + }, + "time_dt": "2024-06-03T14:15:19.382075", + "remediation": { + "desc": "Ensure IAM Roles do not allow assume role from any role of a cross account but only from specific roles of specific accounts.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html#principal-roles" + ] + }, + "risk_details": "If an IAM role allows assume role from any role of a cross account, it can lead to privilege escalation.", + "type_uid": 200401, + "type_name": "Create" +}] \ No newline at end of file diff --git a/unittests/scans/aws_prowler_v3plus/one_vuln_after_4_5_0.ocsf.json b/unittests/scans/aws_prowler_v3plus/one_vuln_after_4_5_0.ocsf.json new file mode 100644 index 00000000000..e8e79e2f71f --- /dev/null +++ b/unittests/scans/aws_prowler_v3plus/one_vuln_after_4_5_0.ocsf.json @@ -0,0 +1,80 @@ +[{ + "metadata": { + "event_code": "iam_role_administratoraccess_policy_permissive_trust_relationship", + "product": { + "name": "Prowler", + "vendor_name": "Prowler", + "version": "4.2.1" + }, + "version": "1.2.0" + }, + "severity_id": 4, + "severity": "High", + "status": "New", + "status_code": "FAIL", + "status_detail": "IAM Role myAdministratorExecutionRole has AdministratorAccess policy attached that has too permissive trust relationship.", + "status_id": 3, + "unmapped": { + "check_type": "", + "related_url": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions.html#jf_administrator", + "categories": "trustboundaries", + "depends_on": "", + "related_to": "", + "notes": "CAF Security Epic: IAM", + "compliance": {} + }, + "activity_name": "Create", + "activity_id": 1, + "finding_info": { + "created_time": "2024-06-03T14:15:19.382075", + "desc": "Ensure IAM Roles with attached AdministratorAccess policy have a well defined trust relationship", + "product_uid": "prowler", + "title": "Ensure IAM Roles with attached AdministratorAccess policy have a well defined trust relationship", + "uid": "prowler-aws-iam_role_administratoraccess_policy_permissive_trust_relationship-123456789012-us-east-1-myAdministratorExecutionRole" + }, + "resources": [ + { + "cloud_partition": "aws", + "region": "us-east-1", + "data": { + "details": "" + }, + "group": { + "name": "iam" + }, + "labels": [], + "name": "myAdministratorExecutionRole", + "type": "AwsIamRole", + "uid": "arn:aws:iam::123456789012:role/myAdministratorExecutionRole" + } + ], + "category_name": "Findings", + "category_uid": 2, + "class_name": "DetectionFinding", + "class_uid": 2004, + "cloud": { + "account": { + "name": "", + "type": "AWS_Account", + "type_id": 10, + "uid": "123456789012", + "labels": [] + }, + "org": { + "name": "", + "uid": "" + }, + "provider": "aws", + "region": "us-east-1" + }, + "time_dt": "2024-06-03T14:15:19.382075", + "remediation": { + "desc": "Apply the principle of least privilege. Instead of AdministratorAccess, assign only the permissions necessary for specific roles and tasks. Create custom IAM policies with minimal permissions based on the principle of least privilege. If a role really needs AdministratorAccess, the trust relationship must be well defined to restrict it usage only to the Principal, Action, Audience and Subject intended for it.", + "references": [ + "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege" + ] + }, + "risk_details": "The AWS-managed AdministratorAccess policy grants all actions for all AWS services and for all resources in the account and as such exposes the customer to a significant data leakage threat. It is therefore particularly important that the trust relationship is well defined to restrict it usage only to the Principal, Action, Audience and Subject intended for it.", + "type_uid": 200401, + "type_name": "Create" +}] \ No newline at end of file diff --git a/unittests/tools/test_aws_prowler_v3plus_parser.py b/unittests/tools/test_aws_prowler_v3plus_parser.py index 6eb22c296cf..5ef20b764af 100644 --- a/unittests/tools/test_aws_prowler_v3plus_parser.py +++ b/unittests/tools/test_aws_prowler_v3plus_parser.py @@ -1,3 +1,5 @@ +from datetime import date + from dojo.models import Test from dojo.tools.aws_prowler_v3plus.parser import AWSProwlerV3plusParser from unittests.dojo_test_case import DojoTestCase @@ -23,6 +25,7 @@ def test_aws_prowler_parser_with_critical_vuln_has_one_findings_json(self): self.assertIn("Check if ACM Certificates are about to expire in specific days or less", findings[0].description) self.assertEqual("arn:aws:acm:us-east-1:999999999999:certificate/ffffffff-0000-0000-0000-000000000000", findings[0].component_name) self.assertIn("https://docs.aws.amazon.com/config/latest/developerguide/acm-certificate-expiration-check.html", findings[0].references) + self.assertEqual(date.fromisoformat("2023-04-25"), findings[0].date) def test_aws_prowler_parser_with_many_vuln_has_many_findings_json(self): findings = self.setup( @@ -31,18 +34,44 @@ def test_aws_prowler_parser_with_many_vuln_has_many_findings_json(self): with self.subTest(i=0): self.assertEqual("prowler-aws-acm_certificates_expiration_check-999999999999-us-east-1-api.teste.teste.com", findings[0].unique_id_from_tool) self.assertIn("Check if ACM Certificates are about to expire in specific days or less", findings[0].description) + self.assertEqual(date.fromisoformat("2023-04-25"), findings[0].date) with self.subTest(i=1): self.assertEqual("prowler-aws-accessanalyzer_enabled-999999999999-us-east-1-999999999999", findings[1].unique_id_from_tool) self.assertIn("Check if IAM Access Analyzer is enabled", findings[1].description) + self.assertEqual(date.fromisoformat("2023-04-25"), findings[1].date) with self.subTest(i=3): self.assertEqual("prowler-aws-account_maintain_current_contact_details-999999999999-us-east-1-999999999999", findings[2].unique_id_from_tool) self.assertIn("Maintain current contact details.", findings[2].description) + self.assertEqual(date.fromisoformat("2023-04-25"), findings[2].date) def test_aws_prowler_parser_with_no_vuln_has_no_findings_ocsf_json(self): findings = self.setup( open("unittests/scans/aws_prowler_v3plus/no_vuln.ocsf.json", encoding="utf-8")) self.assertEqual(0, len(findings)) + def test_aws_prowler_parser_after_4_5_0_with_critical_vuln_has_one_findings_ocsf_json(self): + findings = self.setup( + open("unittests/scans/aws_prowler_v3plus/one_vuln_after_4_5_0.ocsf.json", encoding="utf-8")) + self.assertEqual(1, len(findings)) + self.assertEqual("prowler-aws-iam_role_administratoraccess_policy_permissive_trust_relationship-123456789012-us-east-1-myAdministratorExecutionRole", findings[0].unique_id_from_tool) + self.assertIn("Ensure IAM Roles with attached AdministratorAccess policy have a well defined trust relationship", findings[0].description) + self.assertEqual("arn:aws:iam::123456789012:role/myAdministratorExecutionRole", findings[0].component_name) + self.assertIn("https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege", findings[0].references) + self.assertEqual(date.fromisoformat("2024-06-03"), findings[0].date) + + def test_aws_prowler_parser_after_4_5_0_with_many_vuln_has_many_findings_ocsf_json(self): + findings = self.setup( + open("unittests/scans/aws_prowler_v3plus/many_vuln_after_4_5_0.ocsf.json", encoding="utf-8")) + self.assertEqual(2, len(findings)) + with self.subTest(i=0): + self.assertEqual("prowler-aws-iam_role_administratoraccess_policy_permissive_trust_relationship-123456789012-us-east-1-myAdministratorExecutionRole", findings[0].unique_id_from_tool) + self.assertIn("Ensure IAM Roles with attached AdministratorAccess policy have a well defined trust relationship", findings[0].description) + self.assertEqual(date.fromisoformat("2024-06-03"), findings[0].date) + with self.subTest(i=1): + self.assertEqual("prowler-aws-iam_role_cross_account_readonlyaccess_policy-123456789012-us-east-1-AuditRole", findings[1].unique_id_from_tool) + self.assertIn("Ensure IAM Roles do not have ReadOnlyAccess access for external AWS accounts", findings[1].description) + self.assertEqual(date.fromisoformat("2024-06-03"), findings[1].date) + def test_aws_prowler_parser_with_critical_vuln_has_one_findings_ocsf_json(self): findings = self.setup( open("unittests/scans/aws_prowler_v3plus/one_vuln.ocsf.json", encoding="utf-8")) @@ -51,6 +80,7 @@ def test_aws_prowler_parser_with_critical_vuln_has_one_findings_ocsf_json(self): self.assertIn("Ensure IAM Roles with attached AdministratorAccess policy have a well defined trust relationship", findings[0].description) self.assertEqual("arn:aws:iam::123456789012:role/myAdministratorExecutionRole", findings[0].component_name) self.assertIn("https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege", findings[0].references) + self.assertEqual(date.fromisoformat("2024-06-03"), findings[0].date) def test_aws_prowler_parser_with_many_vuln_has_many_findings_ocsf_json(self): findings = self.setup( @@ -59,6 +89,8 @@ def test_aws_prowler_parser_with_many_vuln_has_many_findings_ocsf_json(self): with self.subTest(i=0): self.assertEqual("prowler-aws-iam_role_administratoraccess_policy_permissive_trust_relationship-123456789012-us-east-1-myAdministratorExecutionRole", findings[0].unique_id_from_tool) self.assertIn("Ensure IAM Roles with attached AdministratorAccess policy have a well defined trust relationship", findings[0].description) + self.assertEqual(date.fromisoformat("2024-06-03"), findings[0].date) with self.subTest(i=1): self.assertEqual("prowler-aws-iam_role_cross_account_readonlyaccess_policy-123456789012-us-east-1-AuditRole", findings[1].unique_id_from_tool) self.assertIn("Ensure IAM Roles do not have ReadOnlyAccess access for external AWS accounts", findings[1].description) + self.assertEqual(date.fromisoformat("2024-06-03"), findings[1].date) From 62add9821b4a67be858b22cbf994156705fad2f3 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 18 Nov 2024 16:04:13 +0000 Subject: [PATCH 11/14] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 82cd7446c69..01c5545e503 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.41.0-dev", + "version": "2.40.2", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index f912fa15f5d..a924075055d 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = "2.40.1" +__version__ = "2.40.2" __url__ = "https://github.com/DefectDojo/django-DefectDojo" __docs__ = "https://documentation.defectdojo.com" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index 9d7a99e3609..ff59c76c305 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.41.0-dev" +appVersion: "2.40.2" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.160-dev +version: 1.6.160 icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 2ba5cee412a2d4c70421cb45793c4819a1cd00a3 Mon Sep 17 00:00:00 2001 From: Cody Maffucci <46459665+Maffooch@users.noreply.github.com> Date: Mon, 18 Nov 2024 10:09:50 -0600 Subject: [PATCH 12/14] Attempt to fix release drafter --- .github/workflows/release-drafter.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 2a4d7ef037a..0e42769cd76 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -48,6 +48,8 @@ jobs: steps: - name: Load OAS files from artifacts uses: actions/download-artifact@v4 + with: + pattern: oas-* - name: Upload Release Asset - OpenAPI Specification - YAML id: upload-release-asset-yaml From 892fc392a04252229406eee17dca0c4e07cd8409 Mon Sep 17 00:00:00 2001 From: DefectDojo release bot Date: Mon, 18 Nov 2024 16:52:04 +0000 Subject: [PATCH 13/14] Update versions in application files --- components/package.json | 2 +- dojo/__init__.py | 2 +- helm/defectdojo/Chart.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/package.json b/components/package.json index 01c5545e503..82cd7446c69 100644 --- a/components/package.json +++ b/components/package.json @@ -1,6 +1,6 @@ { "name": "defectdojo", - "version": "2.40.2", + "version": "2.41.0-dev", "license" : "BSD-3-Clause", "private": true, "dependencies": { diff --git a/dojo/__init__.py b/dojo/__init__.py index a924075055d..be4cc157e16 100644 --- a/dojo/__init__.py +++ b/dojo/__init__.py @@ -4,6 +4,6 @@ # Django starts so that shared_task will use this app. from .celery import app as celery_app # noqa: F401 -__version__ = "2.40.2" +__version__ = "2.41.0-dev" __url__ = "https://github.com/DefectDojo/django-DefectDojo" __docs__ = "https://documentation.defectdojo.com" diff --git a/helm/defectdojo/Chart.yaml b/helm/defectdojo/Chart.yaml index ff59c76c305..cef251c3c01 100644 --- a/helm/defectdojo/Chart.yaml +++ b/helm/defectdojo/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 -appVersion: "2.40.2" +appVersion: "2.41.0-dev" description: A Helm chart for Kubernetes to install DefectDojo name: defectdojo -version: 1.6.160 +version: 1.6.161-dev icon: https://www.defectdojo.org/img/favicon.ico maintainers: - name: madchap From 5e4331139149ee193a5eafaca02e86d0c53c63d2 Mon Sep 17 00:00:00 2001 From: Ross Esposito Date: Mon, 18 Nov 2024 11:06:28 -0600 Subject: [PATCH 14/14] Fixing sha --- dojo/settings/.settings.dist.py.sha256sum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dojo/settings/.settings.dist.py.sha256sum b/dojo/settings/.settings.dist.py.sha256sum index 415f1117aa1..f4b9461b96e 100644 --- a/dojo/settings/.settings.dist.py.sha256sum +++ b/dojo/settings/.settings.dist.py.sha256sum @@ -1 +1 @@ -f85484f23e59aabe591b30db10e0de05aaeeb9d8979d236d565dc8279e03e116 \ No newline at end of file +01215b397651163c0403b028adb08b18fa83c4abb188b0536dfb9e43eddcd9cd