serverless / serverless/serverless
Custom Resource Cognito Pool event triggers not responding to pool changes on updates
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 46.9k
- Forks
- 5.7k
- Avg merge
- 10h 7m
- Merged PRs (30d)
- 57
Description
Are you certain it's a bug?
- Yes, it looks like a bug
Is the issue caused by a plugin?
- It is not a plugin issue
Are you using the latest v3 release?
- Yes, I'm using the latest v3 release
Is there an existing issue for this?
- I have searched existing issues, it hasn't been reported yet
Issue description
Context
I have a Lambda that's listening to a cognitoUserPool trigger event. (I've used CustomMessage in my example, but in my actual code i'm also using PreAuthentication, PostConfirmation etc.). I have previously deployed the stack, and now I want to change the pool that the lambda is hooked into (in the example from dev to prod). I'm doing this by changing the pool property on the cognitoUserPool object.
Problem
When I deploy following updating the pool, the resource-based policy statement attached to the Lambda to allow Cognito to invoke the Lambda doesn't get updated. The policy statement is still called serverless-custom-resource-issue-prod-hello-my-user-pool-dev, and it is still pointing at the arn of the dev pool. I would have expected this statement to become serverless-custom-resource-issue-prod-hello-my-user-pool-prod, and this statement to contain the arn of the prod pool.
It looks like this is because this is causing the AWS Custom Resource RequestType to be Update - which in turn is calling the update function here. The update function is successfully changing the config to point the Cognito pool at this Lambda - I've confirmed this in the Cognito Console. Crucially however, it's not doing the permission changes to allow Cognito to invoke the Lambda. If you look at both the create() and delete() functions in the same Lambda, you can see these are creating/deleting this permission respectively. Essentially, there's no way to update this policy statement without deleting and recreating the Custom Resource.
Proposed Fix
I'm not entirely sure what the best approach here would be, as not all update events would necessarily require a permissions change - e.g. if you're changing the trigger type, the permissions stay the same.
The approach that requires the least code changes would likely be to add both removePermission(..) then addPermission(..) to the update fn, but maybe that's too lazy? As sometimes it would be removing/deleting needlessly.
Could alternatively create an updatePermission function that checks the current permission, and sees if it matches what the new information would require - likely just check that the StatementId and SourceArn match what would be created? This could then inform whether or not to remove the old and add a new permission at that point.
Extra Notes
Initially I thought forceDeploy might be the fix, but I think that isn't actually helping here, as that just changes a property on the Custom Resource, which is the cause for an update RequestUpdate. Given the pool has changed - and the Custom::CognitoUserPool object in the cloudformation template update has successfully pulled across the Properties.UserPoolName as anonymous-user-pool-prod I don't think adding this did anything for this flow.
Service configuration (serverless.yml) content
First deploy
service: serverless-custom-resource-issue
frameworkVersion: "3"
provider:
name: aws
runtime: nodejs18.x
region: eu-west-2
functions:
hello:
handler: handler.hello
events:
- cognitoUserPool:
pool: "my-user-pool-dev"
trigger: 'CustomMessage'
existing: true
forceDeploy: true
Second deploy
```yaml
service: serverless-custom-resource-issue
frameworkVersion: "3"
provider:
name: aws
runtime: nodejs18.x
region: eu-west-2
functions:
hello:
handler: handler.hello
events:
- cognitoUserPool:
pool: "my-user-pool-prod"
trigger: 'CustomMessage'
existing: true
forceDeploy: true
### Command name and used flags
sls deploy
### Command output
```shell
N/A
Environment information
Framework Core: 3.36.0
Plugin: 7.1.0
SDK: 4.4.0
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in lib/plugins/aws/custom-resources/resources/cognito-user-pool/handler.js, especially the update function at lines 43-55, and compare it with the create() and delete() functions. Reproduce the change with sls deploy, switching the pool from dev to prod. Done means the Lambda permission statement and source ARN follow the updated Cognito pool without breaking unchanged trigger updates.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, javascript
- Domain
- authentication, backend, cloud
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100