mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 04:21:52 +00:00
fix(aws): handle AccessDenied when retrieving resource policy (#6908)
Co-authored-by: Pedro Martín <pedromarting3@gmail.com>
This commit is contained in:
+2
@@ -7,6 +7,8 @@ class awslambda_function_not_publicly_accessible(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for function in awslambda_client.functions.values():
|
||||
if function.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=function)
|
||||
|
||||
report.status = "PASS"
|
||||
|
||||
+2
@@ -7,6 +7,8 @@ class dynamodb_table_cross_account_access(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for table in dynamodb_client.tables.values():
|
||||
if table.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=table)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
|
||||
+2
@@ -8,6 +8,8 @@ class ecr_repositories_not_publicly_accessible(Check):
|
||||
findings = []
|
||||
for registry in ecr_client.registries.values():
|
||||
for repository in registry.repositories:
|
||||
if repository.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=repository)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
|
||||
@@ -87,6 +87,7 @@ class ECR(AWSService):
|
||||
logger.warning(
|
||||
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
repository.policy = {}
|
||||
|
||||
except Exception as error:
|
||||
if "RepositoryPolicyNotFoundException" not in str(error):
|
||||
|
||||
+2
@@ -7,6 +7,8 @@ class efs_not_publicly_accessible(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for fs in efs_client.filesystems.values():
|
||||
if fs.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=fs)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"EFS {fs.id} has a policy which does not allow access to any client within the VPC."
|
||||
|
||||
@@ -164,7 +164,7 @@ class FileSystem(BaseModel):
|
||||
id: str
|
||||
arn: str
|
||||
region: str
|
||||
policy: Optional[dict] = {}
|
||||
policy: Optional[dict]
|
||||
backup_policy: Optional[str] = "DISABLED"
|
||||
encrypted: bool
|
||||
availability_zone_id: Optional[str]
|
||||
|
||||
+2
@@ -9,6 +9,8 @@ class eventbridge_bus_cross_account_access(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for bus in eventbridge_client.buses.values():
|
||||
if bus.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=bus)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
|
||||
+2
@@ -9,6 +9,8 @@ class eventbridge_bus_exposed(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for bus in eventbridge_client.buses.values():
|
||||
if bus.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=bus)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
|
||||
+2
@@ -7,6 +7,8 @@ class eventbridge_schema_registry_cross_account_access(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for registry in schema_client.registries.values():
|
||||
if registry.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=registry)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"EventBridge schema registry {registry.name} does not allow cross-account access."
|
||||
|
||||
+2
@@ -7,6 +7,8 @@ class glue_data_catalogs_not_publicly_accessible(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for data_catalog in glue_client.data_catalogs.values():
|
||||
if data_catalog.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=data_catalog)
|
||||
report.resource_id = glue_client.audited_account
|
||||
report.resource_arn = glue_client._get_data_catalog_arn_template(
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ class opensearch_service_domains_not_publicly_accessible(Check):
|
||||
|
||||
if domain.vpc_id:
|
||||
report.status_extended = f"Opensearch domain {domain.name} is in a VPC, then it is not publicly accessible."
|
||||
elif domain.access_policy and is_policy_public(
|
||||
elif domain.access_policy is not None and is_policy_public(
|
||||
domain.access_policy, opensearch_client.audited_account
|
||||
):
|
||||
report.status = "FAIL"
|
||||
|
||||
+2
@@ -7,6 +7,8 @@ class s3_bucket_cross_account_access(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for bucket in s3_client.buckets.values():
|
||||
if bucket.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=bucket)
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"S3 Bucket {bucket.name} has a bucket policy but it does not allow cross account access."
|
||||
|
||||
+2
@@ -8,6 +8,8 @@ class s3_bucket_policy_public_write_access(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for bucket in s3_client.buckets.values():
|
||||
if bucket.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=bucket)
|
||||
# Check if bucket policy allow public write access
|
||||
if not bucket.policy:
|
||||
|
||||
+3
-1
@@ -45,7 +45,9 @@ class s3_bucket_public_access(Check):
|
||||
report.status_extended = f"S3 Bucket {bucket.name} has public access due to bucket ACL."
|
||||
|
||||
# 4. Check bucket policy
|
||||
if is_policy_public(bucket.policy, s3_client.audited_account):
|
||||
if bucket.policy is not None and is_policy_public(
|
||||
bucket.policy, s3_client.audited_account
|
||||
):
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"S3 Bucket {bucket.name} has public access due to bucket policy."
|
||||
findings.append(report)
|
||||
|
||||
@@ -681,7 +681,7 @@ class Bucket(BaseModel):
|
||||
logging: bool = False
|
||||
public_access_block: Optional[PublicAccessBlock]
|
||||
acl_grantees: List[ACL_Grantee] = Field(default_factory=list)
|
||||
policy: Dict = Field(default_factory=dict)
|
||||
policy: Optional[dict]
|
||||
encryption: Optional[str]
|
||||
region: str
|
||||
logging_target_bucket: Optional[str]
|
||||
|
||||
+2
@@ -9,6 +9,8 @@ class secretsmanager_not_publicly_accessible(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for secret in secretsmanager_client.secrets.values():
|
||||
if secret.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=secret)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
|
||||
+2
@@ -7,6 +7,8 @@ class ses_identity_not_publicly_accessible(Check):
|
||||
def execute(self):
|
||||
findings = []
|
||||
for identity in ses_client.email_identities.values():
|
||||
if identity.policy is None:
|
||||
continue
|
||||
report = Check_Report_AWS(metadata=self.metadata(), resource=identity)
|
||||
report.status = "PASS"
|
||||
report.status_extended = (
|
||||
|
||||
+73
-48
@@ -104,12 +104,15 @@ class Test_dynamodb_table_cross_account_access:
|
||||
def test_no_tables(self):
|
||||
dynamodb_client = mock.MagicMock
|
||||
dynamodb_client.tables = {}
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.dynamodb.dynamodb_table_cross_account_access.dynamodb_table_cross_account_access import (
|
||||
dynamodb_table_cross_account_access,
|
||||
@@ -131,15 +134,19 @@ class Test_dynamodb_table_cross_account_access:
|
||||
arn=arn,
|
||||
name=test_table_name,
|
||||
region=AWS_REGION_EU_WEST_1,
|
||||
policy={},
|
||||
)
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.dynamodb.dynamodb_table_cross_account_access.dynamodb_table_cross_account_access import (
|
||||
dynamodb_table_cross_account_access,
|
||||
@@ -172,12 +179,15 @@ class Test_dynamodb_table_cross_account_access:
|
||||
policy=test_restricted_policy,
|
||||
)
|
||||
}
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.dynamodb.dynamodb_table_cross_account_access.dynamodb_table_cross_account_access import (
|
||||
dynamodb_table_cross_account_access,
|
||||
@@ -211,12 +221,15 @@ class Test_dynamodb_table_cross_account_access:
|
||||
)
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.dynamodb.dynamodb_table_cross_account_access.dynamodb_table_cross_account_access import (
|
||||
dynamodb_table_cross_account_access,
|
||||
@@ -251,12 +264,15 @@ class Test_dynamodb_table_cross_account_access:
|
||||
)
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.dynamodb.dynamodb_table_cross_account_access.dynamodb_table_cross_account_access import (
|
||||
dynamodb_table_cross_account_access,
|
||||
@@ -291,12 +307,15 @@ class Test_dynamodb_table_cross_account_access:
|
||||
)
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.dynamodb.dynamodb_table_cross_account_access.dynamodb_table_cross_account_access import (
|
||||
dynamodb_table_cross_account_access,
|
||||
@@ -330,12 +349,15 @@ class Test_dynamodb_table_cross_account_access:
|
||||
)
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.dynamodb.dynamodb_table_cross_account_access.dynamodb_table_cross_account_access import (
|
||||
dynamodb_table_cross_account_access,
|
||||
@@ -369,12 +391,15 @@ class Test_dynamodb_table_cross_account_access:
|
||||
)
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_service.DynamoDB",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.dynamodb.dynamodb_client.dynamodb_client",
|
||||
new=dynamodb_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.dynamodb.dynamodb_table_cross_account_access.dynamodb_table_cross_account_access import (
|
||||
dynamodb_table_cross_account_access,
|
||||
|
||||
+46
-31
@@ -43,12 +43,15 @@ class Test_ecr_repositories_not_publicly_accessible:
|
||||
ecr_client = mock.MagicMock
|
||||
ecr_client.registries = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible.ecr_client",
|
||||
ecr_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible.ecr_client",
|
||||
ecr_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible import (
|
||||
ecr_repositories_not_publicly_accessible,
|
||||
@@ -70,12 +73,15 @@ class Test_ecr_repositories_not_publicly_accessible:
|
||||
rules=[],
|
||||
)
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible.ecr_client",
|
||||
ecr_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible.ecr_client",
|
||||
ecr_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible import (
|
||||
ecr_repositories_not_publicly_accessible,
|
||||
@@ -109,12 +115,15 @@ class Test_ecr_repositories_not_publicly_accessible:
|
||||
rules=[],
|
||||
)
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible.ecr_client",
|
||||
ecr_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible.ecr_client",
|
||||
ecr_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible import (
|
||||
ecr_repositories_not_publicly_accessible,
|
||||
@@ -145,7 +154,7 @@ class Test_ecr_repositories_not_publicly_accessible:
|
||||
arn=repository_arn,
|
||||
region=AWS_REGION_EU_WEST_1,
|
||||
scan_on_push=True,
|
||||
policy=None,
|
||||
policy={},
|
||||
images_details=None,
|
||||
lifecycle_policy=None,
|
||||
)
|
||||
@@ -153,12 +162,15 @@ class Test_ecr_repositories_not_publicly_accessible:
|
||||
rules=[],
|
||||
)
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible.ecr_client",
|
||||
ecr_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible.ecr_client",
|
||||
ecr_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible import (
|
||||
ecr_repositories_not_publicly_accessible,
|
||||
@@ -199,12 +211,15 @@ class Test_ecr_repositories_not_publicly_accessible:
|
||||
rules=[],
|
||||
)
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
), mock.patch(
|
||||
"prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible.ecr_client",
|
||||
ecr_client,
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible.ecr_client",
|
||||
ecr_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.ecr.ecr_repositories_not_publicly_accessible.ecr_repositories_not_publicly_accessible import (
|
||||
ecr_repositories_not_publicly_accessible,
|
||||
|
||||
Reference in New Issue
Block a user