serverless-iam-roles-per-function-v4
v0.2.3-rc
Published
Serverless framework plugin to manage IAM roles. Compatible with serverless-aws-alias-v4 and AWS
Maintainers
Readme
serverless-iam-roles-per-function-v4
Serverless framework plugin to manage IAM roles. Compatible with serverless-aws-alias-v4 and AWS
This plugin facilitates the management of your IAM roles across different stages with or without function aliases.
Key features:
- Function-level IAM role management
- Custom role naming options
- Provider-level IAM statements inheritance
- Configurable default inheritance behavior
- Support for permissions boundaries
- Automatic inclusion of essential permissions
RELEASE CANDIDATE STATUS
THIS PLUGIN IS CURRENTLY IN RELEASE CANDIDATE STATUS. PLEASE EXERCISE CAUTION WHEN USING IT IN PRODUCTION ENVIRONMENTS.
Installation
npm install --save-dev serverless-iam-roles-per-function-v4Usage
Add the plugin to your serverless.yml file:
plugins:
- serverless-iam-roles-per-function-v4Plugin Order
This plugin must be placed after serverless-aws-alias-v4 in your plugins list.
Example:
plugins:
- serverless-esbuild # Must be the first
- serverless-aws-alias-v4 # Must be before serverless-iam-roles-per-function-v4
- serverless-iam-roles-per-function-v4
- serverless-offline # Must be the lastRoles Configuration
All roles includes permissions for creating and writing to CloudWatch logs, handling stream events, and if a VPC is defined, the AWSLambdaVPCAccessExecutionRole policy will be included.
Provider Level
Define your IAM role statements at the provider-level:
provider:
name: aws
iam:
role:
statements:
- Effect: "Allow"
Action:
- xray:PutTelemetryRecords
- xray:PutTraceSegments
Resource: "*"Function Level
The plugin creates a dedicated IAM role for each function that has an iamRoleStatements definition.
functions:
func1:
handler: handler.get
iamRoleStatementsName: my-custom-role-name # Optional custom name instead of using the default generated one
iamRoleStatements:
- Effect: "Allow"
Action:
- dynamodb:GetItem
Resource: "arn:aws:dynamodb:${self:provider.region}:*:table/name"
...
func2:
handler: handler.put
iamRoleStatements:
- Effect: "Allow"
Action:
- dynamodb:PutItem
Resource: "arn:aws:dynamodb:${self:provider.region}:*:table/name"
...If iamRoleStatements are not defined at the function level, the default behavior is maintained and the function will use the global IAM role. You can also define an empty iamRoleStatements array for a function, which will give the function a dedicated role with only the essential permissions needed for CloudWatch and, if applicable, stream events and VPC access.
Below is an example of a function with empty iamRoleStatements and a configured VPC. This function will receive a custom role with CloudWatch logs permissions and the AWSLambdaVPCAccessExecutionRole policy:
functions:
func1:
handler: handler.get
iamRoleStatements: []
vpc:
securityGroupIds:
- sg-xxxxxx
subnetIds:
- subnet-xxxx
- subnet-xxxxxBy default, function-level iamRoleStatements override any provider-level definitions. However, you can inherit the provider-level definitions by adding the option iamRoleStatementsInherit: true to your function configuration:
provider:
name: aws
iam:
role:
statements:
- Effect: "Allow"
Action:
- xray:PutTelemetryRecords
- xray:PutTraceSegments
Resource: "*"
...
functions:
func1:
handler: handler.get
iamRoleStatementsInherit: true
iamRoleStatements:
- Effect: "Allow"
Action:
- dynamodb:GetItem
Resource: "arn:aws:dynamodb:${self:provider.region}:*:table/name"The role generated for func1 will include both the statements defined at the provider level and those defined at the function level.
If you want to change the default behavior from override to inherit for all functions, you can specify the following custom configuration:
custom:
serverless-iam-roles-per-function-v4:
defaultInherit: trueRole Names
The plugin adopts a normalized naming convention for function roles. Function roles follow this naming pattern:
<FunctionName><StageOrAlias><Region>LambdaRoleWhere:
- Each component is normalized by removing underscores, converting to PascalCase
- No hyphens are used between components to maximize available space
This naming convention ensures that:
- Each stage/alias deployment gets its own dedicated role (e.g., development, staging, production)
- Roles are uniquely identifiable by function, stage/alias, and region
- Roles remain isolated between different stages or aliases
AWS imposes a 64-character limit on role names. If the generated name exceeds this limit, the plugin will throw an error with a descriptive message suggesting that you use a custom role name.
To avoid exceeding the 64-character limit, you have two options:
- Explicitly set a custom role name using the
iamRoleStatementsNameproperty
functions:
func1:
handler: handler.get
iamRoleStatementsName: my-custom-role-name
iamRoleStatements:
- Effect: "Allow"
Action:
- dynamodb:GetItem
Resource: "arn:aws:dynamodb:${self:provider.region}:*:table/name"
...- Enable the
shortenFunctionNamesoption in your custom configuration, which will automatically shorten function names in role generation:
custom:
serverless-iam-roles-per-function-v4:
shortenFunctionNames: trueWhen role names exceed the 64-character AWS limit, the plugin employs a two-step shortening process:
- First, it attempts to remove the
LambdaRolesuffix from the name - If the name is still too long and
shortenFunctionNamesis enabled, it will then shorten the function name portion
This approach helps maintain meaningful role names while staying within AWS limits.
Working with Aliases
This plugin automatically detects if you're using the serverless-aws-alias-v4 plugin and adjusts its behavior accordingly:
How Aliases Are Handled
- With serverless-aws-alias-v4 Plugin: When the plugin detects serverless-aws-alias-v4 in your plugins list, it treats all deployments as alias deployments and adopts the alias-specific deployment patterns as implemented by serverless-aws-alias-v4.
- Without serverless-aws-alias-v4 Plugin: Regular stage deployments behave normally with roles scoped to functions but without alias-specific handling.
PermissionsBoundary
You can define permission boundaries at the function level using the iamPermissionsBoundary property:
functions:
func1:
handler: handler.get
iamPermissionsBoundary: !Sub arn:aws:iam::xxxxx:policy/your_permissions_boundary_policy
iamRoleStatementsName: my-custom-role-name
iamRoleStatements:
- Effect: "Allow"
Action:
- sqs:*
Resource: "*"
...You can set a permissions boundary for all roles by using the iamGlobalPermissionsBoundary property in the custom section:
custom:
serverless-iam-roles-per-function-v4:
iamGlobalPermissionsBoundary: !Sub arn:aws:iam::xxxx:policy/permissions-boundary-policyFor more information, see Permissions Boundaries.
Controlling Role Updates
By default, this plugin overwrites existing IAM roles during deployment with the same name. You can change this behavior with the overwriteExistingRoles configuration option:
custom:
serverless-iam-roles-per-function-v4:
overwriteExistingRoles: falseWhen overwriteExistingRoles is set to:
true(default): The plugin creates or updates IAM roles for all functions. Any existing roles with the same name will be overwritten with the new definition.false: The plugin only creates new roles if they don't already exist. Existing roles are left untouched, and functions will use these existing roles as-is.
This option is particularly useful when:
- You have roles that were manually customized outside of the serverless framework
- You want to ensure that specific IAM permissions aren't accidentally modified
- You're working in environments where you want to deploy function code changes without updating IAM permissions
Preserving Roles Across Deployments
When using this plugin with serverless-aws-alias-v4, IAM roles are preserved by default during stack updates and even when the CloudFormation stack is deleted. This preservation behavior, managed by the preserveRoles option, ensures:
- Each stage/alias (dev, staging, prod) gets its own dedicated roles with unique names
- Role updates within the same stage/alias will modify the existing role instead of replacing it
- Roles are preserved even when the CloudFormation stack is updated, preventing disruption to running functions
This approach is particularly useful for multi-stage/alias deployments where you want to maintain separate but persistent IAM roles for each stage or alias.
You can control this behavior with the preserveRoles configuration:
custom:
serverless-iam-roles-per-function-v4:
preserveRoles: false # Disables role preservation with or without `serverless-aws-alias-v4`Setting preserveRoles: false will make roles follow the standard CloudFormation lifecycle, meaning they will be deleted when the stack is deleted or when they're removed from the template.
[!NOTE] When roles are preserved, you need to manually delete them from the AWS console or CLI if you want to completely clean up resources after deleting a stack.
Multi-Stage Deployment Example
When deploying to multiple stages with commands like:
serverless deploy --stage development
serverless deploy --stage staging
serverless deploy --stage productionThe plugin creates separate roles for each stage:
- Development:
MyFunctionDevelopmentUsEastLambdaRole - Staging:
MyFunctionStagingUsEastLambdaRole - Production:
MyFunctionProductionUsEastLambdaRole
Each role has the permissions defined for that function. When you update a function's permissions and redeploy to the same stage, the role is updated rather than replaced, preserving its ARN and any resources that reference it.
Statement Deduplication
The plugin automatically deduplicates IAM policy statements to prevent redundant permissions. This helps:
- Keep policies concise and clean
- Avoid reaching IAM policy size limits
- Prevent duplicate statements when inheriting provider statements
Deduplication occurs across all policy types, including CloudWatch logs, stream access, SQS permissions, and custom statements. Statements are considered duplicates when they have the same Effect, Action, Resource, and Condition properties.
Debugging
By default, only error messages are displayed. To view detailed logs, use one of these methods:
- Set the environment variable
SLS_DEBUG=* - Use the
--verboseor-vflag when deploying:sls deploy --verbose - Enable verbose logging in your custom configuration:
custom:
serverless-iam-roles-per-function-v4:
verbose: trueLicense
This project is licensed under the MIT License - see the LICENSE.md file for details.
Contributing
Contributions are welcome! Feel free to submit a pull request or open an issue.
Acknowledgments
This plugin is inspired by:
