
Overview
This comprehensive guide demonstrates how to:
- Host static assets in an AWS S3 bucket;
- Serve them globally via CloudFront with an Origin Access Control (OAC);
- Enforce Basic Authentication at edge locations using Lambda@Edge;
- Secure access through precise IAM policies and example ARNs.
Step 1: Create and Secure Your S3 Bucket
1.1 Create a New S3 Bucket
- Console:
S3 → Create bucket
. - Bucket name:
your-docs-bucket
(must be globally unique). - Region:
us-east-1
(required for Lambda@Edge). - Uncheck Block all public access. We'll lock it down with CloudFront.
1.2 Configure Bucket Policy
Allow only CloudFront to fetch objects. Replace placeholders with your IDs:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "cloudfront.amazonaws.com" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-docs-bucket/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/EDFDVBD632BHDS5"
}
}
}
]
}
Explanation: This policy permits the CloudFront distribution with ARN arn:aws:cloudfront::123456789012:distribution/EDFDVBD632BHDS5
to read any object in the bucket.
Step 2: Set Up CloudFront Distribution
2.1 Create CloudFront Distribution
- Console:
CloudFront → Create distribution → Web
. - Origin domain:
your-docs-bucket.s3.amazonaws.com
. - Origin access: Select Create origin access control.
- Viewer Protocol Policy: Redirect HTTP to HTTPS.
- Alternate Domain Name:
docs.example.com
. - SSL Certificate: Choose ACM certificate in
us-east-1
. - Cache Behavior: Use CachingOptimized or custom policy.
2.2 Configure Origin Access Control (OAC)
- After distribution creation, go to
Origins
tab. - Select your origin → Edit → Origin access → Apply the new OAC.
- This replaces legacy Origin Access Identity (OAI).
Automatic update: CloudFront will update the bucket policy OAC principal automatically if you choose that option.
2.3 Example CloudFront Resource ARN
arn:aws:cloudfront::123456789012:distribution/EDFDVBD632BHDS5
Step 3: Implement Basic Authentication with Lambda@Edge
3.1 Create IAM Role for Lambda@Edge
The Lambda function needs a role that trusts both Lambda service and CloudFront:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": ["lambda.amazonaws.com","edgelambda.amazonaws.com"] },
"Action": "sts:AssumeRole"
}
]
}
Name: lambda-edge-basic-auth-role
3.2 Attach Execution Policy
Grant CloudWatch Logs access for debugging:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],
"Resource": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/basic-auth*"
}
]
}
3.3 Create Lambda@Edge Function
- Console:
Lambda → Create function → Author from scratch
. - Name:
basic-auth-edge
, Runtime: Node.js 18.x, Region:us-east-1
. - Attach Role:
lambda-edge-basic-auth-role
.
Use this code:
'use strict'; exports.handler = async (event) => { const request = event.Records[0].cf.request; const headers = request.headers; const username = 'admin'; const password = 'P@ssw0rd!'; const authHeader = 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'); if (!headers.authorization || headers.authorization[0].value !== authHeader) { return { status: '401', statusDescription: 'Unauthorized', headers: { 'www-authenticate': [{ key: 'WWW-Authenticate', value: 'Basic realm="Docs"' }] } }; } return request; };
3.4 Publish and Version Lambda
- In Lambda console, go to Actions → Publish new version.
- Enter description: Initial BasicAuth v1.
- Note the version ARN:
arn:aws:lambda:us-east-1:123456789012:function:basic-auth-edge:1
.
3.5 Attach Lambda@Edge to CloudFront
- CloudFront → Distributions → Edit behavior → Function associations.
- Select Viewer Request and paste the version ARN
:1
. - Save and deploy. Edge locations will propagate in minutes.
Step 4: Final Verification
- Visit
https://docs.example.com
. You should see a Basic Auth prompt. - Enter credentials
admin/P@ssw0rd!
to proceed. - Attempt direct S3 URL:
https://your-docs-bucket.s3.amazonaws.com/index.html
(should be Access Denied).
Final Notes
Your setup is now:
- Scalable S3 storage with hidden public access
- Global CloudFront CDN with HTTPS
- Edge-level Basic Authentication
Security Tip: Rotate your Basic Auth credentials periodically and monitor CloudFront logs (S3 bucket logs or Lambda@Edge logs) for unauthorized attempts.
Need Expert Help?
We’re here to support you and manage your tasks.