mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-09 21:14:22 +00:00
fix(aws): recognize service-specific condition keys as restrictive in is_policy_public (#10600)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
2be2753c55
commit
89fe867944
@@ -33,6 +33,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- `--list-checks` and `--list-checks-json` now include `threat-detection` category checks in their output [(#10578)](https://github.com/prowler-cloud/prowler/pull/10578)
|
||||
- Missing `__init__.py` in `codebuild_project_uses_allowed_github_organizations` check preventing discovery by `--list-checks` [(#10584)](https://github.com/prowler-cloud/prowler/pull/10584)
|
||||
- Azure Key Vault checks emitting incorrect findings for keys, secrets, and vault logging [(#10332)](https://github.com/prowler-cloud/prowler/pull/10332)
|
||||
- `is_policy_public` now recognizes `kms:CallerAccount`, `kms:ViaService`, `aws:CalledVia`, `aws:CalledViaFirst`, and `aws:CalledViaLast` as restrictive condition keys, fixing false positives in `kms_key_policy_is_not_public` and other checks that use `is_condition_block_restrictive` [(#10600)](https://github.com/prowler-cloud/prowler/pull/10600)
|
||||
- `_enabled_regions` empty-set bug in `AwsProvider.generate_regional_clients` creating boto3 clients for all 36 AWS regions instead of the audited ones, causing random CI timeouts and slow test runs [(#10598)](https://github.com/prowler-cloud/prowler/pull/10598)
|
||||
- Retrieve only the latest version from a package in AWS CodeArtifact [(#10243)](https://github.com/prowler-cloud/prowler/pull/10243)
|
||||
|
||||
|
||||
@@ -617,6 +617,11 @@ def is_condition_block_restrictive(
|
||||
"aws:sourceorgpaths",
|
||||
"aws:userid",
|
||||
"aws:username",
|
||||
"aws:calledvia",
|
||||
"aws:calledviafirst",
|
||||
"aws:calledvialast",
|
||||
"kms:calleraccount",
|
||||
"kms:viaservice",
|
||||
"s3:resourceaccount",
|
||||
"lambda:eventsourcetoken", # For Alexa Home functions, a token that the invoker must supply.
|
||||
],
|
||||
@@ -635,6 +640,11 @@ def is_condition_block_restrictive(
|
||||
"aws:sourceorgpaths",
|
||||
"aws:userid",
|
||||
"aws:username",
|
||||
"aws:calledvia",
|
||||
"aws:calledviafirst",
|
||||
"aws:calledvialast",
|
||||
"kms:calleraccount",
|
||||
"kms:viaservice",
|
||||
"s3:resourceaccount",
|
||||
"lambda:eventsourcetoken",
|
||||
],
|
||||
|
||||
@@ -1413,6 +1413,115 @@ class Test_Policy:
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_aws_CalledVia_str(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"aws:CalledVia": "cloudformation.amazonaws.com"}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_aws_CalledViaFirst_str(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"aws:CalledViaFirst": "cloudformation.amazonaws.com"}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_aws_CalledViaLast_str(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"aws:CalledViaLast": "glue.amazonaws.com"}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_string_like_aws_CalledVia_str(self):
|
||||
condition_statement = {"StringLike": {"aws:CalledVia": "*.amazonaws.com"}}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_kms_CallerAccount_str(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"kms:CallerAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_kms_CallerAccount_str_not_valid(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"kms:CallerAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
||||
}
|
||||
assert not is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_kms_CallerAccount_list(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"kms:CallerAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_kms_CallerAccount_list_not_valid(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {
|
||||
"kms:CallerAccount": [
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
NON_TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
]
|
||||
}
|
||||
}
|
||||
assert not is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_kms_ViaService_str(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"kms:ViaService": "glue.eu-central-1.amazonaws.com"}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_string_like_kms_CallerAccount_str(self):
|
||||
condition_statement = {
|
||||
"StringLike": {"kms:CallerAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_like_kms_CallerAccount_str_not_valid(self):
|
||||
condition_statement = {
|
||||
"StringLike": {"kms:CallerAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
||||
}
|
||||
assert not is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_like_kms_ViaService_str(self):
|
||||
condition_statement = {"StringLike": {"kms:ViaService": "glue.*.amazonaws.com"}}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_two_lists_unrestrictive(self):
|
||||
condition_statement = {
|
||||
"StringLike": {
|
||||
@@ -2357,6 +2466,71 @@ class Test_Policy:
|
||||
trusted_ips=["1.2.3.4", "5.6.7.8"],
|
||||
)
|
||||
|
||||
def test_is_policy_public_kms_caller_account_and_via_service(self):
|
||||
policy = {
|
||||
"Version": "2008-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": "*"},
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:CreateGrant",
|
||||
"kms:DescribeKey",
|
||||
],
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"kms:ViaService": "glue.eu-central-1.amazonaws.com",
|
||||
"kms:CallerAccount": TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
||||
|
||||
def test_is_policy_public_kms_caller_account_only(self):
|
||||
policy = {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": "*"},
|
||||
"Action": ["kms:Decrypt"],
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"kms:CallerAccount": TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
||||
|
||||
def test_is_policy_public_kms_via_service_without_account_restriction(self):
|
||||
policy = {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": "*"},
|
||||
"Action": ["kms:Decrypt"],
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"kms:ViaService": "glue.eu-central-1.amazonaws.com",
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
||||
|
||||
def test_check_admin_access(self):
|
||||
policy = {
|
||||
"Version": "2012-10-17",
|
||||
|
||||
Reference in New Issue
Block a user