Shared Lambda authorizer setup in Serverless Framework

Dan*_*Dan 7 amazon-web-services serverless-framework

I am trying to create a custom Lambda authorizer that will be shared between a few different services/serverless stacks. If I understand the documentation here https://serverless.com/framework/docs/providers/aws/events/apigateway/#note-while-using-authorizers-with-shared-api-gateway, that means that I need to create a shared authorizer resource in a “common resources” service/serverless stack, and then refer to that shared authorizer from my other services. First of all: Is my understanding correct?

If my understanding is correct, my next question becomes: How do I do this? The documentation doesn’t provide a clear example for lambda authorizers, so here’s how I tried to customize it:

functions:
authorizerFunc:
handler: authorizer/authorizer.handler
runtime: nodejs8.10

resources:
Resources:
authorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
AuthorizerResultTtlInSeconds: 0
Name: Authorizer
Type: REQUEST
AuthorizerUri: ???
RestApiId:
Fn::ImportValue: myRestApiId
Run Code Online (Sandbox Code Playgroud)

I don’t understand what the syntax for AuthorizerUri is supposed to be. I’ve tried “Ref: authorizerFunc”, “Fn::GetAtt: [authorizerFunc, Arn]” etc. to no avail.

When I get the authorizerUri working, do I just add an Output for my authorizer resource, then Fn::ImportValue it from the services containing my API Lambdas?

Link to my question on the Serverless forum for posterity: https://forum.serverless.com/t/shared-lambda-authorizer/6447

Dan*_*Dan 5

编辑:显然我的答案现在已经过时了。对于较新版本的无服务器,请参阅其他答案。我不知道哪个答案是最好/最新的,但如果有人让我知道,我会更改该答案所接受的答案。

我最终让它工作起来,所以这是我设置我的autherizer的serverless.yml的方法:

service: user-admin-authorizer

custom:
  region: ${file(serverless.env.yml):${opt:stage}.REGION}

provider:
  name: aws
  region: ${self:custom.region}

functions:
  authorizer:
    handler: src/authorizer.handler
    runtime: nodejs8.10

resources:
  Resources:
    Authorizer:
      Type: AWS::ApiGateway::Authorizer
      Properties:
        Name: Authorizer
        Type: REQUEST
        AuthorizerUri:
          Fn::Join: [ "",
            [
              "arn:aws:apigateway:",
              "${self:custom.region}",
              ":lambda:path/",
              "2015-03-31/functions/",
              Fn::GetAtt: ["AuthorizerLambdaFunction", "Arn" ],
              "/invocations"
            ]]
        RestApiId:
          Fn::ImportValue: api-gateway:${opt:stage}:rest-api-id
    apiGatewayLambdaPermissions:
      Type: AWS::Lambda::Permission
      Properties:
        FunctionName:
          Fn::GetAtt: [ AuthorizerLambdaFunction, Arn]
        Action: lambda:InvokeFunction
        Principal:
          Fn::Join: [ "",
          [
            "apigateway.",
            Ref: AWS::URLSuffix
          ]]

  Outputs:
    AuthorizerRef:
      Value:
        Ref: Authorizer
      Export:
        Name: authorizer-ref:${opt:stage}

Run Code Online (Sandbox Code Playgroud)

需要注意的是:尽管授权者函数名为“authorizer”,但与 GetAtt 一起使用时,需要将首字母大写并在其名称后附加“LambdaFunction”,因此“authorizer”由于某种原因变成了“AuthorizerLambdaFunction”。我还必须添加 lambda 权限资源。

API 网关资源还需要两个输出,即其 API ID 和 API 根资源 ID。以下是我的 API 网关的 serverless.yml 的设置方式:

resources:
  Resources:
    ApiGateway:
      Type: AWS::ApiGateway::RestApi
      Properties:
        Name: ApiGateway
  
  Outputs:
    ApiGatewayRestApiId:
      Value:
        Ref: ApiGateway
      Export:
        Name: api-gateway:${opt:stage}:rest-api-id
    ApiGatewayRestApiRootResourceId:
      Value:
        Fn::GetAtt:
          - ApiGateway
          - RootResourceId
      Export:
        Name: api-gateway:${opt:stage}:root-resource-id
Run Code Online (Sandbox Code Playgroud)

现在您只需向其他服务指定它们应该使用此 API 网关(导入的值是 API 网关的输出):

provider:
  name: aws
  apiGateway:
    restApiId:
      Fn::ImportValue: api-gateway:${opt:stage}:rest-api-id
    restApiRootResourceId:
      Fn::ImportValue: api-gateway:${opt:stage}:root-resource-id
Run Code Online (Sandbox Code Playgroud)

之后,可以将授权者添加到该服务中的各个功能中,如下所示:

          authorizer:
            type: CUSTOM
            authorizerId:
              Fn::ImportValue: authorizer-ref:${opt:stage}
Run Code Online (Sandbox Code Playgroud)