feat(s3): add new fixer s3_bucket_public_access_fixer (#6164)

Co-authored-by: MrCloudSec <hello@mistercloudsec.com>
This commit is contained in:
Daniel Barranquero
2024-12-12 17:17:41 +01:00
committed by GitHub
parent 83c204e010
commit 7d2c50991b
2 changed files with 215 additions and 0 deletions
@@ -0,0 +1,46 @@
from prowler.lib.logger import logger
from prowler.providers.aws.services.s3.s3_client import s3_client
def fixer(resource_id: str, region: str) -> bool:
"""
Modify the S3 bucket's public access settings to block all public access.
Specifically, this fixer configures the bucket's public access block settings to
prevent any public access (ACLs and policies). Requires the s3:PutBucketPublicAccessBlock
permission to modify the public access settings.
Permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:PutBucketPublicAccessBlock",
"Resource": "*"
}
]
}
Args:
resource_id (str): The S3 bucket name.
region (str): AWS region where the S3 bucket exists.
Returns:
bool: True if the operation is successful (public access is blocked),
False otherwise.
"""
try:
regional_client = s3_client.regional_clients[region]
regional_client.put_public_access_block(
Bucket=resource_id,
PublicAccessBlockConfiguration={
"BlockPublicAcls": True,
"IgnorePublicAcls": True,
"BlockPublicPolicy": True,
"RestrictPublicBuckets": True,
},
)
except Exception as error:
logger.error(
f"{region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
return False
else:
return True
@@ -0,0 +1,169 @@
from unittest import mock
from boto3 import client
from moto import mock_aws
from tests.providers.aws.utils import (
AWS_ACCOUNT_NUMBER,
AWS_REGION_US_EAST_1,
set_mocked_aws_provider,
)
class Test_s3_bucket_public_access_fixer:
@mock_aws
def test_no_buckets(self):
from prowler.providers.aws.services.s3.s3_service import S3
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,
):
with mock.patch(
"prowler.providers.aws.services.s3.s3_bucket_public_access.s3_bucket_public_access_fixer.s3_client",
new=S3(aws_provider),
):
# Test Fixer
from prowler.providers.aws.services.s3.s3_bucket_public_access.s3_bucket_public_access_fixer import (
fixer,
)
assert not fixer("bucket_test_us", AWS_REGION_US_EAST_1)
@mock_aws
def test_bucket_public_ACL(self):
s3_client = client("s3", region_name=AWS_REGION_US_EAST_1)
bucket_name_us = "bucket_test_us"
s3_client.create_bucket(Bucket=bucket_name_us)
bucket_owner = s3_client.get_bucket_acl(Bucket=bucket_name_us)["Owner"]
s3_client.put_public_access_block(
Bucket=bucket_name_us,
PublicAccessBlockConfiguration={
"BlockPublicAcls": False,
"IgnorePublicAcls": False,
"BlockPublicPolicy": False,
"RestrictPublicBuckets": False,
},
)
s3_client.put_bucket_acl(
Bucket=bucket_name_us,
AccessControlPolicy={
"Grants": [
{
"Grantee": {
"URI": "http://acs.amazonaws.com/groups/global/AllUsers",
"Type": "Group",
},
"Permission": "READ",
},
],
"Owner": bucket_owner,
},
)
from prowler.providers.aws.services.s3.s3_service import S3
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,
):
with mock.patch(
"prowler.providers.aws.services.s3.s3_bucket_public_access.s3_bucket_public_access_fixer.s3_client",
new=S3(aws_provider),
):
# Test Fixer
from prowler.providers.aws.services.s3.s3_bucket_public_access.s3_bucket_public_access_fixer import (
fixer,
)
assert fixer(bucket_name_us, AWS_REGION_US_EAST_1)
@mock_aws
def test_bucket_public_policy(self):
s3_client = client("s3", region_name=AWS_REGION_US_EAST_1)
bucket_name_us = "bucket_test_us"
s3_client.create_bucket(Bucket=bucket_name_us)
# Generate S3Control Client
s3control_client = client("s3control", region_name=AWS_REGION_US_EAST_1)
s3control_client.put_public_access_block(
AccountId=AWS_ACCOUNT_NUMBER,
PublicAccessBlockConfiguration={
"BlockPublicAcls": False,
"IgnorePublicAcls": False,
"BlockPublicPolicy": False,
"RestrictPublicBuckets": False,
},
)
s3_client.put_public_access_block(
Bucket=bucket_name_us,
PublicAccessBlockConfiguration={
"BlockPublicAcls": False,
"IgnorePublicAcls": False,
"BlockPublicPolicy": False,
"RestrictPublicBuckets": False,
},
)
public_write_policy = '{"Version": "2012-10-17","Id": "PutObjPolicy","Statement": [{"Sid": "PublicWritePolicy","Effect": "Allow","Principal": "*","Action": "s3:PutObject","Resource": "arn:aws:s3:::bucket_test_us/*"}]}'
s3_client.put_bucket_policy(
Bucket=bucket_name_us,
Policy=public_write_policy,
)
from prowler.providers.aws.services.s3.s3_service import S3
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,
):
with mock.patch(
"prowler.providers.aws.services.s3.s3_bucket_public_access.s3_bucket_public_access_fixer.s3_client",
new=S3(aws_provider),
):
# Test Fixer
from prowler.providers.aws.services.s3.s3_bucket_public_access.s3_bucket_public_access_fixer import (
fixer,
)
assert fixer(bucket_name_us, AWS_REGION_US_EAST_1)
@mock_aws
def test_bucket_public_due_to_policy_conditions_from_public_ip(self):
s3_client = client("s3", region_name=AWS_REGION_US_EAST_1)
bucket_name_us = "bucket_test_us"
s3_client.create_bucket(Bucket=bucket_name_us)
s3_client.put_public_access_block(
Bucket=bucket_name_us,
PublicAccessBlockConfiguration={
"BlockPublicAcls": False,
"IgnorePublicAcls": False,
"BlockPublicPolicy": False,
"RestrictPublicBuckets": False,
},
)
public_write_policy = '{"Version": "2012-10-17","Id": "PutObjPolicy","Statement": [{"Sid": "PublicWritePolicy","Effect": "Allow","Principal": "*","Action": "s3:PutObject","Resource": "arn:aws:s3:::bucket_test_us/*","Condition": {"IpAddress": {"aws:SourceIp": "1.2.3.4"}}}]}'
s3_client.put_bucket_policy(
Bucket=bucket_name_us,
Policy=public_write_policy,
)
from prowler.providers.aws.services.s3.s3_service import S3
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,
):
with mock.patch(
"prowler.providers.aws.services.s3.s3_bucket_public_access.s3_bucket_public_access_fixer.s3_client",
new=S3(aws_provider),
):
# Test Fixer
from prowler.providers.aws.services.s3.s3_bucket_public_access.s3_bucket_public_access_fixer import (
fixer,
)
assert fixer(bucket_name_us, AWS_REGION_US_EAST_1)