How do you add CloudFront in front of API Gateway

天涯浪子 提交于 2019-11-28 15:44:27

Until API Gateway (APIG) supports edge caching via its internal use of CloudFormation (CF), I have come up with a workaround.

You can indeed put CF dist in front of APIG, the trick is to force HTTPS only "Viewer Protocol Policy" AND to NOT forward the HOST header because APIG needs SNI.

I setup my CF "Default Cache Behavior Settings" to not forward any headers, and forced "Viewer Protocol Policy" to "HTTPS Only" and it works. Hope this helps others.

Here is a CloudFormation resource object that has all the required configuration (Note: I use the convention <stage>--<app name> for StackName):

CloudFront:  
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Enabled: true
        IPV6Enabled: true
        HttpVersion: http2
        Comment: !Join [ '--', [!Ref 'AWS::StackName', ' Cloud Front']]
        Aliases: [!Ref CloudFrontCname]
        ViewerCertificate:
          AcmCertificateArn: !Ref AcmCertificateArn
          SslSupportMethod: sni-only
          MinimumProtocolVersion: TLSv1.1_2016
        Origins:
        - Id: APIGOrigin
          DomainName: !Sub
            - ${apigId}.execute-api.${AWS::Region}.amazonaws.com
            - { apigId: !Ref ApiGatewayLambdaProxy }
          OriginPath: !Sub
            - /${Stage}
            - { Stage: !Select [ "0", !Split [ '--', !Ref 'AWS::StackName' ] ] }
          CustomOriginConfig:
            # HTTPPort: 80
            HTTPSPort: 443
            OriginProtocolPolicy: https-only
          OriginCustomHeaders:
            - HeaderName: 'Verify-From-Cf'
              HeaderValue: !Ref VerifyFromCfHeaderVal
        DefaultCacheBehavior:
          AllowedMethods: ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
          CachedMethods: ["GET", "HEAD", "OPTIONS"]
          ForwardedValues:
            Headers:
            - Access-Control-Request-Headers
            - Access-Control-Request-Method
            - Origin
            - Authorization
            # - Host APIG needs to use SNI
            QueryString: true
          TargetOriginId: APIGOrigin
          ViewerProtocolPolicy: https-only
          Compress: true
          DefaultTTL: 0
        CustomErrorResponses:
        - ErrorCachingMinTTL: 0
          ErrorCode: 400
        - ErrorCachingMinTTL: 1
          ErrorCode: 403
        - ErrorCachingMinTTL: 5
          ErrorCode: 500
  DNSARecord:    
    Type: AWS::Route53::RecordSet
    Properties:
      Comment: !Ref 'AWS::StackName'
      Name: !Ref CloudFrontCname
      Type: A
      HostedZoneName: !Join ['.', [ !Select [1, !Split ['.', !Ref CloudFrontCname]], !Select [2, !Split ['.', !Ref CloudFrontCname]], '']]
      AliasTarget:
        HostedZoneId: !Ref Route53HostedZoneId
        DNSName: !GetAtt CloudFront.DomainName
  DNSAAAARecord:    
    Type: AWS::Route53::RecordSet
    Properties:
      Comment: !Ref 'AWS::StackName'
      Name: !Ref CloudFrontCname
      Type: AAAA
      HostedZoneName: !Join ['.', [ !Select [1, !Split ['.', !Ref CloudFrontCname]], !Select [2, !Split ['.', !Ref CloudFrontCname]], '']]
      AliasTarget:
        HostedZoneId: !Ref Route53HostedZoneId
        DNSName: !GetAtt CloudFront.DomainName

Late 2018 updates

  • CloudFormation finally supports setting SSL proto ver: MinimumProtocolVersion: TLSv1.1_2016
  • I've baked this (and many other) best practices into an OSS project: aws-blueprint

Adding to previous answers:

it's important that behavior path pattern is actually something that matches "real" path.


If API endpoint is <id>.execute-api.<region>.amazonaws.com/stage-name/my-api

And origin domain + path is <id>.execute-api.<region>.amazonaws.com/stage-name

Behavior path pattern has to be my-api, my-api/*, my-api/something, etc


I don't know why, but I thought that path pattern can be used as alias, for example:

https://www.example.com/random-name (path pattern random-name) resolves to domain + path set in origin, e.g <id>.execute-api.<region>.amazonaws.com/stage-name.

That's not the case.

If API Gateway returns a 403 error with:

Authorization header requires 'Credential' parameter. Authorization header requires 'Signature' parameter. Authorization header requires 'SignedHeaders' parameter. Authorization header requires existence of either a 'X-Amz-Date' or a 'Date' header.

it can also be that the origin endpoint is incorrect. "API Gateway treats all errors to non-existent paths as 403 permission denied errors rather than a 404 not found error." (see this support thread).

I got this error and assumed I was incorrectly forwarding the Authorization header, but I had simply misconfigured the origin path.

With the launch of API Gateway regional endpoints in Nov 2017 I believe it is now optimal to use these with CloudFront Distributions on top. Some detailed instructions for moving from Edge Optimized API's to Regional API's and setting up the CloudFront Distributions are here:

AWS API Gateway should prevent use of TLS v1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!