Not authorized to perform lambda:InvokeFunction from Cognito trigger


#1

One of my lambda functions (authSignup) creates user account in Cognito user pool. And there is another function (authEmailTrigger) set as Custom message trigger (to change text of email confirmation). But now it started to fail with this message:

arn:aws:lambda:us-east-1:...-authSignup invocation failed with error User: arn:aws:sts::745623467555:assumed-role/awscognitoidentityproviderservice-ec2-InstanceRole-... is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-1:...-authEmailTrigger (Service: AWSLambda; Status Code: 403; Error Code: AccessDeniedException; Request ID: ...)

Weird is that it worked before in functions created by RC version of Serverless but now it fails in service deployed by latest Serverless. And I’m not aware that I would change anything in my code which could cause it (however downgrading to the rc version doesn’t help). Would anyone have some clue where could be a problem or how to fix it?

I tried to put policy allowing lambda:InvokeFunction on * to iamRoleStatements of serverless.yml but without success (anyway it wasn’t there earlier).


#2

Hi @JakubMatejka
I have the same problem but I don’t know how to deploy and assign a lambda function directly as a cognito trigger. Please, can you explain me this?

Regarding your problem the only thing seems to work is:
deploy using serverless (in my case only creates the lambda), go to amazon web console, reselect your lamdbda function on your cognito triggers section and apply changes.

Tell me if it works.
As far as I know the permission is set to the lambda function by cognito and it is not for invoke the lambda itself but allow your lambda to invoke other amazon lambda (I suppose).
I couldn’t sucess by adding lambda:InvokeFunction permission to the role…


#3

OMG, you’re right @endymion. When I remove the trigger and put it there again manually using aws console, it works. But how is that possible? I described the pool (using cli command aws cognito-idp describe-user-pool) and the trigger was set up correctly.

As far as I know setting the trigger is not possible in Serverless. We have a makefile which creates Cognito pool, then deploys lambda functions using Serverless and then assigns the function as trigger. You can see it here: https://github.com/keboola/developer-portal/blob/master/Makefile (and: https://github.com/keboola/developer-portal/blob/master/scripts/aws-setup.js#L73).


#4

So it looks like a bug in aws. If I set the trigger either by aws cli or by Javascript sdk then the lambda function fails. However when I remove it and set again from aws console, it works ok. Good news is that it is easily reproducible on the same user pool (when I remove the trigger and set again using cli, lambda function again fails). So I am going to report it to aws.


#5

@JakubMatejka can you please tell me how to do it by using the aws cli?
By the way, thank you very much for posting the links about cognito pool creation and lambda deployment :slight_smile:


#6

Sure, it is aws cognito-idp update-user-pool --region us-east-1 --user-pool-id ${poolId} --lambda-config '{"CustomMessage": "${messageHandlerArn}"}' (But be aware that you have to include all your custom settings like auto-verification, password policy, etc. or they will be reset to default values).


#8

I eventually found a solution to this:


#9

@samredway How did you set up the permission for the lambda trigger via Serverless? Is there a way to do so? We are running into the same issue with our post-confirmation lambda trigger. We used CloudFormation template to configure the Cognito user pool but the LambdaConfig doesn’t add the proper permission to lambda. And there is no way to run add-permission on Serverless.


#10

We added the following item under Resources:

UserPoolLambdaInvokePermission:
  Type: AWS::Lambda::Permission
  Properties:
    Action: lambda:invokeFunction
    Principal: cognito-idp.amazonaws.com
    FunctionName: <function-name>
    SourceArn: arn:aws:cognito-idp:<your region>:<your account>:userpool/*

This allows all your user pools to invoke the specified function.

It took me ages to find it, so I hope this helps someone!