diff --git a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/__init__.py b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket.metadata.json b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket.metadata.json new file mode 100644 index 0000000000..5910db0594 --- /dev/null +++ b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket.metadata.json @@ -0,0 +1,34 @@ +{ + "Provider": "aws", + "CheckID": "cloudfront_distributions_s3_origin_non_existent_bucket", + "CheckTitle": "CloudFront distributions should not point to non-existent S3 origins.", + "CheckType": [ + "Software and Configuration Checks/Industry and Regulatory Standards/NIST 800-53 Controls" + ], + "ServiceName": "cloudfront", + "SubServiceName": "", + "ResourceIdTemplate": "arn:partition:cloudfront:region:account-id:distribution/resource-id", + "Severity": "high", + "ResourceType": "AwsCloudFrontDistribution", + "Description": "This control checks whether Amazon CloudFront distributions are pointing to non-existent Amazon S3 origins. The control fails if the origin is configured to point to a non-existent bucket.", + "Risk": "Pointing a CloudFront distribution to a non-existent S3 bucket can allow malicious actors to create the bucket and potentially serve unauthorized content through your distribution, leading to security and integrity issues.", + "RelatedUrl": "https://docs.aws.amazon.com/whitepapers/latest/secure-content-delivery-amazon-cloudfront/s3-origin-with-cloudfront.html", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/cloudfront-controls.html#cloudfront-12", + "Terraform": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/CloudFront/cloudfront-existing-s3-bucket.html" + }, + "Recommendation": { + "Text": "Verify that all CloudFront distributions are configured to point to valid, existing S3 buckets. Update the origin settings as needed to ensure that your distributions are linked to appropriate and secure origins.", + "Url": "https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/HowToUpdateDistribution.html" + } + }, + "Categories": [ + "trustboundaries" + ], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket.py b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket.py new file mode 100644 index 0000000000..1ba7fc41b1 --- /dev/null +++ b/prowler/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket.py @@ -0,0 +1,32 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.cloudfront.cloudfront_client import ( + cloudfront_client, +) +from prowler.providers.aws.services.s3.s3_client import s3_client + + +class cloudfront_distributions_s3_origin_non_existent_bucket(Check): + def execute(self): + findings = [] + for distribution in cloudfront_client.distributions.values(): + report = Check_Report_AWS(self.metadata()) + report.region = distribution.region + report.resource_arn = distribution.arn + report.resource_id = distribution.id + report.resource_tags = distribution.tags + report.status = "PASS" + report.status_extended = f"CloudFront Distribution {distribution.id} does not have non-existent S3 buckets as origins." + non_existent_buckets = [] + + for origin in distribution.origins: + bucket_name = origin.domain_name.split(".")[0] + if not s3_client._head_bucket(bucket_name): + non_existent_buckets.append(bucket_name) + + if non_existent_buckets: + report.status = "FAIL" + report.status_extended = f"CloudFront Distribution {distribution.id} has non-existent S3 buckets as origins: {','.join(non_existent_buckets)}." + + findings.append(report) + + return findings diff --git a/prowler/providers/aws/services/cloudfront/cloudfront_service.py b/prowler/providers/aws/services/cloudfront/cloudfront_service.py index d33edd4b94..f6d8f63365 100644 --- a/prowler/providers/aws/services/cloudfront/cloudfront_service.py +++ b/prowler/providers/aws/services/cloudfront/cloudfront_service.py @@ -36,7 +36,6 @@ class CloudFront(AWSService): origin_group.get("Members", {}).get("Quantity", 0) >= 2 for origin_group in origin_groups ) - default_certificate = item["ViewerCertificate"][ "CloudFrontDefaultCertificate" ] diff --git a/prowler/providers/aws/services/s3/s3_service.py b/prowler/providers/aws/services/s3/s3_service.py index a208c01686..fdf87d8ed3 100644 --- a/prowler/providers/aws/services/s3/s3_service.py +++ b/prowler/providers/aws/services/s3/s3_service.py @@ -442,6 +442,27 @@ class S3(AWSService): f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + def _head_bucket(self, bucket_name): + logger.info("S3 - Checking if bucket exists...") + try: + self.client.head_bucket(Bucket=bucket_name) + return True + except ClientError as error: + if error.response["Error"]["Message"] == "Not Found": + logger.warning( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return False + else: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return True + except Exception as error: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + class S3Control(AWSService): def __init__(self, provider): diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_custom_ssl_certificate/cloudfront_distributions_custom_ssl_certificate_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_custom_ssl_certificate/cloudfront_distributions_custom_ssl_certificate_test.py index 2c15423afe..bd7bb8dd05 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_custom_ssl_certificate/cloudfront_distributions_custom_ssl_certificate_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_custom_ssl_certificate/cloudfront_distributions_custom_ssl_certificate_test.py @@ -31,7 +31,7 @@ class Test_cloudfront_distributions_custom_ssl_certificate: def test_distribution_default_certificate(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -66,7 +66,7 @@ class Test_cloudfront_distributions_custom_ssl_certificate: def test_distribution_custom_certificate(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_default_root_object/cloudfront_distributions_default_root_object_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_default_root_object/cloudfront_distributions_default_root_object_test.py index dca7a2e3fd..71be6e2fa8 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_default_root_object/cloudfront_distributions_default_root_object_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_default_root_object/cloudfront_distributions_default_root_object_test.py @@ -35,7 +35,7 @@ class Test_cloudfront_distributions_default_root_object: def test_distribution_no_root_object(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -75,7 +75,7 @@ class Test_cloudfront_distributions_default_root_object: cloudfront_client = mock.MagicMock dro = "index.html" cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_field_level_encryption_enabled/cloudfront_distributions_field_level_encryption_enabled_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_field_level_encryption_enabled/cloudfront_distributions_field_level_encryption_enabled_test.py index af639bc63a..970f4b6ec2 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_field_level_encryption_enabled/cloudfront_distributions_field_level_encryption_enabled_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_field_level_encryption_enabled/cloudfront_distributions_field_level_encryption_enabled_test.py @@ -35,7 +35,7 @@ class Test_cloudfront_distributions_field_level_encryption_enabled: def test_one_distribution_field_level_encryption_enabled(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -75,7 +75,7 @@ class Test_cloudfront_distributions_field_level_encryption_enabled: def test_one_distribution_field_level_encryption_disabled(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_geo_restrictions_enabled/cloudfront_distributions_geo_restrictions_enabled_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_geo_restrictions_enabled/cloudfront_distributions_geo_restrictions_enabled_test.py index 46396b6ef6..0b64ad726e 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_geo_restrictions_enabled/cloudfront_distributions_geo_restrictions_enabled_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_geo_restrictions_enabled/cloudfront_distributions_geo_restrictions_enabled_test.py @@ -34,7 +34,7 @@ class Test_cloudfront_distributions_geo_restrictions_enabled: def test_one_distribution_geo_restriction_disabled(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -69,7 +69,7 @@ class Test_cloudfront_distributions_geo_restrictions_enabled: def test_one_distribution_geo_restriction_enabled_whitelist(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -105,7 +105,7 @@ class Test_cloudfront_distributions_geo_restrictions_enabled: def test_one_distribution_geo_restriction_enabled_blacklist(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_https_enabled/cloudfront_distributions_https_enabled_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_https_enabled/cloudfront_distributions_https_enabled_test.py index 44ac23ae36..7729b82f84 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_https_enabled/cloudfront_distributions_https_enabled_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_https_enabled/cloudfront_distributions_https_enabled_test.py @@ -35,7 +35,7 @@ class Test_cloudfront_distributions_https_enabled: def test_one_distribution_https_disabled(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -75,7 +75,7 @@ class Test_cloudfront_distributions_https_enabled: def test_one_distribution_https_redirect(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -115,7 +115,7 @@ class Test_cloudfront_distributions_https_enabled: def test_one_distribution_https_only(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_https_sni_enabled/cloudfront_distributions_https_sni_enabled_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_https_sni_enabled/cloudfront_distributions_https_sni_enabled_test.py index 7c2bfaeae1..a70735668a 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_https_sni_enabled/cloudfront_distributions_https_sni_enabled_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_https_sni_enabled/cloudfront_distributions_https_sni_enabled_test.py @@ -34,7 +34,7 @@ class Test_cloudfront_distributions_https_sni_enabled: def test_distribution_no_certificate(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -60,7 +60,7 @@ class Test_cloudfront_distributions_https_sni_enabled: def test_distribution_certificate_not_set_up(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -96,7 +96,7 @@ class Test_cloudfront_distributions_https_sni_enabled: def test_distribution_valid_configuration(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_logging_enabled/cloudfront_distributions_logging_enabled_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_logging_enabled/cloudfront_distributions_logging_enabled_test.py index 41c46cb822..4a084cf71a 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_logging_enabled/cloudfront_distributions_logging_enabled_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_logging_enabled/cloudfront_distributions_logging_enabled_test.py @@ -35,7 +35,7 @@ class Test_cloudfront_distributions_logging_enabled: def test_one_distribution_logging_enabled(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -70,7 +70,7 @@ class Test_cloudfront_distributions_logging_enabled: def test_one_distribution_logging_disabled_realtime_disabled(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -111,7 +111,7 @@ class Test_cloudfront_distributions_logging_enabled: def test_one_distribution_logging_disabled_realtime_enabled(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -152,7 +152,7 @@ class Test_cloudfront_distributions_logging_enabled: def test_one_distribution_logging_enabled_realtime_enabled(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_multiple_origin_failover_configured/cloudfront_distributions_multiple_origin_failover_configured_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_multiple_origin_failover_configured/cloudfront_distributions_multiple_origin_failover_configured_test.py index cc0ecd7bc3..eaf27e4ebb 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_multiple_origin_failover_configured/cloudfront_distributions_multiple_origin_failover_configured_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_multiple_origin_failover_configured/cloudfront_distributions_multiple_origin_failover_configured_test.py @@ -35,7 +35,7 @@ class Test_cloudfront_distributions_multiple_origin_failover_configured: def test_no_origin_failover(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -75,7 +75,7 @@ class Test_cloudfront_distributions_multiple_origin_failover_configured: def test_origin_failover(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_origin_traffic_encrypted/cloudfront_distributions_origin_traffic_encrypted_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_origin_traffic_encrypted/cloudfront_distributions_origin_traffic_encrypted_test.py index 0a43f4fdb5..4063794ee0 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_origin_traffic_encrypted/cloudfront_distributions_origin_traffic_encrypted_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_origin_traffic_encrypted/cloudfront_distributions_origin_traffic_encrypted_test.py @@ -37,7 +37,7 @@ class Test_cloudfront_distributions_origin_traffic_encrypted: cloudfront_client = mock.MagicMock id = "origin1" cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -86,7 +86,7 @@ class Test_cloudfront_distributions_origin_traffic_encrypted: cloudfront_client = mock.MagicMock id = "origin1" cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -134,7 +134,7 @@ class Test_cloudfront_distributions_origin_traffic_encrypted: cloudfront_client = mock.MagicMock id = "origin1" cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -182,7 +182,7 @@ class Test_cloudfront_distributions_origin_traffic_encrypted: def test_distribution_traffic_encrypted(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_access_control/cloudfront_distributions_s3_origin_access_control_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_access_control/cloudfront_distributions_s3_origin_access_control_test.py index 717262a325..c3de591a8c 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_access_control/cloudfront_distributions_s3_origin_access_control_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_access_control/cloudfront_distributions_s3_origin_access_control_test.py @@ -34,7 +34,7 @@ class Test_cloudfront_distributions_s3_origin_access_control: def test_no_s3_origin_distributions(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -66,7 +66,7 @@ class Test_cloudfront_distributions_s3_origin_access_control: def test_distribution_using_origin_access_control(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -112,7 +112,7 @@ class Test_cloudfront_distributions_s3_origin_access_control: cloudfront_client = mock.MagicMock id = "EXAMPLE-OAC-ID" cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket_test.py new file mode 100644 index 0000000000..e09dd1806f --- /dev/null +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_s3_origin_non_existent_bucket/cloudfront_distributions_s3_origin_non_existent_bucket_test.py @@ -0,0 +1,151 @@ +from unittest import mock + +from prowler.providers.aws.services.cloudfront.cloudfront_service import ( + Distribution, + Origin, +) +from prowler.providers.aws.services.s3.s3_service import Bucket +from tests.providers.aws.utils import AWS_ACCOUNT_NUMBER, AWS_REGION_EU_WEST_1 + +DISTRIBUTION_ID = "E27LVI50CSW06W" +DISTRIBUTION_ARN = ( + f"arn:aws:cloudfront::{AWS_ACCOUNT_NUMBER}:distribution/{DISTRIBUTION_ID}" +) + + +class Test_cloudfront_s3_origin_non_existent_bucket: + def test_no_distributions(self): + # Distributions + cloudfront_client = mock.MagicMock + cloudfront_client.distributions = {} + s3_client = mock.MagicMock + # Buckets + s3_client.buckets = {} + + with mock.patch( + "prowler.providers.aws.services.s3.s3_service.S3", new=s3_client + ), mock.patch( + "prowler.providers.aws.services.cloudfront.cloudfront_service.CloudFront", + new=cloudfront_client, + ): + # Test Check + from prowler.providers.aws.services.cloudfront.cloudfront_distributions_s3_origin_non_existent_bucket.cloudfront_distributions_s3_origin_non_existent_bucket import ( + cloudfront_distributions_s3_origin_non_existent_bucket, + ) + + check = cloudfront_distributions_s3_origin_non_existent_bucket() + result = check.execute() + + assert len(result) == 0 + + @mock.patch( + "prowler.providers.aws.services.s3.s3_service.S3._head_bucket", + new=mock.MagicMock(return_value=False), + ) + def test_distribution_nonexistent_origins(self): + # Distributions + domain = "nonexistent-bucket.s3.eu-west-1.amazonaws.com" + cloudfront_client = mock.MagicMock + cloudfront_client.distributions = { + DISTRIBUTION_ID: Distribution( + arn=DISTRIBUTION_ARN, + id=DISTRIBUTION_ID, + region=AWS_REGION_EU_WEST_1, + logging_enabled=True, + origins=[ + Origin( + domain_name=domain, + id="S3-ORIGIN", + origin_protocol_policy="", + origin_ssl_protocols=[], + ), + ], + ) + } + # Buckets + nonexistent_bucket = "nonexistent-bucket" + s3_client = mock.MagicMock + s3_client.buckets = {} + + with mock.patch( + "prowler.providers.aws.services.s3.s3_service.S3", new=s3_client + ), mock.patch( + "prowler.providers.aws.services.cloudfront.cloudfront_service.CloudFront", + new=cloudfront_client, + ): + # Test Check + from prowler.providers.aws.services.cloudfront.cloudfront_distributions_s3_origin_non_existent_bucket.cloudfront_distributions_s3_origin_non_existent_bucket import ( + cloudfront_distributions_s3_origin_non_existent_bucket, + ) + + check = cloudfront_distributions_s3_origin_non_existent_bucket() + result = check.execute() + + assert len(result) == 1 + assert result[0].region == AWS_REGION_EU_WEST_1 + assert result[0].resource_arn == DISTRIBUTION_ARN + assert result[0].resource_id == DISTRIBUTION_ID + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"CloudFront Distribution {DISTRIBUTION_ID} has non-existent S3 buckets as origins: {nonexistent_bucket}." + ) + + @mock.patch( + "prowler.providers.aws.services.s3.s3_service.S3._head_bucket", + new=mock.MagicMock(return_value=True), + ) + def test_distribution_no_nonexistent_origins(self): + # Distributions + domain = "existent-bucket.s3.eu-west-1.amazonaws.com" + cloudfront_client = mock.MagicMock + cloudfront_client.distributions = { + DISTRIBUTION_ID: Distribution( + arn=DISTRIBUTION_ARN, + id=DISTRIBUTION_ID, + region=AWS_REGION_EU_WEST_1, + logging_enabled=True, + origins=[ + Origin( + domain_name=domain, + id="S3-ORIGIN", + origin_protocol_policy="", + origin_ssl_protocols=[], + ), + ], + ) + } + # Buckets + bucket_name = "existent-bucket" + s3_client = mock.MagicMock + s3_client.audited_account = AWS_ACCOUNT_NUMBER + s3_client.buckets = { + f"arn:aws:s3:::{bucket_name}": Bucket( + name=bucket_name, + region=AWS_REGION_EU_WEST_1, + ) + } + + with mock.patch( + "prowler.providers.aws.services.s3.s3_service.S3", new=s3_client + ), mock.patch( + "prowler.providers.aws.services.cloudfront.cloudfront_service.CloudFront", + new=cloudfront_client, + ): + # Test Check + from prowler.providers.aws.services.cloudfront.cloudfront_distributions_s3_origin_non_existent_bucket.cloudfront_distributions_s3_origin_non_existent_bucket import ( + cloudfront_distributions_s3_origin_non_existent_bucket, + ) + + check = cloudfront_distributions_s3_origin_non_existent_bucket() + result = check.execute() + + assert len(result) == 1 + assert result[0].region == AWS_REGION_EU_WEST_1 + assert result[0].resource_arn == DISTRIBUTION_ARN + assert result[0].resource_id == DISTRIBUTION_ID + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"CloudFront Distribution {DISTRIBUTION_ID} does not have non-existent S3 buckets as origins." + ) diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_using_deprecated_ssl_protocols/cloudfront_distributions_using_deprecated_ssl_protocols_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_using_deprecated_ssl_protocols/cloudfront_distributions_using_deprecated_ssl_protocols_test.py index 201a717d76..4115abb17e 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_using_deprecated_ssl_protocols/cloudfront_distributions_using_deprecated_ssl_protocols_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_using_deprecated_ssl_protocols/cloudfront_distributions_using_deprecated_ssl_protocols_test.py @@ -34,7 +34,7 @@ class Test_cloudfront_distributions_using_deprecated_ssl_protocols: def test_one_distribution_using_deprecated_ssl_protocols(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -76,7 +76,7 @@ class Test_cloudfront_distributions_using_deprecated_ssl_protocols: def test_one_distribution_using_SSL_and_TLS(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -121,7 +121,7 @@ class Test_cloudfront_distributions_using_deprecated_ssl_protocols: def test_one_distribution_using_SSL_and_bad_TLS(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -166,7 +166,7 @@ class Test_cloudfront_distributions_using_deprecated_ssl_protocols: def test_one_distribution_not_using_deprecated_ssl_protocols(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/cloudfront/cloudfront_distributions_using_waf/cloudfront_distributions_using_waf_test.py b/tests/providers/aws/services/cloudfront/cloudfront_distributions_using_waf/cloudfront_distributions_using_waf_test.py index 260b342bcf..a901722f54 100644 --- a/tests/providers/aws/services/cloudfront/cloudfront_distributions_using_waf/cloudfront_distributions_using_waf_test.py +++ b/tests/providers/aws/services/cloudfront/cloudfront_distributions_using_waf/cloudfront_distributions_using_waf_test.py @@ -32,7 +32,7 @@ class Test_cloudfront_distributions_using_waf: wef_acl_id = "TEST-WAF-ACL" cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, @@ -68,7 +68,7 @@ class Test_cloudfront_distributions_using_waf: def test_one_distribution_no_waf(self): cloudfront_client = mock.MagicMock cloudfront_client.distributions = { - "DISTRIBUTION_ID": Distribution( + DISTRIBUTION_ID: Distribution( arn=DISTRIBUTION_ARN, id=DISTRIBUTION_ID, region=REGION, diff --git a/tests/providers/aws/services/s3/s3_service_test.py b/tests/providers/aws/services/s3/s3_service_test.py index 1e02f7cc3b..dc902b3437 100644 --- a/tests/providers/aws/services/s3/s3_service_test.py +++ b/tests/providers/aws/services/s3/s3_service_test.py @@ -2,6 +2,7 @@ import json from unittest.mock import patch import botocore +import botocore.exceptions from boto3 import client from moto import mock_aws @@ -478,6 +479,32 @@ class Test_S3_Service: assert s3.buckets[bucket_arn].lifecycle[0].id == "test" assert s3.buckets[bucket_arn].lifecycle[0].status == "Enabled" + # Test S3 Head Bucket + @mock_aws + @patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call) + def test_head_bucket(self): + # Generate S3 Client + s3_client = client("s3") + + # Create S3 Bucket + bucket_name = "test-bucket" + bucket_arn = f"arn:aws:s3:::{bucket_name}" + s3_client.create_bucket( + Bucket=bucket_name, + ObjectOwnership="BucketOwnerEnforced", + ObjectLockEnabledForBucket=True, + ) + + # S3 client for this test class + aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1]) + s3 = S3(aws_provider) + assert len(s3.buckets) == 1 + assert s3.buckets[bucket_arn].name == bucket_name + assert s3._head_bucket( + bucket_name=bucket_name, + ) + assert s3.buckets[bucket_arn].region == AWS_REGION_US_EAST_1 + # Test S3 List Access Points @patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call) @mock_aws