Using the Serverless framework to create a Cognito User Pool as well as several lambdas to be used for cognito events during TOPT SMS Authorization. Everything is created however the lambda functions are not registered with Cognito.
Relatively new to Serverless jut can't seem to get them to connect. Have tried pool names as others have tried to mark as already present at the end of creation the pool is there and the lambdas are there but there is no connection.
Currently following another post tried changing user pool to CognitoUserPoolMyUserPool and then in lambda referencing it as MyUserPool. Have also tried just CognitoUserPool in both locations and neither work.
Example serverless.yaml file:
service: cognito-authentication
frameworkVersion: ">=1.1.0 <2.0.0"
package:
individually: false
plugins:
- serverless-bundle
custom:
stage: ${opt:stage, self:provider.stage}
poolName: ${self:custom.stage}-user-pool
provider:
name: aws
runtime: nodejs10.x
stage: dev
iamRoleStatements:
- Effect: Allow
Action:
- sns:*
Resource:
- "*"
functions:
preSignUp:
handler: functions/pre-signup.main
events:
- cognitoUserPool:
pool: MyUserPool
trigger: PreSignUp
defineAuthChallenge:
handler: functions/define-auth-challenge.main
events:
- cognitoUserPool:
pool: MyUserPool
trigger: DefineAuthChallenge
createAuthChallenge:
handler: functions/create-auth-challenge.main
events:
- cognitoUserPool:
pool: MyUserPool
trigger: CreateAuthChallenge
verifyAuthChallengeResponse:
handler: functions/verify-auth-challenge-response.main
events:
- cognitoUserPool:
pool: MyUserPool
trigger: VerifyAuthChallengeResponse
resources:
Resources:
CognitoUserPoolMyUserPool:
Type: "AWS::Cognito::UserPool"
Properties:
# Generate a name based on the stage
UserPoolName: ${self:custom.poolName}
# Set phone_number as an alias
UsernameAttributes:
- phone_number
Policies:
PasswordPolicy:
MinimumLength: 6
RequireLowercase: False
RequireNumbers: False
RequireSymbols: False
RequireUppercase: False
CognitoUserPoolClient:
Type: "AWS::Cognito::UserPoolClient"
Properties:
# Generate an app client name based on the stage
ClientName: ${self:custom.stage}-sms-auth-client
UserPoolId:
Ref: CognitoUserPoolMyUserPool
ExplicitAuthFlows:
- CUSTOM_AUTH_FLOW_ONLY
GenerateSecret: false
Expectation is the User Pool is correctly created and configured to use the lambdas for triggered workflow execution.
I've copied pasted your code (and added relevant Lambda functions) and it works for me.
I've tested the PreSignUp with the following command:
aws cognito-idp admin-create-user --region <region> --user-pool-id <user-pool-id> --username <phone>
While not showing in the AWS Console Lambda UI, the triggers do show up in the Cognito->User Pools->dev-user-pool->Triggers, which is confusing.
Example repo: https://github.com/erezrokah/serverless-cognito-triggers
I found the issue in your serverless.yml. You are missing an indentation under cognitoUserPool. I tried it both ways and it works with the additional indentation.
preSignUp:
handler: functions/pre-signup.main
events:
- cognitoUserPool:
pool: MyUserPool
trigger: PreSignUp
Related
I have a SAM template that was working fine until I added a trigger to my cognito user pool.
I searched about the error that is throwing me: Circular dependency between resources I can understand that the trigger is creating a reference to the user pool and then the circular dependency arises, but I can not find how to solve the problem. I only need to set the trigger of my cognito user pool to get custom messages/emails when a user is created.
This is my SAM code:
AdminCognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
AutoVerifiedAttributes:
- email
VerificationMessageTemplate:
DefaultEmailOption: CONFIRM_WITH_LINK
Policies:
PasswordPolicy:
MinimumLength: 8
UsernameAttributes:
- email
Schema:
- AttributeDataType: String
Name: email
Required: true
Mutable: true
- AttributeDataType: String
Name: id
# Required: false
Mutable: true
AdminCognitoChangePassword:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/config.customCognitoEvents
Role: !GetAtt lambdaRole.Arn
Events:
CognitoEvent:
Type: Cognito
Properties:
UserPool: !Ref AdminCognitoUserPool
Trigger: CustomMessage
The problem was in the globals function environment variables. I was calling AdminCognitoUserPool and thats why the circular dependency was rising.
I have created AWS Lambda function to run when new fils in S3 at specific path is created, which works perfectly.
service: redshift
frameworkVersion: '2'
custom:
bucket: extapp
path_prefix: 'xyz'
database: ABC
schema: xyz_dbo
table_prefix: shipmentlog
user: admin
password: "#$%^&*(*&^%$%"
port: 5439
endpoint: "*********.redshift.amazonaws.com"
role: "arn:aws:iam::*****:role/RedshiftFileTransfer"
provider:
name: aws
runtime: python3.8
stage: prod
region: us-west-2
stackName: redshift-prod-copy
stackTags:
Service: "it"
lambdaHashingVersion: 20201221
memorySize: 128
timeout: 900
logRetentionInDays: 14
environment:
S3_BUCKET: ${self:custom.bucket}
S3_BUCKET_PATH_PREFIX: ${self:custom.path_prefix}
REDSHIFT_DATABASE: ${self:custom.database}
REDSHIFT_SCHEMA: ${self:custom.schema}
REDSHIFT_TABEL_PREFIX: ${self:custom.table_prefix}
REDSHIFT_USER: ${self:custom.user}
REDSHIFT_PASSWORD: ${self:custom.password}
REDSHIFT_PORT: ${self:custom.port}
REDSHIFT_ENDPOINT: ${self:custom.endpoint}
REDSHIFT_ROLE: ${self:custom.role}
iam:
role:
name: s3-to-redshift-copy
statements:
- Effect: Allow
Action:
- s3:GetObject
Resource: "arn:aws:s3:::${self:custom.bucket}/*"
functions:
copy:
handler: handler.run
events:
- s3:
bucket: ${self:custom.bucket}
event: s3:ObjectCreated:*
rules:
- prefix: ${self:custom.path_prefix}/
- suffix: .json
existing: true
package:
exclude:
- node_modules/**
- package*.json
- README.md
plugins:
- serverless-python-requirements
But when I deployed this function, there was also another function get deployed with name redshift-prod-custom-resource-existing-s3 which is Node.js function. I want to understand why this second function necessary for triggering primary lambda function when new file is creates in S3 bucket at specific path.
It's the serverless Framework's method of adding the trigger to call the lambda to the S3 bucket via a Custom Resource
I'm trying to setup simple authorizer based on this doc. Also using serverless plugin serverless-pseudo-parameters.
My serverless configuration for authorizer:
provider:
...
logs:
httpApi: true
httpApi:
cors: true
authorizers:
simpleAuthorizer:
identitySource: $request.header.Authorization
issuerUrl:
- Fn::Join:
- '/'
- - https://cognito-idp.#{AWS::Region}.amazonaws.com
- "#{CognitoUserPool}"
audience:
- "#CognitoUserPoolClient"
My configuration for simple lambda:
functions:
ping:
name: ${self:provider.stage}-ping
handler: test.handler
events:
- httpApi:
method: GET
path: /test
authorizer:
name: simpleAuthorizer
My configuration of user pool and user pool client:
resources:
Resources:
CognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: ${self:service}-${self:provider.stage}-user
UsernameAttributes:
- email
Policies:
PasswordPolicy:
MinimumLength: 6
RequireLowercase: False
RequireNumbers: True
RequireSymbols: False
RequireUppercase: True
Schema:
- Name: email
Required: false
DeveloperOnlyAttribute: false
Mutable: true
AttributeDataType: String
CognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: cognito-example-client
GenerateSecret: False
UserPoolId: "#{CognitoUserPool}"
User pool, user pool client, HTTP API, lambda successfully created, but I can't see a authorizer at the AWS console of API Gateway service.
So, the problem has simple solution: just update your serverless (I used 1.63.0 which gave me this problem).
I am trying to deploy with VPC and this is my serverless.yaml
vpcSettings: &vpcSettings
vpc: ${self:custom.allVpcSettings.${self:provider.stage}.vpc}
provider:
name: aws
runtime: nodejs10.x
stage: ${opt:stage, 'local'}
region: us-west-1
memorySize: 256
timeout: 30
deploymentPrefix: fs-sls-${self:provider.stage}-deploy
deploymentBucket: fs-serverless-deployment
variables: ${file(.env.${opt:stage, self:provider.stage}.json)}
environment:
NODE_ENV: ${self:provider.variables.NODE_ENV}
functions:
ping:
handler: src/handler.ping
description: Let us know if the service is up and running
events:
- http:
path: ping
method: get
cors: true
graphql:
handler: src/handler.graphqlHandler
<<: *vpcSettings
description: One function where all GQL request comes
memorySize: 1024
events:
- http:
path: graphql
method: post
cors: true
- http:
path: graphql
method: get
cors: true
plugins:
- serverless-offline
custom:
serverless-offline:
port: 6000
allVpcSettings:
local:
vpc: 'This is a dummy value that should be ignored'
dev:
vpc:
securityGroupIds:
- sg-xxxxxxxxxxxxxxx
subnetIds:
- subnet-xxxxxxxxxxxxxxx
- subnet-xxxxxxxxxxxxxxx
prod:
vpc:
securityGroupIds:
- sg-xxxxxxxxxxxxxxx
subnetIds:
- subnet-xxxxxxxxxxxxxxx
- subnet-xxxxxxxxxxxxxxx
It fails with the following error
Serverless Error ---------------------------------------
The provided execution role does not have permissions to call CreateNetworkInterface on EC2
Get Support --------------------------------------------
Docs: docs.serverless.com
Bugs: github.com/serverless/serverless/issues
Issues: forum.serverless.com
Your Environment Information ---------------------------
Operating System: darwin
Node Version: 10.16.0
Framework Version: 1.52.0
Plugin Version: 2.0.0
SDK Version: 2.1.1
The user that I created for this purpose has AdministratorAccess as well as AWSLambdaVPCAccessExecutionRole in it's permissions. What else is expected here?
So I fixed it. It means the role of deploying lambda doesn't have permission. So it boils down to the fact to give it the role. First, confirm if you have the role.
Check in the image where to look for the role.
Once you don't find it. Which you most likely won't. Take the Role name and goto IAM -> Roles and Search for the role name and add AWSLambdaVPCAccessExecutionRole to the selected role.
This should give it the required permission.
Now try deploying the SLS and it should work.
Once you have the role, edit it by adding the
Although the user that you've created to deploy this lambda function has Administrator access, the lambda function itself needs networking permissions if you're deploying it into a VPC.
Try adding these permissions in the provider block of your serverless.yml template:
- Effect: Allow
Action:
- ec2:DescribeNetworkInterfaces
- ec2:CreateNetworkInterface
- ec2:DeleteNetworkInterface
- ec2:DescribeInstances
- ec2:AttachNetworkInterface
Resource:
- *
If that works, you'll want to deploy a more limited permission structure for your production environment.
In my AWS project, I use the serverless framework to deploy lambda functions and a Cognito user pool.
I want 2 of my lambda functions to be triggered by Cognito user pool events, so here is what I did:
functions:
autoMoveToUserGroup:
handler: src/auto-move-to-user-group.handler
name: auto-move-to-user-group
events:
- cognitoUserPool:
pool: test-user-pool
trigger: PostAuthentication
existing: True
autoValidationUserEmailModification:
handler: src/auto-validation-user-email-modification.handler
name: auto-validation-user-email-modification
events:
- cognitoUserPool:
pool: test-user-pool
trigger: CustomMessage
existing: True
resources:
Resources:
MyCognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: test-user-pool
AutoVerifiedAttributes:
- email
UsernameAttributes:
- email
Schema:
- Name: email
Required: True
When I deploy using the serverless deploy command, I sometimes got the following error:
An error occurred: AutoDashvalidationDashuserDashemailDashmodificationCustomCognitoUserPool1 - Failed to create resource.
Only one request to update this UserPool can be processed at a time.
It looks like a random bug, since it doesn’t occurs everytime (happens very often, though). Also, when it occurs, it doesn’t always occurs on the same function.
Did I do something wrong? How can I fix that?
Thanks for your help.
OK so here is a workaround: without using the events part in the serverless syntax, we can do this only using raw CloudFormation syntax:
resources:
Resources:
MyCognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
...
LambdaConfig:
CustomMessage: arn:aws:lambda:eu-central-1:123456789012:function:auto-validation-user-email-modification
lambdaCognitoPermissionCustomMessage:
Type: AWS::Lambda::Permission
Properties:
Action: 'lambda:InvokeFunction'
FunctionName: !Ref 'AutoValidationUserEmailModificationLambdaFunction'
Principal: cognito-idp.amazonaws.com
SourceArn: !GetAtt
- MyCognitoUserPool
- Arn
Also, according to the serverless team, it's actually a bug that should be fixed and deployed on August, 14th 2019.
Hope it helps.