Specifying a custom role for lambda with the AWS CDK
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
When you create a Lambda function with the AWS CDK, the construct can generate an execution role for you automatically. That is convenient, but sometimes you need to provide a custom IAM role instead so you can enforce least privilege, reuse an existing policy design, or integrate the function into a broader security model.
Creating a custom role in CDK
In the CDK, the main requirement is that the role must trust the Lambda service. In TypeScript, that looks like this:
The critical part is the role property on the function. Once you pass it, Lambda uses that role instead of creating a new default execution role.
Add only the permissions you actually need
Every Lambda function needs some baseline logging permissions if it writes to CloudWatch Logs. The AWS managed policy AWSLambdaBasicExecutionRole is a common starting point, but many functions also need service-specific access.
For example, if the function reads from S3:
This is usually better than attaching broad administrator-style permissions, because it keeps the function’s blast radius smaller.
Reusing an existing role
If the role already exists, import it instead of creating a new one:
This is common in organizations where IAM roles are managed centrally and infrastructure stacks are not allowed to create their own execution roles freely.
Why a custom role is useful
A custom role helps when:
- security policy requires explicit IAM review
- several functions should share the same permission set
- you want stable role names and policies across deployments
- you need to separate infrastructure generation from IAM governance
It also makes the role visible in code as a first-class design decision instead of an implicit side effect of the Lambda construct. That usually leads to clearer reviews and better least-privilege decisions.
Grant helpers and imported-role caveats
The CDK also provides higher-level helpers such as bucket.grantRead(role) or table.grantReadWriteData(role). Those are often preferable to handwritten policy statements because they stay aligned with the resource definition and reduce policy mistakes.
If you import an existing role, remember that some imported roles are effectively immutable from the current stack. In that case, attaching new policies may not behave the way a newly created role would.
Common Pitfalls
- Forgetting the Lambda trust relationship by using the wrong
assumedByprincipal. - Passing a custom role but forgetting to include basic CloudWatch Logs permissions.
- Granting permissions too broadly instead of tailoring them to the function’s real actions.
- Importing an existing role without checking whether that role is mutable from the current stack.
Summary
- In the CDK, pass a role through the Lambda
roleproperty to use a custom execution role. - The role must trust
lambda.amazonaws.com. - Add only the permissions the function actually needs, including basic logging permissions.
- Import existing roles when IAM is managed outside the stack.
Related reading
- Spring boot startup error for AWS application There is not EC2 meta data available
- Spring boot startup error for AWS application There is not EC2 meta data available
- Spring Cloud - SQS - The specified queue does not exist for this wsdl version
- Spring Cloud AWS SQS fails to connect to service endpoint locally
- Spring Cloud AWS SQS fails to connect to service endpoint locally
- Spring cloud stream and consume multiple kafka topics
- Spring Cloud Stream dynamic channels
- Spring cloud stream kafka binding configuration max request

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.