Search code examples
aws-cloudformation

Resource handler returned message: "Invalid request provided: AWS::Cognito::UserPoolUser"


I use cloudformation template from other AWS account but today I have this error:

Resource handler returned message: "Invalid request provided: AWS::Cognito::UserPoolUser" (RequestToken: d55c7a26-473f-3eda-b1af-fdc97afc5364, HandlerErrorCode: InvalidRequest)

My cloudformation template:

  CGNAdminUser:
    Type: AWS::Cognito::UserPoolUser
    Properties:
      DesiredDeliveryMediums:
        - EMAIL
      UserAttributes:
        - Name: email
          Value: !Ref Email
      Username: !Ref Username 
      UserPoolId: !Ref CGNUserPool

I try add this but do not work:

DependsOn: CGNUserPool

I try change UserPoolId: !Ref CGNUserPool UserPoolId by UserPoolId: !GetAtt CGNUserPool.UserPoolId but do not work again

May be AWS bug today because, my user is created !!

enter image description here


Solution

  • Check if you have a CustomMessage attribute in your CGNuserPool. If so, it may be this one that fails. Checkout if you have an event named AdminCreateUser in your CloudTrail (you can access it from CloudFormation console under the stack that failed, you should have a link named "View the CloudTrail events for this resource".

    In the CloudTrail event, check in Event record if you have an entry named errorMessage. You'll have the root error.

    If you need your DynamoDB to have data inserted while creating, the problem has been solved here: PutItem in DynamoDB table by CloudFormation

    Solution is to create a custom resource like:

    UsersTable: 
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: !Sub "${AWS::StackName}-my-users-table"
        AttributeDefinitions: 
          - 
            AttributeName: "username"
            AttributeType: "S"
        KeySchema: 
          - 
            AttributeName: "username"
            KeyType: "HASH"
    
    MyFunction:
      Type: AWS::Serverless::Function
        Properties:
          FunctionName: !Sub "${AWS::StackName}-PopulateTable"
          Environment:
            Variables:
              TABLE_NAME: !Ref UsersTable
              USERNAME: !Ref Username
              EMAIL: !Ref Email
          CodeUri: src/populateFunction
          Role: #an execution role defined
    
    SetData:
      Type: Custom::InitFunction
      DependsOn: MyFunction
      Properties:
        ServiceToken: !GetAtt MyFunction.Arn
    

    And under src/populateFunction/index.js your function should contain:

    const axios = require('axios');
    exports.handler = async function(event, context) {
        if (event.RequestType !== "Create") {
            console.log("Not a Create request, exiting.");
            const responseBody = JSON.stringify({
                Status: "SUCCESS",
                Reason: "No action needed.",
                PhysicalResourceId: context.logStreamName,
                StackId: event.StackId,
                RequestId: event.RequestId,
                LogicalResourceId: event.LogicalResourceId
            });
        
            console.log("Sending response to CloudFormation:", responseBody);
        
            try {
                await axios.put(event.ResponseURL, responseBody, { headers: { "Content-Type": "" } });
            } catch (err) {
                console.error("Failed to send response to CloudFormation:", err);
            }
            return;
        }
        // Your function 
    }
    

    Else, CloudFormation will run for hours waiting for your function...

    Finally you can insert your cognito config and don't forget to make it depends on your user table (DependsOn: !Ref UsersTable)