aws-cloudformation-cloudfront

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

AWS CloudFormation CloudFront CDN

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.
使用AWS CloudFormation模板创建生产就绪的CDN基础设施。本内容涵盖CloudFront分发、多源站(ALB、S3、Lambda@Edge、VPC源站)、CacheBehaviors、Functions、SecurityHeaders,以及参数、输出和跨栈引用的最佳实践。

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创建新的CloudFront分发
  • 配置多源站(ALB、S3、API Gateway、Lambda@Edge、VPC源站)
  • 结合CacheBehaviors和缓存策略实施缓存方案
  • 使用ACM证书配置自定义域名
  • 实施SecurityHeaders(CSP、HSTS、XSS防护)
  • 配置CloudFront Functions和Lambda@Edge
  • 管理地域限制和价格等级
  • 将WAF与CloudFront集成
  • 使用参数、输出、映射、条件组织模板
  • 通过导出/导入实现跨栈引用
  • 使用Transform实现宏和复用

CloudFormation Template Structure

CloudFormation模板结构

Standard Format Base Template

标准格式基础模板

yaml
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"
yaml
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

AWS特定参数类型

yaml
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
yaml
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

参数约束

yaml
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
yaml
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

SSM参数引用

yaml
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
yaml
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

导出/导入模式

yaml
undefined
yaml
undefined

Stack A - Network/Infrastructure Stack

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"

```yaml
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"

```yaml

Stack B - Application Stack (imports from Infrastructure Stack)

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
undefined
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
undefined

Nested Stacks for Modularity

嵌套栈实现模块化

yaml
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
yaml
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源站

S3 Origin with OAI

带OAI的S3源站

yaml
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
yaml
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)

带Origin Access Control (OAC)的S3源站

yaml
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
yaml
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

ALB源站

Application Load Balancer Origin

应用负载均衡器源站

yaml
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
yaml
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

多源站与CacheBehaviors

Multi-Origin with Path Patterns

带路径模式的多源站

yaml
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
yaml
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

托管缓存策略

yaml
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
yaml
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

自定义缓存策略

yaml
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
yaml
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

源站请求策略

yaml
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
yaml
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)

响应头策略(安全头)

yaml
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
yaml
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

CloudFront Functions

Viewer Request Function

查看器请求函数

yaml
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
yaml
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

Lambda@Edge函数

yaml
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
yaml
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

地域限制与价格等级

yaml
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
yaml
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

WAF集成

yaml
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
yaml
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

实时日志

yaml
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
yaml
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

条件与Transform

Conditions for Environment-Specific Configuration

环境特定配置的条件

yaml
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
yaml
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

VPC源站

yaml
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
yaml
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
  • 始终使用HTTPS,最低TLS版本为1.2
  • 实施包含HSTS、XSS防护的SecurityHeaders
  • 使用WAF防护常见攻击
  • 配置适当的CORS访问控制
  • 使用OAI/OAC限制源站访问
  • 对私有内容使用签名URL
  • 实施速率限制
  • 必要时配置地域限制

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
  • 使用合适的PriceClass优化成本
  • 根据内容类型配置缓存TTL
  • 启用压缩(Gzip/Brotli)
  • 使用CloudFront Functions执行轻量级操作
  • 优化头转发(不转发不必要的头)
  • 考虑使用Origin Shield减少源站负载
  • 使用带路径模式的多源站

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
  • 启用CloudWatch指标和告警
  • 配置实时日志用于故障排查
  • 监控缓存命中率
  • 配置错误率和延迟告警
  • 使用CloudFront报告进行流量分析

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
  • 部署前使用变更集
  • 使用cfn-lint测试模板
  • 按生命周期和归属组织栈
  • 使用加权别名实现蓝绿部署
  • 使用StackSets进行多区域部署

CloudFormation Best Practices

CloudFormation最佳实践

Stack Policies

栈策略

Stack Policies prevent accidental updates to critical resources during stack updates.
yaml
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
栈策略可防止在栈更新期间意外更新关键资源。
yaml
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

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: "*"
undefined
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: "*"
undefined

Termination Protection

终止保护

Enable termination protection to prevent accidental stack deletion.
yaml
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFront with termination protection

Resources:
  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Enabled: true
        # ... configuration
启用终止保护以防止意外删除栈。
yaml
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

Note: Termination protection is enabled via AWS Console or CLI

AWS CLI: aws cloudformation update-termination-protection --enable-termination-protection --stack-name my-stack

AWS CLI: aws cloudformation update-termination-protection --enable-termination-protection --stack-name my-stack

Or set it in a separate stack update after creation

Or set it in a separate stack update after creation

undefined
undefined

Drift Detection

漂移检测

Detect when infrastructure has been modified outside of CloudFormation.
yaml
undefined
检测基础设施是否在CloudFormation之外被修改。
yaml
undefined

AWS CLI commands for drift detection

AWS CLI commands for drift detection

Detect drift on a stack

Detect drift on a stack

aws cloudformation detect-stack-drift --stack-name my-cloudfront-stack
aws cloudformation detect-stack-drift --stack-name my-cloudfront-stack

Get drift detection status

Get drift detection status

aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id <detection-id>
aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id <detection-id>

Get resources that have drifted

Get resources that have drifted

aws cloudformation describe-stack-resource-drifts --stack-name my-cloudfront-stack
aws cloudformation describe-stack-resource-drifts --stack-name my-cloudfront-stack

Example drift detection output format

Example drift detection output format

{

{

"StackResourceDrifts": [

"StackResourceDrifts": [

{

{

"ResourceType": "AWS::CloudFront::Distribution",

"ResourceType": "AWS::CloudFront::Distribution",

"LogicalResourceId": "CloudFrontDistribution",

"LogicalResourceId": "CloudFrontDistribution",

"PhysicalResourceId": "E1X2Y3Z4W5X6Y7",

"PhysicalResourceId": "E1X2Y3Z4W5X6Y7",

"ResourceStatus": "UPDATE",

"ResourceStatus": "UPDATE",

"PropertyDifferences": [

"PropertyDifferences": [

{

{

"PropertyPath": "$.DistributionConfig.Enabled",

"PropertyPath": "$.DistributionConfig.Enabled",

"ExpectedValue": "true",

"ExpectedValue": "true",

"ActualValue": "false"

"ActualValue": "false"

}

}

],

],

"StackResourceDriftStatus": "MODIFIED"

"StackResourceDriftStatus": "MODIFIED"

}

}

]

]

}

}

undefined
undefined

Change Sets

变更集

Preview and review changes before executing stack updates.
yaml
undefined
在执行栈更新前预览和审查变更。
yaml
undefined

AWS CLI commands for change sets

AWS CLI commands for change sets

1. Create a change set (preview)

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
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

2. Describe the change set to review changes

aws cloudformation describe-change-set
--stack-name my-cloudfront-stack
--change-set-name my-changeset
aws cloudformation describe-change-set
--stack-name my-cloudfront-stack
--change-set-name my-changeset

3. Execute the change set if changes are acceptable

3. Execute the change set if changes are acceptable

aws cloudformation execute-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

Or delete if changes are not desired

Or delete if changes are not desired

aws cloudformation delete-change-set
--stack-name my-cloudfront-stack
--change-set-name my-changeset

```yaml
aws cloudformation delete-change-set
--stack-name my-cloudfront-stack
--change-set-name my-changeset

```yaml

Change set with nested stacks example

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

undefined
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

undefined

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
有关资源及其属性的完整详细信息,请参阅:
  • REFERENCE.md - 所有CloudFormation资源的详细参考指南
  • EXAMPLES.md - 完整的生产就绪示例