| name | aws-cloudformation-cloudfront |
| description | AWS CloudFormation patterns for CloudFront distributions, origins (ALB, S3, Lambda@Edge, VPC Origins), CacheBehaviors, Functions, SecurityHeaders, parameters, Outputs and cross-stack references. Use when creating CloudFront distributions with CloudFormation, configuring multiple origins, implementing caching strategies, managing custom domains with ACM, configuring WAF, and optimizing performance. |
| category | aws |
| tags | ["aws","cloudformation","cloudfront","cdn","content-delivery","distributions","origins","cache","waf","security"] |
| version | 1.0.0 |
| allowed-tools | Read, Write, Bash |
AWS CloudFormation CloudFront CDN
Overview
Create production-ready CDN infrastructure using AWS CloudFormation templates. This skill covers CloudFront distributions, multiple origins (ALB, S3, Lambda@Edge, VPC Origins), CacheBehaviors, Functions, SecurityHeaders, and best practices for parameters, outputs, and cross-stack references.
When to Use
Use this skill when:
- Creating new CloudFront distributions with CloudFormation
- Configuring multiple origins (ALB, S3, API Gateway, Lambda@Edge, VPC Origins)
- Implementing caching strategies with CacheBehaviors and Cache Policies
- Configuring custom domains with ACM certificates
- Implementing SecurityHeaders (CSP, HSTS, XSS protection)
- Configuring CloudFront Functions and Lambda@Edge
- Managing Geo-restrictions and Price Classes
- Integrating WAF with CloudFront
- Organizing templates with Parameters, Outputs, Mappings, Conditions
- Implementing cross-stack references with export/import
- Using Transform for macros and reuse
CloudFormation Template Structure
Standard Format Base Template
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront distribution with multiple origins
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Distribution Configuration
Parameters:
- DomainName
- CertificateArn
- PriceClass
- Label:
default: Origin Settings
Parameters:
- OriginDomainName
- OriginPath
- OriginProtocolPolicy
Parameters:
DomainName:
Type: String
Default: cdn.example.com
Description: Custom domain name for CloudFront distribution
CertificateArn:
Type: AWS::ACM::Certificate::Arn
Description: ACM certificate
[ , ]
[ [ , ]]
[, , ]
Best Practices for Parameters
AWS-Specific Parameter Types
Parameters:
CertificateArn:
Type: AWS::ACM::Certificate::Arn
Description: ACM certificate for the domain
StaticAssetsBucket:
Type: AWS::S3::Bucket
Description: S3 bucket for static assets
StaticAssetsBucketDomainName:
Type: AWS::S3::Bucket::RegionalDomainName
Description: Regional domain name of the S3 bucket
LoadBalancerArn:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer::Arn
Description: ARN of the Application Load Balancer
LoadBalancerDNSName:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer::DnsName
Description: DNS name of the ALB
Parameter Constraints
Parameters:
DomainName:
Type: String
Default: cdn.example.com
Description: Custom domain name for CloudFront
ConstraintDescription: Must be a valid domain name
MinLength: 4
MaxLength: 253
AllowedPattern: "[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*"
PriceClass:
Type: String
Default: PriceClass_All
Description: CloudFront price class
AllowedValues:
- PriceClass_All
- PriceClass_100
- PriceClass_200
DefaultTTL:
Type: Number
Default: 86400
Description: Default cache TTL in seconds
MinValue: 0
MaxValue:
SSM Parameter References
Parameters:
WafWebAclArn:
Type: AWS::SSM::Parameter::Value<String>
Default: /cloudfront/waf-webacl-arn
Description: WAF Web ACL ARN from Parameter Store
CloudFrontKeyId:
Type: AWS::SSM::Parameter::Value<String>
Default: /cloudfront/keys/cloudfront-key-id
Description: CloudFront key pair ID for signed URLs
Outputs and Cross-Stack References
Export/Import Patterns
AWSTemplateFormatVersion: 2010-09-09
Description: Infrastructure stack exporting CloudFront resources
Resources:
StaticAssetsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "static-assets-${AWS::AccountId}-${AWS::Region}"
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
VersioningConfiguration:
Status: Enabled
CorsConfiguration:
CorsRules:
- AllowedHeaders:
- "*"
AllowedMethods:
- GET
- HEAD
AllowedOrigins:
-
AWSTemplateFormatVersion: 2010-09-09
Description: Application stack importing from infrastructure stack
Parameters:
InfrastructureStackName:
Type: String
Default: infrastructure-stack
Description: Name of the infrastructure stack
DomainName:
Type: String
Default: cdn.example.com
Description: Custom domain name
CertificateArn:
Type: AWS::ACM::Certificate::Arn
Description: ACM certificate ARN
Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
CallerReference: !Sub "${AWS::StackName}-${AWS::AccountId}"
Comment: !Sub "CloudFront for ${DomainName}"
Enabled: true
Nested Stacks for Modularity
AWSTemplateFormatVersion: 2010-09-09
Description: Main stack with nested CloudFront stacks
Resources:
StaticAssetsDistributionStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/cloudfront-static.yaml
TimeoutInMinutes: 15
Parameters:
DomainName: !Ref DomainName
CertificateArn: !Ref CertificateArn
StaticAssetsBucketName: !Ref StaticAssetsBucketName
Environment: !Ref Environment
ApiDistributionStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/bucket/cloudfront-api.yaml
TimeoutInMinutes: 15
Parameters:
DomainName: !Ref ApiDomainName
CertificateArn: !Ref CertificateArn
LoadBalancerDnsName: !Ref
S3 Origins
S3 Origin with OAI
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront distribution with S3 origin
Resources:
StaticBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "static-assets-${AWS::AccountId}-${AWS::Region}"
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
CloudFrontOAI:
Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
Properties:
CloudFrontOriginAccessIdentityConfig:
Comment: !Sub "OAI for ${StaticBucket}"
S3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref StaticBucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
S3 Origin with Origin Access Control (OAC)
Resources:
StaticBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "static-assets-oac-${AWS::AccountId}-${AWS::Region}"
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerPreferred
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
S3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref StaticBucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: cloudfront.amazonaws.com
Action: s3:GetObject
Resource: !Sub "${StaticBucket.Arn}/*"
Condition:
StringEquals:
AWS:SourceArn: !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/${CloudFrontDistribution}"
ALB Origins
Application Load Balancer Origin
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront with ALB origin
Resources:
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub "${AWS::StackName}-alb"
Scheme: internet-facing
SecurityGroups:
- !Ref ALBSecurityGroup
Subnets:
- !Ref PublicSubnet1
- !Ref PublicSubnet2
Type: application
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: ALB security group
VpcId: !Ref VPCId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
SourceSecurityGroupId: !Ref
Multiple Origins and CacheBehaviors
Multi-Origin with Path Patterns
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront with multiple origins and cache behaviors
Resources:
StaticAssetsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "static-assets-${AWS::AccountId}-${AWS::Region}"
CloudFrontOAI:
Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
Properties:
CloudFrontOriginAccessIdentityConfig:
Comment: !Sub "OAI for ${StaticAssetsBucket}"
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Sub "${AWS::StackName}-api-alb"
Scheme: internet-facing
SecurityGroups:
- !Ref ALBSecurityGroup
Subnets: !Ref PublicSubnets
Type: application
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Cache Policies
Managed Cache Policy
Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
CacheBehaviors:
- PathPattern: "/static/*"
TargetOriginId: StaticAssetsOrigin
ViewerProtocolPolicy: redirect-to-https
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
Compress: true
CachePolicyId: !Ref ManagedCachingOptimizedPolicyId
FunctionAssociations:
- FunctionARN: !GetAtt CloudFrontFunction.FunctionARN
EventType: viewer-request
- PathPattern: "/api/*"
TargetOriginId: ApiOrigin
ViewerProtocolPolicy: redirect-to-https
AllowedMethods:
- GET
- HEAD
- OPTIONS
Custom Cache Policy
Resources:
StaticAssetsCachePolicy:
Type: AWS::CloudFront::CachePolicy
Properties:
CachePolicyConfig:
Name: !Sub "${AWS::StackName}-static-assets-policy"
DefaultTTL: 86400
MaxTTL: 31536000
MinTTL: 0
ParametersInCacheKeyAndForwardedToOrigin:
CookiesConfig:
CookieBehavior: none
HeadersConfig:
HeaderBehavior: none
QueryStringsConfig:
QueryStringBehavior: none
EnableAcceptEncodingBrotli: true
EnableAcceptEncodingGzip: true
ApiCachePolicy:
Type: AWS::CloudFront::CachePolicy
Properties:
CachePolicyConfig:
Name: !Sub "${AWS::StackName}-api-cache-policy"
DefaultTTL: 300
MaxTTL: 600
MinTTL: 60
ParametersInCacheKeyAndForwardedToOrigin:
CookiesConfig:
CookieBehavior: all
Origin Request Policies
Resources:
StaticAssetsOriginRequestPolicy:
Type: AWS::CloudFront::OriginRequestPolicy
Properties:
OriginRequestPolicyConfig:
Name: !Sub "${AWS::StackName}-static-assets-origin-request"
CookiesConfig:
CookieBehavior: none
HeadersConfig:
HeaderBehavior: none
QueryStringsConfig:
QueryStringBehavior: none
ApiOriginRequestPolicy:
Type: AWS::CloudFront::OriginRequestPolicy
Properties:
OriginRequestPolicyConfig:
Name: !Sub "${AWS::StackName}-api-origin-request"
CookiesConfig:
CookieBehavior: all
HeadersConfig:
HeaderBehavior: whitelist
Headers:
- Authorization
- Content-Type
- X-Request-ID
QueryStringsConfig:
QueryStringBehavior: all
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Response Headers Policies (Security Headers)
Resources:
SecurityHeadersPolicy:
Type: AWS::CloudFront::ResponseHeadersPolicy
Properties:
ResponseHeadersPolicyConfig:
Name: !Sub "${AWS::StackName}-security-headers"
SecurityHeadersConfig:
ContentTypeOptions:
Override: true
FrameOptions:
FrameOption: DENY
Override: true
ReferrerPolicy:
ReferrerPolicy: strict-origin-when-cross-origin
Override: true
StrictTransportSecurity:
AccessControlMaxAgeSec: 31536000
IncludeSubdomains: true
Override: true
Preload: true
XSSProtection:
ModeBlock: true
Override: true
Protection: true
CorsConfig:
AccessControlAllowCredentials: false
AccessControlAllowHeaders:
Items:
- "*"
AccessControlAllowMethods:
CloudFront Functions
Viewer Request Function
Resources:
RewritePathFunction:
Type: AWS::CloudFront::Function
Properties:
Name: !Sub "${AWS::StackName}-rewrite-path"
FunctionCode: |
function handler(event) {
var request = event.request;
var uri = request.uri;
// Remove trailing slash
if (uri.endsWith('/')) {
request.uri = uri.substring(0, uri.length - 1);
}
// Add .html extension for HTML pages
if (!uri.includes('.') && !uri.endsWith('/')) {
request.uri = uri + '.html';
}
return request;
}
Runtime: cloudfront-js-1.0
AutoPublish: true
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
Lambda@Edge Functions
Resources:
LambdaEdgeFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Sub "${AWS::StackName}-lambda-edge"
Code:
S3Bucket: !Ref CodeBucket
S3Key: lambda/edge-function.zip
Handler: index.handler
Runtime: nodejs20.x
Role: !GetAtt LambdaEdgeRole.Arn
LambdaEdgeVersion:
Type: AWS::Lambda::Version
Properties:
FunctionName: !Ref LambdaEdgeFunction
Description: Lambda@Edge version
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- Id: Origin
DomainName: !Ref OriginDomainName
CustomOriginConfig:
HTTPPort: 443
HTTPSPort: 443
OriginProtocolPolicy:
Geo-Restrictions and Price Class
Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
CallerReference: !Sub "${AWS::StackName}-${AWS::AccountId}"
Comment: !Sub "CloudFront with geo restrictions"
Enabled: true
IPV6Enabled: true
PriceClass: PriceClass_200
GeoRestriction:
RestrictionType: whitelist
Locations:
- US
- CA
- GB
- DE
- FR
- IT
- JP
- AU
Origins:
- Id: Origin
DomainName: !Ref OriginDomainName
CustomOriginConfig:
HTTPPort: 443
HTTPSPort: 443
WAF Integration
Resources:
CloudFrontWebACL:
Type: AWS::WAFv2::WebACL
Properties:
Name: !Sub "${AWS::StackName}-waf-acl"
Scope: CLOUDFRONT
DefaultAction:
Allow: {}
Rules:
- Name: AWSCommonRule
Priority: 1
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesCommonRuleSet
ExcludedRules:
- Name: SizeRestrictions_BODY
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: AWSCommonRule
- Name: RateLimitRule
Priority: 2
Statement:
RateBasedStatementKey:
SingleHeader:
Name: ip
{}
{}
{}
{}
{}
{}
{}
Real-Time Logs
Resources:
CloudFrontLogsStream:
Type: AWS::Kinesis::Stream
Properties:
Name: !Sub "${AWS::StackName}-cloudfront-logs"
ShardCount: 1
RetentionPeriodHours: 24
CloudFrontLoggingRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${AWS::StackName}-cloudfront-logging"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: cloudfront.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: KinesisPutRecord
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- kinesis:PutRecord
- kinesis:PutRecords
Resource:
Conditions and Transform
Conditions for Environment-Specific Configuration
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront with conditional configuration
Parameters:
Environment:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- production
Description: Deployment environment
EnableWAF:
Type: String
Default: false
AllowedValues:
- true
- false
Description: Enable WAF protection
Conditions:
IsProduction: !Equals [!Ref Environment, production]
IsStaging: !Equals [!Ref Environment, staging]
EnableWAFProtection: !And
- !Equals [!Ref EnableWAF, true]
-
[ [ , ]]
[ [ , ]]
[, , ]
[, , ]
[, , ]
[, , ]
[, , ]
[, , ]
[, , ]
{}
[]
VPC Origins
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront with VPC Origin
Resources:
VPCOriginEndpoint:
Type: AWS::GlobalAccelerator::EndpointGroup
Properties:
EndpointGroupRegion: !Ref VPCOriginRegion
ListenerArn: !Ref AcceleratorListener
EndpointConfigurations:
- EndpointId: !Ref VPCEndpointService
Weight: 128
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
CallerReference: !Sub "${AWS::StackName}-${AWS::AccountId}"
Comment: !Sub "CloudFront with VPC Origin"
Enabled: true
IPV6Enabled: true
Origins:
- Id: VPCOrigin
DomainName: !Ref VPCOriginDomain
CustomOriginConfig:
HTTPPort:
Best Practices
Security
- Always use HTTPS with minimum TLS 1.2
- Implement SecurityHeaders with HSTS, XSS protection
- Use WAF for protection against common attacks
- Configure appropriate Access-Control for CORS
- Limit origin access with OAI/OAC
- Use Signed URLs for private content
- Implement rate limiting
- Configure geo-restrictions if needed
Performance
- Use appropriate PriceClass to optimize costs
- Configure Cache TTL based on content type
- Enable compression (Gzip/Brotli)
- Use CloudFront Functions for lightweight operations
- Optimize header forwarding (do not forward unnecessary headers)
- Consider Origin Shield to reduce load on origins
- Use multiple origins with path patterns
Monitoring
- Enable CloudWatch metrics and alarms
- Configure real-time logs for troubleshooting
- Monitor cache hit ratio
- Configure alerts for error rate and latency
- Use CloudFront reports for traffic analysis
Deployment
- Use change sets before deployment
- Test templates with cfn-lint
- Organize stacks by lifecycle and ownership
- Implement blue/green deployments with weighted aliases
- Use StackSets for multi-region deployment
CloudFormation Best Practices
Stack Policies
Stack Policies prevent accidental updates to critical resources during stack updates.
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront distribution with stack policy
Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
CloudFrontWebACL:
Type: AWS::WAFv2::WebACL
Properties:
Name: !Sub "${AWS::StackName}-waf"
Scope: CLOUDFRONT
DefaultAction:
Allow: {}
Rules: []
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: CloudFrontWAF
Metadata:
AWS::CloudFormation::StackPolicy:
Statement:
- Effect: Allow
Action: Update:*
Resource: "*"
- Effect: Deny
Action:
Termination Protection
Enable termination protection to prevent accidental stack deletion.
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront with termination protection
Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Drift Detection
Detect when infrastructure has been modified outside of CloudFormation.
aws cloudformation detect-stack-drift --stack-name my-cloudfront-stack
aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id <detection-id>
aws cloudformation describe-stack-resource-drifts --stack-name my-cloudfront-stack
Change Sets
Preview and review changes before executing stack updates.
aws cloudformation create-change-set \
--stack-name my-cloudfront-stack \
--template-body file://cloudfront-template.yaml \
--change-set-name my-changeset \
--capabilities CAPABILITY_IAM \
--parameters ParameterKey=Environment,ParameterValue=production
aws cloudformation describe-change-set \
--stack-name my-cloudfront-stack \
--change-set-name my-changeset
aws cloudformation execute-change-set \
--stack-name my-cloudfront-stack \
--change-set-name my-changeset
aws cloudformation delete-change-set \
--stack-name my-cloudfront-stack \
--change-set-name my-changeset
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront infrastructure with nested stacks for change set management
Resources:
CloudFrontParentStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub "https://${ArtifactBucket}.s3.amazonaws.com/cloudfront-parent.yaml"
TimeoutInMinutes: 30
Parameters:
Environment: !Ref Environment
CertificateArn: !Ref CertificateArn
DomainName: !Ref DomainName
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Project
Value: !Ref ProjectName
- Key: ManagedBy
Value: CloudFormation
Related Resources
Additional Files
For complete details on resources and their properties, see:
- REFERENCE.md - Detailed reference guide for all CloudFormation resources
- EXAMPLES.md - Complete production-ready examples