From dd1cc2d025ec7494d97ef9f09cbcf6757eeb9d86 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 25 Mar 2025 11:39:19 +0100 Subject: [PATCH] fix(s3): handle None S3 account public access block (#7350) --- .../s3_account_level_public_access_blocks.py | 45 ++++++++++--------- .../providers/aws/services/s3/s3_service.py | 7 +-- ...account_level_public_access_blocks_test.py | 30 +++++++++++++ 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/prowler/providers/aws/services/s3/s3_account_level_public_access_blocks/s3_account_level_public_access_blocks.py b/prowler/providers/aws/services/s3/s3_account_level_public_access_blocks/s3_account_level_public_access_blocks.py index 5e027c1510..bbb123fdfb 100644 --- a/prowler/providers/aws/services/s3/s3_account_level_public_access_blocks/s3_account_level_public_access_blocks.py +++ b/prowler/providers/aws/services/s3/s3_account_level_public_access_blocks/s3_account_level_public_access_blocks.py @@ -6,27 +6,28 @@ from prowler.providers.aws.services.s3.s3control_client import s3control_client class s3_account_level_public_access_blocks(Check): def execute(self): findings = [] - report = Check_Report_AWS( - metadata=self.metadata(), - resource=s3control_client.account_public_access_block, - ) - if ( - s3control_client.account_public_access_block - and s3control_client.account_public_access_block.ignore_public_acls - and s3control_client.account_public_access_block.restrict_public_buckets - ): - report.status = "PASS" - report.status_extended = f"Block Public Access is configured for the account {s3control_client.audited_account}." - report.region = s3control_client.region - report.resource_id = s3control_client.audited_account - report.resource_arn = s3_client.account_arn_template - findings.append(report) - elif s3_client.buckets or s3_client.provider.scan_unused_services: - report.status = "FAIL" - report.status_extended = f"Block Public Access is not configured for the account {s3control_client.audited_account}." - report.region = s3control_client.region - report.resource_id = s3control_client.audited_account - report.resource_arn = s3_client.account_arn_template - findings.append(report) + if s3control_client.account_public_access_block is not None: + report = Check_Report_AWS( + metadata=self.metadata(), + resource=s3control_client.account_public_access_block, + ) + if ( + s3control_client.account_public_access_block + and s3control_client.account_public_access_block.ignore_public_acls + and s3control_client.account_public_access_block.restrict_public_buckets + ): + report.status = "PASS" + report.status_extended = f"Block Public Access is configured for the account {s3control_client.audited_account}." + report.region = s3control_client.region + report.resource_id = s3control_client.audited_account + report.resource_arn = s3_client.account_arn_template + findings.append(report) + elif s3_client.buckets or s3_client.provider.scan_unused_services: + report.status = "FAIL" + report.status_extended = f"Block Public Access is not configured for the account {s3control_client.audited_account}." + report.region = s3control_client.region + report.resource_id = s3control_client.audited_account + report.resource_arn = s3_client.account_arn_template + findings.append(report) return findings diff --git a/prowler/providers/aws/services/s3/s3_service.py b/prowler/providers/aws/services/s3/s3_service.py index 3894e1001d..c8f7c0343d 100644 --- a/prowler/providers/aws/services/s3/s3_service.py +++ b/prowler/providers/aws/services/s3/s3_service.py @@ -511,9 +511,10 @@ class S3Control(AWSService): def __init__(self, provider): # Call AWSService's __init__ super().__init__(__class__.__name__, provider) - self.account_public_access_block = self._get_public_access_block() + self.account_public_access_block = None self.access_points = {} self.multi_region_access_points = {} + self._get_public_access_block() self.__threading_call__(self._list_access_points) self.__threading_call__(self._get_access_point, self.access_points.values()) if self.audited_partition == "aws": @@ -525,7 +526,7 @@ class S3Control(AWSService): public_access_block = self.client.get_public_access_block( AccountId=self.audited_account )["PublicAccessBlockConfiguration"] - return PublicAccessBlock( + self.account_public_access_block = PublicAccessBlock( block_public_acls=public_access_block["BlockPublicAcls"], ignore_public_acls=public_access_block["IgnorePublicAcls"], block_public_policy=public_access_block["BlockPublicPolicy"], @@ -534,7 +535,7 @@ class S3Control(AWSService): except Exception as error: if "NoSuchPublicAccessBlockConfiguration" in str(error): # Set all block as False - return PublicAccessBlock( + self.account_public_access_block = PublicAccessBlock( block_public_acls=False, ignore_public_acls=False, block_public_policy=False, diff --git a/tests/providers/aws/services/s3/s3_account_level_public_access_blocks/s3_account_level_public_access_blocks_test.py b/tests/providers/aws/services/s3/s3_account_level_public_access_blocks/s3_account_level_public_access_blocks_test.py index 994a6bcbe6..96b02bd88b 100644 --- a/tests/providers/aws/services/s3/s3_account_level_public_access_blocks/s3_account_level_public_access_blocks_test.py +++ b/tests/providers/aws/services/s3/s3_account_level_public_access_blocks/s3_account_level_public_access_blocks_test.py @@ -156,3 +156,33 @@ class Test_s3_account_level_public_access_blocks: result = check.execute() assert len(result) == 0 + + def test_none_bucket_account_public_block(self): + from prowler.providers.aws.services.s3.s3_service import S3, S3Control + + aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1]) + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + mock.patch( + "prowler.providers.aws.services.s3.s3_account_level_public_access_blocks.s3_account_level_public_access_blocks.s3_client", + new=S3(aws_provider), + ), + mock.patch( + "prowler.providers.aws.services.s3.s3_account_level_public_access_blocks.s3_account_level_public_access_blocks.s3control_client", + new=S3Control(aws_provider), + ) as s3control_client, + ): + # Test Check + from prowler.providers.aws.services.s3.s3_account_level_public_access_blocks.s3_account_level_public_access_blocks import ( + s3_account_level_public_access_blocks, + ) + + s3control_client.account_public_access_block = None + check = s3_account_level_public_access_blocks() + result = check.execute() + + assert len(result) == 0