我正在尝试创建一个自定义Lambda授权者,该授权者将在一些不同的服务/无服务器堆栈之间共享。如果我在这里https://serverless.com/framework/docs/providers/aws/events/apigateway/#note-while-using-authorizers-with-shared-api-gateway了解文档,则意味着我需要在“公共资源”服务/无服务器堆栈中创建共享授权者资源,然后从我的其他服务中引用该共享授权者。首先:我的理解正确吗?
如果我的理解正确,那么我的下一个问题将变成:我该怎么做?该文档没有为lambda授权者提供清晰的示例,因此我尝试自定义它:
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正常工作时,是否只为我的Authorizer资源添加一个Output,然后从包含我的API Lambda的服务中为Fn :: ImportValue添加它?
在无服务器论坛上链接到我的问题以供后代使用:https://forum.serverless.com/t/shared-lambda-authorizer/6447
答案 0 :(得分:3)
我最终使它能够工作,所以这是我设置身份验证器的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}
注意事项:尽管授权者函数被称为“授权者”,但与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
现在,您只需要向其他服务指定它们应该使用此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}
答案 1 :(得分:2)
我遇到了与您描述的问题相同的问题。或者至少我是这样认为的。我设法通过遵循您提供的链接上的文档来解决它。
无服务器文档指出授权者格式为
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
根据我的理解,我的解决方案(下面提供)遵循硬编码的授权者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属性至关重要。至少在目前,没有它将无法正常工作。
有关详细信息,请参见
不幸的是,与您将授权者定义为资源的建议相比,我不能说这种方法是否有某些局限性。实际上,这可能会使在同一服务中的多个功能中重复使用同一授权者变得容易。
答案 2 :(得分:0)
无服务器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
答案 3 :(得分:0)
这是我的设置方式,因为上面发布的答案对我不起作用。可能对某人有帮助。
resources:
Resources:
ApiGatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
AuthorizerResultTtlInSeconds: 0
IdentitySource: method.request.header.Authorization
AuthorizerUri:
Fn::Join: ["",
[
"arn:aws:apigateway:",
"${self:custom.region}",
":lambda:path/",
"2015-03-31/functions/",
Fn::GetAtt: ["YourFunctionNameLambdaFunction", "Arn" ],
"/invocations"
]]
RestApiId:
Fn::ImportValue: ${self:custom.stage}-ApiGatewayRestApiId
Name: api-${self:custom.stage}-authorizer
Type: REQUEST
ApiGatewayAuthorizerPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName:
Fn::GetAtt: ["YourFunctionNameLambdaFunction", "Arn"]
Action: lambda:InvokeFunction
Principal:
Fn::Join: ["",["apigateway.", { Ref: "AWS::URLSuffix"}]]
Outputs:
AuthorizerRef:
Value:
Ref: ApiGatewayAuthorizer
Export:
Name: authorizer-ref:${self:custom.stage}
我希望您知道如何添加API网关并将其导入到这里
RestApiId:
Fn::ImportValue: ${self:custom.stage}-ApiGatewayRestApiId
,因为已经在接受的答案中指定了
在我的情况下,我在事件标头中将值传递为授权 键入以在authorizer lambda函数中获取它,我的类型是 请求
答案 4 :(得分:0)
更改为共享的自定义API网关Lambda授权器非常简单,因为它已作为服务的一部分工作。那时,它只是向已部署的lambda(授权者)添加了一个arn:,并将服务中的“ authorizer”定义从服务中删除到单独的可部署服务中。
df1 <- structure(list(id = 1:17, sex = c("Female", "Female", "Female",
"Female", "Female", "Female", "Female", "Male", "Male", "Male",
"Male", "Male", "Male", "Male", "Male", "Male", "Male"), age = c(1L,
2L, 3L, 4L, 5L, 6L, 7L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L
), length = c(45L, 54L, 56L, 60L, 60L, 61L, 63L, 55L, 54L, 58L,
61L, 65L, 63L, 65L, 67L, 68L, 69L)), class = "data.frame", row.names = c(NA,
-17L))
lookup <- structure(list(sex = c("Female", "Female", "Female", "Female",
"Female", "Female", "Female", "Male", "Male", "Male", "Male",
"Male", "Male", "Male", "Male", "Male", "Male"), age = c(1L,
2L, 3L, 4L, 5L, 6L, 7L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L
), length = c(50L, 53L, 56L, 58L, 60L, 61L, 63L, 50L, 54L, 57L,
60L, 62L, 63L, 65L, 66L, 67L, 69L)), class = "data.frame", row.names = c(NA,
-17L))
然后另一个“服务”只有一些自定义授权者,由多个部署的微服务共享。
myLambdaName:
handler: handler.someNodeFunction
name: something-someNodeFunction
events:
- http:
path: /path/to/resource
method: get
cors: true
authorizer:
name: myCustomAuthorizer
# forwarding lambda proxy event stuff to the custom authorizer
IdentitySource: method.request.header.Authorization, context.path
type: request
arn: 'arn:aws:lambda:region:##:function:something-else-myCustomAuthorizer'
旁注:
如果您想要一个令牌类型授权者,它将一个简单的事件转发“ authorization:bearer xyzsddfsf”:
functions:
myCustomAuthorizer:
name: something-else-myCustomAuthorizer
handler: handler.myCustomAuthorizer
{
"type": "TOKEN",
"methodArn": "arn:aws:execute-api:region:####:apigwIdHere/dev/GET/path/to/resource",
"authorizationToken": "Bearer ...."
}