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?
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?
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 C
Late 2018 updates
MinimumProtocolVersion: TLSv1.1_2016
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.
I just want to reiterate here, for anyone who's following the guide from AWS premium support knowledge center,
How do I set up API Gateway with my own CloudFront distribution? https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-cloudfront-distribution/
If you are using AWS console to set up the CloudFront distribution, the root cause is that you set Cache Based on Selected Request Headers to all.
Setting it to None or exclude the Host
header in the Whitelist would solve the problem.
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:
You could use the behavior and origin feature of cloudfront.
Have multiple origins for example S3 bucket and another api gateway.
Then based on behavior you can route to specific origin.
Like Default(*) behavior will point to S3.
/api/* behavior will point to api gateway.
https://kuchbhilearning.blogspot.com/2022/10/add-cloudfront-behavior-and-origin.html code.
Much detail explanation https://kuchbhilearning.blogspot.com/2022/10/api-gateway-and-cloud-front-in-same.html