2
votes

I'm using serverless to deploy an AWS CloudFormation template and some functions, here is a part of my serverless.yml file:

resources:
  Resources:
    MyUserPool: #An inline comment
      Type: "AWS::Cognito::UserPool"
      Properties:
        UserPoolName: "MyUserPool"
        Policies:
          PasswordPolicy: 
            MinimumLength: 7
            RequireLowercase: false
            RequireNumbers: true
            RequireSymbols: false
            RequireUppercase: false
functions:
  preSignUp:
    handler: presignup.validate
    events:
      - cognitoUserPool:
          pool: "MyUserPool"
          trigger: PreSignUp

As you can see, both user pool names are the same, but when I run serverless deploy, 2 user pools with the same name are created.

enter image description here

Is this a bug or am I missing something?

2

2 Answers

6
votes

I also found this to be counter-intuitive and confusing at first. However, this is actually the expected (and documented) behavior.

When you attach a Cognito event to a function as a trigger, Serverless will create a user pool for you, without even being asked. Source:

This will create a Cognito User Pool with the specified name.

So in your case, one user pool is being created by the cognitoUserPool event, and the other is being created by your Resources section. The one created by Resources is correct (has the custom password policy), and the one created by the lambda trigger has default configuration. The fix is described under the "Overriding a generated User Pool" heading.

You prefix the User Pool key in the Resources section with CognitoUserPool, which will cause both your trigger and your resource to refer to the same User Pool in the generated CloudFormation template.

In your case, this means simply changing this:

resources:
  Resources:
    MyUserPool:
      Type: "AWS::Cognito::UserPool"

to this:

resources:
  Resources:
    CognitoUserPoolMyUserPool:
      Type: "AWS::Cognito::UserPool"

Tested with Serverless 1.26.0

5
votes

The correct way to do this is by setting existing: true on your functions cognitoUserPool properties like so...

  createAuthChallenge:
    handler: services/auth/createAuthChallenge.handler
    events:
      - cognitoUserPool:
          pool: ${self:custom.stage}-user-pool
          trigger: CreateAuthChallenge
          existing: true

Serverless added support for this in July 2019.