mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 21:11:53 +00:00
refactor(arn): fine tune arn and resources id for unknown values (#5841)
This commit is contained in:
@@ -160,16 +160,20 @@ else:
|
||||
All the checks MUST fill the `report.resource_id` and `report.resource_arn` with the following criteria:
|
||||
|
||||
- AWS
|
||||
- Resource ID -- `report.resource_id`
|
||||
- AWS Account --> Account Number `123456789012`
|
||||
- AWS Resource --> Resource ID / Name
|
||||
- Root resource --> `<root_account>`
|
||||
- Unknown resource --> `unknown`
|
||||
- Resource ARN -- `report.resource_arn`
|
||||
- AWS Account --> Root ARN `arn:aws:iam::123456789012:root`
|
||||
- AWS Resource --> Resource ARN
|
||||
- Root resource --> Resource Type ARN `f"arn:{service_client.audited_partition}:<service_name>:{service_client.region}:{service_client.audited_account}:<resource_type>"`
|
||||
- Unknown Resource --> `arn:{service_client.audited_partition}:{service_name}:{service_client.region}:{service_client.audited_account}:unknown`
|
||||
- Resouce ID and resource ARN:
|
||||
- If the resource audited is the AWS account:
|
||||
- `resource_id` -> AWS Account Number
|
||||
- `resource_arn` -> AWS Account Root ARN
|
||||
- If we can’t get the ARN from the resource audited, we create a valid ARN with the `resource_id` part as the resource audited. Examples:
|
||||
- Bedrock -> `arn:<partition>:bedrock:<region>:<account-id>:model-invocation-logging`
|
||||
- DirectConnect -> `arn:<partition>:directconnect:<region>:<account-id>:dxcon`
|
||||
- If there is no real resource to audit we do the following:
|
||||
- resource_id -> `resource_type/unknown`
|
||||
- resource_arn -> `arn:<partition>:<service>:<region>:<account-id>:<resource_type>/unknown`
|
||||
- Examples:
|
||||
- AWS Security Hub -> `arn:<partition>:security-hub:<region>:<account-id>:hub/unknown`
|
||||
- Access Analyzer -> `arn:<partition>:access-analyzer:<region>:<account-id>:analyzer/unknown`
|
||||
- GuardDuty -> `arn:<partition>:guardduty:<region>:<account-id>:detector/unknown`
|
||||
- GCP
|
||||
- Resource ID -- `report.resource_id`
|
||||
- GCP Resource --> Resource ID
|
||||
|
||||
@@ -102,15 +102,16 @@ class AWSService:
|
||||
# Handle exceptions if necessary
|
||||
pass # Replace 'pass' with any additional exception handling logic. Currently handled within the called function
|
||||
|
||||
def get_unknown_arn(self, region: str = None) -> str:
|
||||
def get_unknown_arn(self, resource_type: str = None, region: str = None) -> str:
|
||||
"""
|
||||
Generate an unknown ARN for the service
|
||||
Args:
|
||||
region (str): The region to get the unknown ARN for.
|
||||
resource_type (str): The resource type to get the unknown ARN for
|
||||
Returns:
|
||||
str: The unknown ARN for the region.
|
||||
Examples:
|
||||
>>> service.get_unknown_arn("us-east-1")
|
||||
"arn:aws:service:us-east-1:0123456789012:unknown"
|
||||
>>> service.get_unknown_arn(resource_type="bucket", region="us-east-1")
|
||||
arn:aws:s3:us-east-1:123456789012:bucket/unknown
|
||||
"""
|
||||
return f"arn:{self.audited_partition}:{self.service}:{f'{region}' if region else ''}:{self.audited_account}:unknown"
|
||||
return f"arn:{self.audited_partition}:{self.service}:{f'{region}' if region else ''}:{self.audited_account}:{f'{resource_type}/' if resource_type else ''}unknown"
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ class accessanalyzer_enabled(Check):
|
||||
else:
|
||||
if analyzer.status == "NOT_AVAILABLE":
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"IAM Access Analyzer in account {analyzer.name} is not enabled."
|
||||
report.status_extended = f"IAM Access Analyzer in account {accessanalyzer_client.audited_account} is not enabled."
|
||||
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
|
||||
@@ -43,8 +43,10 @@ class AccessAnalyzer(AWSService):
|
||||
if analyzer_count == 0:
|
||||
self.analyzers.append(
|
||||
Analyzer(
|
||||
arn=self.get_unknown_arn(regional_client.region),
|
||||
name="unknown",
|
||||
arn=self.get_unknown_arn(
|
||||
region=regional_client.region, resource_type="analyzer"
|
||||
),
|
||||
name="analyzer/unknown",
|
||||
status="NOT_AVAILABLE",
|
||||
tags=[],
|
||||
type="",
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ class bedrock_model_invocation_logging_enabled(Check):
|
||||
for region, logging in bedrock_client.logging_configurations.items():
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = region
|
||||
report.resource_id = "unknown"
|
||||
report.resource_id = "model-invocation-logging"
|
||||
report.resource_arn = (
|
||||
bedrock_client._get_model_invocation_logging_arn_template(region)
|
||||
)
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ class bedrock_model_invocation_logs_encryption_enabled(Check):
|
||||
cloudwatch_encryption = True
|
||||
report = Check_Report_AWS(self.metadata())
|
||||
report.region = region
|
||||
report.resource_id = "unknown"
|
||||
report.resource_id = "model-invocation-logging"
|
||||
report.resource_arn = (
|
||||
bedrock_client._get_model_invocation_logging_arn_template(region)
|
||||
)
|
||||
|
||||
@@ -42,8 +42,10 @@ class GuardDuty(AWSService):
|
||||
if not detectors:
|
||||
self.detectors.append(
|
||||
Detector(
|
||||
id="unknown",
|
||||
arn=self.get_unknown_arn(regional_client.region),
|
||||
id="detector/unknown",
|
||||
arn=self.get_unknown_arn(
|
||||
region=regional_client.region, resource_type="detector"
|
||||
),
|
||||
region=regional_client.region,
|
||||
enabled_in_account=False,
|
||||
)
|
||||
|
||||
@@ -27,8 +27,10 @@ class SecurityHub(AWSService):
|
||||
if e.response["Error"]["Code"] == "InvalidAccessException":
|
||||
self.securityhubs.append(
|
||||
SecurityHubHub(
|
||||
arn=self.audited_account_arn,
|
||||
id="unknown",
|
||||
arn=self.get_unknown_arn(
|
||||
region=regional_client.region, resource_type="hub"
|
||||
),
|
||||
id="hub/unknown",
|
||||
status="NOT_AVAILABLE",
|
||||
standards="",
|
||||
integrations="",
|
||||
@@ -73,8 +75,10 @@ class SecurityHub(AWSService):
|
||||
# SecurityHub is filtered
|
||||
self.securityhubs.append(
|
||||
SecurityHubHub(
|
||||
arn=self.get_unknown_arn(regional_client.region),
|
||||
id="unknown",
|
||||
arn=self.get_unknown_arn(
|
||||
region=regional_client.region, resource_type="hub"
|
||||
),
|
||||
id="hub/unknown",
|
||||
status="NOT_AVAILABLE",
|
||||
standards="",
|
||||
integrations="",
|
||||
|
||||
@@ -121,3 +121,34 @@ class TestAWSService:
|
||||
service.get_unknown_arn()
|
||||
== f"arn:aws:{service_name}::{AWS_ACCOUNT_NUMBER}:unknown"
|
||||
)
|
||||
|
||||
def test_AWSService_get_unknown_arn_resource_type_set(self):
|
||||
service_name = "s3"
|
||||
provider = set_mocked_aws_provider()
|
||||
service = AWSService(service_name, provider)
|
||||
|
||||
assert (
|
||||
service.get_unknown_arn(resource_type="bucket")
|
||||
== f"arn:aws:{service_name}::{AWS_ACCOUNT_NUMBER}:bucket/unknown"
|
||||
)
|
||||
|
||||
def test_AWSService_get_unknown_arn_resource_type_set_cn_partition(self):
|
||||
service_name = "s3"
|
||||
provider = set_mocked_aws_provider()
|
||||
service = AWSService(service_name, provider)
|
||||
service.audited_partition = "aws-cn"
|
||||
|
||||
assert (
|
||||
service.get_unknown_arn(resource_type="bucket")
|
||||
== f"arn:{service.audited_partition}:{service_name}::{AWS_ACCOUNT_NUMBER}:bucket/unknown"
|
||||
)
|
||||
|
||||
def test_AWSService_get_unknown_arn_resource_type_set_region(self):
|
||||
service_name = "s3"
|
||||
provider = set_mocked_aws_provider()
|
||||
service = AWSService(service_name, provider)
|
||||
|
||||
assert (
|
||||
service.get_unknown_arn(region="eu-west-1", resource_type="bucket")
|
||||
== f"arn:aws:{service_name}:eu-west-1:{AWS_ACCOUNT_NUMBER}:bucket/unknown"
|
||||
)
|
||||
|
||||
+9
-6
@@ -126,12 +126,12 @@ class Test_accessanalyzer_enabled:
|
||||
accessanalyzer_client.audited_partition = "aws"
|
||||
accessanalyzer_client.audited_account = AWS_ACCOUNT_NUMBER
|
||||
accessanalyzer_client.get_unknown_arn = (
|
||||
lambda x: f"arn:aws:accessanalyzer:{x}:{AWS_ACCOUNT_NUMBER}:unknown"
|
||||
lambda x: f"arn:aws:accessanalyzer:{x}:{AWS_ACCOUNT_NUMBER}:analyzer/unknown"
|
||||
)
|
||||
accessanalyzer_client.analyzers = [
|
||||
Analyzer(
|
||||
arn=AWS_ACCOUNT_ARN,
|
||||
name=AWS_ACCOUNT_NUMBER,
|
||||
arn=f"arn:aws:accessanalyzer:{AWS_REGION_1}:{AWS_ACCOUNT_NUMBER}:analyzer/unknown",
|
||||
name="analyzer/unknown",
|
||||
status="NOT_AVAILABLE",
|
||||
tags=[],
|
||||
type="",
|
||||
@@ -153,7 +153,7 @@ class Test_accessanalyzer_enabled:
|
||||
new=accessanalyzer_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.accessanalyzer.accessanalyzer_service.AccessAnalyzer.get_unknown_arn",
|
||||
return_value="arn:aws:accessanalyzer:eu-west-1:123456789012:unknown",
|
||||
return_value="arn:aws:accessanalyzer:eu-west-1:123456789012:analyzer/unknown",
|
||||
):
|
||||
# Test Check
|
||||
from prowler.providers.aws.services.accessanalyzer.accessanalyzer_enabled.accessanalyzer_enabled import (
|
||||
@@ -170,8 +170,11 @@ class Test_accessanalyzer_enabled:
|
||||
result[0].status_extended
|
||||
== f"IAM Access Analyzer in account {AWS_ACCOUNT_NUMBER} is not enabled."
|
||||
)
|
||||
assert result[0].resource_id == "123456789012"
|
||||
assert result[0].resource_arn == "arn:aws:iam::123456789012:root"
|
||||
assert result[0].resource_id == "analyzer/unknown"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:accessanalyzer:eu-west-1:123456789012:analyzer/unknown"
|
||||
)
|
||||
assert result[0].resource_tags == []
|
||||
assert result[0].region == AWS_REGION_1
|
||||
|
||||
|
||||
+5
-5
@@ -39,7 +39,7 @@ class Test_bedrock_model_invocation_logging_enabled:
|
||||
result[0].status_extended
|
||||
== "Bedrock Model Invocation Logging is disabled."
|
||||
)
|
||||
assert result[0].resource_id == "unknown"
|
||||
assert result[0].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== f"arn:aws:bedrock:{result[0].region}:123456789012:model-invocation-logging"
|
||||
@@ -50,7 +50,7 @@ class Test_bedrock_model_invocation_logging_enabled:
|
||||
result[1].status_extended
|
||||
== "Bedrock Model Invocation Logging is disabled."
|
||||
)
|
||||
assert result[1].resource_id == "unknown"
|
||||
assert result[1].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[1].resource_arn
|
||||
== f"arn:aws:bedrock:{result[1].region}:123456789012:model-invocation-logging"
|
||||
@@ -99,7 +99,7 @@ class Test_bedrock_model_invocation_logging_enabled:
|
||||
result[0].status_extended
|
||||
== "Bedrock Model Invocation Logging is enabled in CloudWatch Log Group: Test and S3 Bucket: testconfigbucket."
|
||||
)
|
||||
assert result[0].resource_id == "unknown"
|
||||
assert result[0].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:bedrock:us-east-1:123456789012:model-invocation-logging"
|
||||
@@ -142,7 +142,7 @@ class Test_bedrock_model_invocation_logging_enabled:
|
||||
result[0].status_extended
|
||||
== "Bedrock Model Invocation Logging is enabled in S3 Bucket: testconfigbucket."
|
||||
)
|
||||
assert result[0].resource_id == "unknown"
|
||||
assert result[0].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:bedrock:us-east-1:123456789012:model-invocation-logging"
|
||||
@@ -186,7 +186,7 @@ class Test_bedrock_model_invocation_logging_enabled:
|
||||
result[0].status_extended
|
||||
== "Bedrock Model Invocation Logging is enabled in CloudWatch Log Group: Test."
|
||||
)
|
||||
assert result[0].resource_id == "unknown"
|
||||
assert result[0].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:bedrock:us-east-1:123456789012:model-invocation-logging"
|
||||
|
||||
+6
-6
@@ -91,7 +91,7 @@ class Test_bedrock_model_invocation_logs_encryption_enabled:
|
||||
result[0].status_extended
|
||||
== "Bedrock Model Invocation logs are not encrypted in S3 bucket: testconfigbucket and CloudWatch Log Group: Test."
|
||||
)
|
||||
assert result[0].resource_id == "unknown"
|
||||
assert result[0].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:bedrock:us-east-1:123456789012:model-invocation-logging"
|
||||
@@ -144,7 +144,7 @@ class Test_bedrock_model_invocation_logs_encryption_enabled:
|
||||
result[0].status_extended
|
||||
== "Bedrock Model Invocation logs are not encrypted in S3 bucket: testconfigbucket."
|
||||
)
|
||||
assert result[0].resource_id == "unknown"
|
||||
assert result[0].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:bedrock:us-east-1:123456789012:model-invocation-logging"
|
||||
@@ -199,7 +199,7 @@ class Test_bedrock_model_invocation_logs_encryption_enabled:
|
||||
result[0].status_extended
|
||||
== "Bedrock Model Invocation logs are not encrypted in CloudWatch Log Group: Test."
|
||||
)
|
||||
assert result[0].resource_id == "unknown"
|
||||
assert result[0].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:bedrock:us-east-1:123456789012:model-invocation-logging"
|
||||
@@ -274,7 +274,7 @@ class Test_bedrock_model_invocation_logs_encryption_enabled:
|
||||
result[0].status_extended
|
||||
== "Bedrock Model Invocation logs are encrypted."
|
||||
)
|
||||
assert result[0].resource_id == "unknown"
|
||||
assert result[0].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:bedrock:us-east-1:123456789012:model-invocation-logging"
|
||||
@@ -340,7 +340,7 @@ class Test_bedrock_model_invocation_logs_encryption_enabled:
|
||||
result[0].status_extended
|
||||
== "Bedrock Model Invocation logs are encrypted."
|
||||
)
|
||||
assert result[0].resource_id == "unknown"
|
||||
assert result[0].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:bedrock:us-east-1:123456789012:model-invocation-logging"
|
||||
@@ -395,7 +395,7 @@ class Test_bedrock_model_invocation_logs_encryption_enabled:
|
||||
result[0].status_extended
|
||||
== "Bedrock Model Invocation logs are encrypted."
|
||||
)
|
||||
assert result[0].resource_id == "unknown"
|
||||
assert result[0].resource_id == "model-invocation-logging"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:bedrock:us-east-1:123456789012:model-invocation-logging"
|
||||
|
||||
+6
-6
@@ -11,12 +11,12 @@ class Test_securityhub_enabled:
|
||||
securityhub_client = mock.MagicMock
|
||||
securityhub_client.region = AWS_REGION_EU_WEST_1
|
||||
securityhub_client.get_unknown_arn = (
|
||||
lambda x: f"arn:aws:securityhub:{x}:0123456789012:unknown"
|
||||
lambda x: f"arn:aws:securityhub:{x}:0123456789012:hub/unknown"
|
||||
)
|
||||
securityhub_client.securityhubs = [
|
||||
SecurityHubHub(
|
||||
arn=f"arn:aws:securityhub:{AWS_REGION_EU_WEST_1}:0123456789012:unknown",
|
||||
id="Security Hub",
|
||||
arn=f"arn:aws:securityhub:{AWS_REGION_EU_WEST_1}:0123456789012:hub/unknown",
|
||||
id="hub/unknown",
|
||||
status="NOT_AVAILABLE",
|
||||
standards="",
|
||||
integrations="",
|
||||
@@ -29,7 +29,7 @@ class Test_securityhub_enabled:
|
||||
new=securityhub_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.securityhub.securityhub_service.SecurityHub.get_unknown_arn",
|
||||
return_value="arn:aws:securityhub:eu-west-1:0123456789012:unknown",
|
||||
return_value="arn:aws:securityhub:eu-west-1:0123456789012:hub/unknown",
|
||||
):
|
||||
# Test Check
|
||||
from prowler.providers.aws.services.securityhub.securityhub_enabled.securityhub_enabled import (
|
||||
@@ -41,10 +41,10 @@ class Test_securityhub_enabled:
|
||||
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].status_extended == "Security Hub is not enabled."
|
||||
assert result[0].resource_id == "Security Hub"
|
||||
assert result[0].resource_id == "hub/unknown"
|
||||
assert (
|
||||
result[0].resource_arn
|
||||
== "arn:aws:securityhub:eu-west-1:0123456789012:unknown"
|
||||
== "arn:aws:securityhub:eu-west-1:0123456789012:hub/unknown"
|
||||
)
|
||||
assert result[0].region == AWS_REGION_EU_WEST_1
|
||||
assert result[0].resource_tags == [{"test_key": "test_value"}]
|
||||
|
||||
Reference in New Issue
Block a user