Claude-skill-registry aws-cloudformation-cloudfront
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.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/aws-cloudformation-cloudfront" ~/.claude/skills/majiayu000-claude-skill-registry-aws-cloudformation-cloudfront && rm -rf "$T"
skills/data/aws-cloudformation-cloudfront/SKILL.mdAWS 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 ARN for HTTPS PriceClass: Type: String Default: PriceClass_All AllowedValues: - PriceClass_All - PriceClass_100 - PriceClass_200 Description: CloudFront price class OriginDomainName: Type: String Description: Domain name of the origin (ALB or S3) OriginPath: Type: String Default: "" Description: Optional origin path Mappings: EnvironmentConfig: us-east-1: CertificateRegion: us-east-1 other: CertificateRegion: us-east-1 Conditions: IsUsEast1: !Equals [!Ref AWS::Region, us-east-1] HasOriginPath: !Not [!Equals [!Ref OriginPath, ""]] Transform: - AWS::Serverless-2016-10-31 Resources: # CloudFront Distribution CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: CallerReference: !Sub "${AWS::StackName}-${AWS::AccountId}" Comment: !Sub "CloudFront distribution for ${DomainName}" DomainNames: - !Ref DomainName Enabled: true PriceClass: !Ref PriceClass IPV6Enabled: true DefaultRootObject: index.html Origins: - Id: !Sub "${DomainName}-origin" DomainName: !Ref OriginDomainName OriginPath: !If [HasOriginPath, !Ref OriginPath, !Ref AWS::NoValue] CustomOriginConfig: HTTPPort: 80 HTTPSPort: 443 OriginProtocolPolicy: https-only OriginSSLProtocols: - TLSv1.2 DefaultCacheBehavior: TargetOriginId: !Sub "${DomainName}-origin" ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD CachedMethods: - GET - HEAD Compress: true ForwardedValues: QueryString: false Cookies: Forward: none MinTTL: 0 DefaultTTL: 86400 MaxTTL: 31536000 ViewerCertificate: AcmCertificateArn: !Ref CertificateArn MinimumProtocolVersion: TLSv1.2_2021 SslSupportMethod: sni-only Outputs: DistributionDomainName: Description: CloudFront distribution domain name Value: !GetAtt CloudFrontDistribution.DomainName Export: Name: !Sub "${AWS::StackName}-DistributionDomainName" DistributionId: Description: CloudFront distribution ID Value: !Ref CloudFrontDistribution Export: Name: !Sub "${AWS::StackName}-DistributionId"
Best Practices for Parameters
AWS-Specific Parameter Types
Parameters: # ACM Certificate for domain CertificateArn: Type: AWS::ACM::Certificate::Arn Description: ACM certificate for the domain # S3 Bucket origins 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 # ALB origins 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 # Lambda function origins LambdaFunctionArn: Type: AWS::Lambda::Function::Arn Description: ARN of the Lambda function for Lambda@Edge # VPC Origin VPCOriginEndpoint: Type: AWS::GlobalAccelerator::Endpoint::EndpointId Description: VPC Origin endpoint ID # IAM Role for Lambda@Edge LambdaEdgeRoleArn: Type: AWS::IAM::Role::Arn Description: IAM role for Lambda@Edge execution
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: 31536000 ConstraintDescription: Must be between 0 and 31536000 seconds MaxTTL: Type: Number Default: 31536000 Description: Maximum cache TTL in seconds MinValue: 0 MaxValue: 31536000 MinTTL: Type: Number Default: 0 Description: Minimum cache TTL in seconds MinValue: 0 MaxValue: 31536000
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
# Stack A - Network/Infrastructure Stack AWSTemplateFormatVersion: 2010-09-09 Description: Infrastructure stack exporting CloudFront resources Resources: # S3 Bucket for static content 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: - "*" MaxAge: 3600 # OAI for CloudFront access CloudFrontOAI: Type: AWS::CloudFront::CloudFrontOriginAccessIdentity Properties: CloudFrontOriginAccessIdentityConfig: Comment: !Sub "OAI for ${StaticAssetsBucket}" Outputs: StaticAssetsBucketName: Description: S3 bucket name for static assets Value: !Ref StaticAssetsBucket Export: Name: !Sub "${AWS::StackName}-StaticAssetsBucketName" StaticAssetsBucketArn: Description: S3 bucket ARN Value: !GetAtt StaticAssetsBucket.Arn Export: Name: !Sub "${AWS::StackName}-StaticAssetsBucketArn" StaticAssetsBucketRegionalDomainName: Description: Regional domain name of the S3 bucket Value: !GetAtt StaticAssetsBucket.RegionalDomainName Export: Name: !Sub "${AWS::StackName}-StaticAssetsBucketRegionalDomainName" CloudFrontOAIId: Description: CloudFront OAI ID Value: !Ref CloudFrontOAI Export: Name: !Sub "${AWS::StackName}-CloudFrontOAIId" CloudFrontOAIArn: Description: CloudFront OAI ARN Value: !GetAtt CloudFrontOAI.Arn Export: Name: !Sub "${AWS::StackName}-CloudFrontOAIArn"
# Stack B - Application Stack (imports from Infrastructure Stack) 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 IPV6Enabled: true DefaultRootObject: index.html Origins: - Id: StaticAssetsOrigin DomainName: !ImportValue !Sub "${InfrastructureStackName}-StaticAssetsBucketRegionalDomainName" S3OriginConfig: OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${InfrastructureStackName}-CloudFrontOAIId" DefaultCacheBehavior: TargetOriginId: StaticAssetsOrigin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD CachedMethods: - GET - HEAD Compress: true ForwardedValues: QueryString: false Cookies: Forward: none MinTTL: 0 DefaultTTL: 86400 MaxTTL: 31536000 ViewerCertificate: AcmCertificateArn: !Ref CertificateArn MinimumProtocolVersion: TLSv1.2_2021 SslSupportMethod: sni-only
Nested Stacks for Modularity
AWSTemplateFormatVersion: 2010-09-09 Description: Main stack with nested CloudFront stacks Resources: # Nested stack for static assets distribution 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 # Nested stack for API distribution 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 LoadBalancerDnsName Environment: !Ref Environment
S3 Origins
S3 Origin with OAI
AWSTemplateFormatVersion: 2010-09-09 Description: CloudFront distribution with S3 origin Resources: # S3 Bucket StaticBucket: Type: AWS::S3::Bucket Properties: BucketName: !Sub "static-assets-${AWS::AccountId}-${AWS::Region}" PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true # CloudFront OAI CloudFrontOAI: Type: AWS::CloudFront::CloudFrontOriginAccessIdentity Properties: CloudFrontOriginAccessIdentityConfig: Comment: !Sub "OAI for ${StaticBucket}" # S3 Bucket Policy - Allow CloudFront OAI S3BucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref StaticBucket PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: CanonicalUser: !GetAtt CloudFrontOAI.S3CanonicalUserId Action: s3:GetObject Resource: !Sub "${StaticBucket.Arn}/*" - Effect: Deny Principal: "*" Action: s3:GetObject Resource: !Sub "${StaticBucket.Arn}/*" Condition: Bool: aws:SecureTransport: false # CloudFront Distribution CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: CallerReference: !Sub "${AWS::StackName}-${AWS::AccountId}" Comment: !Sub "Static assets CDN" Enabled: true IPV6Enabled: true Origins: - Id: S3Origin DomainName: !GetAtt StaticBucket.RegionalDomainName S3OriginConfig: OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOAI}" DefaultCacheBehavior: TargetOriginId: S3Origin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD CachedMethods: - GET - HEAD Compress: true ForwardedValues: QueryString: false Cookies: Forward: none MinTTL: 0 DefaultTTL: 86400 MaxTTL: 31536000 Outputs: DistributionDomainName: Value: !GetAtt CloudFrontDistribution.DomainName
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 # S3 Bucket Policy for OAC 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}" CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: Origins: - Id: S3Origin DomainName: !GetAtt StaticBucket.RegionalDomainName S3OriginConfig: OriginAccessIdentity: "" # For OAC, use OriginAccessControl instead of S3OriginConfig # but CloudFormation supports both
ALB Origins
Application Load Balancer Origin
AWSTemplateFormatVersion: 2010-09-09 Description: CloudFront with ALB origin Resources: # Application Load Balancer ApplicationLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: !Sub "${AWS::StackName}-alb" Scheme: internet-facing SecurityGroups: - !Ref ALBSecurityGroup Subnets: - !Ref PublicSubnet1 - !Ref PublicSubnet2 Type: application # ALB Security Group ALBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: ALB security group VpcId: !Ref VPCId SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: !Ref CloudFrontSecurityGroup - IpProtocol: tcp FromPort: 443 ToPort: 443 SourceSecurityGroupId: !Ref CloudFrontSecurityGroup # CloudFront Security Group (for ALB ingress) CloudFrontSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: CloudFront security group for ALB VpcId: !Ref VPCId SecurityGroupEgress: - IpProtocol: tcp FromPort: 80 ToPort: 80 DestinationSecurityGroupId: !Ref ALBSecurityGroup - IpProtocol: tcp FromPort: 443 ToPort: 443 DestinationSecurityGroupId: !Ref ALBSecurityGroup # CloudFront Distribution CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: CallerReference: !Sub "${AWS::StackName}-${AWS::AccountId}" Comment: !Sub "CloudFront with ALB origin" Enabled: true Origins: - Id: ALBOrigin DomainName: !GetAtt ApplicationLoadBalancer.DNSName CustomOriginConfig: HTTPPort: 80 HTTPSPort: 443 OriginProtocolPolicy: https-only OriginSSLProtocols: - TLSv1.2 DefaultCacheBehavior: TargetOriginId: ALBOrigin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD - OPTIONS CachedMethods: - GET - HEAD Compress: true ForwardedValues: QueryString: true Headers: - Origin - Access-Control-Request-Method - Access-Control-Request-Headers Cookies: Forward: all QueryStringSettings: - Name: "*" MinTTL: 0 DefaultTTL: 0 MaxTTL: 0
Multiple Origins and CacheBehaviors
Multi-Origin with Path Patterns
AWSTemplateFormatVersion: 2010-09-09 Description: CloudFront with multiple origins and cache behaviors Resources: # S3 Bucket for static assets 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}" # Application Load Balancer for API ApplicationLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: !Sub "${AWS::StackName}-api-alb" Scheme: internet-facing SecurityGroups: - !Ref ALBSecurityGroup Subnets: !Ref PublicSubnets Type: application # CloudFront Distribution CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: CallerReference: !Sub "${AWS::StackName}-${AWS::AccountId}" Comment: !Sub "Multi-origin CloudFront distribution" Enabled: true IPV6Enabled: true DefaultRootObject: index.html Origins: # Static assets origin - Id: StaticAssetsOrigin DomainName: !GetAtt StaticAssetsBucket.RegionalDomainName S3OriginConfig: OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOAI}" # API origin - Id: ApiOrigin DomainName: !GetAtt ApplicationLoadBalancer.DNSName CustomOriginConfig: HTTPPort: 80 HTTPSPort: 443 OriginProtocolPolicy: https-only # Lambda origin - Id: LambdaOrigin DomainName: !Sub "${LambdaFunction}.execute-api.${AWS::Region}.amazonaws.com" CustomOriginConfig: HTTPPort: 443 HTTPSPort: 443 OriginProtocolPolicy: https-only DefaultCacheBehavior: # Default: static assets TargetOriginId: StaticAssetsOrigin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD CachedMethods: - GET - HEAD Compress: true ForwardedValues: QueryString: false Cookies: Forward: none MinTTL: 0 DefaultTTL: 86400 MaxTTL: 31536000 CacheBehaviors: # API cache behavior - PathPattern: "/api/*" TargetOriginId: ApiOrigin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD - OPTIONS - PUT - POST - PATCH - DELETE CachedMethods: - GET - HEAD Compress: true ForwardedValues: QueryString: true Headers: - Accept - Accept-Language - Authorization Cookies: Forward: all MinTTL: 0 DefaultTTL: 0 MaxTTL: 0 # Lambda function path - PathPattern: "/lambda/*" TargetOriginId: LambdaOrigin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD - OPTIONS CachedMethods: - GET - HEAD Compress: true ForwardedValues: QueryString: true Cookies: Forward: none MinTTL: 0 DefaultTTL: 0 MaxTTL: 0
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 CachedMethods: - GET - HEAD Compress: true CachePolicyId: !Ref ManagedSecurityHeadersPolicyId
Custom Cache Policy
Resources: # Custom Cache Policy 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 # Custom Cache Policy for API ApiCachePolicy: Type: AWS::CloudFront::CachePolicy Properties: CachePolicyConfig: Name: !Sub "${AWS::StackName}-api-cache-policy" DefaultTTL: 300 MaxTTL: 600 MinTTL: 60 ParametersInCacheKeyAndForwardedToOrigin: CookiesConfig: CookieBehavior: all HeadersConfig: HeaderBehavior: whitelist Headers: - Authorization - Content-Type - Accept QueryStringsConfig: QueryStringBehavior: all EnableAcceptEncodingBrotli: true EnableAcceptEncodingGzip: true CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: Origins: - Id: StaticAssetsOrigin DomainName: !GetAtt StaticAssetsBucket.RegionalDomainName S3OriginConfig: OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOAI}" CacheBehaviors: - PathPattern: "/static/*" TargetOriginId: StaticAssetsOrigin CachePolicyId: !GetAtt StaticAssetsCachePolicy.Id
Origin Request Policies
Resources: # Origin Request Policy 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: CacheBehaviors: - PathPattern: "/api/*" TargetOriginId: ApiOrigin CachePolicyId: !GetAtt ApiCachePolicy.Id OriginRequestPolicyId: !GetAtt ApiOriginRequestPolicy.Id
Response Headers Policies (Security Headers)
Resources: # Security Headers Policy 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: Items: - GET - HEAD - OPTIONS AccessControlAllowOrigins: Items: - !Ref AllowedOrigin AccessControlMaxAgeSec: 600 OriginOverride: true CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: DefaultCacheBehavior: TargetOriginId: StaticAssetsOrigin ResponseHeadersPolicyId: !GetAtt SecurityHeadersPolicy.Id
CloudFront Functions
Viewer Request Function
Resources: # CloudFront Function 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: DistributionConfig: DefaultCacheBehavior: TargetOriginId: StaticAssetsOrigin FunctionAssociations: - FunctionARN: !GetAtt RewritePathFunction.FunctionARN EventType: viewer-request
Lambda@Edge Functions
Resources: # Lambda@Edge Function 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 # Lambda Version for Lambda@Edge 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: https-only DefaultCacheBehavior: TargetOriginId: Origin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD CachedMethods: - GET - HEAD LambdaFunctionAssociations: - FunctionARN: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${LambdaEdgeFunction}:${LambdaEdgeVersion}" EventType: origin-request
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 # Price Class - optimize costs PriceClass: PriceClass_200 # Geo Restrictions GeoRestriction: RestrictionType: whitelist Locations: - US - CA - GB - DE - FR - IT - JP - AU Origins: - Id: Origin DomainName: !Ref OriginDomainName CustomOriginConfig: HTTPPort: 443 HTTPSPort: 443 OriginProtocolPolicy: https-only DefaultCacheBehavior: TargetOriginId: Origin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD CachedMethods: - GET - HEAD Compress: true ForwardedValues: QueryString: false Cookies: Forward: none MinTTL: 0 DefaultTTL: 86400 MaxTTL: 31536000
WAF Integration
Resources: # WAF Web ACL CloudFrontWebACL: Type: AWS::WAFv2::WebACL Properties: Name: !Sub "${AWS::StackName}-waf-acl" Scope: CLOUDFRONT DefaultAction: Allow: {} Rules: # AWS Managed Rule - Common - Name: AWSCommonRule Priority: 1 Statement: ManagedRuleGroupStatement: VendorName: AWS Name: AWSManagedRulesCommonRuleSet ExcludedRules: - Name: SizeRestrictions_BODY OverrideAction: None: {} VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: AWSCommonRule # Rate-based rule - Name: RateLimitRule Priority: 2 Statement: RateBasedStatementKey: SingleHeader: Name: ip AggregateKeyType: IP Limit: 1000 OverrideAction: None: {} VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: RateLimitRule # SQL Injection protection - Name: SQLInjectionRule Priority: 3 Statement: SqliMatchStatement: FieldToMatch: QueryString: {} UriPath: {} TextTransformations: - Priority: 1 Type: URL_DECODE - Priority: 2 Type: LOWERCASE OverrideAction: None: {} VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: SQLInjectionRule # XSS protection - Name: XSSRule Priority: 4 Statement: XssMatchStatement: FieldToMatch: QueryString: {} UriPath: {} TextTransformations: - Priority: 1 Type: URL_DECODE - Priority: 2 Type: LOWERCASE OverrideAction: None: {} VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: XSSRule VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: CloudFrontWAFACL CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: CallerReference: !Sub "${AWS::StackName}-${AWS::AccountId}" Comment: !Sub "CloudFront with WAF" Enabled: true WebACLId: !GetAtt CloudFrontWebACL.Arn Origins: - Id: Origin DomainName: !Ref OriginDomainName CustomOriginConfig: HTTPPort: 443 HTTPSPort: 443 OriginProtocolPolicy: https-only DefaultCacheBehavior: TargetOriginId: Origin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD CachedMethods: - GET - HEAD ForwardedValues: QueryString: false Cookies: Forward: none MinTTL: 0 DefaultTTL: 86400 MaxTTL: 31536000
Real-Time Logs
Resources: # Kinesis Data Stream CloudFrontLogsStream: Type: AWS::Kinesis::Stream Properties: Name: !Sub "${AWS::StackName}-cloudfront-logs" ShardCount: 1 RetentionPeriodHours: 24 # IAM Role for CloudFront 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: !GetAtt CloudFrontLogsStream.Arn CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: CallerReference: !Sub "${AWS::StackName}-${AWS::AccountId}" Comment: !Sub "CloudFront with real-time logs" Enabled: true RealTimeConfig: Endpoint: !GetAtt CloudFrontLogsStream.Arn RoleArn: !GetAtt CloudFrontLoggingRole.Arn Fields: - timestamp - c-ip - cs-method - cs-uri - sc-status - time-taken Origins: - Id: Origin DomainName: !Ref OriginDomainName CustomOriginConfig: HTTPPort: 443 HTTPSPort: 443 OriginProtocolPolicy: https-only DefaultCacheBehavior: TargetOriginId: Origin ViewerProtocolPolicy: redirect-to-https AllowedMethods: - GET - HEAD CachedMethods: - GET - HEAD ForwardedValues: QueryString: false Cookies: Forward: none MinTTL: 0 DefaultTTL: 86400 MaxTTL: 31536000
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] - !Or - [!Equals [!Ref Environment, staging]] - [!Equals [!Ref Environment, production]] Resources: CloudFrontDistribution: Type: AWS::CloudFront::Distribution Properties: DistributionConfig: CallerReference: !Sub "${AWS::StackName}-${AWS::AccountId}" Comment: !Sub "CloudFront for ${Environment}" Enabled: true IPV6Enabled: true PriceClass: !If [IsProduction, PriceClass_All, PriceClass_100] WebACLId: !If [EnableWAFProtection, !Ref CloudFrontWebACL, !Ref AWS::NoValue] Origins: - Id: Origin DomainName: !Ref OriginDomainName CustomOriginConfig: HTTPPort: 443 HTTPSPort: 443 OriginProtocolPolicy: https-only DefaultCacheBehavior: TargetOriginId: Origin ViewerProtocolPolicy: !If [IsProduction, redirect-to-https, allow-all] AllowedMethods: - GET - HEAD CachedMethods: - GET - HEAD Compress: !If [IsProduction, true, false] ForwardedValues: QueryString: false Cookies: Forward: none MinTTL: !If [IsProduction, 0, 0] DefaultTTL: !If [IsProduction, 86400, 3600] MaxTTL: !If [IsProduction, 31536000, 86400] # WAF only for staging and production CloudFrontWebACL: Type: AWS::WAFv2::WebACL Condition: EnableWAFProtection Properties: Name: !Sub "${AWS::StackName}-waf-acl" Scope: CLOUDFRONT DefaultAction: Allow: {} Rules: [] VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: CloudFrontWAFACL
VPC Origins
AWSTemplateFormatVersion: 2010-09-09 Description: CloudFront with VPC Origin Resources: # VPC Origin Endpoint VPCOriginEndpoint: Type: AWS::GlobalAccelerator::EndpointGroup Properties: EndpointGroupRegion: !Ref VPCOriginRegion ListenerArn: !Ref AcceleratorListener EndpointConfigurations: - EndpointId: !Ref VPCEndpointService Weight: 128 # CloudFront Distribution 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: 443 HTTPSPort: 443 OriginProtocolPolicy: https-only OriginKeepaliveTimeout: 60 OriginReadTimeout: 30 DefaultCacheBehavior: TargetOriginId: VPCOrigin ViewerProtocolPolicy: https-only AllowedMethods: - GET - HEAD - OPTIONS CachedMethods: - GET - HEAD Compress: true ForwardedValues: QueryString: true Headers: - "*" Cookies: Forward: all MinTTL: 0 DefaultTTL: 3600 MaxTTL: 86400
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 # ... configuration CloudFrontWebACL: Type: AWS::WAFv2::WebACL Properties: Name: !Sub "${AWS::StackName}-waf" Scope: CLOUDFRONT DefaultAction: Allow: {} Rules: [] VisibilityConfig: SampledRequestsEnabled: true CloudWatchMetricsEnabled: true MetricName: CloudFrontWAF # Stack Policy - protect critical resources Metadata: AWS::CloudFormation::StackPolicy: Statement: - Effect: Allow Action: Update:* Resource: "*" - Effect: Deny Action: - Update:Replace - Update:Delete Resource: "LogicalID=CloudFrontDistribution" Principal: "*" - Effect: Deny Action: - Update:Replace - Update:Delete Resource: "LogicalID=CloudFrontWebACL" Principal: "*"
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 # ... configuration # Note: Termination protection is enabled via AWS Console or CLI # AWS CLI: aws cloudformation update-termination-protection --enable-termination-protection --stack-name my-stack # Or set it in a separate stack update after creation
Drift Detection
Detect when infrastructure has been modified outside of CloudFormation.
# AWS CLI commands for drift detection # Detect drift on a stack aws cloudformation detect-stack-drift --stack-name my-cloudfront-stack # Get drift detection status aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id <detection-id> # Get resources that have drifted aws cloudformation describe-stack-resource-drifts --stack-name my-cloudfront-stack # Example drift detection output format # { # "StackResourceDrifts": [ # { # "ResourceType": "AWS::CloudFront::Distribution", # "LogicalResourceId": "CloudFrontDistribution", # "PhysicalResourceId": "E1X2Y3Z4W5X6Y7", # "ResourceStatus": "UPDATE", # "PropertyDifferences": [ # { # "PropertyPath": "$.DistributionConfig.Enabled", # "ExpectedValue": "true", # "ActualValue": "false" # } # ], # "StackResourceDriftStatus": "MODIFIED" # } # ] # }
Change Sets
Preview and review changes before executing stack updates.
# AWS CLI commands for change sets # 1. Create a change set (preview) 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 # 2. Describe the change set to review changes aws cloudformation describe-change-set \ --stack-name my-cloudfront-stack \ --change-set-name my-changeset # 3. Execute the change set if changes are acceptable aws cloudformation execute-change-set \ --stack-name my-cloudfront-stack \ --change-set-name my-changeset # Or delete if changes are not desired aws cloudformation delete-change-set \ --stack-name my-cloudfront-stack \ --change-set-name my-changeset
# Change set with nested stacks example AWSTemplateFormatVersion: 2010-09-09 Description: CloudFront infrastructure with nested stacks for change set management Resources: # Parent stack managing multiple CloudFront distributions 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 # Change set will show impacts across all nested stacks # When updating, CloudFormation will show: # - Which nested stacks will be updated # - Resources being added, modified, or deleted # - IAM changes requiring special attention
Related Resources
- AWS CloudFront Documentation
- AWS CloudFormation User Guide
- CloudFront Developer Guide
- CloudFront Best Practices
- CloudFormation Stack Policies
- CloudFormation Drift Detection
- CloudFormation Change Sets
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