aws-cloudformation-cloudfront

AWS CloudFormation CloudFront CDN

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "aws-cloudformation-cloudfront" with this command: npx skills add giuseppe-trisciuoglio/developer-kit/giuseppe-trisciuoglio-developer-kit-aws-cloudformation-cloudfront

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 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?)*"

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('.') &#x26;&#x26; !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

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

shadcn-ui

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

tailwind-css-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

unit-test-bean-validation

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

react-patterns

No summary provided by upstream source.

Repository SourceNeeds Review