From 70fdc2693ed4d5c64bddcdb52b0ce3a491a5220c Mon Sep 17 00:00:00 2001
From: Amogh Bantwal <100332169+abant07@users.noreply.github.com>
Date: Mon, 2 Sep 2024 01:13:06 -0700
Subject: [PATCH] feat(html): Add number of muted findings in HTML report
#4703 (#4895)
---
prowler/lib/outputs/html/html.py | 6 ++++
prowler/lib/outputs/outputs.py | 10 +++++++
tests/lib/outputs/html/html_test.py | 20 +++++++++----
tests/lib/outputs/outputs_test.py | 46 +++++++++++++++++++++++++++++
4 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/prowler/lib/outputs/html/html.py b/prowler/lib/outputs/html/html.py
index 9d75af8a13..a7b27093da 100644
--- a/prowler/lib/outputs/html/html.py
+++ b/prowler/lib/outputs/html/html.py
@@ -173,9 +173,15 @@ class HTML(Output):
Passed: {str(stats.get("total_pass", 0))}
+
+ Passed (Muted): {str(stats.get("total_muted_pass", 0))}
+
Failed: {str(stats.get("total_fail", 0))}
+
+ Failed (Muted): {str(stats.get("total_muted_fail", 0))}
+
Total Resources: {str(stats.get("resources_count", 0))}
diff --git a/prowler/lib/outputs/outputs.py b/prowler/lib/outputs/outputs.py
index d6c5fe1022..0f99ef7de5 100644
--- a/prowler/lib/outputs/outputs.py
+++ b/prowler/lib/outputs/outputs.py
@@ -91,6 +91,8 @@ def extract_findings_statistics(findings: list) -> dict:
stats = {}
total_pass = 0
total_fail = 0
+ muted_pass = 0
+ muted_fail = 0
resources = set()
findings_count = 0
all_fails_are_muted = True
@@ -98,17 +100,25 @@ def extract_findings_statistics(findings: list) -> dict:
for finding in findings:
# Save the resource_id
resources.add(finding.resource_id)
+
if finding.status == "PASS":
total_pass += 1
findings_count += 1
+ if finding.muted is True:
+ muted_pass += 1
+
if finding.status == "FAIL":
total_fail += 1
findings_count += 1
+ if finding.muted is True:
+ muted_fail += 1
if not finding.muted and all_fails_are_muted:
all_fails_are_muted = False
stats["total_pass"] = total_pass
+ stats["total_muted_pass"] = muted_pass
stats["total_fail"] = total_fail
+ stats["total_muted_fail"] = muted_fail
stats["resources_count"] = len(resources)
stats["findings_count"] = findings_count
stats["all_fails_are_muted"] = all_fails_are_muted
diff --git a/tests/lib/outputs/html/html_test.py b/tests/lib/outputs/html/html_test.py
index 9e978a9f80..0fa5ccbe3e 100644
--- a/tests/lib/outputs/html/html_test.py
+++ b/tests/lib/outputs/html/html_test.py
@@ -14,10 +14,12 @@ from tests.providers.kubernetes.kubernetes_fixtures import (
)
html_stats = {
- "total_pass": 0,
- "total_fail": 1,
+ "total_pass": 25,
+ "total_muted_pass": 20,
+ "total_fail": 5,
+ "total_muted_fail": 5,
"resources_count": 1,
- "findings_count": 1,
+ "findings_count": 30,
}
pass_html_finding = """
@@ -300,13 +302,19 @@ def get_aws_html_header(args: list) -> str:
-
- Total Findings: 1
+ Total Findings: 30
-
- Passed: 0
+ Passed: 25
-
- Failed: 1
+ Passed (Muted): 20
+
+ -
+ Failed: 5
+
+ -
+ Failed (Muted): 5
-
Total Resources: 1
diff --git a/tests/lib/outputs/outputs_test.py b/tests/lib/outputs/outputs_test.py
index f6f59b274f..4419a4d44c 100644
--- a/tests/lib/outputs/outputs_test.py
+++ b/tests/lib/outputs/outputs_test.py
@@ -252,6 +252,8 @@ class TestOutputs:
stats = extract_findings_statistics(findings)
assert stats["total_pass"] == 1
assert stats["total_fail"] == 1
+ assert stats["total_muted_pass"] == 0
+ assert stats["total_muted_fail"] == 0
assert stats["resources_count"] == 2
assert stats["findings_count"] == 2
@@ -267,6 +269,8 @@ class TestOutputs:
stats = extract_findings_statistics(findings)
assert stats["total_pass"] == 2
assert stats["total_fail"] == 0
+ assert stats["total_muted_pass"] == 0
+ assert stats["total_muted_fail"] == 0
assert stats["resources_count"] == 1
assert stats["findings_count"] == 2
@@ -282,6 +286,8 @@ class TestOutputs:
stats = extract_findings_statistics(findings)
assert stats["total_pass"] == 1
assert stats["total_fail"] == 0
+ assert stats["total_muted_pass"] == 0
+ assert stats["total_muted_fail"] == 0
assert stats["resources_count"] == 1
assert stats["findings_count"] == 1
@@ -291,6 +297,8 @@ class TestOutputs:
stats = extract_findings_statistics(findings)
assert stats["total_pass"] == 0
assert stats["total_fail"] == 0
+ assert stats["total_muted_pass"] == 0
+ assert stats["total_muted_fail"] == 0
assert stats["resources_count"] == 0
assert stats["findings_count"] == 0
@@ -304,6 +312,8 @@ class TestOutputs:
stats = extract_findings_statistics(findings)
assert stats["total_pass"] == 0
assert stats["total_fail"] == 1
+ assert stats["total_muted_pass"] == 0
+ assert stats["total_muted_fail"] == 1
assert stats["resources_count"] == 1
assert stats["findings_count"] == 1
assert stats["all_fails_are_muted"]
@@ -322,10 +332,46 @@ class TestOutputs:
stats = extract_findings_statistics(findings)
assert stats["total_pass"] == 0
assert stats["total_fail"] == 2
+ assert stats["total_muted_pass"] == 0
+ assert stats["total_muted_fail"] == 1
assert stats["resources_count"] == 1
assert stats["findings_count"] == 2
assert not stats["all_fails_are_muted"]
+ def test_extract_findings_statistics_all_passes_are_not_muted(self):
+ finding_1 = mock.MagicMock()
+ finding_1.status = "PASS"
+ finding_1.muted = True
+ finding_1.resource_id = "test_resource_1"
+ finding_2 = mock.MagicMock()
+ finding_2.status = "PASS"
+ finding_2.muted = False
+ finding_2.resource_id = "test_resource_1"
+ findings = [finding_1, finding_2]
+
+ stats = extract_findings_statistics(findings)
+ assert stats["total_pass"] == 2
+ assert stats["total_fail"] == 0
+ assert stats["total_muted_pass"] == 1
+ assert stats["total_muted_fail"] == 0
+ assert stats["resources_count"] == 1
+ assert stats["findings_count"] == 2
+
+ def test_extract_findings_statistics_all_passes_are_muted(self):
+ finding_1 = mock.MagicMock()
+ finding_1.status = "PASS"
+ finding_1.muted = True
+ finding_1.resource_id = "test_resource_1"
+ findings = [finding_1]
+
+ stats = extract_findings_statistics(findings)
+ assert stats["total_pass"] == 1
+ assert stats["total_fail"] == 0
+ assert stats["total_muted_pass"] == 1
+ assert stats["total_muted_fail"] == 0
+ assert stats["resources_count"] == 1
+ assert stats["findings_count"] == 1
+
def test_report_with_aws_provider_not_muted_pass(self):
# Mocking check_findings and provider
finding_1 = MagicMock()