【问题标题】:Disabling security for one method resource endpoint in API Gateway via AWS SAM template通过 AWS SAM 模板禁用 API Gateway 中一个方法资源端点的安全性
【发布时间】:2022-03-16 03:09:35
【问题描述】:

我正在使用 AWS Serverless 创建一个支持 Lambda 函数的 API 网关。

我定义了以下资源和方法:

/projects
   -> GET (should require API key)
   -> OPTIONS (should not, since it is used for CORS preflight)

我遇到了 CORS 问题并需要 API 密钥。前端客户端代码在启动预检 CORS OPTIONS 请求时收到 403 Forbidden 错误,因为对于 OPTIONS 方法,AWS 管理控制台中的 API Key Required 设置为 True

我想专门为 OPTIONS 请求禁用安全性,但为所有其他方法(GETPOST 等)保留它。这是我的资源定义(你可以看到我在 Auth 对象中设置了默认的 ApiKeyRequired: true

  MyApi:
    Type: 'AWS::Serverless::Api'
    Name: MyApi
    Properties:
      Auth:
        AddDefaultAuthorizerToCorsPreflight: true
        ApiKeyRequired: true # sets for all methods
      Cors:
        AllowCredentials: true
        AllowHeaders: '"Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token"'
        AllowMethods: '"POST,GET,OPTION"'
        AllowOrigin: '"*"'
        MaxAge: '"600"'
      StageName: !Ref StageName
      DefinitionBody:
        swagger: 2.0
        info:
          title: !Sub API-Lambda-${StageName}
          description: "API for MyApi"
          version: "1.0.0"
        paths:
          /projects:
            get:
              produces:
                - application/json
              responses:
                "200":
                  description: OK
              x-amazon-apigateway-any-method:
                produces:
                  - application/json
              x-amazon-apigateway-integration:
                httpMethod: post
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetAllProjectsFunction.Arn}/invocations
            options:
              consumes:
                - application/json
              produces:
                - application/json
              responses:
                '200':
                  description: 200 response
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
                      method.response.header.Access-Control-Allow-Headers: "'Content-Type,mode,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'"
                      method.response.header.Access-Control-Allow-Origin: "'*'"
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: "{\"statusCode\": 200}"
                type: mock
          /projects/{userId}:
            get:
              responses:
                "200":
                  description: OK
              x-amazon-apigateway-any-method:
                produces:
                  - application/json
              x-amazon-apigateway-integration:
                httpMethod: post
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetProjectsForUserFunction.Arn}/invocations
            options:
              consumes:
                - application/json
              responses:
                '200':
                  description: 200 response
                  headers:
                    Access-Control-Allow-Origin:
                      type: string
                    Access-Control-Allow-Methods:
                      type: string
                    Access-Control-Allow-Headers:
                      type: string
              x-amazon-apigateway-integration:
                responses:
                  default:
                    statusCode: 200
                    responseParameters:
                      method.response.header.Access-Control-Allow-Methods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
                      method.response.header.Access-Control-Allow-Headers: "'Content-Type,mode,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'"
                      method.response.header.Access-Control-Allow-Origin: "'*'"
                passthroughBehavior: when_no_match
                requestTemplates:
                  application/json: "{\"statusCode\": 200}"
                type: mock

我知道Swagger documentation 表示我可以通过为每个资源方法添加security 对象来覆盖安全性。这个SO post 还建议我可以通过将security 对象设为空列表来禁用安全性。

但是,我尝试了以下方法:

        options:
          consumes:
            - application/json
          produces:
            - application/json
          security:
            -
          responses: ...

并且还简单地将 security 设为 None 对象:

        options:
          consumes:
            - application/json
          produces:
            - application/json
          security:
          responses: ...

在这两种情况下,我在尝试使用 aws sam deploy 进行部署时都会收到以下错误:

等待创建变更集。错误:创建失败 堆栈的变更集:my-app,例如:Waiter ChangeSetCreateComplete 失败:服务员遇到终端故障状态状态:FAILED。 原因:转换 AWS::Serverless-2016-10-31 失败:内部 转换失败。

我的security 定义似乎是错误的。如何禁用资源的一种方法(即OPTIONS 方法)的安全性?

更新:

我使用以下语法获得了要部署的模板:

    options:
      consumes:
        - application/json
      produces:
        - application/json
      security:
        - {}
      responses:

但是,即使在部署之后,我的控制台中仍然有这个:

老实说,我现在不知所措,因为使用常规 AWS::ApiGateway::Method 资源很容易做到这一点(只需将 ApiKeyRequired 设置为 true)。

【问题讨论】:

    标签: amazon-web-services swagger amazon-cloudformation aws-api-gateway aws-serverless


    【解决方案1】:

    您可以简单地设置AddDefaultAuthorizerToCorsPreflight: false,这将导致OPTIONS 请求如您所愿不安全。

    请参阅这部分文档:

    如果设置了 DefaultAuthorizer 和 Cors 属性,则设置 AddDefaultAuthorizerToCorsPreflight 将导致将默认授权方添加到 OpenAPI 部分的 Options 属性中。

    参考:https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-api-apiauth.html

    【讨论】:

      【解决方案2】:

      不太好,但我认为您必须在每个 OPTIONS 方法上禁用 api_key —— 使用 openapi 提供该方法的定义并在其中跳过/省略“安全”键

      【讨论】:

        【解决方案3】:

        AddDefaultAuthorizerToCorsPreflight: false 确实省略了默认授权者,它可以是CognitoAuthorizer | LambdaTokenAuthorizer | LambdaRequestAuthorizer 之一,但不幸的是它没有省略ApiKeyRequired。预检请求仍需要 ApiKey。但是,浏览器不会将X-API-Key Header 附加到OPTIONS 请求。

        为每个预检请求手动跳过 ApiKey 要求似乎是唯一的选择。不幸的是,除了在每次部署后手动通过控制台之外,我不知道如何做到这一点。

        我在 github 上打开了一个 issue:https://github.com/aws/aws-sam-cli/issues/3735

        【讨论】:

          猜你喜欢
          • 2020-05-23
          • 2021-05-29
          • 1970-01-01
          • 2019-09-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-11
          相关资源
          最近更新 更多