如何在不达到每个 API 授权人限制的情况下在模板之间共享授权人

How to share an authorizer between templates without hitting limit of authorizers per API

我有十几个服务,每个服务都有自己的无服务器模板文件,在 API 网关上共享相同的根目录 API。 我的根 serverless.yml 文件定义了 API 和一个授权者:

...
resources:
  Resources:
    ApiGatewayRestApi:
      Type: AWS::ApiGateway::RestApi
      Properties:
        Name: ${self:service.name}-${self:provider.stage}
        Description: Medimap API Gateway
    GatewayResponseDefault4XX:
      Type: "AWS::ApiGateway::GatewayResponse"
      Properties:
        ResponseParameters:
          gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
          gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
        ResponseType: DEFAULT_4XX
        RestApiId:
          Ref: "ApiGatewayRestApi"

  Outputs:
    RestApiId:
      Value:
        Ref: ApiGatewayRestApi
      Export:
        Name: ${self:service.name}-${self:provider.stage}-RestApiId
    RootResourceId:
      Value:
        Fn::GetAtt: ApiGatewayRestApi.RootResourceId
      Export:
        Name: ${self:service.name}-${self:provider.stage}-ApiGatewayRestApiRootResourceId
    AuthenticationService:
      Value:
        Fn::GetAtt: AuthenticationServiceLambdaFunction.Arn
      Export:
        Name: ${self:service.name}-${self:provider.stage}-AuthenticationService

functions:
  authenticationService:
    handler: src/api/common/authenticationService.handler
    environment:
      JWT_SECRET: ${env:JWT_SECRET}
    events:
      - http:
          path: authenticationService
          method: post
          cors: true

在我的每项服务的模板中,我都有如下代码:

provider:
  ...
  apiGateway:
    restApiId:
      "Fn::ImportValue": "medimap-api-${self:provider.stage}-RestApiId"
    restApiRootResourceId:
      "Fn::ImportValue": "medimap-api-${self:provider.stage}-ApiGatewayRestApiRootResourceId"

custom:
  authorizer:
    name: example-authorizer
    arn:
      Fn::ImportValue: medimap-api-${self:provider.stage}-AuthenticationService

functions:
  exampleFunction:
    handler: src/api/example/exampleFunction.handler
    events:
      - http:
          path: example/exampleFunction
          method: get
          cors: true
          authorizer: ${self:custom.authorizer}

这工作正常,但是一旦我部署了 10 个服务,尝试使用相同的授权方部署第 11 个服务会出现以下错误:

Maximum number of Authorizers for this API has been reached.  Please contact AWS if you need additional Authorizers.

现在,我可以联系 AWS 来提高限制,但由于它们在技术上都是相同的授权方,我觉得我应该有一种方法可以让它工作而无需为每个模板创建单独的授权方文件。

我尝试对所有授权人使用相同的授权人名称,但我最终收到错误:

Authorizer name must be unique. Authorizer example-authorizer already exists in this RestApi

有没有一种方法可以让我在同一个 API 上的所有服务中共享这个授权者,而不必为每个服务创建一个新命名的授权者,这样我就不会达到这个限制?

您可以共享授权方本身,而不是只共享每个(新)授权方的 Lambda 函数:

Api 网关堆栈:

resources:
  Resources:
    ApiGatewayRestApi:
      Type: AWS::ApiGateway::RestApi
      Properties:
        Name: ${self:service.name}-${self:provider.stage}
        Description: Medimap API Gateway
    GatewayResponseDefault4XX:
      Type: "AWS::ApiGateway::GatewayResponse"
      Properties:
        ResponseParameters:
          gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
          gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
        ResponseType: DEFAULT_4XX
        RestApiId:
          Ref: "ApiGatewayRestApi"
    ApiGatewayAuthorizer:
      Type: AWS::ApiGateway::Authorizer
      Properties:
        AuthorizerUri:
          Fn::Join:
            - ''
            - - 'arn:'
              - { Ref: AWS::Partition }
              - ":apigateway:"
              - { Ref: AWS::Region }
              - ":lambda:path/2015-03-31/functions/"
              - { 'Fn::GetAtt': [${self:service.name}-${self:provider.stage}-authenticationService, 'Arn'] }
              - "/invocations"
        IdentitySource: method.request.header.Authorization
        Name: LambdaAuthorizer
        RestApiId:
          Ref: ApiGatewayRestApi
        Type: TOKEN

  Outputs:
    RestApiId:
      Value:
        Ref: ApiGatewayRestApi
      Export:
        Name: ${self:service.name}-${self:provider.stage}-RestApiId
    RootResourceId:
      Value:
        Fn::GetAtt: ApiGatewayRestApi.RootResourceId
      Export:
        Name: ${self:service.name}-${self:provider.stage}-ApiGatewayRestApiRootResourceId
    AuthenticationService:
      Value:
        { Ref: ApiGatewayAuthorizer }
      Export:
        Name: ${self:service.name}-${self:provider.stage}-AuthenticationService

functions:
  authenticationService:
    handler: src/api/common/authenticationService.handler
    environment:
      JWT_SECRET: ${env:JWT_SECRET}
    events:
      - http:
          path: authenticationService
          method: post
          cors: true

在你的其他堆栈中:

functions:
  exampleFunction:
    handler: src/api/example/exampleFunction.handler
    events:
      - http:
          path: example/exampleFunction
          method: get
          cors: true
          authorizer:           
            type: TOKEN 
            authorizerId:
              Fn::ImportValue: medimap-api-${self:provider.stage}-AuthenticationService

这是根据记忆+ CloudFormation文档完成的,所以请原谅任何编译错误...

来源:

https://serverless.com/framework/docs/providers/aws/events/apigateway#share-authorizer