API Gateway (APIG), while it uses CloudFront (CF) it does not support CDN edge caching. When I configured a CF distribution to use APIG as the custom origin, I get a permission denied error.
How do I configure CF to fix this?
Neither option is wrong, but using CloudFront in front of ALB does provide some advantanges even for non-cacheable, dynamic content -- including faster TLS negotiation for viewers who are more distant from the ALB and optimized routing of requests, globally on the AWS Edge Network, from an edge location near the viewer ...
CloudFront has a built-in caching capability. It's the first place you should consider caching on the server-side. Caching at the edge is very cost-efficient as it cuts out most of the calls to API Gateway and Lambda. Skipping these calls also improve the end-to-end latency and ultimately the user experience.
Until API Gateway (APIG) supports edge caching via its internal use of CloudFront (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
MinimumProtocolVersion: TLSv1.1_2016
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With