Home > Software engineering >  Call Lambda using CustomResource
Call Lambda using CustomResource

Time:11-12

I created a CustomResource to call a lambda function when the CloudFormation stack is created. It fails with the following error:

 Received response status [FAILED] from custom resource. Message returned: User: arn:aws:sts::<account>:assumed-role/stack-role is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-1:<account>:function:<lambda> because no identity-based policy allows the lambda:InvokeFunction action

This is the code in the CDK:

import * as cr from '@aws-cdk/custom-resources';

const callLambda = new cr.AwsCustomResource(this, 'MyCustomResource', {
        onCreate: {
            service: 'Lambda',
            action: 'invoke',
            region: 'us-east-1',
            physicalResourceId: cr.PhysicalResourceId.of(Date.now.toString()),
            parameters: {
                FunctionName: `my-function`,
                Payload: '{}'
            }, 
        },
        policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
            resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
        })
    });

How can I grant permissions to the stack's assumed role so that it can perform lambda:InvokeFunction?

CodePudding user response:

Add a ResourcePolicy to your construct.

// infer the required permissions; fine-grained controls also available
policy: AwsCustomResourcePolicy.fromSdkCalls({resources: AwsCustomResourcePolicy.ANY_RESOURCE})

CodePudding user response:

I solved the issue by creating a role that assumes the lambda service principal, and adding a policy statement allowing the lambda:InvokeFunction.

import * as cr from '@aws-cdk/custom-resources';
import * as iam from "@aws-cdk/aws-iam";

let role = new iam.Role(this, `my-role`, {
        assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
    });
    role.addToPolicy(new iam.PolicyStatement({
        effect: iam.Effect.ALLOW,
        actions: ['lambda:InvokeFunction'],
        resources: ['*']
    }));
    
const callLambda = new cr.AwsCustomResource(this, 'MyCustomResource', {
    onCreate: {
        service: 'Lambda',
        action: 'invoke',
        region: 'us-east-1',
        physicalResourceId: cr.PhysicalResourceId.of(Date.now.toString()),
        parameters: {
            FunctionName: `my-function`,
            Payload: '{}'
        }, 
    },
    policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
        resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
    }),
    role: role as any
});
  • Related