web-dev-qa-db-ja.com

API Gatewayの前にCloudFrontを追加する方法

API Gateway(APIG)は、CloudFront(CF)を使用しますが、CDN Edgeキャッシングをサポートしません。 APIGをカスタムオリジンとして使用するようにCFディストリビューションを構成すると、アクセス許可拒否エラーが発生します。

これを修正するためにCFを構成するにはどうすればよいですか?

31
rynop

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年後半の更新

  • CloudFormationは、SSLプロトタイプver:MinimumProtocolVersion: TLSv1.1_2016
  • この(および他の多くの)ベストプラクティスをOSSプロジェクトに組み込みました。 aws-blueprint
51
rynop

前の回答に追加:

動作パスパターンが実際に「実際の」パスに一致するものであることが重要です。


APIエンドポイントが<id>.execute-api.<region>.amazonaws.com/stage-name/my-apiの場合

そして、Originドメイン+パスは<id>.execute-api.<region>.amazonaws.com/stage-nameです

動作パスパターンmy-apimy-api/*my-api/somethingなどでなければなりません


理由はわかりませんが、たとえば次のようにパスパターンをエイリアスとして使用できると考えました。

https://www.example.com/random-name (path pattern random-name)は、Originで設定されたドメイン+パスに解決されます(例:<id>.execute-api.<region>.amazonaws.com/stage-name)。

そうではありません。

4
Solo

API Gatewayが403エラーを返した場合:

Authorizationヘッダーには「Credential」パラメーターが必要です。 Authorizationヘッダーには「Signature」パラメーターが必要です。 Authorizationヘッダーには「SignedHeaders」パラメーターが必要です。 Authorizationヘッダーには、「X-Amz-Date」または「Date」ヘッダーのいずれかが存在する必要があります。

originエンドポイントが正しくない可能性もあります。 「API Gatewayは、存在しないパスへのすべてのエラーを、404 not foundエラーではなく、403許可拒否エラーとして扱います。」 ( このサポートスレッド を参照)。

このエラーが発生し、Authorizationヘッダーを誤って転送していると想定しましたが、Originパスを誤って設定しただけでした。

2
Kevin

2017年11月にAPI Gatewayリージョナルエンドポイントがリリースされたことで、CloudFrontディストリビューションでこれらを使用することが最適だと思います。 Edge Optimized APIからRegional APIに移行してCloudFrontディストリビューションを設定するための詳細な手順は次のとおりです。

AWS API GatewayはTLS v1の使用を防止する必要があります

0
Alistair