1

我在 API Gateway(与 Lambda 代理集成)中创建了一个私有 REST API,它需要可从 VPC 访问。我已经在 VPC 中为 API Gateway 设置了 VPC Endpoint。正如预期的那样,可以从 VPC 内访问 API。

VPC 端点(实际上是整个 VPC 环境)是通过 CloudFormation 创建的。

API 需要使用Authorization标头,这不是我可以更改的。该标题的内容是我们公司特有的,不是标准的。问题是,当我Authorization向请求添加标头时,API Gateway 拒绝它并出现以下错误(来自 CloudWatch 中的 API Gateway 日志):

IncompleteSignatureException
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.
Authorization=[the header content here]

如果我删除了Authorization标头,请求就会被接受,并且我会从我的 lambda 中得到预期的响应。我正在调用的方法将 Auth 设置为 NONE。

奇怪的是,如果我删除 VPC 端点并通过控制台手动创建它,它会正常工作 -Authorization标头被传递给我的 lambda,而不是 API Gateway 检查和拒绝它。

我已经拆除了端点,并使用 CloudFormation 手动重新创建了多次,结果是一致的。但我已经将它们相互比较,它们看起来完全一样:相同的设置、相同的子网、相同的安全组、相同的策略。由于我看不出它们之间没有区别,所以我对它为什么不适用于 CloudFormation 版本有点茫然。

我能够找到的唯一区别是每个版本的 aws 标头(Authorization删除了标头,否则它不会像使用 CF 端点记录标头那样)。对于 CF 端点,标头包括x-amzn-vpce-config=0x-amzn-vpce-policy-url=MQ==. 使用我得到的手动端点x-amzn-vpce-config=1,并且不包括 policy-url 标头。

我还尝试将 API 更改为设置和删除 VPC 端点(可以在设置部分的 API 上设置),然后重新部署它,但在任何一种情况下它都没有效果 - 请求继续工作/被拒绝和以前一样。

有没有人有任何想法?我也在AWS 论坛上发布了这个,但以防万一这里的任何人以前遇到过这个......

如果有任何兴趣,可以像这样创建端点([]= 已编辑):

ApiGatewayVPCEndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    PrivateDnsEnabled: true
    PolicyDocument:
      Statement:
        - Action: '*'
          Effect: Allow
          Resource: '*'
          Principal: '*'
    ServiceName: !Sub com.amazonaws.${AWS::Region}.execute-api
    SecurityGroupIds:
      - !Ref [my sec group]
    SubnetIds:
      - !Ref [subnet a]
      - !Ref [subnet b]
      - !Ref [subnet c]
    VpcEndpointType: Interface
    VpcId: !Ref [my vpc]
4

1 回答 1

0

我设法让它工作,这是最荒谬的事情。

这是 CF 中的端点策略(包括在上下文中显示的属性名称):

PolicyDocument:
  Statement:
    - Action: '*'
      Effect: Allow
      Resource: '*'
      Principal: '*'

这是该策略在控制台中的显示方式:

{
    "Statement": [
        {
            "Action": "*",
            "Effect": "Allow",
            "Resource": "*",
            "Principal": "*"
        }
    ]
}

这是该政策在以下文件中的显示方式describe-vpc-endpoints

"PolicyDocument": "{\"Statement\":[{\"Action\":\"*\",\"Resource\":\"*\",\"Effect\":\"Allow\",\"Principal\":\"*\"}]}"

现在让我们看一下手动创建的端点的策略。

安慰:

{
    "Statement": [
        {
            "Action": "*",
            "Effect": "Allow",
            "Resource": "*",
            "Principal": "*"
        }
    ]
}

describe-vpc-endpoints

"PolicyDocument": "{\n  \"Statement\": [\n    {\n      \"Action\": \"*\", \n      \"Effect\": \"Allow\", \n      \"Principal\": \"*\", \n      \"Resource\": \"*\"\n    }\n  ]\n}"

控制台显示它们完全相同,并且返回的 JSON 本身describe-vpc-endpoints是相同的,除了一些“美化”换行符和空格,这肯定不会有任何效果吗?错误的!正是这些换行符使该政策真正起作用!

无论如何,解决方案是以 JSON 格式提供策略,例如:

ApiGatewayVPCEndpoint:
  Type: AWS::EC2::VPCEndpoint
  Properties:
    PrivateDnsEnabled: true
    PolicyDocument: '
    {
      "Statement": [
        {
          "Action": "*",
          "Effect": "Allow",
          "Resource": "*",
          "Principal": "*"
        }
      ]
    }'
    ServiceName: !Sub com.amazonaws.${AWS::Region}.execute-api
    SecurityGroupIds:
      - !Ref [my sec group]
    SubnetIds:
      - !Ref [subnet a]
      - !Ref [subnet b]
      - !Ref [subnet c]
    VpcEndpointType: Interface
    VpcId: !Ref [my vpc]

您甚至可以将所有 JSON 放在一行中,它会在某些时候让 AWS 将换行符放入其中。只是 YAML 在没有换行符的情况下转换为 JSON 并导致此问题。

使用这样的 CF 资源,API Gateway 接受我的Authorization标头并将其传递给 Lambda,没有任何问题。

于 2021-10-18T14:01:49.227 回答