【发布时间】:2015-12-25 20:06:54
【问题描述】:
API Gateway (APIG),虽然它使用 CloudFront (CF),但它不支持 CDN 边缘缓存。当我将 CF 分发配置为使用 APIG 作为自定义源时,我收到权限被拒绝错误。
如何配置 CF 来解决这个问题?
【问题讨论】:
标签: amazon-web-services cdn amazon-cloudfront aws-api-gateway
API Gateway (APIG),虽然它使用 CloudFront (CF),但它不支持 CDN 边缘缓存。当我将 CF 分发配置为使用 APIG 作为自定义源时,我收到权限被拒绝错误。
如何配置 CF 来解决这个问题?
【问题讨论】:
标签: amazon-web-services cdn amazon-cloudfront aws-api-gateway
我只想在这里重申,对于任何遵循 AWS 高级支持知识中心指南的人,
如何使用自己的 CloudFront 分配设置 API Gateway? https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-cloudfront-distribution/
如果您使用 AWS 控制台设置 CloudFront 分配,根本原因是您将 Cache Based on Selected Request Headers 设置为 all。
将其设置为 None 或在白名单中排除 Host 标头将解决问题。
【讨论】:
在 API Gateway (APIG) 通过其内部使用 CloudFront (CF) 支持边缘缓存之前,我想出了一个解决方法。
您确实可以将 CF dist 放在 APIG 前面,诀窍是强制 HTTPS 仅“查看器协议策略”并不转发 HOST 标头,因为 APIG 需要 SNI。
我将我的 CF“默认缓存行为设置”设置为不转发任何标头,并将“查看器协议策略”强制设置为“仅 HTTPS”并且它可以工作。希望这对其他人有帮助。
这是一个具有所有必需配置的 CloudFormation 资源对象(注意:我使用约定 <stage>--<app name> 作为 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
2018 年末更新
MinimumProtocolVersion: TLSv1.1_2016
【讨论】:
curl https://api.cloudprowess.com 来看看它的实际效果。我这样做是为了能够设置一个自定义域,该域使用由 AWS Certificate Manager 颁发的 SSL 证书,否则我的 API Gateway 将无法使用该证书。我现在的问题是,这是否会使 CloudFront 带宽和请求花费我两倍,或者 CloudFront 内部的成本是否为零,我将作为一个新问题提出这个问题。
如果 API Gateway 返回 403 错误:
授权标头需要“凭据”参数。授权 标头需要“签名”参数。授权标头需要 'SignedHeaders' 参数。授权标头需要存在 'X-Amz-Date' 或 'Date' 标题。
也可能是源端点不正确。 “API Gateway 将不存在路径的所有错误视为 403 权限被拒绝错误,而不是 404 未找到错误。” (见this support thread)。
我收到此错误并假设我错误地转发了 Authorization 标头,但我只是错误地配置了原始路径。
【讨论】:
随着 2017 年 11 月 API Gateway 区域端点的推出,我相信现在最好将这些与 CloudFront Distributions 结合使用。有关从边缘优化 API 迁移到区域 API 以及设置 CloudFront 分配的一些详细说明如下:
【讨论】:
添加到以前的答案:
重要的是,行为路径模式实际上是匹配“真实”路径的东西。
如果 API 端点是 <id>.execute-api.<region>.amazonaws.com/stage-name/my-api
源域+路径为<id>.execute-api.<region>.amazonaws.com/stage-name
行为路径模式必须是my-api、my-api/*、my-api/something等
我不知道为什么,但我认为路径模式可以用作别名,例如:
https://www.example.com/random-name(路径模式random-name)解析为域+在原点设置的路径,例如<id>.execute-api.<region>.amazonaws.com/stage-name。
事实并非如此。
【讨论】:
<id>.execute-api.<region>.amazonaws.com/stage-name/api/endpoint1,起源+路径:<id>.execute-api.<region>.amazonaws.com/stage-name,路径模式:/api/*,最终端点:https://<id>.cloudfront.net/api/endpoint1,不相关但我也发现这个答案对于传递标头很有用:stackoverflow.com/a/47380572/728602