Enhancing Your API Security with CloudFront and AWS Managed Prefix Lists
- 3 days ago
- 5 min read
Introduction
When deploying APIs on AWS using Application Load Balancers (ALB), it is common to configure Security Groups to allow HTTP/HTTPS traffic from any source (0.0.0.0/0). While this works, it violates the principle of least privilege and exposes your infrastructure to unnecessary risks.
In this article, I’ll show you how to improve your API security by using CloudFront as a distribution layer and restricting access to your ALB so that it only accepts traffic from CloudFront IPs through AWS Managed Prefix Lists.
Current Architecture (Insecure)

Our initial infrastructure includes:
VPC: 10.100.0.0/16 with public and private subnets across 2 AZs.
Application Load Balancer: Internet-facing, deployed in public subnets
EC2 Instance: Running Nginx in a private subnet.
CloudFront: Distribution with a custom domain testmauro.sandbox.teratest.net
Route53: DNS pointing to CloudFront.
ACM Certificate: SSL/TLS certificate for the custom domain.
The Security Issue
Currently, the ALB Security Group is configured as follows:
{
"IpProtocol": "tcp",
"FromPort": 80,
"ToPort": 80,
"CidrIpv4": "0.0.0.0/0"
}
What does this mean?
Anyone on the internet can directly access the ALB.
CloudFront and its benefits (caching, DDoS protection, WAF) can be bypassed.
There is no control over who can access your origin.
Validating the Issue
Test 1: Direct Access to the ALB
Let’s try accessing the ALB directly without going through CloudFront:
curl -s -o /dev/null -w "Status: %{http_code}\n" \ http://demo-sbx-alb-142673723.us-east-1.elb.amazonaws.com
Result:
Status: 200
The ALB responds successfully — this is a security issue.
Test 2: Accessible Content
Result:
<!DOCTYPE html>
<html>
<head>
<title>Teratest</title>
</head>
<body>
<h1>Hola desde teratest</h1>
</body>
</html>
The full content is accessible without any restrictions.
Test 3: Access via CloudFront
Both paths work, but only CloudFront should be the entry point.

Security Group Analysis
Let’s inspect the current rules of the ALB Security Group:
aws ec2 describe-security-group-rules \
--filters Name=group-id,Values=sg-0482d99e7921588bc \
--profile teracloud-sbx --region us-east-1
Current Rules:
Type | Protocol | Port | Source | Description |
Ingress | TCP | 80 | 0.0.0.0/0 | Entire internet |
Egress | All | All | 0.0.0.0/0 | Unrestricted outbound |
Why is this a problem?
CloudFront bypass: Attackers can discover the ALB URL and access it directly.
No DDoS protection: CloudFront includes AWS Shield Standard, but it gets bypassed.
No WAF protection: If you configure AWS WAF on CloudFront, it won’t apply to direct traffic.
No caching: Every request hits your origin directly.
Higher costs: You pay more for data transfer from the ALB compared to CloudFront.
Compliance violation: Many security frameworks require the principle of least privilege.
Hardening Implementation
In the following section, we will implement the following improvements:
Identify the CloudFront Managed Prefix List for the region.
Remove the insecure 0.0.0.0/0 rule from the Security Group.
Add a rule allowing only the CloudFront Prefix List.
Validate that direct access to the ALB fails.
Confirm that access via CloudFront continues to work.
Improved architecture (secure)

Secure Traffic Flow:
User → CloudFront (HTTPS) → ALB (HTTP, only from CloudFront IPs) → EC2
Blocked Flow:
User → Direct ALB access ❌ BLOCKED
Infrastructure Resources
All infrastructure was created in AWS account 208619972546 (region us-east-1):
VPC: vpc-0e56f6e80dd047044.
Security Group ALB: sg-0482d99e7921588bc.
CloudFront Distribution: EYE32G0U68ZU6.
Domain: testmauro.sandbox.teratest.net.
Next steps
In the next part of this article, we will implement the security hardening and validate that:
Direct access to the ALB is blocked.
Access via CloudFront works correctly.
The configuration complies with the principle of least privilege.
Part 2: Hardening Implementation
Step 1: Identify the CloudFront Managed Prefix List
AWS provides Managed Prefix Lists for CloudFront services. First, we need to identify the prefix list ID:
aws ec2 describe-managed-prefix-lists \
--filters "Name=prefix-list-name,Values=com.amazonaws.global.cloudfront.origin-facing" \
--region us-east-1

Step 2: Modify the Security Group
Now we will modify the ALB Security Group to: Remove the insecure rule that allows 0.0.0.0/0 and add a new rule that only allows the CloudFront Prefix List
Command to remove the insecure rule:
aws ec2 revoke-security-group-ingress \
--group-id sg-0482d99e7921588bc \
--ip-permissions IpProtocol=tcp,FromPort=80,ToPort=80,IpRanges='[{CidrIp=0.0.0.0/0}]' \
--region us-east-1
Command to add the secure rule:
aws ec2 authorize-security-group-ingress \
--group-id sg-0482d99e7921588bc \
--ip-permissions IpProtocol=tcp,FromPort=80,ToPort=80,PrefixListIds='[{PrefixListId=<PREFIX_LIST_ID>}]' \
--region us-east-1
Step 3: Post-Hardening Validation
Test 1: Direct access to the ALB (should fail)
Expected result:
Status: 000curl: (28) Connection timed out
Direct access is now blocked — Success!

Test 2: Access via CloudFront (should work)
curl -s -o /dev/null -w "Status: %{http_code}\n" \
Expected result:
Status: 200
CloudFront works correctly — the application remains accessible through the proper path.

Test 3: Verify content
Result:
<!DOCTYPE html>
<html>
<head>
<title>Teratest</title>
</head>
<body>
<h1>Hola desde teratest</h1>
</body>
</html>
The content is served correctly through CloudFront.

Step 4: Inspect the New Rules
aws ec2 describe-security-group-rules \
--filters Name=group-id,Values=sg-0482d99e7921588bc \
--region us-east-1
Updated rules:
Type | Protocol | Port | Source | Description |
Ingress | TCP | 80 | pl-xxxxxx (CloudFront) | Only CloudFront |
Egress | All | All | 0.0.0.0/0 | Unrestricted outbound |
Comparison: before vs after
Before (insecure)

After (secure)

Benefits Achieved
Security
Principle of least privilege: Only CloudFront can access the ALB.
DDoS protection: AWS Shield Standard protects CloudFront.
WAF ready: You can add AWS WAF at the CloudFront level.
Origin obfuscation: The ALB URL is not useful for attackers.
Performance
Global caching: Content is served from edge locations.
Lower latency: Users access from the nearest edge location.
Compression: CloudFront automatically compresses content.
Cost
Reduced origin transfer: CloudFront caches content.
Free tier: 50GB/month + 2M requests free for 12 months.
Request optimization: Less load on the ALB and EC2.
Operational
No IP maintenance: AWS automatically updates the Prefix List.
Auditable: All changes are tracked in CloudTrail.
Compliance: Aligns with security frameworks (CIS, NIST).
Additional Considerations
1. Custom headers for enhanced security
You can add a custom header in CloudFront that the ALB validates.
{
"CustomHeaders": {
"Quantity": 1,
"Items": [{
"HeaderName": "X-Custom-Secret",
"HeaderValue": "tu-secreto-aleatorio"
}]
}
}
Then, configure the ALB to reject requests that do not include this header.
2. Monitoring and alerts
Configure CloudWatch Alarms to detect:
Direct access attempts to the ALB (even if they are blocked)
Changes to the Security Group
CloudFront distribution being disabled
3. Multiple origins
If you have multiple ALBs or origins, all of them should use the same CloudFront Prefix List.
4. IPv6
The CloudFront Managed Prefix List includes both IPv4 and IPv6. Make sure your VPC and ALB support IPv6 if needed.
Conclusion
Implementing the principle of least privilege in AWS doesn’t have to be complex. By using AWS Managed Prefix Lists for CloudFront, we can:
Restrict access to the ALB to CloudFront only.
Eliminate unnecessary exposure to the internet.
Keep the configuration automatically up to date.
Improve security, performance, and cost efficiency.
This configuration is especially important for:
Public APIs
Web applications with static content
Environments that require compliance (PCI-DSS, HIPAA, SOC 2)
Multi-region architectures
Resources

Mauro Rosales
Cloud Engineer



