首页 > 解决方案 > 通过 AWS SAM 模板禁用 API Gateway 中一个方法资源端点的安全性

问题描述

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

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

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

我遇到了 CORS 问题并需要 API 密钥。前端客户端代码403 Forbidden在启动预检 CORSOPTIONS请求时出现错误,因为API Key RequiredAWS 管理控制台中TrueOPTIONS方法设置为。

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

  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 文档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 失败:Waiter 遇到终端故障状态状态:FAILED。原因:转换 AWS::Serverless-2016-10-31 失败,原因是:内部转换失败。

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

更新:

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

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

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

在此处输入图像描述

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

标签: amazon-web-servicesswaggeramazon-cloudformationaws-api-gatewayaws-serverless

解决方案


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

请参阅文档的这一部分:

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

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


推荐阅读