API Gateway(APIG)は、CloudFront(CF)を使用しますが、CDN Edgeキャッシングをサポートしません。 APIGをカスタムオリジンとして使用するようにCFディストリビューションを構成すると、アクセス許可拒否エラーが発生します。
これを修正するためにCFを構成するにはどうすればよいですか?
API Gateway(APIG)がCloudFormation(CF)の内部使用を介してEdgeキャッシングをサポートするまで、回避策を思いつきました。
実際、CF distをAPIGの前に置くことができます。トリックは、HTTPSのみに「Viewer Protocol Policy」を強制し、[〜#〜] not [〜#〜]APIGはSNIを必要とするため、Hostヘッダーを転送します。
ヘッダーを転送しないようにCFの「デフォルトのキャッシュ動作設定」を設定し、「ビューアープロトコルポリシー」を「HTTPSのみ」に設定すると、機能します。これが他の人の役に立つことを願っています。
以下は、必要なすべての構成を持つCloudFormationリソースオブジェクトです(注:規則<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
2018年後半の更新
MinimumProtocolVersion: TLSv1.1_2016
前の回答に追加:
動作パスパターンが実際に「実際の」パスに一致するものであることが重要です。
APIエンドポイントが<id>.execute-api.<region>.amazonaws.com/stage-name/my-api
の場合
そして、Originドメイン+パスは<id>.execute-api.<region>.amazonaws.com/stage-name
です
動作パスパターンはmy-api
、my-api/*
、my-api/something
などでなければなりません
理由はわかりませんが、たとえば次のようにパスパターンをエイリアスとして使用できると考えました。
https://www.example.com/random-name (path pattern random-name
)は、Originで設定されたドメイン+パスに解決されます(例:<id>.execute-api.<region>.amazonaws.com/stage-name
)。
そうではありません。
API Gatewayが403エラーを返した場合:
Authorizationヘッダーには「Credential」パラメーターが必要です。 Authorizationヘッダーには「Signature」パラメーターが必要です。 Authorizationヘッダーには「SignedHeaders」パラメーターが必要です。 Authorizationヘッダーには、「X-Amz-Date」または「Date」ヘッダーのいずれかが存在する必要があります。
originエンドポイントが正しくない可能性もあります。 「API Gatewayは、存在しないパスへのすべてのエラーを、404 not foundエラーではなく、403許可拒否エラーとして扱います。」 ( このサポートスレッド を参照)。
このエラーが発生し、Authorizationヘッダーを誤って転送していると想定しましたが、Originパスを誤って設定しただけでした。
2017年11月にAPI Gatewayリージョナルエンドポイントがリリースされたことで、CloudFrontディストリビューションでこれらを使用することが最適だと思います。 Edge Optimized APIからRegional APIに移行してCloudFrontディストリビューションを設定するための詳細な手順は次のとおりです。