mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-03-22 03:08:23 +00:00
2763 lines
97 KiB
Python
2763 lines
97 KiB
Python
import pytest
|
|
|
|
from prowler.providers.aws.services.iam.lib.policy import (
|
|
_get_patterns_from_standard_value,
|
|
check_admin_access,
|
|
check_full_service_access,
|
|
get_effective_actions,
|
|
has_codebuild_trusted_principal,
|
|
has_public_principal,
|
|
has_restrictive_source_arn_condition,
|
|
is_codebuild_using_allowed_github_org,
|
|
is_condition_block_restrictive,
|
|
is_condition_block_restrictive_organization,
|
|
is_condition_block_restrictive_sns_endpoint,
|
|
is_condition_restricting_from_private_ip,
|
|
is_policy_public,
|
|
)
|
|
|
|
TRUSTED_AWS_ACCOUNT_NUMBER = "123456789012"
|
|
NON_TRUSTED_AWS_ACCOUNT_NUMBER = "111222333444"
|
|
TRUSTED_AWS_ACCOUNT_NUMBER_LIST = ["123456789012", "123456789013", "123456789014"]
|
|
|
|
TRUSTED_ORGANIZATION_ID = "o-123456789012"
|
|
NON_TRUSTED_ORGANIZATION_ID = "o-111222333444"
|
|
|
|
ALL_ORGS = "*"
|
|
|
|
|
|
class Test_Policy:
|
|
def test_get_patterns_from_standard_value_string(self):
|
|
"""Test _get_patterns_from_standard_value with a string input"""
|
|
result = _get_patterns_from_standard_value("s3:GetObject")
|
|
assert result == {"s3:GetObject"}
|
|
|
|
result = _get_patterns_from_standard_value("")
|
|
assert result == {""}
|
|
|
|
def test_get_patterns_from_standard_value_list(self):
|
|
"""Test _get_patterns_from_standard_value with a list input"""
|
|
result = _get_patterns_from_standard_value(["s3:GetObject", "s3:PutObject"])
|
|
assert result == {"s3:GetObject", "s3:PutObject"}
|
|
|
|
result = _get_patterns_from_standard_value([])
|
|
assert result == set()
|
|
|
|
result = _get_patterns_from_standard_value(["s3:GetObject", 123, None])
|
|
assert result == {"s3:GetObject"}
|
|
|
|
def test_get_patterns_from_standard_value_invalid_input(self):
|
|
"""Test _get_patterns_from_standard_value with invalid inputs"""
|
|
result = _get_patterns_from_standard_value(None)
|
|
assert result == set()
|
|
|
|
result = _get_patterns_from_standard_value(123)
|
|
assert result == set()
|
|
|
|
def test_get_effective_actions_empty_policy(self):
|
|
"""Test get_effective_actions with an empty policy"""
|
|
result = get_effective_actions({})
|
|
assert result == set()
|
|
|
|
result = get_effective_actions({"Version": "2012-10-17"})
|
|
assert result == set()
|
|
|
|
def test_get_effective_actions_simple_allow(self):
|
|
"""Test get_effective_actions with a simple Allow statement"""
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": {"Effect": "Allow", "Action": "s3:GetObject"},
|
|
}
|
|
result = get_effective_actions(policy)
|
|
assert result == {"s3:GetObject"}
|
|
|
|
def test_get_effective_actions_simple_deny(self):
|
|
"""Test get_effective_actions with a simple Deny statement"""
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": {"Effect": "Deny", "Action": "s3:GetObject"},
|
|
}
|
|
result = get_effective_actions(policy)
|
|
assert result == set()
|
|
|
|
def test_get_effective_actions_allow_and_deny(self):
|
|
"""Test get_effective_actions with both Allow and Deny statements"""
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{"Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject"]},
|
|
{"Effect": "Deny", "Action": "s3:GetObject"},
|
|
],
|
|
}
|
|
result = get_effective_actions(policy)
|
|
assert result == {"s3:PutObject"}
|
|
|
|
def test_get_effective_actions_with_not_action(self):
|
|
"""Test get_effective_actions with NotAction statements"""
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": {"Effect": "Allow", "NotAction": "s3:GetObject"},
|
|
}
|
|
result = get_effective_actions(policy)
|
|
assert "s3:GetObject" not in result
|
|
assert "s3:PutObject" in result
|
|
|
|
def test_get_effective_actions_with_wildcards(self):
|
|
"""Test get_effective_actions with wildcard actions"""
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": {"Effect": "Allow", "Action": "s3:*"},
|
|
}
|
|
result = get_effective_actions(policy)
|
|
assert "s3:GetObject" in result
|
|
assert "s3:PutObject" in result
|
|
assert "s3:ListBucket" in result
|
|
|
|
def test_get_effective_actions_with_invalid_effect(self):
|
|
"""Test get_effective_actions with invalid Effect value"""
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": {"Effect": "Invalid", "Action": "s3:GetObject"},
|
|
}
|
|
result = get_effective_actions(policy)
|
|
assert result == set()
|
|
|
|
def test_get_effective_actions_with_multiple_statements(self):
|
|
"""Test get_effective_actions with multiple statements"""
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{"Effect": "Allow", "Action": ["s3:GetObject", "s3:PutObject"]},
|
|
{"Effect": "Allow", "Action": "s3:ListBucket"},
|
|
{"Effect": "Deny", "Action": "s3:PutObject"},
|
|
],
|
|
}
|
|
result = get_effective_actions(policy)
|
|
assert result == {"s3:GetObject", "s3:ListBucket"}
|
|
assert "s3:PutObject" not in result
|
|
|
|
# Test lowercase context key name --> aws
|
|
def test_condition_parser_string_equals_aws_SourceAccount_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:SourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_SourceAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"aws:SourceAccount": [
|
|
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_aws_SourceAccount_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:SourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_SourceAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:SourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_SourceAccount_list(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:SourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_SourceAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:SourceAccount": [
|
|
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_like_aws_SourceAccount_str(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:SourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_SourceAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:SourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_SourceOwner_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_SourceOwner_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:SourceOwner": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_SourceOwner_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:SourceOwner": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_SourceOwner_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"aws:SourceOwner": [
|
|
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_like_aws_SourceOwner_list(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:SourceOwner": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_SourceOwner_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:SourceOwner": [
|
|
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_like_aws_SourceOwner_str(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_SourceOwner_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:SourceOwner": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_s3_ResourceAccount_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"s3:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_s3_ResourceAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"s3:ResourceAccount": [
|
|
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_s3_ResourceAccount_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"s3:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_s3_ResourceAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"s3:ResourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_PrincipalAccount_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:PrincipalAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_PrincipalAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"aws:PrincipalAccount": [
|
|
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_aws_PrincipalAccount_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:PrincipalAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_PrincipalAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:PrincipalAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_SourceArn_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"aws:SourceArn": f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_SourceArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"aws:SourceArn": f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_PrincipalAccount_list(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:PrincipalAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_PrincipalAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:PrincipalAccount": [
|
|
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_like_aws_PrincipalAccount_str(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:PrincipalAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_PrincipalAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:PrincipalAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_aws_SourceArn_list(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"aws:SourceArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_aws_SourceArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"aws:SourceArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_aws_SourceArn_str(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"aws:SourceArn": f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_aws_SourceArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"aws:SourceArn": f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_aws_PrincipalArn_list(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"aws:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_aws_PrincipalArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"aws:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_aws_PrincipalArn_str(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"aws:PrincipalArn": f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_aws_PrincipalArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"aws:PrincipalArn": f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_aws_SourceArn_list(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"aws:SourceArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_aws_SourceArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"aws:SourceArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_aws_SourceArn_str(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"aws:SourceArn": f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_aws_SourceArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"aws:SourceArn": f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_aws_PrincipalArn_list(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"aws:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_aws_PrincipalArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"aws:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_aws_PrincipalArn_str(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"aws:PrincipalArn": f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_aws_PrincipalArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"aws:PrincipalArn": f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_SourceArn_list(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:SourceArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_SourceArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:SourceArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_SourceArn_str(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:SourceArn": f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_SourceArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:SourceArn": f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_PrincipalArn_list(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_PrincipalArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_PrincipalArn_str(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:PrincipalArn": f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_PrincipalArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:PrincipalArn": f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_ResourceAccount_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_ResourceAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"aws:ResourceAccount": [
|
|
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_aws_ResourceAccount_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_ResourceAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:ResourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_ResourceAccount_list(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_ResourceAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"aws:ResourceAccount": [
|
|
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_like_aws_ResourceAccount_str(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_aws_ResourceAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {"aws:ResourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
# Test uppercase context key name --> AWS
|
|
def test_condition_parser_string_equals_AWS_SourceAccount_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:SourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_SourceAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"AWS:SourceAccount": [
|
|
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_AWS_SourceAccount_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:SourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_SourceAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:SourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_SourceAccount_list(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:SourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_SourceAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:SourceAccount": [
|
|
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_like_AWS_SourceAccount_str(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:SourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_SourceAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:SourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_SourceOwner_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_SourceOwner_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:SourceOwner": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_SourceOwner_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:SourceOwner": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_SourceOwner_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"AWS:SourceOwner": [
|
|
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_like_AWS_SourceOwner_list(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:SourceOwner": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_SourceOwner_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:SourceOwner": [
|
|
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_like_AWS_SourceOwner_str(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_SourceOwner_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:SourceOwner": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_S3_ResourceAccount_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"S3:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_S3_ResourceAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"S3:ResourceAccount": [
|
|
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_S3_ResourceAccount_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"S3:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_S3_ResourceAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"S3:ResourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_PrincipalAccount_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:PrincipalAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_PrincipalAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"AWS:PrincipalAccount": [
|
|
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_AWS_PrincipalAccount_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:PrincipalAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_PrincipalAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:PrincipalAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_PrincipalAccount_list(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:PrincipalAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_PrincipalAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:PrincipalAccount": [
|
|
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_like_AWS_PrincipalAccount_str(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:PrincipalAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_PrincipalAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:PrincipalAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_AWS_SourceArn_list(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"AWS:SourceArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_AWS_SourceArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"AWS:SourceArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_AWS_SourceArn_str(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"AWS:SourceArn": f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_AWS_SourceArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"AWS:SourceArn": f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_AWS_PrincipalArn_list(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"AWS:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_AWS_PrincipalArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"AWS:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_AWS_PrincipalArn_str(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"AWS:PrincipalArn": f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_like_AWS_PrincipalArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"ArnLike": {
|
|
"AWS:PrincipalArn": f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_AWS_SourceArn_list(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"AWS:SourceArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_AWS_SourceArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"AWS:SourceArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_AWS_SourceArn_str(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"AWS:SourceArn": f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_AWS_SourceArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"AWS:SourceArn": f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_AWS_PrincipalArn_list(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"AWS:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_AWS_PrincipalArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"AWS:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_AWS_PrincipalArn_str(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"AWS:PrincipalArn": f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_arn_equals_AWS_PrincipalArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"ArnEquals": {
|
|
"AWS:PrincipalArn": f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_SourceArn_list(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:SourceArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_SourceArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:SourceArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_SourceArn_str(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:SourceArn": f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_SourceArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:SourceArn": f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_PrincipalArn_list(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
]
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_PrincipalArn_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:PrincipalArn": [
|
|
f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test",
|
|
]
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_PrincipalArn_str(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:PrincipalArn": f"arn:aws:cloudtrail:eu-west-1:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_PrincipalArn_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:PrincipalArn": f"arn:aws:cloudtrail:eu-west-1:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/test"
|
|
}
|
|
}
|
|
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_ResourceAccount_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_ResourceAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"AWS:ResourceAccount": [
|
|
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_AWS_ResourceAccount_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_equals_AWS_ResourceAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"AWS:ResourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_ResourceAccount_list(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_ResourceAccount_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:ResourceAccount": [
|
|
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_like_AWS_ResourceAccount_str(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_string_like_AWS_ResourceAccount_str_not_valid(self):
|
|
condition_statement = {
|
|
"StringLike": {"AWS:ResourceAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_two_lists_unrestrictive(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:ResourceAccount": [
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
NON_TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
]
|
|
},
|
|
"ArnLike": {
|
|
"AWS:SourceArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
]
|
|
},
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_two_lists_both_restrictive(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:ResourceAccount": [
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
]
|
|
},
|
|
"ArnLike": {
|
|
"AWS:SourceArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
]
|
|
},
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_two_lists_first_restrictive(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:ResourceAccount": [
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
]
|
|
},
|
|
"ArnLike": {
|
|
"AWS:SourceArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
]
|
|
},
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_two_lists_second_restrictive(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"AWS:ResourceAccount": [
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
NON_TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
]
|
|
},
|
|
"ArnLike": {
|
|
"AWS:SourceArn": [
|
|
f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*",
|
|
]
|
|
},
|
|
}
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_condition_parser_allowing_cross_account_with_invalid_block(self):
|
|
condition_statement = {
|
|
"StringLike": {
|
|
"s3:prefix": [
|
|
"home/",
|
|
]
|
|
},
|
|
}
|
|
assert not is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER, True
|
|
)
|
|
|
|
def test_condition_parser_string_equals_vpc(self):
|
|
condition_statement = {"StringEquals": {"aws:SourceVpc": "vpc-123456"}}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER, True
|
|
)
|
|
|
|
def test_condition_parser_string_equals_vpc_list(self):
|
|
condition_statement = {"StringEquals": {"aws:sourcevpc": ["vpc-123456"]}}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER, True
|
|
)
|
|
|
|
def test_condition_parser_string_equals_vpc_list_not_valid(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:SourceVpc": ["vpc-123456", "vpc-654321"]}
|
|
}
|
|
|
|
assert is_condition_block_restrictive(
|
|
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER, True
|
|
)
|
|
|
|
def test_condition_parser_string_equals_aws_PrincipalOrgID_list(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:PrincipalOrgID": [TRUSTED_ORGANIZATION_ID]}
|
|
}
|
|
assert is_condition_block_restrictive_organization(condition_statement)
|
|
|
|
def test_condition_parser_string_equals_aws_PrincipalOrgID_list_multiple_items(
|
|
self,
|
|
):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"aws:PrincipalOrgID": [
|
|
TRUSTED_ORGANIZATION_ID,
|
|
NON_TRUSTED_ORGANIZATION_ID,
|
|
]
|
|
}
|
|
}
|
|
assert is_condition_block_restrictive_organization(condition_statement)
|
|
|
|
def test_condition_parser_string_equals_aws_PrincipalOrgID_str(self):
|
|
condition_statement = {
|
|
"StringEquals": {"aws:PrincipalOrgID": TRUSTED_ORGANIZATION_ID}
|
|
}
|
|
assert is_condition_block_restrictive_organization(condition_statement)
|
|
|
|
def test_condition_parser_string_equals_aws_All_Orgs_list_multiple_items(
|
|
self,
|
|
):
|
|
condition_statement = {
|
|
"StringEquals": {
|
|
"aws:PrincipalOrgID": [
|
|
TRUSTED_ORGANIZATION_ID,
|
|
ALL_ORGS,
|
|
]
|
|
}
|
|
}
|
|
assert not is_condition_block_restrictive_organization(condition_statement)
|
|
|
|
def test_condition_parser_string_equals_aws_All_Orgs_str(self):
|
|
condition_statement = {"StringEquals": {"aws:PrincipalOrgID": ALL_ORGS}}
|
|
assert not is_condition_block_restrictive_organization(condition_statement)
|
|
|
|
@pytest.mark.parametrize(
|
|
"condition_value,expected",
|
|
[
|
|
("*@example.com", True),
|
|
("https://events.pagerduty.com/integration/<api-key>/enqueue", True),
|
|
(
|
|
"arn:aws:sns:eu-west-2:123456789012:example-topic:995be20c-a7e3-44ca-8c18-77cb263d15e7",
|
|
True,
|
|
),
|
|
("*@*.com", False),
|
|
("*@*", False),
|
|
("*@example.*", False),
|
|
("https://events.pagerduty.com/integration/*/enqueue", False),
|
|
("arn:aws:sns:eu-west-2:123456789012:example-topic:*", False),
|
|
(
|
|
"arn:aws:sns:eu-west-2:*:example-topic:995be20c-a7e3-44ca-8c18-77cb263d15e7",
|
|
False,
|
|
),
|
|
],
|
|
)
|
|
def test_condition_parser_string_equals_sns_endpoint_str(
|
|
self, condition_value: str, expected: bool
|
|
):
|
|
condition_statement = {"StringEquals": {"SNS:Endpoint": condition_value}}
|
|
assert (
|
|
is_condition_block_restrictive_sns_endpoint(condition_statement) == expected
|
|
)
|
|
|
|
condition_statement = {"StringLike": {"SNS:Endpoint": condition_value}}
|
|
assert (
|
|
is_condition_block_restrictive_sns_endpoint(condition_statement) == expected
|
|
)
|
|
|
|
def test_policy_allows_cross_account_access_with_root_and_wildcard_principal(self):
|
|
policy_allow_root_and_wildcard_principal = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"AWS": [f"arn:aws:iam::{TRUSTED_AWS_ACCOUNT_NUMBER}:root", "*"]
|
|
},
|
|
"Action": "s3:*",
|
|
"Resource": "arn:aws:s3:::example_bucket/*",
|
|
}
|
|
]
|
|
}
|
|
assert is_policy_public(
|
|
policy_allow_root_and_wildcard_principal,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
is_cross_account_allowed=False,
|
|
)
|
|
|
|
def test_policy_does_not_allow_cross_account_access_with_specific_root_principal(
|
|
self,
|
|
):
|
|
policy_allow_specific_root_principal = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"AWS": [f"arn:aws:iam::{TRUSTED_AWS_ACCOUNT_NUMBER}:root"]
|
|
},
|
|
"Action": "s3:*",
|
|
"Resource": "arn:aws:s3:::example_bucket/*",
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(
|
|
policy_allow_specific_root_principal,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
is_cross_account_allowed=False,
|
|
)
|
|
|
|
def test_policy_does_not_allow_cross_account_access_with_deny_effect(self):
|
|
policy_deny_specific_root_principal = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Deny",
|
|
"Principal": {
|
|
"AWS": [f"arn:aws:iam::{TRUSTED_AWS_ACCOUNT_NUMBER}:root"]
|
|
},
|
|
"Action": "s3:*",
|
|
"Resource": "arn:aws:s3:::example_bucket/*",
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(
|
|
policy_deny_specific_root_principal,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
is_cross_account_allowed=False,
|
|
)
|
|
|
|
def test_cross_account_access_trusted_account_list(self):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"AWS": f"arn:aws:iam::{TRUSTED_AWS_ACCOUNT_NUMBER_LIST[0]}:root"
|
|
},
|
|
"Action": "*",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(
|
|
policy,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
is_cross_account_allowed=False,
|
|
trusted_account_ids=TRUSTED_AWS_ACCOUNT_NUMBER_LIST,
|
|
)
|
|
|
|
def test_cross_account_access_with_principal_list_trusted_account_list(self):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"AWS": [
|
|
f"arn:aws:iam::{TRUSTED_AWS_ACCOUNT_NUMBER_LIST[0]}:root",
|
|
f"arn:aws:iam::{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:root",
|
|
]
|
|
},
|
|
"Action": "*",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert is_policy_public(
|
|
policy,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
is_cross_account_allowed=False,
|
|
trusted_account_ids=TRUSTED_AWS_ACCOUNT_NUMBER_LIST,
|
|
)
|
|
|
|
def test_policy_allows_public_access_with_wildcard_principal(self):
|
|
policy_allow_wildcard_principal = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "s3:*",
|
|
"Resource": "arn:aws:s3:::example_bucket/*",
|
|
}
|
|
]
|
|
}
|
|
assert is_policy_public(
|
|
policy_allow_wildcard_principal,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
not_allowed_actions=["s3:*"],
|
|
)
|
|
|
|
def test_policy_allows_public_access_with_aws_wildcard_principal(self):
|
|
policy_allow_aws_wildcard_principal = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"AWS": "*"},
|
|
"Action": "s3:*",
|
|
"Resource": "arn:aws:s3:::example_bucket/*",
|
|
}
|
|
]
|
|
}
|
|
assert is_policy_public(
|
|
policy_allow_aws_wildcard_principal,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
not_allowed_actions=["s3:*"],
|
|
)
|
|
|
|
def test_policy_does_not_allow_public_access_with_specific_aws_principal(self):
|
|
policy_allow_specific_aws_principal = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"AWS": f"arn:aws:iam::{TRUSTED_AWS_ACCOUNT_NUMBER}:root"
|
|
},
|
|
"Action": "s3:*",
|
|
"Resource": "arn:aws:s3:::example_bucket/*",
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(
|
|
policy_allow_specific_aws_principal, TRUSTED_AWS_ACCOUNT_NUMBER
|
|
)
|
|
|
|
def test_policy_does_not_allow_public_access_with_condition(self):
|
|
policy_allow_aws_wildcard_principal_with_condition = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"AWS": "*"},
|
|
"Action": "s3:*",
|
|
"Resource": "arn:aws:s3:::example_bucket/*",
|
|
"Condition": {"IpAddress": {"aws:SourceIp": "192.0.2.0/24"}},
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(
|
|
policy_allow_aws_wildcard_principal_with_condition,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
)
|
|
|
|
def test_policy_allows_full_service_access_with_wildcard_action_and_resource(self):
|
|
policy_allow_wildcard_action_and_resource = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": "s3:*",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert check_full_service_access(
|
|
"s3", policy_allow_wildcard_action_and_resource
|
|
)
|
|
|
|
def test_policy_allows_full_service_access_with_wildcard_action_and_resource_using_unicode(
|
|
self,
|
|
):
|
|
policy_allow_wildcard_action_and_resource = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "\u0041llow",
|
|
"Action": "\u00733:*",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert check_full_service_access(
|
|
"s3", policy_allow_wildcard_action_and_resource
|
|
)
|
|
|
|
def test_policy_allows_full_service_access_with_wildcard_action_and_resource_using_double_start(
|
|
self,
|
|
):
|
|
policy_allow_wildcard_action_and_resource = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": "s3:**",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert check_full_service_access(
|
|
"s3", policy_allow_wildcard_action_and_resource
|
|
)
|
|
|
|
def test_policy_does_not_allow_full_service_access_with_specific_get_action(self):
|
|
policy_allow_specific_get_action = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": "s3:Get*",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert not check_full_service_access("s3", policy_allow_specific_get_action)
|
|
|
|
def test_policy_does_not_allow_full_service_access_with_bucket_wildcard_resource(
|
|
self,
|
|
):
|
|
policy_allow_bucket_wildcard_resource = {
|
|
"Statement": {
|
|
"Effect": "Allow",
|
|
"Action": "s3:*",
|
|
"Resource": "arn:aws:s3:::example_bucket/*",
|
|
}
|
|
}
|
|
assert not check_full_service_access(
|
|
"s3", policy_allow_bucket_wildcard_resource
|
|
)
|
|
|
|
def test_policy_does_not_allow_full_service_access_with_specific_bucket(self):
|
|
policy_allow_specific_bucket = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": "s3:*",
|
|
"Resource": "arn:aws:s3:::example_bucket",
|
|
}
|
|
]
|
|
}
|
|
assert not check_full_service_access("s3", policy_allow_specific_bucket)
|
|
|
|
def test_policy_allows_full_service_access_with_not_action_excluding_other_service(
|
|
self,
|
|
):
|
|
policy_allow_not_action_excluding_other_service = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"NotAction": "ec2:*",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert check_full_service_access(
|
|
"s3", policy_allow_not_action_excluding_other_service
|
|
)
|
|
|
|
def test_policy_allows_full_service_access_with_invalid_service_as_not_action(
|
|
self,
|
|
):
|
|
policy_allow_not_action_excluding_other_service = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"NotAction": "prowler:check",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert check_full_service_access(
|
|
"s3", policy_allow_not_action_excluding_other_service
|
|
)
|
|
|
|
def test_policy_does_not_allow_full_service_access_with_not_action_including_service(
|
|
self,
|
|
):
|
|
policy_not_action_including_service = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"NotAction": "s3:*",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert not check_full_service_access("s3", policy_not_action_including_service)
|
|
|
|
def test_is_condition_restricting_from_private_ip_no_condition(self):
|
|
assert not is_condition_restricting_from_private_ip({})
|
|
|
|
def test_is_condition_restricting_from_private_ip(self):
|
|
condition_from_private_ip = {
|
|
"IpAddress": {"aws:SourceIp": "10.0.0.22"},
|
|
}
|
|
assert is_condition_restricting_from_private_ip(condition_from_private_ip)
|
|
|
|
def test_is_condition_restricting_from_public_ip(self):
|
|
condition_not_from_private_ip = {
|
|
"IpAddress": {"aws:SourceIp": "1.2.3.4"},
|
|
}
|
|
assert not is_condition_restricting_from_private_ip(
|
|
condition_not_from_private_ip
|
|
)
|
|
|
|
def test_is_condition_restricting_from_private_ipv6(self):
|
|
condition_from_private_ipv6 = {
|
|
"IpAddress": {"aws:SourceIp": "fd00::1"},
|
|
}
|
|
assert is_condition_restricting_from_private_ip(condition_from_private_ipv6)
|
|
|
|
def test_is_condition_restricting_from_public_ipv6(self):
|
|
condition_not_from_private_ipv6 = {
|
|
"IpAddress": {"aws:SourceIp": "2001:0db8::1"},
|
|
}
|
|
assert is_condition_restricting_from_private_ip(condition_not_from_private_ipv6)
|
|
|
|
def test_is_condition_restricting_from_private_ip_network(self):
|
|
condition_from_private_ip_network = {
|
|
"IpAddress": {"aws:SourceIp": "10.0.0.0/24"},
|
|
}
|
|
assert is_condition_restricting_from_private_ip(
|
|
condition_from_private_ip_network
|
|
)
|
|
|
|
def test_is_condition_restricting_from_public_ip_network(self):
|
|
condition_from_public_ip_network = {
|
|
"IpAddress": {"aws:SourceIp": "1.2.3.0/24"},
|
|
}
|
|
|
|
assert not is_condition_restricting_from_private_ip(
|
|
condition_from_public_ip_network
|
|
)
|
|
|
|
def test_is_condition_restricting_from_private_ipv6_network(self):
|
|
condition_from_private_ipv6_network = {
|
|
"IpAddress": {"aws:SourceIp": "fd00::/8"},
|
|
}
|
|
assert is_condition_restricting_from_private_ip(
|
|
condition_from_private_ipv6_network
|
|
)
|
|
|
|
def test_is_condition_restricting_from_private_ip_array(self):
|
|
condition_from_private_ip_array = {
|
|
"IpAddress": {"aws:SourceIp": ["10.0.0.22", "192.168.1.1"]},
|
|
}
|
|
assert is_condition_restricting_from_private_ip(condition_from_private_ip_array)
|
|
|
|
def test_is_condition_restricting_from_private_ipv6_array(self):
|
|
condition_from_private_ipv6_array = {
|
|
"IpAddress": {"aws:SourceIp": ["fd00::1", "fe80::1"]},
|
|
}
|
|
assert is_condition_restricting_from_private_ip(
|
|
condition_from_private_ipv6_array
|
|
)
|
|
|
|
def test_is_condition_restricting_from_mixed_ip_array(self):
|
|
condition_from_mixed_ip_array = {
|
|
"IpAddress": {"aws:SourceIp": ["10.0.0.22", "2001:0db8::1"]},
|
|
}
|
|
assert is_condition_restricting_from_private_ip(condition_from_mixed_ip_array)
|
|
|
|
def test_is_condition_restricting_from_mixed_ip_array_not_private(self):
|
|
condition_from_mixed_ip_array_not_private = {
|
|
"IpAddress": {"aws:SourceIp": ["1.2.3.4", "2001:0db8::1"]},
|
|
}
|
|
assert not is_condition_restricting_from_private_ip(
|
|
condition_from_mixed_ip_array_not_private
|
|
)
|
|
|
|
def test_is_condition_restricting_from_private_ip_from_invalid_ip(self):
|
|
condition_from_invalid_ip = {
|
|
"IpAddress": {"aws:SourceIp": "256.256.256.256"},
|
|
}
|
|
assert not is_condition_restricting_from_private_ip(condition_from_invalid_ip)
|
|
|
|
def test_is_policy_public_(self):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "elasticfilesystem:ClientMount",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert is_policy_public(
|
|
policy,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
not_allowed_actions=["elasticfilesystem:ClientMount"],
|
|
)
|
|
|
|
def test_is_policy_public_with_principal_dict(self):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"AWS": "*"},
|
|
"Action": "elasticfilesystem:ClientMount",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert is_policy_public(
|
|
policy,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
not_allowed_actions=["elasticfilesystem:ClientMount"],
|
|
)
|
|
|
|
def test_is_policy_public_with_secure_conditions_and_allowed_conditions(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "elasticfilesystem:ClientMount",
|
|
"Resource": "*",
|
|
"Condition": {
|
|
"Bool": {"elasticfilesystem:AccessedViaMountTarget": "true"},
|
|
"StringEquals": {"aws:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER},
|
|
},
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_public_with_secure_conditions_and_allowed_conditions_nested(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "elasticfilesystem:ClientMount",
|
|
"Resource": "*",
|
|
"Condition": {
|
|
"Bool": {"elasticfilesystem:AccessedViaMountTarget": "true"},
|
|
"StringEquals": {"aws:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER},
|
|
"StringEqualsIfExists": {
|
|
"aws:SourceVpce": "vpce-1234567890abcdef0"
|
|
},
|
|
},
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_public_with_secure_conditions_and_allowed_conditions_nested_dict(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "elasticfilesystem:ClientMount",
|
|
"Resource": "*",
|
|
"Condition": {
|
|
"Bool": {"elasticfilesystem:AccessedViaMountTarget": "true"},
|
|
"StringEquals": {"aws:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER},
|
|
"StringEqualsIfExists": {
|
|
"aws:SourceVpce": {
|
|
"vpce-1234567890abcdef0": "vpce-1234567890abcdef0"
|
|
}
|
|
},
|
|
},
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_public_with_secure_conditions_and_allowed_conditions_nested_dict_key(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "elasticfilesystem:ClientMount",
|
|
"Resource": "*",
|
|
"Condition": {
|
|
"Bool": {"elasticfilesystem:AccessedViaMountTarget": "true"},
|
|
"StringEquals": {"aws:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER},
|
|
"StringEqualsIfExists": {
|
|
"aws:SourceVpce": {
|
|
"vpce-1234567890abcdef0": "vpce-1234567890abcdef0"
|
|
}
|
|
},
|
|
},
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_public_with_action_wildcard(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "elasticfilesystem:*",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_public_allowing_all_actions(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "*",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_public_allowing_other_account(self):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"AWS": f"arn:aws:iam::{TRUSTED_AWS_ACCOUNT_NUMBER}:root"
|
|
},
|
|
"Action": "*",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_public_secrets_manager(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Sid": "test",
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "secretsmanager.amazonaws.com"},
|
|
"Action": "lambda:GetFunction",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_public_eks(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Sid": "test",
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "eks.amazonaws.com"},
|
|
"Action": "lambda:GetFunction",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_public_cross_cross_service_confused_deputy(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Sid": "test",
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "ec2.amazonaws.com"},
|
|
"Action": "lambda:InvokeFunction",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert is_policy_public(
|
|
policy, TRUSTED_AWS_ACCOUNT_NUMBER, check_cross_service_confused_deputy=True
|
|
)
|
|
|
|
def test_is_policy_public_cross_cross_service_confused_deputy_ignored(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Sid": "test",
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "ec2.amazonaws.com"},
|
|
"Action": "lambda:InvokeFunction",
|
|
"Resource": "*",
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(
|
|
policy,
|
|
TRUSTED_AWS_ACCOUNT_NUMBER,
|
|
check_cross_service_confused_deputy=False,
|
|
)
|
|
|
|
def test_is_policy_public_alexa_condition(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Sid": "test",
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "alexa-connectedhome.amazon.com"},
|
|
"Action": "lambda:GetFunction",
|
|
"Resource": "*",
|
|
"Condition": {"StringEquals": {"lambda:EventSourceToken": "test"}},
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_private_org_s3_bucket(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Statement": [
|
|
{
|
|
"Sid": "test",
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "personalize.amazonaws.com"},
|
|
"Action": "*",
|
|
"Resource": "*",
|
|
"Condition": {"StringLike": {"aws:SourceOrgID": "o-123456"}},
|
|
}
|
|
]
|
|
}
|
|
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_is_policy_public_ip(
|
|
self,
|
|
):
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"AWS": "*"},
|
|
"Action": ["*"],
|
|
"Condition": {"IpAddress": {"aws:SourceIp": ["0.0.0.0/0"]}},
|
|
"Resource": "*",
|
|
}
|
|
],
|
|
}
|
|
assert is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
|
|
|
def test_check_admin_access(self):
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [{"Effect": "Allow", "Action": ["*"], "Resource": "*"}],
|
|
}
|
|
assert check_admin_access(policy)
|
|
|
|
def test_check_admin_access_false(self):
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [{"Effect": "Allow", "Action": ["s3:*"], "Resource": "*"}],
|
|
}
|
|
assert not check_admin_access(policy)
|
|
|
|
def test_check_admin_access_not_action(self):
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [{"Effect": "Allow", "NotAction": "s3:*", "Resource": "*"}],
|
|
}
|
|
assert check_admin_access(policy)
|
|
|
|
def test_check_admin_access_not_action_with_random_action(self):
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{"Effect": "Allow", "NotAction": "prowler:action", "Resource": "*"}
|
|
],
|
|
}
|
|
assert check_admin_access(policy)
|
|
|
|
def test_check_admin_access_not_resource(self):
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [{"Effect": "Allow", "Action": "*", "NotResource": "*"}],
|
|
}
|
|
assert not check_admin_access(policy)
|
|
|
|
def test_check_admin_access_not_resource_with_random_resource(self):
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{"Effect": "Allow", "Action": "*", "NotResource": "prowler:resource"}
|
|
],
|
|
}
|
|
assert check_admin_access(policy)
|
|
|
|
|
|
def test_is_codebuild_using_allowed_github_org_allows():
|
|
trust_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "codebuild.amazonaws.com"},
|
|
"Action": "sts:AssumeRole",
|
|
}
|
|
],
|
|
}
|
|
github_repo_url = "https://github.com/allowed-org/repo"
|
|
allowed_organizations = ["allowed-org"]
|
|
is_allowed, org_name = is_codebuild_using_allowed_github_org(
|
|
trust_policy, github_repo_url, allowed_organizations
|
|
)
|
|
assert is_allowed is True
|
|
assert org_name == "allowed-org"
|
|
|
|
|
|
def test_is_codebuild_using_allowed_github_org_denies():
|
|
trust_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "codebuild.amazonaws.com"},
|
|
"Action": "sts:AssumeRole",
|
|
}
|
|
],
|
|
}
|
|
github_repo_url = "https://github.com/not-allowed-org/repo"
|
|
allowed_organizations = ["allowed-org"]
|
|
is_allowed, org_name = is_codebuild_using_allowed_github_org(
|
|
trust_policy, github_repo_url, allowed_organizations
|
|
)
|
|
assert is_allowed is False
|
|
assert org_name == "not-allowed-org"
|
|
|
|
|
|
def test_is_codebuild_using_allowed_github_org_no_codebuild_principal():
|
|
trust_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "lambda.amazonaws.com"},
|
|
"Action": "sts:AssumeRole",
|
|
}
|
|
],
|
|
}
|
|
github_repo_url = "https://github.com/allowed-org/repo"
|
|
allowed_organizations = ["allowed-org"]
|
|
is_allowed, org_name = is_codebuild_using_allowed_github_org(
|
|
trust_policy, github_repo_url, allowed_organizations
|
|
)
|
|
assert is_allowed is False
|
|
assert org_name is None
|
|
|
|
|
|
def test_is_codebuild_using_allowed_github_org_invalid_url():
|
|
trust_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "codebuild.amazonaws.com"},
|
|
"Action": "sts:AssumeRole",
|
|
}
|
|
],
|
|
}
|
|
github_repo_url = "https://github.com//test" # Malformed, no org
|
|
allowed_organizations = ["allowed-org"]
|
|
is_allowed, org_name = is_codebuild_using_allowed_github_org(
|
|
trust_policy, github_repo_url, allowed_organizations
|
|
)
|
|
assert is_allowed is False
|
|
assert org_name is None
|
|
|
|
|
|
def test_has_codebuild_trusted_principal_true():
|
|
trust_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "codebuild.amazonaws.com"},
|
|
"Action": "sts:AssumeRole",
|
|
}
|
|
],
|
|
}
|
|
assert has_codebuild_trusted_principal(trust_policy) is True
|
|
|
|
|
|
def test_has_codebuild_trusted_principal_false():
|
|
trust_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"Service": "lambda.amazonaws.com"},
|
|
"Action": "sts:AssumeRole",
|
|
}
|
|
],
|
|
}
|
|
assert has_codebuild_trusted_principal(trust_policy) is False
|
|
|
|
|
|
def test_has_codebuild_trusted_principal_empty():
|
|
trust_policy = {}
|
|
assert has_codebuild_trusted_principal(trust_policy) is False
|
|
|
|
|
|
def test_is_codebuild_using_allowed_github_org_principal_string():
|
|
trust_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": "codebuild.amazonaws.com",
|
|
"Action": "sts:AssumeRole",
|
|
}
|
|
],
|
|
}
|
|
github_repo_url = "https://github.com/allowed-org/repo"
|
|
allowed_organizations = ["allowed-org"]
|
|
is_allowed, org_name = is_codebuild_using_allowed_github_org(
|
|
trust_policy, github_repo_url, allowed_organizations
|
|
)
|
|
assert is_allowed is True
|
|
assert org_name == "allowed-org"
|
|
|
|
|
|
def test_is_codebuild_using_allowed_github_org_principal_list():
|
|
trust_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": ["codebuild.amazonaws.com", "lambda.amazonaws.com"],
|
|
"Action": "sts:AssumeRole",
|
|
}
|
|
],
|
|
}
|
|
github_repo_url = "https://github.com/allowed-org/repo"
|
|
allowed_organizations = ["allowed-org"]
|
|
is_allowed, org_name = is_codebuild_using_allowed_github_org(
|
|
trust_policy, github_repo_url, allowed_organizations
|
|
)
|
|
assert is_allowed is True
|
|
assert org_name == "allowed-org"
|
|
|
|
|
|
def test_has_codebuild_trusted_principal_string():
|
|
trust_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": "codebuild.amazonaws.com",
|
|
"Action": "sts:AssumeRole",
|
|
}
|
|
],
|
|
}
|
|
assert has_codebuild_trusted_principal(trust_policy) is True
|
|
|
|
|
|
def test_has_codebuild_trusted_principal_list():
|
|
trust_policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": ["codebuild.amazonaws.com", "lambda.amazonaws.com"],
|
|
"Action": "sts:AssumeRole",
|
|
}
|
|
],
|
|
}
|
|
assert has_codebuild_trusted_principal(trust_policy) is True
|
|
|
|
|
|
class Test_has_public_principal:
|
|
"""Tests for the has_public_principal function"""
|
|
|
|
def test_has_public_principal_wildcard_string(self):
|
|
"""Test public principal detection with wildcard string"""
|
|
statement = {"Principal": "*"}
|
|
assert has_public_principal(statement) is True
|
|
|
|
def test_has_public_principal_root_arn_string(self):
|
|
"""Test public principal detection with root ARN string"""
|
|
statement = {"Principal": "arn:aws:iam::*:root"}
|
|
assert has_public_principal(statement) is True
|
|
|
|
def test_has_public_principal_aws_dict_wildcard(self):
|
|
"""Test public principal detection with AWS dict containing wildcard"""
|
|
statement = {"Principal": {"AWS": "*"}}
|
|
assert has_public_principal(statement) is True
|
|
|
|
def test_has_public_principal_aws_dict_root_arn(self):
|
|
"""Test public principal detection with AWS dict containing root ARN"""
|
|
statement = {"Principal": {"AWS": "arn:aws:iam::*:root"}}
|
|
assert has_public_principal(statement) is True
|
|
|
|
def test_has_public_principal_aws_list_wildcard(self):
|
|
"""Test public principal detection with AWS list containing wildcard"""
|
|
statement = {"Principal": {"AWS": ["arn:aws:iam::123456789012:user/test", "*"]}}
|
|
assert has_public_principal(statement) is True
|
|
|
|
def test_has_public_principal_aws_list_root_arn(self):
|
|
"""Test public principal detection with AWS list containing root ARN"""
|
|
statement = {
|
|
"Principal": {
|
|
"AWS": ["arn:aws:iam::123456789012:user/test", "arn:aws:iam::*:root"]
|
|
}
|
|
}
|
|
assert has_public_principal(statement) is True
|
|
|
|
def test_has_public_principal_canonical_user_wildcard(self):
|
|
"""Test public principal detection with CanonicalUser wildcard"""
|
|
statement = {"Principal": {"CanonicalUser": "*"}}
|
|
assert has_public_principal(statement) is True
|
|
|
|
def test_has_public_principal_canonical_user_root_arn(self):
|
|
"""Test public principal detection with CanonicalUser root ARN"""
|
|
statement = {"Principal": {"CanonicalUser": "arn:aws:iam::*:root"}}
|
|
assert has_public_principal(statement) is True
|
|
|
|
def test_has_public_principal_no_principal(self):
|
|
"""Test with statement that has no Principal field"""
|
|
statement = {"Effect": "Allow", "Action": "s3:GetObject"}
|
|
assert has_public_principal(statement) is False
|
|
|
|
def test_has_public_principal_empty_principal(self):
|
|
"""Test with empty principal"""
|
|
statement = {"Principal": ""}
|
|
assert has_public_principal(statement) is False
|
|
|
|
def test_has_public_principal_specific_account(self):
|
|
"""Test with specific account principal (not public)"""
|
|
statement = {"Principal": {"AWS": "arn:aws:iam::123456789012:root"}}
|
|
assert has_public_principal(statement) is False
|
|
|
|
def test_has_public_principal_service_principal(self):
|
|
"""Test with service principal (not public)"""
|
|
statement = {"Principal": {"Service": "lambda.amazonaws.com"}}
|
|
assert has_public_principal(statement) is False
|
|
|
|
def test_has_public_principal_mixed_principals(self):
|
|
"""Test with mixed principals including public one"""
|
|
statement = {
|
|
"Principal": {
|
|
"AWS": ["arn:aws:iam::123456789012:user/test"],
|
|
"Service": "lambda.amazonaws.com",
|
|
"CanonicalUser": "*",
|
|
}
|
|
}
|
|
assert has_public_principal(statement) is True
|
|
|
|
|
|
class Test_has_restrictive_source_arn_condition:
|
|
"""Tests for the has_restrictive_source_arn_condition function"""
|
|
|
|
def test_no_condition_block(self):
|
|
"""Test statement without Condition block"""
|
|
statement = {"Effect": "Allow", "Principal": "*", "Action": "s3:GetObject"}
|
|
assert has_restrictive_source_arn_condition(statement) is False
|
|
|
|
def test_no_source_arn_condition(self):
|
|
"""Test with condition block but no aws:SourceArn"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "s3:GetObject",
|
|
"Condition": {"StringEquals": {"aws:SourceAccount": "123456789012"}},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is False
|
|
|
|
def test_restrictive_source_arn_s3_bucket(self):
|
|
"""Test restrictive SourceArn condition with S3 bucket"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {"ArnLike": {"aws:SourceArn": "arn:aws:s3:::my-bucket"}},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is True
|
|
|
|
def test_restrictive_source_arn_lambda_function(self):
|
|
"""Test restrictive SourceArn condition with Lambda function"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {
|
|
"ArnEquals": {
|
|
"aws:SourceArn": "arn:aws:lambda:us-east-1:123456789012:function:MyFunction"
|
|
}
|
|
},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is True
|
|
|
|
def test_non_restrictive_global_wildcard(self):
|
|
"""Test non-restrictive SourceArn with global wildcard"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {"ArnLike": {"aws:SourceArn": "*"}},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is False
|
|
|
|
def test_non_restrictive_service_wildcard(self):
|
|
"""Test non-restrictive SourceArn with service wildcard"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {"ArnLike": {"aws:SourceArn": "arn:aws:s3:::*"}},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is False
|
|
|
|
def test_non_restrictive_multi_wildcard(self):
|
|
"""Test non-restrictive SourceArn with multiple wildcards"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {"ArnLike": {"aws:SourceArn": "arn:aws:*:*:*:*"}},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is False
|
|
|
|
def test_non_restrictive_resource_wildcard(self):
|
|
"""Test non-restrictive SourceArn with resource wildcard"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {
|
|
"ArnLike": {"aws:SourceArn": "arn:aws:lambda:us-east-1:123456789012:*"}
|
|
},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is False
|
|
|
|
def test_source_arn_list_with_valid_arn(self):
|
|
"""Test SourceArn condition with list containing valid ARN"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {
|
|
"ArnLike": {
|
|
"aws:SourceArn": ["arn:aws:s3:::bucket1", "arn:aws:s3:::bucket2"]
|
|
}
|
|
},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is True
|
|
|
|
def test_source_arn_list_with_wildcard(self):
|
|
"""Test SourceArn condition with list containing wildcard"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {"ArnLike": {"aws:SourceArn": ["arn:aws:s3:::bucket1", "*"]}},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is False
|
|
|
|
def test_source_arn_with_account_validation_match(self):
|
|
"""Test SourceArn with account validation - matching account"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {
|
|
"ArnLike": {
|
|
"aws:SourceArn": "arn:aws:lambda:us-east-1:123456789012:function:MyFunction"
|
|
}
|
|
},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement, "123456789012") is True
|
|
|
|
def test_source_arn_with_account_validation_mismatch(self):
|
|
"""Test SourceArn with account validation - non-matching account"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {
|
|
"ArnLike": {
|
|
"aws:SourceArn": "arn:aws:lambda:us-east-1:123456789012:function:MyFunction"
|
|
}
|
|
},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement, "987654321098") is False
|
|
|
|
def test_source_arn_with_account_wildcard(self):
|
|
"""Test SourceArn with account wildcard"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {
|
|
"ArnLike": {
|
|
"aws:SourceArn": "arn:aws:lambda:us-east-1:*:function:MyFunction"
|
|
}
|
|
},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement, "123456789012") is False
|
|
|
|
def test_source_arn_s3_bucket_no_account_field(self):
|
|
"""Test SourceArn with S3 bucket (no account field) - should be restrictive"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {"ArnLike": {"aws:SourceArn": "arn:aws:s3:::my-bucket"}},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement, "123456789012") is True
|
|
|
|
def test_source_arn_case_insensitive(self):
|
|
"""Test SourceArn condition key is case insensitive"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {"ArnLike": {"AWS:SourceArn": "arn:aws:s3:::my-bucket"}},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is True
|
|
|
|
def test_source_arn_mixed_operators(self):
|
|
"""Test SourceArn with multiple condition operators"""
|
|
statement = {
|
|
"Effect": "Allow",
|
|
"Principal": "*",
|
|
"Action": "sns:Publish",
|
|
"Condition": {
|
|
"ArnLike": {"aws:SourceArn": "arn:aws:s3:::my-bucket"},
|
|
"StringEquals": {"aws:SourceAccount": "123456789012"},
|
|
},
|
|
}
|
|
assert has_restrictive_source_arn_condition(statement) is True
|