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
});