From dd4cd84248b4f3f21c7815dd7b85764b6b5dc267 Mon Sep 17 00:00:00 2001 From: pedrooot Date: Wed, 24 Jul 2024 11:41:44 +0200 Subject: [PATCH] chore(sns): refactor method and add tests --- .github/workflows/pull-request.yml | 2 +- .pre-commit-config.yaml | 2 +- docs/tutorials/configuration_file.md | 5 + prowler/config/config.yaml | 4 + .../policy_condition_parser.py | 83 ++++- .../dynamodb_table_cross_account_access.py | 4 +- ...ross_service_confused_deputy_prevention.py | 4 +- .../s3_bucket_public_access.py | 4 +- .../sns_topics_not_publicly_accessible.py | 30 +- .../sqs_queues_not_publicly_accessible.py | 4 +- ...c_endpoint_connections_trust_boundaries.py | 8 +- tests/config/config_test.py | 1 + tests/config/fixtures/config.yaml | 4 + .../policy_condition_parser_test.py | 340 +++++++++++------- ...sns_topics_not_publicly_accessible_test.py | 65 +++- 15 files changed, 399 insertions(+), 161 deletions(-) diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 64560a6b44..ea7baba652 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -73,7 +73,7 @@ jobs: - name: Safety if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' run: | - poetry run safety check --ignore 70612 + poetry run safety check --ignore 70612,40459 - name: Vulture if: steps.are-non-ignored-files-changed.outputs.any_changed == 'true' run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 43aa573bf6..28cc3eb224 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -97,7 +97,7 @@ repos: - id: safety name: safety description: "Safety is a tool that checks your installed dependencies for known security vulnerabilities" - entry: bash -c 'safety check --ignore 70612' + entry: bash -c 'safety check --ignore 70612,40459' language: system - id: vulture diff --git a/docs/tutorials/configuration_file.md b/docs/tutorials/configuration_file.md index c891d5442f..9bc4db5e06 100644 --- a/docs/tutorials/configuration_file.md +++ b/docs/tutorials/configuration_file.md @@ -43,6 +43,7 @@ The following list includes all the AWS checks with configurable variables that | `ec2_securitygroup_allow_ingress_from_internet_to_any_port` | `ec2_allowed_interface_types` | List of Strings | | `ec2_securitygroup_allow_ingress_from_internet_to_any_port` | `ec2_allowed_instance_owners` | List of Strings | | `acm_certificates_expiration_check` | `days_to_expire_threshold` | Integer | +| `sns_topics_not_publicly_accessible` | `organization_id` | String | ## Azure @@ -355,6 +356,10 @@ aws: # aws.acm_certificates_expiration_check days_to_expire_threshold: 7 + # AWS SNS Configuration + # aws.sns_topics_not_publicly_accessible + organization_id: null + # Azure Configuration azure: # Azure Network Configuration diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index 90dd925aaa..659b208949 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -272,6 +272,10 @@ aws: # aws.acm_certificates_expiration_check days_to_expire_threshold: 7 + # AWS SNS Configuration + # aws.sns_topics_not_publicly_accessible + organization_id: null + # Azure Configuration azure: # Azure Network Configuration diff --git a/prowler/providers/aws/lib/policy_condition_parser/policy_condition_parser.py b/prowler/providers/aws/lib/policy_condition_parser/policy_condition_parser.py index b74602616f..f81937866d 100644 --- a/prowler/providers/aws/lib/policy_condition_parser/policy_condition_parser.py +++ b/prowler/providers/aws/lib/policy_condition_parser/policy_condition_parser.py @@ -1,11 +1,10 @@ -def is_condition_block_restrictive( +def is_condition_block_restrictive_account( condition_statement: dict, source_account: str, is_cross_account_allowed=False, - org_id: str = None, ): """ - is_condition_block_restrictive parses the IAM Condition policy block and, by default, returns True if the source_account passed as argument is within, False if not. + is_condition_block_restrictive_account parses the IAM Condition policy block and, by default, returns True if the source_account passed as argument is within, False if not. If argument is_cross_account_allowed is True it tests if the Condition block includes any of the operators allowlisted returning True if does, False if not. @@ -21,7 +20,6 @@ def is_condition_block_restrictive( @param is_cross_account_allowed: bool to allow cross-account access, e.g.: True - @param org_id: str with AWS Organization ID, e.g.: o-123456789012 """ is_condition_valid = False @@ -77,7 +75,7 @@ def is_condition_block_restrictive( # if there is an arn/account without the source account -> we do not consider it safe # here by default we assume is true and look for false entries for item in condition_statement[condition_operator][value]: - if source_account not in item or org_id not in item: + if source_account not in item: is_condition_key_restrictive = False break @@ -95,9 +93,80 @@ def is_condition_block_restrictive( if ( source_account in condition_statement[condition_operator][value] - or org_id - in condition_statement[condition_operator][value] ): is_condition_valid = True return is_condition_valid + + +def is_condition_block_restrictive_organization( + condition_statement: dict, + source_organization: str, +): + """ + is_condition_block_restrictive_organization parses the IAM Condition policy block and returns True if the source_organization passed as argument is within, False if not. + + + @param condition_statement: dict with an IAM Condition block, e.g.: + { + "StringLike": { + "AWS:PrincipalOrgID": "o-111122223333" + } + } + + @param source_organization: str with a 12-digit AWS Organization ID, e.g.: o-111122223333 + + + """ + is_condition_valid = False + + # The conditions must be defined in lowercase since the context key names are not case-sensitive. + # For example, including the aws:PrincipalOrgID context key is equivalent to testing for AWS:PrincipalOrgID + # https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html + valid_condition_options = { + "StringEquals": [ + "aws:principalorgid", + ], + "StringLike": [ + "aws:principalorgid", + ], + } + + for condition_operator, condition_operator_key in valid_condition_options.items(): + if condition_operator in condition_statement: + for value in condition_operator_key: + # We need to transform the condition_statement into lowercase + condition_statement[condition_operator] = { + k.lower(): v + for k, v in condition_statement[condition_operator].items() + } + + if value in condition_statement[condition_operator]: + # values are a list + if isinstance( + condition_statement[condition_operator][value], + list, + ): + is_condition_key_restrictive = True + # if there is an arn/organization without the source organization -> we do not consider it safe + # here by default we assume is true and look for false entries + for item in condition_statement[condition_operator][value]: + if source_organization not in item: + is_condition_key_restrictive = False + break + + if is_condition_key_restrictive: + is_condition_valid = True + + # value is a string + elif isinstance( + condition_statement[condition_operator][value], + str, + ): + if ( + source_organization + in condition_statement[condition_operator][value] + ): + is_condition_valid = True + + return is_condition_valid diff --git a/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.py b/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.py index e7492fb221..caebd560bc 100644 --- a/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.py +++ b/prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.py @@ -1,6 +1,6 @@ from prowler.lib.check.models import Check, Check_Report_AWS from prowler.providers.aws.lib.policy_condition_parser.policy_condition_parser import ( - is_condition_block_restrictive, + is_condition_block_restrictive_account, ) from prowler.providers.aws.services.dynamodb.dynamodb_client import dynamodb_client @@ -43,7 +43,7 @@ def execute(self): cross_account_access = True # Check if the condition block is restrictive conditions = statement.get("Condition", {}) - if is_condition_block_restrictive( + if is_condition_block_restrictive_account( conditions, dynamodb_client.audited_account ): cross_account_access = False diff --git a/prowler/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention.py b/prowler/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention.py index 9717101927..72fd901e43 100644 --- a/prowler/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention.py +++ b/prowler/providers/aws/services/iam/iam_role_cross_service_confused_deputy_prevention/iam_role_cross_service_confused_deputy_prevention.py @@ -1,6 +1,6 @@ from prowler.lib.check.models import Check, Check_Report_AWS from prowler.providers.aws.lib.policy_condition_parser.policy_condition_parser import ( - is_condition_block_restrictive, + is_condition_block_restrictive_account, ) from prowler.providers.aws.services.iam.iam_client import iam_client @@ -31,7 +31,7 @@ def execute(self) -> Check_Report_AWS: and "Service" in statement["Principal"] # Check to see if the appropriate condition statements have been implemented and "Condition" in statement - and is_condition_block_restrictive( + and is_condition_block_restrictive_account( statement["Condition"], iam_client.audited_account ) ): diff --git a/prowler/providers/aws/services/s3/s3_bucket_public_access/s3_bucket_public_access.py b/prowler/providers/aws/services/s3/s3_bucket_public_access/s3_bucket_public_access.py index 859659e898..f70994fdf4 100644 --- a/prowler/providers/aws/services/s3/s3_bucket_public_access/s3_bucket_public_access.py +++ b/prowler/providers/aws/services/s3/s3_bucket_public_access/s3_bucket_public_access.py @@ -1,6 +1,6 @@ from prowler.lib.check.models import Check, Check_Report_AWS from prowler.providers.aws.lib.policy_condition_parser.policy_condition_parser import ( - is_condition_block_restrictive, + is_condition_block_restrictive_account, ) from prowler.providers.aws.services.iam.lib.policy import ( is_condition_restricting_from_private_ip, @@ -56,7 +56,7 @@ def execute(self): if ( "Principal" in statement and statement["Effect"] == "Allow" - and not is_condition_block_restrictive( + and not is_condition_block_restrictive_account( statement.get("Condition", {}), "", True ) and ( diff --git a/prowler/providers/aws/services/sns/sns_topics_not_publicly_accessible/sns_topics_not_publicly_accessible.py b/prowler/providers/aws/services/sns/sns_topics_not_publicly_accessible/sns_topics_not_publicly_accessible.py index f637bc2935..40d0896ccf 100644 --- a/prowler/providers/aws/services/sns/sns_topics_not_publicly_accessible/sns_topics_not_publicly_accessible.py +++ b/prowler/providers/aws/services/sns/sns_topics_not_publicly_accessible/sns_topics_not_publicly_accessible.py @@ -1,6 +1,7 @@ from prowler.lib.check.models import Check, Check_Report_AWS from prowler.providers.aws.lib.policy_condition_parser.policy_condition_parser import ( - is_condition_block_restrictive, + is_condition_block_restrictive_account, + is_condition_block_restrictive_organization, ) from prowler.providers.aws.services.sns.sns_client import sns_client @@ -9,6 +10,10 @@ class sns_topics_not_publicly_accessible(Check): def execute(self): findings = [] for topic in sns_client.topics: + # Get the organization id from the provider if it is not available in the client + org_id = sns_client.provider.organizations_metadata.organization_id + if org_id is None: + sns_client.audit_config.get("organization_id", None) report = Check_Report_AWS(self.metadata()) report.region = topic.region report.resource_id = topic.name @@ -33,15 +38,32 @@ def execute(self): and "*" in statement["Principal"]["CanonicalUser"] ) ): + condition_account = False + condition_org = False if ( "Condition" in statement - and is_condition_block_restrictive( + and is_condition_block_restrictive_account( statement["Condition"], sns_client.audited_account, - sns_client.audited_org_id, ) ): - report.status_extended = f"SNS topic {topic.name} is not public because its policy only allows access from the same account." + condition_account = True + if ( + "Condition" in statement + and org_id is not None + and is_condition_block_restrictive_organization( + statement["Condition"], + org_id, + ) + ): + condition_org = True + + if condition_account and condition_org: + report.status_extended = f"SNS topic {topic.name} is not public because its policy only allows access from the account {sns_client.audited_account} and organization {org_id}." + elif condition_account: + report.status_extended = f"SNS topic {topic.name} is not public because its policy only allows access from the account {sns_client.audited_account}." + elif condition_org: + report.status_extended = f"SNS topic {topic.name} is not public because its policy only allows access from the organization {org_id}." else: report.status = "FAIL" report.status_extended = f"SNS topic {topic.name} is public because its policy allows public access." diff --git a/prowler/providers/aws/services/sqs/sqs_queues_not_publicly_accessible/sqs_queues_not_publicly_accessible.py b/prowler/providers/aws/services/sqs/sqs_queues_not_publicly_accessible/sqs_queues_not_publicly_accessible.py index a21e5a8c00..e966ad4f91 100644 --- a/prowler/providers/aws/services/sqs/sqs_queues_not_publicly_accessible/sqs_queues_not_publicly_accessible.py +++ b/prowler/providers/aws/services/sqs/sqs_queues_not_publicly_accessible/sqs_queues_not_publicly_accessible.py @@ -1,6 +1,6 @@ from prowler.lib.check.models import Check, Check_Report_AWS from prowler.providers.aws.lib.policy_condition_parser.policy_condition_parser import ( - is_condition_block_restrictive, + is_condition_block_restrictive_account, ) from prowler.providers.aws.services.sqs.sqs_client import sqs_client @@ -32,7 +32,7 @@ def execute(self): ) ): if "Condition" in statement: - if is_condition_block_restrictive( + if is_condition_block_restrictive_account( statement["Condition"], sqs_client.audited_account, True, diff --git a/prowler/providers/aws/services/vpc/vpc_endpoint_connections_trust_boundaries/vpc_endpoint_connections_trust_boundaries.py b/prowler/providers/aws/services/vpc/vpc_endpoint_connections_trust_boundaries/vpc_endpoint_connections_trust_boundaries.py index 936057e657..45ddae7131 100644 --- a/prowler/providers/aws/services/vpc/vpc_endpoint_connections_trust_boundaries/vpc_endpoint_connections_trust_boundaries.py +++ b/prowler/providers/aws/services/vpc/vpc_endpoint_connections_trust_boundaries/vpc_endpoint_connections_trust_boundaries.py @@ -2,7 +2,7 @@ from prowler.lib.check.models import Check, Check_Report_AWS from prowler.providers.aws.lib.policy_condition_parser.policy_condition_parser import ( - is_condition_block_restrictive, + is_condition_block_restrictive_account, ) from prowler.providers.aws.services.vpc.vpc_client import vpc_client @@ -35,7 +35,7 @@ def execute(self): if "Condition" in statement: for account_id in trusted_account_ids: - if is_condition_block_restrictive( + if is_condition_block_restrictive_account( statement["Condition"], account_id ): access_from_trusted_accounts = True @@ -74,7 +74,7 @@ def execute(self): access_from_trusted_accounts = False if "Condition" in statement: for account_id in trusted_account_ids: - if is_condition_block_restrictive( + if is_condition_block_restrictive_account( statement["Condition"], account_id ): access_from_trusted_accounts = True @@ -106,7 +106,7 @@ def execute(self): if "Condition" in statement: for account_id in trusted_account_ids: - if is_condition_block_restrictive( + if is_condition_block_restrictive_account( statement["Condition"], account_id ): access_from_trusted_accounts = True diff --git a/tests/config/config_test.py b/tests/config/config_test.py index 09a2f61c31..cba59d6b6e 100644 --- a/tests/config/config_test.py +++ b/tests/config/config_test.py @@ -255,6 +255,7 @@ def mock_prowler_get_latest_release(_, **kwargs): ], "check_rds_instance_replicas": False, "days_to_expire_threshold": 7, + "organization_id": None, } config_azure = { diff --git a/tests/config/fixtures/config.yaml b/tests/config/fixtures/config.yaml index 90dd925aaa..659b208949 100644 --- a/tests/config/fixtures/config.yaml +++ b/tests/config/fixtures/config.yaml @@ -272,6 +272,10 @@ aws: # aws.acm_certificates_expiration_check days_to_expire_threshold: 7 + # AWS SNS Configuration + # aws.sns_topics_not_publicly_accessible + organization_id: null + # Azure Configuration azure: # Azure Network Configuration diff --git a/tests/providers/aws/lib/policy_condition_parser/policy_condition_parser_test.py b/tests/providers/aws/lib/policy_condition_parser/policy_condition_parser_test.py index 120b8be4e9..39f7a50e5d 100644 --- a/tests/providers/aws/lib/policy_condition_parser/policy_condition_parser_test.py +++ b/tests/providers/aws/lib/policy_condition_parser/policy_condition_parser_test.py @@ -1,10 +1,14 @@ from prowler.providers.aws.lib.policy_condition_parser.policy_condition_parser import ( - is_condition_block_restrictive, + is_condition_block_restrictive_account, + is_condition_block_restrictive_organization, ) TRUSTED_AWS_ACCOUNT_NUMBER = "123456789012" NON_TRUSTED_AWS_ACCOUNT_NUMBER = "111222333444" +TRUSTED_ORGANIZATION_ID = "o-123456789012" +NON_TRUSTED_ORGANIZATION_ID = "o-111222333444" + class Test_policy_condition_parser: # Test lowercase context key name --> aws @@ -12,7 +16,7 @@ def test_condition_parser_string_equals_aws_SourceAccount_list(self): condition_statement = { "StringEquals": {"aws:SourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -25,7 +29,7 @@ def test_condition_parser_string_equals_aws_SourceAccount_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -33,7 +37,7 @@ def test_condition_parser_string_equals_aws_SourceAccount_str(self): condition_statement = { "StringEquals": {"aws:SourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -41,7 +45,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -49,7 +53,7 @@ def test_condition_parser_string_like_aws_SourceAccount_list(self): condition_statement = { "StringLike": {"aws:SourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -62,7 +66,7 @@ def test_condition_parser_string_like_aws_SourceAccount_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -70,7 +74,7 @@ def test_condition_parser_string_like_aws_SourceAccount_str(self): condition_statement = { "StringLike": {"aws:SourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -78,7 +82,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -86,7 +90,7 @@ def test_condition_parser_string_equals_aws_SourceOwner_str(self): condition_statement = { "StringEquals": {"aws:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -94,7 +98,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -102,7 +106,7 @@ def test_condition_parser_string_equals_aws_SourceOwner_list(self): condition_statement = { "StringEquals": {"aws:SourceOwner": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -115,7 +119,7 @@ def test_condition_parser_string_equals_aws_SourceOwner_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -123,7 +127,7 @@ def test_condition_parser_string_like_aws_SourceOwner_list(self): condition_statement = { "StringLike": {"aws:SourceOwner": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -136,7 +140,7 @@ def test_condition_parser_string_like_aws_SourceOwner_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -144,7 +148,7 @@ def test_condition_parser_string_like_aws_SourceOwner_str(self): condition_statement = { "StringLike": {"aws:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -152,7 +156,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -160,7 +164,7 @@ def test_condition_parser_string_equals_s3_ResourceAccount_list(self): condition_statement = { "StringEquals": {"s3:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -173,7 +177,7 @@ def test_condition_parser_string_equals_s3_ResourceAccount_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -181,7 +185,7 @@ def test_condition_parser_string_equals_s3_ResourceAccount_str(self): condition_statement = { "StringEquals": {"s3:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -189,7 +193,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -197,7 +201,7 @@ def test_condition_parser_string_equals_aws_PrincipalAccount_list(self): condition_statement = { "StringEquals": {"aws:PrincipalAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -210,7 +214,7 @@ def test_condition_parser_string_equals_aws_PrincipalAccount_list_not_valid(self ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -218,7 +222,7 @@ def test_condition_parser_string_equals_aws_PrincipalAccount_str(self): condition_statement = { "StringEquals": {"aws:PrincipalAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -226,7 +230,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -236,7 +240,7 @@ def test_condition_parser_string_equals_aws_SourceArn_str(self): "aws:SourceArn": f"arn:aws:cloudtrail:*:{TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*" } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -246,7 +250,7 @@ def test_condition_parser_string_equals_aws_SourceArn_str_not_valid(self): "aws:SourceArn": f"arn:aws:cloudtrail:*:{NON_TRUSTED_AWS_ACCOUNT_NUMBER}:trail/*" } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -254,7 +258,7 @@ def test_condition_parser_string_like_aws_PrincipalAccount_list(self): condition_statement = { "StringLike": {"aws:PrincipalAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -267,7 +271,7 @@ def test_condition_parser_string_like_aws_PrincipalAccount_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -275,7 +279,7 @@ def test_condition_parser_string_like_aws_PrincipalAccount_str(self): condition_statement = { "StringLike": {"aws:PrincipalAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -283,7 +287,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -296,7 +300,7 @@ def test_condition_parser_arn_like_aws_SourceArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -310,7 +314,7 @@ def test_condition_parser_arn_like_aws_SourceArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -321,7 +325,7 @@ def test_condition_parser_arn_like_aws_SourceArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -332,7 +336,7 @@ def test_condition_parser_arn_like_aws_SourceArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -345,7 +349,7 @@ def test_condition_parser_arn_like_aws_PrincipalArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -359,7 +363,7 @@ def test_condition_parser_arn_like_aws_PrincipalArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -370,7 +374,7 @@ def test_condition_parser_arn_like_aws_PrincipalArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -381,7 +385,7 @@ def test_condition_parser_arn_like_aws_PrincipalArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -394,7 +398,7 @@ def test_condition_parser_arn_equals_aws_SourceArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -408,7 +412,7 @@ def test_condition_parser_arn_equals_aws_SourceArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -419,7 +423,7 @@ def test_condition_parser_arn_equals_aws_SourceArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -430,7 +434,7 @@ def test_condition_parser_arn_equals_aws_SourceArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -443,7 +447,7 @@ def test_condition_parser_arn_equals_aws_PrincipalArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -457,7 +461,7 @@ def test_condition_parser_arn_equals_aws_PrincipalArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -468,7 +472,7 @@ def test_condition_parser_arn_equals_aws_PrincipalArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -479,7 +483,7 @@ def test_condition_parser_arn_equals_aws_PrincipalArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -492,7 +496,7 @@ def test_condition_parser_string_like_aws_SourceArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -506,7 +510,7 @@ def test_condition_parser_string_like_aws_SourceArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -517,7 +521,7 @@ def test_condition_parser_string_like_aws_SourceArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -528,7 +532,7 @@ def test_condition_parser_string_like_aws_SourceArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -541,7 +545,7 @@ def test_condition_parser_string_like_aws_PrincipalArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -555,7 +559,7 @@ def test_condition_parser_string_like_aws_PrincipalArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -566,7 +570,7 @@ def test_condition_parser_string_like_aws_PrincipalArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -577,7 +581,7 @@ def test_condition_parser_string_like_aws_PrincipalArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -585,7 +589,7 @@ def test_condition_parser_string_equals_aws_ResourceAccount_list(self): condition_statement = { "StringEquals": {"aws:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -598,7 +602,7 @@ def test_condition_parser_string_equals_aws_ResourceAccount_list_not_valid(self) ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -606,7 +610,7 @@ def test_condition_parser_string_equals_aws_ResourceAccount_str(self): condition_statement = { "StringEquals": {"aws:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -614,7 +618,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -622,7 +626,7 @@ def test_condition_parser_string_like_aws_ResourceAccount_list(self): condition_statement = { "StringLike": {"aws:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -635,7 +639,7 @@ def test_condition_parser_string_like_aws_ResourceAccount_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -643,7 +647,7 @@ def test_condition_parser_string_like_aws_ResourceAccount_str(self): condition_statement = { "StringLike": {"aws:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -651,7 +655,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -660,7 +664,7 @@ def test_condition_parser_string_equals_AWS_SourceAccount_list(self): condition_statement = { "StringEquals": {"AWS:SourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -673,7 +677,7 @@ def test_condition_parser_string_equals_AWS_SourceAccount_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -681,7 +685,7 @@ def test_condition_parser_string_equals_AWS_SourceAccount_str(self): condition_statement = { "StringEquals": {"AWS:SourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -689,7 +693,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -697,7 +701,7 @@ def test_condition_parser_string_like_AWS_SourceAccount_list(self): condition_statement = { "StringLike": {"AWS:SourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -710,7 +714,7 @@ def test_condition_parser_string_like_AWS_SourceAccount_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -718,7 +722,7 @@ def test_condition_parser_string_like_AWS_SourceAccount_str(self): condition_statement = { "StringLike": {"AWS:SourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -726,7 +730,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -734,7 +738,7 @@ def test_condition_parser_string_equals_AWS_SourceOwner_str(self): condition_statement = { "StringEquals": {"AWS:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -742,7 +746,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -750,7 +754,7 @@ def test_condition_parser_string_equals_AWS_SourceOwner_list(self): condition_statement = { "StringEquals": {"AWS:SourceOwner": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -763,7 +767,7 @@ def test_condition_parser_string_equals_AWS_SourceOwner_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -771,7 +775,7 @@ def test_condition_parser_string_like_AWS_SourceOwner_list(self): condition_statement = { "StringLike": {"AWS:SourceOwner": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -784,7 +788,7 @@ def test_condition_parser_string_like_AWS_SourceOwner_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -792,7 +796,7 @@ def test_condition_parser_string_like_AWS_SourceOwner_str(self): condition_statement = { "StringLike": {"AWS:SourceOwner": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -800,7 +804,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -808,7 +812,7 @@ def test_condition_parser_string_equals_S3_ResourceAccount_list(self): condition_statement = { "StringEquals": {"S3:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -821,7 +825,7 @@ def test_condition_parser_string_equals_S3_ResourceAccount_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -829,7 +833,7 @@ def test_condition_parser_string_equals_S3_ResourceAccount_str(self): condition_statement = { "StringEquals": {"S3:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -837,7 +841,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -845,7 +849,7 @@ def test_condition_parser_string_equals_AWS_PrincipalAccount_list(self): condition_statement = { "StringEquals": {"AWS:PrincipalAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -858,7 +862,7 @@ def test_condition_parser_string_equals_AWS_PrincipalAccount_list_not_valid(self ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -866,7 +870,7 @@ def test_condition_parser_string_equals_AWS_PrincipalAccount_str(self): condition_statement = { "StringEquals": {"AWS:PrincipalAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -874,7 +878,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -882,7 +886,7 @@ def test_condition_parser_string_like_AWS_PrincipalAccount_list(self): condition_statement = { "StringLike": {"AWS:PrincipalAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -895,7 +899,7 @@ def test_condition_parser_string_like_AWS_PrincipalAccount_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -903,7 +907,7 @@ def test_condition_parser_string_like_AWS_PrincipalAccount_str(self): condition_statement = { "StringLike": {"AWS:PrincipalAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -911,7 +915,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -924,7 +928,7 @@ def test_condition_parser_arn_like_AWS_SourceArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -938,7 +942,7 @@ def test_condition_parser_arn_like_AWS_SourceArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -949,7 +953,7 @@ def test_condition_parser_arn_like_AWS_SourceArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -960,7 +964,7 @@ def test_condition_parser_arn_like_AWS_SourceArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -973,7 +977,7 @@ def test_condition_parser_arn_like_AWS_PrincipalArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -987,7 +991,7 @@ def test_condition_parser_arn_like_AWS_PrincipalArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -998,7 +1002,7 @@ def test_condition_parser_arn_like_AWS_PrincipalArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1009,7 +1013,7 @@ def test_condition_parser_arn_like_AWS_PrincipalArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1022,7 +1026,7 @@ def test_condition_parser_arn_equals_AWS_SourceArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1036,7 +1040,7 @@ def test_condition_parser_arn_equals_AWS_SourceArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1047,7 +1051,7 @@ def test_condition_parser_arn_equals_AWS_SourceArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1058,7 +1062,7 @@ def test_condition_parser_arn_equals_AWS_SourceArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1071,7 +1075,7 @@ def test_condition_parser_arn_equals_AWS_PrincipalArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1085,7 +1089,7 @@ def test_condition_parser_arn_equals_AWS_PrincipalArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1096,7 +1100,7 @@ def test_condition_parser_arn_equals_AWS_PrincipalArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1107,7 +1111,7 @@ def test_condition_parser_arn_equals_AWS_PrincipalArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1120,7 +1124,7 @@ def test_condition_parser_string_like_AWS_SourceArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1134,7 +1138,7 @@ def test_condition_parser_string_like_AWS_SourceArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1145,7 +1149,7 @@ def test_condition_parser_string_like_AWS_SourceArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1156,7 +1160,7 @@ def test_condition_parser_string_like_AWS_SourceArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1169,7 +1173,7 @@ def test_condition_parser_string_like_AWS_PrincipalArn_list(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1183,7 +1187,7 @@ def test_condition_parser_string_like_AWS_PrincipalArn_list_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1194,7 +1198,7 @@ def test_condition_parser_string_like_AWS_PrincipalArn_str(self): } } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1205,7 +1209,7 @@ def test_condition_parser_string_like_AWS_PrincipalArn_str_not_valid(self): } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1213,7 +1217,7 @@ def test_condition_parser_string_equals_AWS_ResourceAccount_list(self): condition_statement = { "StringEquals": {"AWS:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1226,7 +1230,7 @@ def test_condition_parser_string_equals_AWS_ResourceAccount_list_not_valid(self) ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1234,7 +1238,7 @@ def test_condition_parser_string_equals_AWS_ResourceAccount_str(self): condition_statement = { "StringEquals": {"AWS:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1242,7 +1246,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1250,7 +1254,7 @@ def test_condition_parser_string_like_AWS_ResourceAccount_list(self): condition_statement = { "StringLike": {"AWS:ResourceAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1263,7 +1267,7 @@ def test_condition_parser_string_like_AWS_ResourceAccount_list_not_valid(self): ] } } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1271,7 +1275,7 @@ def test_condition_parser_string_like_AWS_ResourceAccount_str(self): condition_statement = { "StringLike": {"AWS:ResourceAccount": TRUSTED_AWS_ACCOUNT_NUMBER} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1279,7 +1283,7 @@ 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( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1298,7 +1302,7 @@ def test_condition_parser_two_lists_unrestrictive(self): ] }, } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1315,7 +1319,7 @@ def test_condition_parser_two_lists_both_restrictive(self): ] }, } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1333,7 +1337,7 @@ def test_condition_parser_two_lists_first_restrictive(self): ] }, } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1351,7 +1355,7 @@ def test_condition_parser_two_lists_second_restrictive(self): ] }, } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER ) @@ -1363,21 +1367,21 @@ def test_condition_parser_allowing_cross_account_with_invalid_block(self): ] }, } - assert not is_condition_block_restrictive( + assert not is_condition_block_restrictive_account( 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( + assert is_condition_block_restrictive_account( 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( + assert is_condition_block_restrictive_account( condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER, True ) @@ -1386,6 +1390,80 @@ def test_condition_parser_string_equals_vpc_list_not_valid(self): "StringEquals": {"aws:SourceVpc": ["vpc-123456", "vpc-654321"]} } - assert is_condition_block_restrictive( + assert is_condition_block_restrictive_account( 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, TRUSTED_ORGANIZATION_ID + ) + + def test_condition_parser_string_equals_aws_PrincipalOrgID_list_not_valid(self): + condition_statement = { + "StringEquals": { + "aws:PrincipalOrgID": [ + TRUSTED_ORGANIZATION_ID, + NON_TRUSTED_ORGANIZATION_ID, + ] + } + } + assert not is_condition_block_restrictive_organization( + condition_statement, TRUSTED_ORGANIZATION_ID + ) + + 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, TRUSTED_ORGANIZATION_ID + ) + + def test_condition_parser_string_equals_aws_PrincipalOrgID_str_not_valid(self): + condition_statement = { + "StringEquals": {"aws:PrincipalOrgID": NON_TRUSTED_ORGANIZATION_ID} + } + assert not is_condition_block_restrictive_organization( + condition_statement, TRUSTED_ORGANIZATION_ID + ) + + def test_condition_parser_string_like_aws_PrincipalOrgID_list(self): + condition_statement = { + "StringLike": {"aws:PrincipalOrgID": [TRUSTED_ORGANIZATION_ID]} + } + assert is_condition_block_restrictive_organization( + condition_statement, TRUSTED_ORGANIZATION_ID + ) + + def test_condition_parser_string_like_aws_PrincipalOrgID_list_not_valid(self): + condition_statement = { + "StringLike": { + "aws:PrincipalOrgID": [ + TRUSTED_ORGANIZATION_ID, + NON_TRUSTED_AWS_ACCOUNT_NUMBER, + ] + } + } + assert not is_condition_block_restrictive_organization( + condition_statement, TRUSTED_ORGANIZATION_ID + ) + + def test_condition_parser_string_like_aws_PrincipalOrgID_str(self): + condition_statement = { + "StringLike": {"aws:PrincipalOrgID": TRUSTED_ORGANIZATION_ID} + } + assert is_condition_block_restrictive_organization( + condition_statement, TRUSTED_ORGANIZATION_ID + ) + + def test_condition_parser_string_like_aws_PrincipalOrgID_str_not_valid(self): + condition_statement = { + "StringLike": {"aws:PrincipalOrgID": NON_TRUSTED_ORGANIZATION_ID} + } + assert not is_condition_block_restrictive_organization( + condition_statement, TRUSTED_ORGANIZATION_ID + ) diff --git a/tests/providers/aws/services/sns/sns_topics_not_publicly_accessible/sns_topics_not_publicly_accessible_test.py b/tests/providers/aws/services/sns/sns_topics_not_publicly_accessible/sns_topics_not_publicly_accessible_test.py index b88ea6c8ea..4a0ac94a8c 100644 --- a/tests/providers/aws/services/sns/sns_topics_not_publicly_accessible/sns_topics_not_publicly_accessible_test.py +++ b/tests/providers/aws/services/sns/sns_topics_not_publicly_accessible/sns_topics_not_publicly_accessible_test.py @@ -66,6 +66,23 @@ ] } +test_policy_restricted_principal_account_organization = { + "Statement": [ + { + "Effect": "Allow", + "Principal": {"AWS": "*"}, + "Action": ["sns:Publish"], + "Resource": f"arn:aws:sns:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:{topic_name}", + "Condition": { + "StringEquals": { + "aws:PrincipalOrgID": org_id, + "aws:SourceAccount": AWS_ACCOUNT_NUMBER, + } + }, + } + ] +} + class Test_sns_topics_not_publicly_accessible: def test_no_topics(self): @@ -168,7 +185,7 @@ def test_topic_public_with_condition(self): assert result[0].status == "PASS" assert ( result[0].status_extended - == f"SNS topic {topic_name} is not public because its policy only allows access from the same account." + == f"SNS topic {topic_name} is not public because its policy only allows access from the account {AWS_ACCOUNT_NUMBER}." ) assert result[0].resource_id == topic_name assert result[0].resource_arn == topic_arn @@ -201,7 +218,7 @@ def test_topic_public_with_default_condition(self): assert result[0].status == "PASS" assert ( result[0].status_extended - == f"SNS topic {topic_name} is not public because its policy only allows access from the same account." + == f"SNS topic {topic_name} is not public because its policy only allows access from the account {AWS_ACCOUNT_NUMBER}." ) assert result[0].resource_id == topic_name assert result[0].resource_arn == topic_arn @@ -240,7 +257,7 @@ def test_topic_public(self): assert result[0].region == AWS_REGION_EU_WEST_1 assert result[0].resource_tags == [] - def test_topic_public_with_principal_org_id(self): + def test_topic_public_with_principal_organization(self): sns_client = mock.MagicMock sns_client.audited_account = AWS_ACCOUNT_NUMBER sns_client.topics = [] @@ -250,9 +267,47 @@ def test_topic_public_with_principal_org_id(self): name=topic_name, policy=test_policy_restricted_principal_org_id, region=AWS_REGION_EU_WEST_1, - org_id=org_id, ) ) + sns_client.provider = mock.MagicMock() + sns_client.provider.organizations_metadata = mock.MagicMock() + sns_client.provider.organizations_metadata.organization_id = org_id + with mock.patch( + "prowler.providers.aws.services.sns.sns_service.SNS", + sns_client, + ): + from prowler.providers.aws.services.sns.sns_topics_not_publicly_accessible.sns_topics_not_publicly_accessible import ( + sns_topics_not_publicly_accessible, + ) + + check = sns_topics_not_publicly_accessible() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"SNS topic {topic_name} is not public because its policy only allows access from the organization {org_id}." + ) + assert result[0].resource_id == topic_name + assert result[0].resource_arn == topic_arn + assert result[0].region == AWS_REGION_EU_WEST_1 + assert result[0].resource_tags == [] + + def test_topic_public_with_principal_account_and_organization(self): + sns_client = mock.MagicMock + sns_client.audited_account = AWS_ACCOUNT_NUMBER + sns_client.topics = [] + sns_client.topics.append( + Topic( + arn=topic_arn, + name=topic_name, + policy=test_policy_restricted_principal_account_organization, + region=AWS_REGION_EU_WEST_1, + ) + ) + sns_client.provider = mock.MagicMock() + sns_client.provider.organizations_metadata = mock.MagicMock() + sns_client.provider.organizations_metadata.organization_id = org_id with mock.patch( "prowler.providers.aws.services.sns.sns_service.SNS", sns_client, @@ -267,7 +322,7 @@ def test_topic_public_with_principal_org_id(self): assert result[0].status == "PASS" assert ( result[0].status_extended - == f"SNS topic {topic_name} is not public because its policy only allows access from the same account." + == f"SNS topic {topic_name} is not public because its policy only allows access from the account {AWS_ACCOUNT_NUMBER} and organization {org_id}." ) assert result[0].resource_id == topic_name assert result[0].resource_arn == topic_arn