Настройка общего лямбда-авторизатора в Serverless Framework - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь создать собственный Lambda-авторизатор, который будет распределен между несколькими различными стеками служб / серверов.Если я понимаю документацию здесь https://serverless.com/framework/docs/providers/aws/events/apigateway/#note-while-using-authorizers-with-shared-api-gateway,, это означает, что мне нужно создать общий ресурс авторизатора в стеке службы / общих ресурсов «общие ресурсы», а затем обратиться к этому общему авторизатору из других моих служб.Прежде всего: правильное ли мое понимание?

Если мое понимание правильное, мой следующий вопрос звучит так: как мне это сделать?Документация не дает четкого примера для лямбда-авторизаторов, поэтому вот как я пытался ее настроить:

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

Я не понимаю, каким должен быть синтаксис для AuthorizerUri.Я пытался «Ref: authorizerFunc», «Fn :: GetAtt: [authorizerFunc, Arn]» и т. Д. Безрезультатно.

Когда я получаю, что authorizerUri работает, я просто добавляю вывод для моего авторизатораресурс, затем Fn :: ImportValue это из сервисов, содержащих мой API Lambdas?

Ссылка на мой вопрос на форуме о сервере для потомков: https://forum.serverless.com/t/shared-lambda-authorizer/6447

Ответы [ 3 ]

0 голосов
/ 03 апреля 2019

Я в итоге заставил его работать, вот как я настроил 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}

Вещи, на которые следует обратить внимание: несмотря на то, что функция Authorizer называется «Authorizer», вам необходимо использовать заглавную букву и добавить «LambdaFunction» к ее имени при использовании его с GetAtt, поэтому «Authorizer» становится «AuthorizerLambdaFunction» по некоторым причинам. , Я также должен был добавить ресурс разрешения лямбды.

Ресурсу шлюза API также требуется два выхода: его идентификатор API и идентификатор корневого ресурса API. Вот как настроен serverless.yml моего шлюза API:

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

Теперь вам просто нужно указать другим сервисам, что они должны использовать этот 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

После этого авторизатор может быть добавлен к отдельным функциям в этом сервисе следующим образом:

          authorizer:
            type: CUSTOM
            authorizerId:
              Fn::ImportValue: authorizer-ref:${opt:stage}
0 голосов
/ 28 апреля 2019

Без сервера 1.35.1 Для людей, спотыкающихся по этой теме, вот новый способ

Где бы вы ни создавали пул пользователей, вы можете добавить ApiGatewayAuthorizer

# create a user pool as normal
CognitoUserPoolClient:
  Type: AWS::Cognito::UserPoolClient
  Properties:
    # Generate an app client name based on the stage
    ClientName: ${self:custom.stage}-user-pool-client
    UserPoolId:
      Ref: CognitoUserPool
   ExplicitAuthFlows:
   - ADMIN_NO_SRP_AUTH
   GenerateSecret: true

# then add an authorizer you can reference later
ApiGatewayAuthorizer:
  DependsOn:
  # this is pre-defined by serverless
  - ApiGatewayRestApi
  Type: AWS::ApiGateway::Authorizer
  Properties:
    Name: cognito_auth
    # apparently ApiGatewayRestApi is a global string
    RestApiId: { "Ref" : "ApiGatewayRestApi" }
    IdentitySource: method.request.header.Authorization
    Type: COGNITO_USER_POOLS
    ProviderARNs:
    - Fn::GetAtt: [CognitoUserPool, Arn]

Тогда, когда вы определите свои функции

graphql:
  handler: src/app.graphqlHandler
  events:
  - http:
    path: /
    method: post
    cors: true
    integration: lambda
    # add this and just reference the authorizer
    authorizer:
      type: COGNITO_USER_POOLS
      authorizerId:
        Ref: ApiGatewayAuthorizer
0 голосов
/ 28 января 2019

У меня была та же проблема, которую вы описали. Или, по крайней мере, я так думаю. И мне удалось решить эту проблему, следуя документации по предоставленным вами ссылкам.

В серверной документации указано, что формат авторизатора равен

authorizer:
  # Provide both type and authorizerId
  type: COGNITO_USER_POOLS # TOKEN or COGNITO_USER_POOLS, same as AWS Cloudformation documentation
  authorizerId: 
    Ref: ApiGatewayAuthorizer  # or hard-code Authorizer ID

Насколько я понимаю, мое решение (приведено ниже) следует жестко закодированному идентификатору авторизатора.

В службе, имеющей общий авторизатор, он объявлен в serverless.yml обычным образом, т.е.

functions:
  myCustomAuthorizer:
    handler: path/to/authorizer.handler
    name: my-shared-custom-authorizer

Затем в службе, которая хочет использовать этот общий авторизатор, функция в servlerless.yml объявлена ​​как

functions:
  foo:
    # some properties ...
    events:
      - http:
          # ... other properties ...
          authorizer:
            name: authorize
            arn:
              Fn::Join:
                - ""
                - - "arn:aws:lambda"
                  # References to values such as region, account id, stage, etc
                  # Can be done with Pseudo Parameter Reference
                  - ":"
                  - "function:myCustomAuthorizer"

Важно было добавить свойство name. Без него ничего бы не получилось, по крайней мере, на данный момент.

Подробнее см.

К сожалению, я не могу сказать, имеет ли этот подход некоторые ограничения по сравнению с вашим предложением об определении авторизатора в качестве ресурса. Фактически, это может упростить повторное использование одного и того же авторизатора в нескольких функциях в пределах одной службы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...