Merge branch 'master' of github.com:prowler-cloud/prowler into PRWLR-6129-review-check-report-init-for-region-resource-id-resource-arn

This commit is contained in:
Pepe Fagoaga
2025-01-30 11:24:33 +01:00
9 changed files with 84 additions and 16 deletions
+1 -1
View File
@@ -124,7 +124,7 @@ extra:
make our documentation better.
analytics:
provider: google
property: G-H5TFH6WJRQ
property: G-KBKV70W5Y2
social:
- icon: fontawesome/brands/github
link: https://github.com/prowler-cloud
+9 -6
View File
@@ -332,18 +332,21 @@ def prowler():
# Outputs
# TODO: this part is needed since the checks generates a Check_Report_XXX and the output uses Finding
# This will be refactored for the outputs generate directly the Finding
finding_outputs = [
Finding.generate_output(global_provider, finding, output_options)
for finding in findings
]
finding_outputs = []
for finding in findings:
try:
finding_outputs.append(
Finding.generate_output(global_provider, finding, output_options)
)
except Exception:
continue
generated_outputs = {"regular": [], "compliance": []}
if args.output_formats:
for mode in args.output_formats:
filename = (
f"{output_options.output_directory}/"
f"{output_options.output_filename}"
f"{output_options.output_directory}/{output_options.output_filename}"
)
if mode == "csv":
csv_output = CSV(
+7 -1
View File
@@ -1,7 +1,7 @@
from datetime import datetime
from typing import Optional, Union
from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, ValidationError
from prowler.config.config import prowler_version
from prowler.lib.check.models import Check_Report, CheckMetadata
@@ -257,7 +257,13 @@ class Finding(BaseModel):
)
return cls(**output_data)
except ValidationError as validation_error:
logger.error(
f"{validation_error.__class__.__name__}[{validation_error.__traceback__.tb_lineno}]: {validation_error} - {output_data}"
)
raise validation_error
except Exception as error:
logger.error(
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
raise error
+10 -6
View File
@@ -296,12 +296,16 @@ class Scan:
self.get_completed_checks(),
)
findings = [
Finding.generate_output(
self._provider, finding, output_options=None
)
for finding in check_findings
]
findings = []
for finding in check_findings:
try:
findings.append(
Finding.generate_output(
self._provider, finding, output_options=None
)
)
except Exception:
continue
yield self.progress, findings
# If check does not exists in the provider or is from another provider
@@ -57,7 +57,7 @@ class ACM(AWSService):
certificate_expiration_time = 0
self.certificates[certificate["CertificateArn"]] = Certificate(
arn=certificate["CertificateArn"],
name=certificate["DomainName"],
name=certificate.get("DomainName", ""),
id=certificate["CertificateArn"].split("/")[-1],
type=certificate["Type"],
key_algorithm=certificate["KeyAlgorithm"],
@@ -15,7 +15,7 @@ class iam_user_with_temporary_credentials(Check):
report = Check_Report_AWS(
metadata=self.metadata(),
resource=iam_client.user_temporary_credentials_usage,
resource={"name": user_name, "arn": user_arn},
)
report.resource_id = user_name
report.resource_arn = user_arn
@@ -97,6 +97,7 @@ class SNS(AWSService):
owner=sub["Owner"],
protocol=sub["Protocol"],
endpoint=sub["Endpoint"],
region=sub["SubscriptionArn"].split(":")[3],
)
for sub in response["Subscriptions"]
]
@@ -117,6 +118,7 @@ class Subscription(BaseModel):
owner: str
protocol: str
endpoint: str
region: str
class Topic(BaseModel):
+44
View File
@@ -1,6 +1,9 @@
from datetime import datetime
from unittest.mock import MagicMock, patch
import pytest
from pydantic import ValidationError
from prowler.lib.check.models import (
CheckMetadata,
Code,
@@ -417,3 +420,44 @@ class TestFinding:
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)
@@ -65,6 +65,7 @@ class Test_sns_subscription_not_using_http_endpoints:
owner=AWS_ACCOUNT_NUMBER,
protocol="https",
endpoint="https://www.endpoint.com",
region=AWS_REGION_EU_WEST_1,
)
)
sns_client.topics = []
@@ -100,6 +101,7 @@ class Test_sns_subscription_not_using_http_endpoints:
owner=AWS_ACCOUNT_NUMBER,
protocol="https",
endpoint="https://www.endpoint.com",
region=AWS_REGION_EU_WEST_1,
)
)
sns_client.topics = []
@@ -131,6 +133,7 @@ class Test_sns_subscription_not_using_http_endpoints:
)
assert result[0].resource_id == subscription_id_1
assert result[0].resource_arn == subscription_arn_1
assert result[0].region == AWS_REGION_EU_WEST_1
def test_subscriptions_with_http(self):
sns_client = mock.MagicMock
@@ -142,6 +145,7 @@ class Test_sns_subscription_not_using_http_endpoints:
owner=AWS_ACCOUNT_NUMBER,
protocol="http",
endpoint="http://www.endpoint.com",
region=AWS_REGION_EU_WEST_1,
)
)
sns_client.topics = []
@@ -173,6 +177,7 @@ class Test_sns_subscription_not_using_http_endpoints:
)
assert result[0].resource_id == subscription_id_2
assert result[0].resource_arn == subscription_arn_2
assert result[0].region == AWS_REGION_EU_WEST_1
def test_subscriptions_with_http_and_https(self):
sns_client = mock.MagicMock
@@ -184,6 +189,7 @@ class Test_sns_subscription_not_using_http_endpoints:
owner=AWS_ACCOUNT_NUMBER,
protocol="https",
endpoint="https://www.endpoint.com",
region=AWS_REGION_EU_WEST_1,
)
)
subscriptions.append(
@@ -193,6 +199,7 @@ class Test_sns_subscription_not_using_http_endpoints:
owner=AWS_ACCOUNT_NUMBER,
protocol="http",
endpoint="http://www.endpoint.com",
region=AWS_REGION_EU_WEST_1,
)
)
sns_client.topics = []
@@ -224,6 +231,7 @@ class Test_sns_subscription_not_using_http_endpoints:
)
assert result[0].resource_id == subscription_id_1
assert result[0].resource_arn == subscription_arn_1
assert result[0].region == AWS_REGION_EU_WEST_1
assert result[1].status == "FAIL"
assert (
@@ -232,3 +240,4 @@ class Test_sns_subscription_not_using_http_endpoints:
)
assert result[1].resource_id == subscription_id_2
assert result[1].resource_arn == subscription_arn_2
assert result[1].region == AWS_REGION_EU_WEST_1