mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-10 06:01:52 +00:00
464 lines
20 KiB
Python
464 lines
20 KiB
Python
from datetime import datetime
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
|
|
from prowler.lib.check.models import (
|
|
CheckMetadata,
|
|
Code,
|
|
Recommendation,
|
|
Remediation,
|
|
Severity,
|
|
)
|
|
from prowler.lib.outputs.common import Status
|
|
from prowler.lib.outputs.finding import Finding
|
|
from tests.lib.outputs.fixtures.fixtures import generate_finding_output
|
|
|
|
|
|
def mock_check_metadata(provider):
|
|
return CheckMetadata(
|
|
Provider=provider,
|
|
CheckID="mock_check_id",
|
|
CheckTitle="mock_check_title",
|
|
CheckType=[],
|
|
CheckAliases=[],
|
|
ServiceName="mock_service_name",
|
|
SubServiceName="",
|
|
ResourceIdTemplate="",
|
|
Severity="high",
|
|
ResourceType="",
|
|
Description="",
|
|
Risk="",
|
|
RelatedUrl="",
|
|
Remediation=Remediation(
|
|
Code=Code(
|
|
NativeIaC="",
|
|
Terraform="",
|
|
CLI="",
|
|
Other="",
|
|
),
|
|
Recommendation=Recommendation(
|
|
Text="",
|
|
Url="",
|
|
),
|
|
),
|
|
Categories=[],
|
|
DependsOn=["check1", "check2"],
|
|
RelatedTo=["check1", "check2"],
|
|
Notes="mock_notes",
|
|
Compliance=[],
|
|
)
|
|
|
|
|
|
def mock_get_check_compliance(*_):
|
|
return {"mock_compliance_key": "mock_compliance_value"}
|
|
|
|
|
|
class TestFinding:
|
|
@patch(
|
|
"prowler.lib.outputs.finding.get_check_compliance",
|
|
new=mock_get_check_compliance,
|
|
)
|
|
def test_generate_output_aws(self):
|
|
# Mock provider
|
|
provider = MagicMock()
|
|
provider.type = "aws"
|
|
provider.identity.profile = "mock_auth"
|
|
provider.identity.account = "mock_account_uid"
|
|
provider.identity.partition = "aws"
|
|
provider.organizations_metadata.account_name = "mock_account_name"
|
|
provider.organizations_metadata.account_email = "mock_account_email"
|
|
provider.organizations_metadata.organization_arn = "mock_account_org_uid"
|
|
provider.organizations_metadata.organization_id = "mock_account_org_name"
|
|
provider.organizations_metadata.account_tags = {"tag1": "value1"}
|
|
|
|
# Mock check result
|
|
check_output = MagicMock()
|
|
check_output.resource_id = "test_resource_id"
|
|
check_output.resource_arn = "test_resource_arn"
|
|
check_output.resource_details = "test_resource_details"
|
|
check_output.resource_tags = {"tag1": "value1"}
|
|
check_output.region = "us-west-1"
|
|
check_output.partition = "aws"
|
|
check_output.status = Status.PASS
|
|
check_output.status_extended = "mock_status_extended"
|
|
check_output.muted = False
|
|
check_output.check_metadata = mock_check_metadata(provider="aws")
|
|
check_output.resource = {}
|
|
|
|
# Mock output options
|
|
output_options = MagicMock()
|
|
output_options.unix_timestamp = False
|
|
|
|
# Generate the finding
|
|
finding_output = Finding.generate_output(provider, check_output, output_options)
|
|
|
|
# Finding
|
|
assert isinstance(finding_output, Finding)
|
|
assert finding_output.auth_method == "profile: mock_auth"
|
|
assert finding_output.resource_name == "test_resource_id"
|
|
assert finding_output.resource_uid == "test_resource_arn"
|
|
assert finding_output.resource_details == "test_resource_details"
|
|
assert finding_output.region == "us-west-1"
|
|
assert finding_output.compliance == {
|
|
"mock_compliance_key": "mock_compliance_value"
|
|
}
|
|
assert finding_output.status == Status.PASS
|
|
assert finding_output.status_extended == "mock_status_extended"
|
|
assert finding_output.muted is False
|
|
assert finding_output.resource_tags == {"tag1": "value1"}
|
|
assert finding_output.partition == "aws"
|
|
assert finding_output.account_uid == "mock_account_uid"
|
|
assert finding_output.account_name == "mock_account_name"
|
|
assert finding_output.account_email == "mock_account_email"
|
|
assert finding_output.account_organization_uid == "mock_account_org_uid"
|
|
assert finding_output.account_organization_name == "mock_account_org_name"
|
|
assert finding_output.account_tags == {"tag1": "value1"}
|
|
|
|
# Metadata
|
|
assert finding_output.metadata.Provider == "aws"
|
|
assert finding_output.metadata.CheckID == "mock_check_id"
|
|
assert finding_output.metadata.CheckTitle == "mock_check_title"
|
|
assert finding_output.metadata.CheckType == []
|
|
assert finding_output.metadata.CheckAliases == []
|
|
assert finding_output.metadata.ServiceName == "mock_service_name"
|
|
assert finding_output.metadata.SubServiceName == ""
|
|
assert finding_output.metadata.ResourceIdTemplate == ""
|
|
assert finding_output.metadata.Severity == Severity.high
|
|
assert finding_output.metadata.ResourceType == ""
|
|
assert finding_output.metadata.Description == ""
|
|
assert finding_output.metadata.Risk == ""
|
|
assert finding_output.metadata.RelatedUrl == ""
|
|
assert finding_output.metadata.Remediation.Code.NativeIaC == ""
|
|
assert finding_output.metadata.Remediation.Code.Terraform == ""
|
|
assert finding_output.metadata.Remediation.Code.CLI == ""
|
|
assert finding_output.metadata.Remediation.Code.Other == ""
|
|
assert finding_output.metadata.Remediation.Recommendation.Text == ""
|
|
assert finding_output.metadata.Remediation.Recommendation.Url == ""
|
|
assert finding_output.metadata.Categories == []
|
|
assert finding_output.metadata.DependsOn == ["check1", "check2"]
|
|
assert finding_output.metadata.RelatedTo == ["check1", "check2"]
|
|
assert finding_output.metadata.Notes == "mock_notes"
|
|
assert finding_output.metadata.Compliance == []
|
|
|
|
# Properties
|
|
assert finding_output.provider == "aws"
|
|
assert finding_output.check_id == "mock_check_id"
|
|
assert finding_output.severity == Severity.high.value
|
|
assert finding_output.status == Status.PASS.value
|
|
assert finding_output.resource_type == ""
|
|
assert finding_output.service_name == "mock_service_name"
|
|
assert finding_output.raw == {}
|
|
|
|
@patch(
|
|
"prowler.lib.outputs.finding.get_check_compliance",
|
|
new=mock_get_check_compliance,
|
|
)
|
|
def test_generate_output_azure(self):
|
|
# Mock provider
|
|
provider = MagicMock()
|
|
provider.type = "azure"
|
|
provider.identity.identity_type = "mock_identity_type"
|
|
provider.identity.identity_id = "mock_identity_id"
|
|
provider.identity.subscriptions = {
|
|
"mock_subscription_id": "mock_subscription_name"
|
|
}
|
|
provider.identity.tenant_ids = ["mock_tenant_id_1", "mock_tenant_id_2"]
|
|
provider.identity.tenant_domain = "mock_tenant_domain"
|
|
provider.region_config.name = "AzureCloud"
|
|
|
|
# Mock check result
|
|
check_output = MagicMock()
|
|
check_output.resource_name = "test_resource_name"
|
|
check_output.resource_id = "test_resource_id"
|
|
check_output.resource_details = "test_resource_details"
|
|
check_output.resource_tags = {}
|
|
check_output.subscription = "mock_subscription_id"
|
|
check_output.resource_name = "test_resource_name"
|
|
check_output.location = "us-west-1"
|
|
check_output.region = "us-west-1"
|
|
check_output.status = Status.PASS
|
|
check_output.status_extended = "mock_status_extended"
|
|
check_output.muted = False
|
|
check_output.check_metadata = mock_check_metadata(provider="azure")
|
|
check_output.resource = {}
|
|
|
|
# Mock output options
|
|
output_options = MagicMock()
|
|
output_options.unix_timestamp = True
|
|
|
|
# Generate the finding
|
|
finding_output = Finding.generate_output(provider, check_output, output_options)
|
|
|
|
# Finding
|
|
assert isinstance(finding_output, Finding)
|
|
assert finding_output.auth_method == "mock_identity_type: mock_identity_id"
|
|
assert finding_output.account_organization_uid == "mock_tenant_id_1"
|
|
assert finding_output.account_organization_name == "mock_tenant_domain"
|
|
assert finding_output.account_uid == "mock_subscription_name"
|
|
assert finding_output.account_name == "mock_subscription_id"
|
|
assert finding_output.resource_name == "test_resource_name"
|
|
assert finding_output.resource_uid == "test_resource_id"
|
|
assert finding_output.region == "us-west-1"
|
|
assert finding_output.compliance == {
|
|
"mock_compliance_key": "mock_compliance_value"
|
|
}
|
|
assert finding_output.status == Status.PASS
|
|
assert finding_output.status_extended == "mock_status_extended"
|
|
assert finding_output.muted is False
|
|
assert finding_output.resource_tags == {}
|
|
assert finding_output.partition == "AzureCloud"
|
|
|
|
assert isinstance(finding_output.timestamp, int)
|
|
|
|
# Metadata
|
|
assert finding_output.metadata.Provider == "azure"
|
|
assert finding_output.metadata.CheckID == "mock_check_id"
|
|
assert finding_output.metadata.CheckTitle == "mock_check_title"
|
|
assert finding_output.metadata.CheckType == []
|
|
assert finding_output.metadata.CheckAliases == []
|
|
assert finding_output.metadata.ServiceName == "mock_service_name"
|
|
assert finding_output.metadata.SubServiceName == ""
|
|
assert finding_output.metadata.ResourceIdTemplate == ""
|
|
assert finding_output.metadata.Severity == Severity.high
|
|
assert finding_output.metadata.ResourceType == ""
|
|
assert finding_output.metadata.Description == ""
|
|
assert finding_output.metadata.Risk == ""
|
|
assert finding_output.metadata.RelatedUrl == ""
|
|
assert finding_output.metadata.Remediation.Code.NativeIaC == ""
|
|
assert finding_output.metadata.Remediation.Code.Terraform == ""
|
|
assert finding_output.metadata.Remediation.Code.CLI == ""
|
|
assert finding_output.metadata.Remediation.Code.Other == ""
|
|
assert finding_output.metadata.Remediation.Recommendation.Text == ""
|
|
assert finding_output.metadata.Remediation.Recommendation.Url == ""
|
|
assert finding_output.metadata.Categories == []
|
|
assert finding_output.metadata.DependsOn == ["check1", "check2"]
|
|
assert finding_output.metadata.RelatedTo == ["check1", "check2"]
|
|
assert finding_output.metadata.Notes == "mock_notes"
|
|
assert finding_output.metadata.Compliance == []
|
|
|
|
@patch(
|
|
"prowler.lib.outputs.finding.get_check_compliance",
|
|
new=mock_get_check_compliance,
|
|
)
|
|
def test_generate_output_gcp(self):
|
|
# Mock provider
|
|
provider = MagicMock()
|
|
provider.type = "gcp"
|
|
provider.identity.profile = "mock_auth"
|
|
# Organization
|
|
organization = MagicMock()
|
|
organization.id = "mock_organization_id"
|
|
organization.display_name = "mock_organization_name"
|
|
# Project
|
|
project = MagicMock()
|
|
project.id = "mock_project_id"
|
|
project.name = "mock_project_name"
|
|
project.labels = {"tag1": "value1"}
|
|
project.organization = organization
|
|
provider.projects = {"mock_project_id": project}
|
|
|
|
# Mock check result
|
|
check_output = MagicMock()
|
|
check_output.resource_id = "test_resource_id"
|
|
check_output.resource_name = "test_resource_name"
|
|
check_output.resource_details = "test_resource_details"
|
|
check_output.project_id = "mock_project_id"
|
|
check_output.resource_name = "test_resource_name"
|
|
check_output.location = "us-west-1"
|
|
check_output.status = Status.PASS
|
|
check_output.status_extended = "mock_status_extended"
|
|
check_output.muted = False
|
|
check_output.check_metadata = mock_check_metadata(provider="gcp")
|
|
check_output.resource = {}
|
|
|
|
# Mock output options
|
|
output_options = MagicMock()
|
|
output_options.unix_timestamp = True
|
|
|
|
# Generate the finding
|
|
finding_output = Finding.generate_output(provider, check_output, output_options)
|
|
|
|
# Finding
|
|
assert isinstance(finding_output, Finding)
|
|
assert finding_output.auth_method == "Principal: mock_auth"
|
|
assert finding_output.resource_name == "test_resource_name"
|
|
assert finding_output.resource_uid == "test_resource_id"
|
|
assert finding_output.region == "us-west-1"
|
|
assert finding_output.compliance == {
|
|
"mock_compliance_key": "mock_compliance_value"
|
|
}
|
|
assert finding_output.status == Status.PASS
|
|
assert finding_output.status_extended == "mock_status_extended"
|
|
assert finding_output.muted is False
|
|
assert finding_output.resource_tags == {}
|
|
assert finding_output.partition is None
|
|
assert finding_output.account_uid == "mock_project_id"
|
|
assert finding_output.account_name == "mock_project_name"
|
|
assert finding_output.account_email is None
|
|
assert finding_output.account_organization_uid == "mock_organization_id"
|
|
assert finding_output.account_organization_name == "mock_organization_name"
|
|
assert finding_output.account_tags == {"tag1": "value1"}
|
|
assert isinstance(finding_output.timestamp, int)
|
|
|
|
# Metadata
|
|
assert finding_output.metadata.Provider == "gcp"
|
|
assert finding_output.metadata.CheckID == "mock_check_id"
|
|
assert finding_output.metadata.CheckTitle == "mock_check_title"
|
|
assert finding_output.metadata.CheckType == []
|
|
assert finding_output.metadata.CheckAliases == []
|
|
assert finding_output.metadata.ServiceName == "mock_service_name"
|
|
assert finding_output.metadata.SubServiceName == ""
|
|
assert finding_output.metadata.ResourceIdTemplate == ""
|
|
assert finding_output.metadata.Severity == Severity.high
|
|
assert finding_output.metadata.ResourceType == ""
|
|
assert finding_output.metadata.Description == ""
|
|
assert finding_output.metadata.Risk == ""
|
|
assert finding_output.metadata.RelatedUrl == ""
|
|
assert finding_output.metadata.Remediation.Code.NativeIaC == ""
|
|
assert finding_output.metadata.Remediation.Code.Terraform == ""
|
|
assert finding_output.metadata.Remediation.Code.CLI == ""
|
|
assert finding_output.metadata.Remediation.Code.Other == ""
|
|
assert finding_output.metadata.Remediation.Recommendation.Text == ""
|
|
assert finding_output.metadata.Remediation.Recommendation.Url == ""
|
|
assert finding_output.metadata.Categories == []
|
|
assert finding_output.metadata.DependsOn == ["check1", "check2"]
|
|
assert finding_output.metadata.RelatedTo == ["check1", "check2"]
|
|
assert finding_output.metadata.Notes == "mock_notes"
|
|
assert finding_output.metadata.Compliance == []
|
|
|
|
@patch(
|
|
"prowler.lib.outputs.finding.get_check_compliance",
|
|
new=mock_get_check_compliance,
|
|
)
|
|
def test_generate_output_kubernetes(self):
|
|
# Mock provider
|
|
provider = MagicMock()
|
|
provider.type = "kubernetes"
|
|
provider.identity.context = "In-Cluster"
|
|
provider.identity.cluster = "test_cluster"
|
|
|
|
# Mock check result
|
|
check_output = MagicMock()
|
|
check_output.resource_name = "test_resource_name"
|
|
check_output.resource_id = "test_resource_id"
|
|
check_output.namespace = "test_namespace"
|
|
check_output.resource_details = "test_resource_details"
|
|
check_output.status = Status.PASS
|
|
check_output.status_extended = "mock_status_extended"
|
|
check_output.muted = False
|
|
check_output.check_metadata = mock_check_metadata(provider="kubernetes")
|
|
check_output.timestamp = datetime.now()
|
|
check_output.resource = {}
|
|
|
|
# Mock Output Options
|
|
output_options = MagicMock()
|
|
output_options.unix_timestamp = True
|
|
|
|
# Generate the finding
|
|
finding_output = Finding.generate_output(provider, check_output, output_options)
|
|
|
|
# Finding
|
|
assert isinstance(finding_output, Finding)
|
|
assert finding_output.auth_method == "in-cluster"
|
|
assert finding_output.resource_name == "test_resource_name"
|
|
assert finding_output.resource_uid == "test_resource_id"
|
|
assert finding_output.region == "namespace: test_namespace"
|
|
assert finding_output.account_name == "context: In-Cluster"
|
|
assert finding_output.compliance == {
|
|
"mock_compliance_key": "mock_compliance_value"
|
|
}
|
|
assert finding_output.status == Status.PASS
|
|
assert finding_output.status_extended == "mock_status_extended"
|
|
assert finding_output.muted is False
|
|
assert finding_output.resource_tags == {}
|
|
assert finding_output.partition is None
|
|
assert finding_output.account_uid == "test_cluster"
|
|
assert finding_output.account_name == "context: In-Cluster"
|
|
assert finding_output.account_email is None
|
|
assert finding_output.account_organization_uid is None
|
|
assert finding_output.account_organization_name is None
|
|
assert finding_output.account_tags == {}
|
|
assert isinstance(finding_output.timestamp, int)
|
|
|
|
# Metadata
|
|
assert finding_output.metadata.Provider == "kubernetes"
|
|
assert finding_output.metadata.CheckID == "mock_check_id"
|
|
assert finding_output.metadata.CheckTitle == "mock_check_title"
|
|
assert finding_output.metadata.CheckType == []
|
|
assert finding_output.metadata.CheckAliases == []
|
|
assert finding_output.metadata.ServiceName == "mock_service_name"
|
|
assert finding_output.metadata.SubServiceName == ""
|
|
assert finding_output.metadata.ResourceIdTemplate == ""
|
|
assert finding_output.metadata.Severity == Severity.high
|
|
assert finding_output.metadata.ResourceType == ""
|
|
assert finding_output.metadata.Description == ""
|
|
assert finding_output.metadata.Risk == ""
|
|
assert finding_output.metadata.RelatedUrl == ""
|
|
assert finding_output.metadata.Remediation.Code.NativeIaC == ""
|
|
assert finding_output.metadata.Remediation.Code.Terraform == ""
|
|
assert finding_output.metadata.Remediation.Code.CLI == ""
|
|
assert finding_output.metadata.Remediation.Code.Other == ""
|
|
assert finding_output.metadata.Remediation.Recommendation.Text == ""
|
|
assert finding_output.metadata.Remediation.Recommendation.Url == ""
|
|
assert finding_output.metadata.Categories == []
|
|
assert finding_output.metadata.DependsOn == ["check1", "check2"]
|
|
assert finding_output.metadata.RelatedTo == ["check1", "check2"]
|
|
assert finding_output.metadata.Notes == "mock_notes"
|
|
assert finding_output.metadata.Compliance == []
|
|
|
|
def assert_keys_lowercase(self, d):
|
|
for k, v in d.items():
|
|
assert k.islower()
|
|
if isinstance(v, dict):
|
|
self.assert_keys_lowercase(v)
|
|
|
|
def test_get_metadata(self):
|
|
metadata = generate_finding_output().get_metadata()
|
|
|
|
assert metadata is not None
|
|
assert isinstance(metadata, dict)
|
|
self.assert_keys_lowercase(metadata)
|
|
|
|
@patch(
|
|
"prowler.lib.outputs.finding.get_check_compliance",
|
|
new=mock_get_check_compliance,
|
|
)
|
|
def test_generate_output_validation_error(self):
|
|
# Mock provider
|
|
provider = MagicMock()
|
|
provider.type = "aws"
|
|
provider.identity.profile = "mock_auth"
|
|
provider.identity.account = "mock_account_uid"
|
|
provider.identity.partition = "aws"
|
|
provider.organizations_metadata.account_name = "mock_account_name"
|
|
provider.organizations_metadata.account_email = "mock_account_email"
|
|
provider.organizations_metadata.organization_arn = "mock_account_org_uid"
|
|
provider.organizations_metadata.organization_id = "mock_account_org_name"
|
|
provider.organizations_metadata.account_tags = {"tag1": "value1"}
|
|
|
|
# Mock check result
|
|
check_output = MagicMock()
|
|
check_output.resource_id = "test_resource_id"
|
|
check_output.resource_arn = "test_resource_arn"
|
|
check_output.resource_details = "test_resource_details"
|
|
check_output.resource_tags = {"tag1": "value1"}
|
|
check_output.region = "us-west-1"
|
|
check_output.partition = "aws"
|
|
check_output.status_extended = "mock_status_extended"
|
|
check_output.muted = False
|
|
check_output.check_metadata = mock_check_metadata(provider="aws")
|
|
check_output.resource = {}
|
|
|
|
# Mock output options
|
|
output_options = MagicMock()
|
|
output_options.unix_timestamp = False
|
|
|
|
# Bad Status Value
|
|
check_output.status = "Invalid"
|
|
|
|
# Generate the finding
|
|
with pytest.raises(ValidationError):
|
|
Finding.generate_output(provider, check_output, output_options)
|