【问题标题】:How do you add CloudFront in front of API GatewayAPI网关前面怎么加CloudFront
【发布时间】:2015-12-25 20:06:54
【问题描述】:

API Gateway (APIG),虽然它使用 CloudFront (CF),但它不支持 CDN 边缘缓存。当我将 CF 分发配置为使用 APIG 作为自定义源时,我收到权限被拒绝错误。

如何配置 CF 来解决这个问题?

【问题讨论】:

    标签: amazon-web-services cdn amazon-cloudfront aws-api-gateway


    【解决方案1】:

    我只想在这里重申,对于任何遵循 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 标头将解决问题。

    【讨论】:

      【解决方案2】:

      在 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 年末更新

      • CloudFormation 终于支持设置 SSL proto ver:MinimumProtocolVersion: TLSv1.1_2016
      • 我已经将这个(以及许多其他)最佳实践融入到一个 OSS 项目中:aws-blueprint

      【讨论】:

      • 你可以使用路径模式吗?我有一个有两个来源的云端分发设置:一个用于我的静态文件的 S3 存储桶和一个 APIG API;但我的 APIG 的 PathPattern 没有触发。我认为这是因为我不是在文件名或类型上匹配,而是在特定路径上。
      • API Gateway 在后台使用 CloudFront。如果您将另一个 CloudFront 分配指向您的 API Gateway 终端节点,CloudFront 会阻止该请求,因为 CloudFront 具有反环回检查。 IE。您不能将 CloudFront 指向 CloudFront。 AWS re:Invent 2015 的一位 AWS 工程师告诉我,这种反环回检查将放宽,以允许您将 CloudFront 分配指向 API 网关。我还没有验证它是否有效。
      • 我刚刚测试过,它现在可以工作了,curl https://api.cloudprowess.com 来看看它的实际效果。我这样做是为了能够设置一个自定义域,该域使用由 AWS Certificate Manager 颁发的 SSL 证书,否则我的 API Gateway 将无法使用该证书。我现在的问题是,这是否会使 CloudFront 带宽和请求花费我两倍,或者 CloudFront 内部的成本是否为零,我将作为一个新问题提出这个问题。
      • 首先,是的,您只需要删除主机标头即可完成这项工作。我很好奇是否有人尝试过将 ApiGateway 设置为 IAM 身份验证。我收到签名错误。它需要 host=apigateway host 而不是 host=cloudfront host 的签名
      • 我什至无法描述知道不转发主机标头可以节省多少时间。
      【解决方案3】:

      如果 API Gateway 返回 403 错误:

      授权标头需要“凭据”参数。授权 标头需要“签名”参数。授权标头需要 'SignedHeaders' 参数。授权标头需要存在 'X-Amz-Date' 或 'Date' 标题。

      也可能是源端点不正确。 “API Gateway 将不存在路径的所有错误视为 403 权限被拒绝错误,而不是 404 未找到错误。” (见this support thread)。

      我收到此错误并假设我错误地转发了 Authorization 标头,但我只是错误地配置了原始路径。

      【讨论】:

      • 如果调用者没有列表权限,将“找不到资源”视为“拒绝访问”是很常见的。否则,您将泄露有关资源名称的信息,这可能对攻击者有价值。
      【解决方案4】:

      随着 2017 年 11 月 API Gateway 区域端点的推出,我相信现在最好将这些与 CloudFront Distributions 结合使用。有关从边缘优化 API 迁移到区域 API 以及设置 CloudFront 分配的一些详细说明如下:

      AWS API Gateway should prevent use of TLS v1

      【讨论】:

        【解决方案5】:

        添加到以前的答案:

        重要的是,行为路径模式实际上是匹配“真实”路径的东西。


        如果 API 端点是 <id>.execute-api.<region>.amazonaws.com/stage-name/my-api

        源域+路径为<id>.execute-api.<region>.amazonaws.com/stage-name

        行为路径模式必须是my-apimy-api/*my-api/something


        我不知道为什么,但我认为路径模式可以用作别名,例如:

        https://www.example.com/random-name(路径模式random-name)解析为域+在原点设置的路径,例如<id>.execute-api.<region>.amazonaws.com/stage-name

        事实并非如此。

        【讨论】:

        • 谢谢!就我而言,我使用与路径模式匹配的 api 网关资源实现了这一点。 api:网关:<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
        猜你喜欢
        • 2019-07-30
        • 2017-07-04
        • 2018-03-11
        • 2017-08-17
        • 2022-12-10
        • 2018-04-16
        • 1970-01-01
        • 2020-02-03
        • 1970-01-01
        相关资源
        最近更新 更多