[SOLVED] - scroll down to last post for solution
Hi Everyone,
I’m new to serverless and have a question about accessing resources in serverless.yml. I’ve been searching/googling for a few hours abut nothing works so far.
I have a User Pool created in a resource file: resources/cognito-user-pool.yml. Snippet:
CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
...snipped...
Outputs:
UserPoolId:
Value:
Ref: CognitoUserPool
Then in the serverless.yml I’m trying to access the UserPoolId (or CognitoUserPool) to construct an arn to pass to an event authorizer:
events:
- http:
path: <path>
method: get
cors: true
authorizer:
arn: !Join ['', ['arn:aws:cognito-idp:',!Ref AWS::Region,':',!Ref AWS::AccountId,':userpool/',!Ref CognitoUserPool]]
Now I’ve played around quite a bit with trying to get this to work. It seems that I can’t run “!Join” code on the “arn:” line of an authorizer? Can I create a custom variable?
Can someone help provide some guidance as to how I can programmatically use the generated Cognito User Pool as the authorizer?
Thanks so much for any help
Instead of attempting to construct the Arn, you can use Fn::GetAtt (or !GetAtt) to retrieve the Arn:
- http:
...
authorizer:
arn: !GetAtt 'CognitoUserPool.Arn'
or
- http:
...
authorizer:
arn: Fn::GetAtt: [CognitoUserPool, Arn]
Hope it helps.
hi @bfieber thanks for the suggestion! When I try using Fn::GetAtt: I get
Y A M L Exception --------------------------------------
incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line in "/home/val/cloudlife/git/itsacloudlife/cinekeys-project/cinekeys-test/serverless.yml" at line 98, column 28:
arn: Fn::GetAtt: [CognitoUserPool, Arn]
^
And when I try using !GetAtt I get the error
Type Error ---------------------------------------------
TypeError: functionArn.split is not a function
at Object.extractAuthorizerNameFromArn (/usr/lib/node_modules/serverless/lib/plugins/aws/lib/naming.js:135:34)
at AwsCompileApigEvents.getAuthorizer (/usr/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js:248:39)
...stack trace omitted...
Am I missing something?
Please help me to understand correctly, but, am I correct in that when you include files under resources
# you can add CloudFormation resource templates here
resources:
- ${file(resources/api-gateway-errors.yml)}
- ${file(resources/auroradb.yml)}
- ${file(resources/cognito-user-pool.yml)}
that they are not run/rendered until it gets uploaded to cloudformation? If that is the case, how can the serverless.yml hope to construct the arn: line before the User Pool resource is even created?
In another attempt, I tried having the Arn saved to a SSM, and then read in the SSM, but when the function event runs, the SSM hasn’t been populated, and it errors out.
events:
- http:
path: <path>
method: get
cors: true
authorizer:
arn: ${ssm:/cinekeys/${self:custom.stage}/UserPoolArn, "run_again_to_get_arn"}
This code syntactically works, and if I manually populate the SSM entry, it works, but, when I “serverless remove” and “deploy”, the SSM doesn’t get generated until after it’s being referenced to. Is there some sort of “depends on” or “requires” in serverless?
Thanks again!!
SOLVED.
I was able to reference an explicitly declared authorizer. In my cognito-user-pool.yml file I added the MyApiGatewayAuthorizer section, ending up with
CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: company-${self:custom.stage}-user-pool
UsernameAttributes:
- email
AutoVerifiedAttributes:
- email
MyApiGatewayAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
AuthorizerResultTtlInSeconds: 10
IdentitySource: method.request.header.Authorization
Name: MyCognitoAuthorizer
RestApiId:
Ref: ApiGatewayRestApi
Type: COGNITO_USER_POOLS
ProviderARNs:
- {"Fn::Join": ["", ["arn:aws:cognito-idp:", {Ref: "AWS::Region"}, ":", {Ref: "AWS::AccountId"}, ":userpool/", Ref: CognitoUserPool]]}
and in my function event definition, I specified the authorizer as such:
events:
- http:
path: target
method: get
cors: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId: { Ref: MyApiGatewayAuthorizer }
This worked for me. I hope it can help someone else!
6 Likes
You are god given, thank you a lot. After a day struggling around with cryptic “http parse error” or “providerArns cannot be empty” errors this is finally working.
I know this is marked as solved, but the same config doesn’t seem to apply for typescript configurations.
**Loading ..... failed with: TSError: ⨯ Unable to compile TypeScript:
serverless.ts:102:15 - error TS2322: Type '{ type: string; authorizerId: { Ref: string; }; }' is not assignable to type 'HttpAuthorizer'.
Object literal may only specify known properties, and 'authorizerId' does not exist in type 'HttpAuthorizer'.**
Any suggestions on how to solve for ts configurations?
I am also facing the same problem