DEV Community

Randika Madhushan Perera
Randika Madhushan Perera

Posted on • Edited on

Configuring AWS WAF, CloudFront, and S3 Bucket for Secure Access

How to Set Up AWS WAF, CloudFront and an S3 Bucket to serve content securely and Restrict content Access to certain originating sources only. This guide looks at some issues, for instance, 403 Forbidden, in order to troubleshoot the problem.

1. Objective

The purpose of this assignment is to deploy AWS WAF, CloudFront and S3 bucket:

  • Restrict Access to certain origins, for example, https://dev.test.com and https://int.test.com.
  • When the CloudFront distribution is accessed, the index.html page should be served by default.
  • To prevent unauthorized access and to correct common errors.

2. You will require.

And AWS S3 bucket called, sample-bucket, where the files for the static website are stored.

An AWS CloudFront distribution created with OAC linked to the S3 bucket.

3. Configuration Steps

Step 1: Make Sure S3 Bucket Policy has below

  1. Open the S3 Console.
  2. Select your bucket (e.g., sample-bucket).
  3. Check the following bucket policy to allow access from CloudFront:
{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::sample-bucket/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::AWS_ACC_ID:distribution/CLOUDFRONT_ID"
                }
            }
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure CORS for the S3 Bucket

  1. In the S3 Console, go to the Permissions tab.
  2. Edit the CORS configuration and set the following:
[
    {
        "AllowedHeaders": ["*"],
        "AllowedMethods": ["GET", "HEAD", "PUT", "POST", "DELETE"],
        "AllowedOrigins": [
            "https://dev.test.com",
            "https://int.test.com"
        ]
    }
]
Enter fullscreen mode Exit fullscreen mode
  • Replace AllowedOrigins with your allowed domains.
  • Restrict AllowedHeaders to necessary headers for production.

Step 3: Configure AWS WAF

Create WAF Rules:

  1. Open the AWS WAF Console and select your Web ACL.
  2. Add the following rules:

Rule 1: Allow-Traffic

  • Description: Allows requests from specific origins.
  • Rule Definition:
{
    "Name": "Allow-Traffic",
    "Priority": 1,
    "Statement": {
        "OrStatement": {
            "Statements": [
                {
                    "ByteMatchStatement": {
                        "SearchString": "https://dev.test.com",
                        "FieldToMatch": {
                            "SingleHeader": {
                                "Name": "origin"
                            }
                        },
                        "TextTransformations": [
                            {
                                "Priority": 0,
                                "Type": "NONE"
                            }
                        ],
                        "PositionalConstraint": "EXACTLY"
                    }
                },
                {
                    "ByteMatchStatement": {
                        "SearchString": "https://int.test.com",
                        "FieldToMatch": {
                            "SingleHeader": {
                                "Name": "origin"
                            }
                        },
                        "TextTransformations": [
                            {
                                "Priority": 0,
                                "Type": "NONE"
                            }
                        ],
                        "PositionalConstraint": "EXACTLY"
                    }
                }
            ]
        }
    },
    "Action": {
        "Allow": {}
    },
    "VisibilityConfig": {
        "SampledRequestsEnabled": true,
        "CloudWatchMetricsEnabled": true,
        "MetricName": "Allow-Traffic"
    }
}
Enter fullscreen mode Exit fullscreen mode

Rule 2: Block-All-Other-Traffic

  • Description: Blocks all requests that don’t match the allowed origins.
  • Rule Definition:
{
    "Name": "Block-All-Other-Traffic",
    "Priority": 2,
    "Statement": {
        "NotStatement": {
            "Statement": {
                "OrStatement": {
                    "Statements": [
                        {
                            "ByteMatchStatement": {
                                "SearchString": "https://dev.test.com",
                                "FieldToMatch": {
                                    "SingleHeader": {
                                        "Name": "origin"
                                    }
                                },
                                "TextTransformations": [
                                    {
                                        "Priority": 0,
                                        "Type": "NONE"
                                    }
                                ],
                                "PositionalConstraint": "EXACTLY"
                            }
                        },
                        {
                            "ByteMatchStatement": {
                                "SearchString": "https://int.test.com",
                                "FieldToMatch": {
                                    "SingleHeader": {
                                        "Name": "origin"
                                    }
                                },
                                "TextTransformations": [
                                    {
                                        "Priority": 0,
                                        "Type": "NONE"
                                    }
                                ],
                                "PositionalConstraint": "EXACTLY"
                            }
                        }
                    ]
                }
            }
        }
    },
    "Action": {
        "Block": {}
    },
    "VisibilityConfig": {
        "SampledRequestsEnabled": true,
        "CloudWatchMetricsEnabled": true,
        "MetricName": "Block-All-Other-Traffic"
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Testing and Verification

Test Allowed Origins

Run the following command:

curl -X GET https://cloudfront_domain_name \
     -H "Origin: https://dev.test.com" \
     -v
Enter fullscreen mode Exit fullscreen mode

Expected Result: HTTP 200 OK.

Test Disallowed Origins

Run the following command:

curl -X GET https://cloudfront_domain_name \
     -H "Origin: https://unauthorized.com" \
     -v
Enter fullscreen mode Exit fullscreen mode

Expected Result: HTTP 403 Forbidden.

Check WAF Logs

  1. Enable logging for the Web ACL in the AWS WAF Console.
  2. Monitor logs in CloudWatch to verify rule matches.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →

Top comments (0)

Image of Timescale

Timescale – the developer's data platform for modern apps, built on PostgreSQL

Timescale Cloud is PostgreSQL optimized for speed, scale, and performance. Over 3 million IoT, AI, crypto, and dev tool apps are powered by Timescale. Try it free today! No credit card required.

Try free