import sys
from io import StringIO
from mock import patch
from prowler.config.config import prowler_version, timestamp
from prowler.lib.outputs.html.html import HTML
from tests.lib.outputs.fixtures.fixtures import generate_finding_output
from tests.providers.aws.utils import AWS_REGION_EU_WEST_1, set_mocked_aws_provider
from tests.providers.azure.azure_fixtures import set_mocked_azure_provider
from tests.providers.gcp.gcp_fixtures import GCP_PROJECT_ID, set_mocked_gcp_provider
from tests.providers.kubernetes.kubernetes_fixtures import (
set_mocked_kubernetes_provider,
)
from tests.providers.m365.m365_fixtures import set_mocked_m365_provider
html_stats = {
"total_pass": 25,
"total_muted_pass": 20,
"total_fail": 5,
"total_muted_fail": 5,
"resources_count": 1,
"findings_count": 30,
}
pass_html_finding = """
PASS
high
test-service
eu-west-1
test-check-id
test-check-id
test-risk
•test-compliance: test-compliance
"""
fail_html_finding = """
FAIL
high
test-service
eu-west-1
test-check-id
test-check-id
test-resource-uid
•key1=value1
•key2=value2
test-status-extended
test-risk
test-remediation-recommendation-text
•test-compliance: test-compliance
"""
muted_html_finding = """
MUTED (PASS)
high
test-service
eu-west-1
test-check-id
test-check-id
test-risk
•test-compliance: test-compliance
"""
manual_html_finding = """
MANUAL
high
test-service
eu-west-1
test-check-id
test-check-id
test-risk
•test-compliance: test-compliance
"""
aws_html_assessment_summary = """
AWS Account: 123456789012
AWS-CLI Profile: default
Audited Regions: eu-west-1
User Id: None
Caller Identity ARN: None
"""
azure_html_assessment_summary = """
Azure Tenant IDs: 00000000-0000-0000-0000-000000000000
Azure Tenant Domain: Unknown tenant domain (missing AAD permissions)
Azure Subscriptions: 4f647f43-15d2-4e3a-a7f0-8517cc4d977b : Subscription Name
Azure Identity Type: Service Principal
Azure Identity ID: 00000000-0000-0000-0000-000000000000
"""
gcp_html_assessment_summary = """
GCP Project IDs: 123456789012
GCP Account: test@test.com
"""
kubernetes_html_assessment_summary = """
"""
m365_html_assessment_summary = """
M365 Tenant Domain: user.onmicrosoft.com
M365 Identity Type: Application
M365 Identity ID: 00000000-0000-0000-0000-000000000000
M365 User: user@email.com
"""
def get_aws_html_header(args: list) -> str:
"""
Generate the HTML header for AWS
Args:
args (list): List of arguments passed to the script
Returns:
str: HTML header for AWS
"""
aws_html_header = f"""
Prowler - The Handy Cloud Security Tool
Version: {prowler_version}
Parameters used: {" ".join(args)}
Date: {timestamp.isoformat()}
{aws_html_assessment_summary}
Total Findings: 30
Passed: 25
Passed (Muted): 20
Failed: 5
Failed (Muted): 5
Total Resources: 1
Status
Severity
Service Name
Region
Check ID
Check Title
Resource ID
Resource Tags
Status Extended
Risk
Recommendation
Compliance
"""
return aws_html_header
html_footer = """
"""
class TestHTML:
def test_transform_fail_finding(self):
findings = [
generate_finding_output(
status="FAIL",
resource_tags={"key1": "value1", "key2": "value2"},
severity="high",
service_name="test-service",
region=AWS_REGION_EU_WEST_1,
check_id="test-check-id",
check_title="test-check-id",
resource_uid="test-resource-uid",
status_extended="test-status-extended",
risk="test-risk",
remediation_recommendation_text="test-remediation-recommendation-text",
compliance={"test-compliance": "test-compliance"},
)
]
html = HTML(findings)
output_data = html.data[0]
assert isinstance(output_data, str)
assert output_data == fail_html_finding
def test_transform_pass_finding(self):
findings = [generate_finding_output()]
html = HTML(findings)
output_data = html.data[0]
assert isinstance(output_data, str)
assert output_data == pass_html_finding
def test_transform_muted_finding(self):
findings = [generate_finding_output(muted=True)]
html = HTML(findings)
output_data = html.data[0]
assert isinstance(output_data, str)
assert output_data == muted_html_finding
def test_transform_manual_finding(self):
findings = [generate_finding_output(status="MANUAL")]
html = HTML(findings)
output_data = html.data[0]
assert isinstance(output_data, str)
assert output_data == manual_html_finding
def test_batch_write_data_to_file(self):
mock_file = StringIO()
findings = [generate_finding_output()]
output = HTML(findings)
output._file_descriptor = mock_file
provider = set_mocked_aws_provider(audited_regions=[AWS_REGION_EU_WEST_1])
with patch.object(mock_file, "close", return_value=None):
output.batch_write_data_to_file(provider, html_stats)
mock_file.seek(0)
content = mock_file.read()
args = sys.argv[1:]
assert content == get_aws_html_header(args) + pass_html_finding + html_footer
def test_batch_write_data_to_file_without_findings(self):
assert not HTML([])._file_descriptor
def test_write_header(self):
mock_file = StringIO()
findings = [generate_finding_output()]
output = HTML(findings)
output._file_descriptor = mock_file
provider = set_mocked_aws_provider(audited_regions=[AWS_REGION_EU_WEST_1])
output.write_header(mock_file, provider, html_stats)
mock_file.seek(0)
content = mock_file.read()
args = sys.argv[1:]
assert content == get_aws_html_header(args)
def test_write_footer(self):
mock_file = StringIO()
findings = [generate_finding_output()]
output = HTML(findings)
output._file_descriptor = mock_file
output.write_footer(mock_file)
mock_file.seek(0)
content = mock_file.read()
assert content == html_footer
def test_aws_get_assessment_summary(self):
findings = [generate_finding_output()]
output = HTML(findings)
provider = set_mocked_aws_provider(audited_regions=[AWS_REGION_EU_WEST_1])
summary = output.get_assessment_summary(provider)
assert summary == aws_html_assessment_summary
def test_azure_get_assessment_summary(self):
findings = [generate_finding_output()]
output = HTML(findings)
provider = set_mocked_azure_provider()
summary = output.get_assessment_summary(provider)
assert summary == summary
def test_gcp_get_assessment_summary(self):
findings = [generate_finding_output()]
output = HTML(findings)
provider = set_mocked_gcp_provider(project_ids=[GCP_PROJECT_ID])
summary = output.get_assessment_summary(provider)
assert summary == gcp_html_assessment_summary
def test_kubernetes_get_assessment_summary(self):
findings = [generate_finding_output()]
output = HTML(findings)
provider = set_mocked_kubernetes_provider()
summary = output.get_assessment_summary(provider)
assert summary == kubernetes_html_assessment_summary
def test_m365_get_assessment_summary(self):
findings = [generate_finding_output()]
output = HTML(findings)
provider = set_mocked_m365_provider()
summary = output.get_assessment_summary(provider)
expected_summary = m365_html_assessment_summary
assert summary == expected_summary