Serverless - one dedicated IAM role per function
Need
Enforce separate IAM roles for each Lambda function
Context
- Usage of Terraform for Infrastructure as Code (IaC)
- Usage of AWS SDK for interacting with Amazon Web Services
- Usage of AWS IAM Roles for managing access and permissions in AWS services
- Usage of AWS Lambda Function for serverless computing and event-driven applications
Description
Non compliant code
provider "aws" {
region = "us-west-2"
}
resource "aws_iam_role" "iam_for_lambda" {
name = "iam_for_lambda"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_lambda_function" "lambda_function1" {
filename = "lambda_function_payload.zip"
function_name = "lambda_function_name1"
role = aws_iam_role.iam_for_lambda.arn
handler = "exports.test"
}
resource "aws_lambda_function" "lambda_function2" {
filename = "lambda_function_payload.zip"
function_name = "lambda_function_name2"
role = aws_iam_role.iam_for_lambda.arn
handler = "exports.test"
}
In the above Terraform code, we have defined an AWS IAM role iam_for_lambda
and two AWS Lambda functions lambda_function1
and lambda_function2
. Both of these Lambda functions are using the same IAM role iam_for_lambda
for execution.
The issue here is that if we need to add any specific permission to lambda_function1
, we would add it to the IAM role iam_for_lambda
. However, since lambda_function2
is also using the same IAM role, it will also get the same permissions. This can lead to unnecessary access and potential security risks.
The best practice is to have separate IAM roles for each Lambda function. This way, we can manage the permissions for each function separately, reducing the risk of unnecessary access.
Steps
- Create a separate IAM role for each Lambda function
- Update the 'aws_iam_role' resource block to define a unique name for each IAM role
- Update the 'aws_lambda_function' resource blocks to use the respective IAM role ARNs for each Lambda function
Compliant code
provider "aws" {
region = "us-west-2"
}
resource "aws_iam_role" "iam_for_lambda1" {
name = "iam_for_lambda1"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_lambda_function" "lambda_function1" {
filename = "lambda_function_payload.zip"
function_name = "lambda_function_name1"
role = aws_iam_role.iam_for_lambda1.arn
handler = "exports.test"
}
resource "aws_iam_role" "iam_for_lambda2" {
name = "iam_for_lambda2"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_lambda_function" "lambda_function2" {
filename = "lambda_function_payload.zip"
function_name = "lambda_function_name2"
role = aws_iam_role.iam_for_lambda2.arn
handler = "exports.test"
}
The updated code creates a separate IAM role for each Lambda function. This is done by defining two aws_iam_role
resource blocks, each with a unique name (iam_for_lambda1
and iam_for_lambda2
).
The aws_lambda_function
resource blocks are then updated to use the respective IAM role ARNs for each Lambda function. This is done by setting the role
attribute to the ARN of the respective IAM role (aws_iam_role.iam_for_lambda1.arn
for lambda_function1
and aws_iam_role.iam_for_lambda2.arn
for lambda_function2
).
This approach ensures that each Lambda function has its own dedicated IAM role, allowing for more granular control over permissions. This mitigates the risk of permissions being unintentionally shared across multiple functions, enhancing the security of the infrastructure.