Use the Conformity Knowledge Base AI to help improve your Cloud Posture

Lambda Function With Admin Privileges

Trend Cloud One™ – Conformity is a continuous assurance tool that provides peace of mind for your cloud infrastructure, delivering over 1000 automated best practice checks.

Risk Level: Medium (should be achieved)
Rule ID: Lambda-005

Ensure that your Amazon Lambda functions don't have administrative permissions (i.e. access to all AWS cloud services and resources) in order to promote the Principle of Least Privilege (POLP) and provide your functions the minimal amount of access required to perform their tasks.

This rule can help you with the following compliance standards:

  • PCI
  • APRA
  • MAS
  • NIST4

For further details on compliance standards supported by Conformity, see here.

This rule can help you work with the AWS Well-Architected Framework.

This rule resolution is part of the Conformity Security & Compliance tool for AWS.

Security

The permissions assumed by a Lambda function are determined by the IAM execution role associated with the function. With the right execution role, you can control the privileges that your Amazon Lambda function has, therefore, instead of providing administrative permissions you should grant the role the necessary permissions that your function really needs.


Audit

To identify any Amazon Lambda functions with admin privileges, available in your AWS account, perform the following actions:

Using AWS Console

01 Sign in to the AWS Management Console.

02 Navigate to Amazon Lambda console at https://console.aws.amazon.com/lambda/.

03 In the left navigation panel, under AWS Lambda, choose Functions.

04 Click on the name (link) of the function that you want to examine.

05 Select the Configuration tab and choose Permissions from the left menu.

06 In the Execution role section, click on the name of the execution role listed under Role name to access the IAM role details.

07 Select the Permissions tab to access the identity–based policies attached to the selected IAM role.

08 In the Permissions policies section, click on the Expand button (right arrow icon) available next to each managed/inline policy, and choose {} JSON to show the policy document in JSON format.

09 Within the {} JSONpolicy document box, identify the "Action" element defined for each statement and check the element value. If the "Action" element value is set to "*" and the "Effect" element is set to "Allow", the role policy provides access to all the supported AWS cloud services and resources. Repeat this step for each IAM policy attached to the selected execution role. If one or more policies allow access to all AWS services and resources, the execution role provides administrative permissions, therefore the selected Amazon Lambda function has admin privileges.

10 Repeat steps no. 4 – 9 for each Lambda function available within the current AWS region.

11 Change the AWS cloud region from the console navigation bar and repeat the Audit process for other regions.

Using AWS CLI

01 Run list-functions command (OSX/Linux/UNIX) to list the names of all the Amazon Lambda functions available in the selected AWS region:

aws lambda list-functions
  --region us-east-1
  --output table
  --query 'Functions[*].FunctionName'

02 The command output should return a table with the requested function name(s):

--------------------------
|      ListFunctions     |
+------------------------+
|  cc-process-app-queue  |
|  cc-export-user-data   |
|  cc-get-ec2-log-data   |
+------------------------+

03 Run get-function command (OSX/Linux/UNIX) using the name of the Amazon Lambda function that you want to examine as the identifier parameter, to describe the Amazon Resource Name (ARN) of the execution role associated with the selected function:

aws lambda get-function
  --region us-east-1
  --function-name cc-process-app-queue
  --query 'Configuration.Role'

04 The command output should return the execution role ARN. The Amazon Resource Name (ARN) includes the role name, e.g. "cc-app-function-execution-role":

"arn:aws:iam::123456789012:role/service-role/cc-app-function-execution-role"

05 Run list-attached-role-policies command (OSX/Linux/UNIX) using the name of the execution role returned at the previous step as the identifier parameter and custom query filters to list the Amazon Resource Name (ARN) of each managed policy attached to the selected IAM role:

aws iam list-attached-role-policies
  --role-name cc-app-function-execution-role
  --query 'AttachedPolicies[*].PolicyArn'

06 The command output should return the ARN of each managed policy attached to the selected role:

[
	"arn:aws:iam::123456789012:policy/cc-lambda-managed-policy"
]

07 Run get-policy-version command (OSX/Linux/UNIX) using the ARN of the IAM managed policy that you want to examine as the identifier parameter and custom filtering to describe the policy document (JSON format) defined for the selected policy version:

aws iam get-policy-version
  --policy-arn arn:aws:iam::123456789012:policy/cc-lambda-managed-policy
  --version-id v1
  --query 'PolicyVersion.Document'

08 The command output should return the requested IAM policy document:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Action": "*",
			"Resource": "*",
			"Effect": "Allow"
		}
	]
}

Identify the "Action" element defined for each policy statement and check the element value. If the "Action" element value is set to "*" and the Effect element is set to "Allow", as shown in the example above, the execution role policy provides access to all the supported AWS cloud services and resources, therefore the selected Amazon Lambda function has admin privileges.

09 Run list-role-policies command (OSX/Linux/UNIX) using the name of the execution role associated with your function as the identifier parameter and custom filtering to describe the name of each inline policy attached to the selected role:

aws iam list-role-policies
  --role-name cc-app-function-execution-role
  --query 'PolicyNames'

10 The command output should return the name of each inline policy associated with the selected role:

[
	"cc-lambda-inline-policy"
]

11 Run get-group-policy command (OSX/Linux/UNIX) using the name of the inline policy returned at the previous step as the identifier parameter and custom query filters to describe the policy document (JSON format) defined for the selected inline policy:

aws iam get-role-policy
  --role-name cc-app-function-execution-role
  --policy-name cc-lambda-inline-policy
  --query 'PolicyDocument'

12 The command output should return the requested inline policy document:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Action": [
				"*"
			],
			"Resource": [
				"*"
			],
			"Effect": "Allow",
			"Sid": "FullAccess"
		}
	]
}

Identify the "Action" element defined for each policy statement and check the element value. If the "Action" element value is set to "*" and the Effect element is set to "Allow", as shown in the output example above, the execution role policy provides access to all the supported AWS services and resources, therefore the selected Amazon Lambda function has admin privileges.

13 Repeat steps no. 3 – 12 for each Lambda function available in the selected AWS region.

14 Change the AWS cloud region by updating the --region command parameter value and repeat steps no. 1 – 13 to perform the Audit process for other regions.

Remediation / Resolution

To implement the Principle of Least Privilege (POLP) and provide your Lambda functions with the right set of permissions instead of full admin permissions, perform the following actions:

Using AWS CloudFormation

01 CloudFormation template (JSON):

{
	"AWSTemplateFormatVersion": "2010-09-09",
	"Resources": {
		"FunctionExecutionRole": {
			"Type": "AWS::IAM::Role",
			"Properties": {
				"RoleName": "LambdaExecutionRole",
				"AssumeRolePolicyDocument": {
					"Version": "2012-10-17",
					"Statement": [
						{
							"Effect": "Allow",
							"Principal": {
								"Service": [
									"lambda.amazonaws.com"
								]
							},
							"Action": [
								"sts:AssumeRole"
							]
						}
					]
				},
				"Path": "/",
				"ManagedPolicyArns": [
					"arn:aws:iam::aws:policy/AdministratorAccess"
					"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
					"arn:aws:iam::aws:policy/service-role/AWSXRayDaemonWriteAccess"
				]
			}
		},
		"LambdaFunction": {
			"Type": "AWS::Lambda::Function",
			"Properties": {
				"FunctionName": "cc-app-worker-function",
				"Handler": "lambda_function.lambda_handler",
				"Role": {
					"Fn::GetAtt": [
						"FunctionExecutionRole",
						"Arn"
					]
				},
				"Code": {
					"S3Bucket": "cc-lambda-functions",
					"S3Key": "worker.zip"
				},
				"Runtime": "python3.9",
				"MemorySize": 1024,
				"Timeout": 45,
				"VpcConfig": {
					"SecurityGroupIds": [
						"sg-0abcd1234abcd1234"
					],
					"SubnetIds": [
						"subnet-abcd1234",
						"subnet-1234abcd"
					]
				}
			}
		}
	}
}

02 CloudFormation template (YAML):

AWSTemplateFormatVersion: '2010-09-09'
	Resources:
	FunctionExecutionRole:
		Type: AWS::IAM::Role
		Properties:
		RoleName: LambdaExecutionRole
		AssumeRolePolicyDocument:
			Version: '2012-10-17'
			Statement:
			- Effect: Allow
				Principal:
				Service:
					- lambda.amazonaws.com
				Action:
				- sts:AssumeRole
		Path: /
		ManagedPolicyArns:
			- arn:aws:iam::aws:policy/AdministratorAccess
			- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
			- arn:aws:iam::aws:policy/service-role/AWSXRayDaemonWriteAccess
	LambdaFunction:
		Type: AWS::Lambda::Function
		Properties:
		FunctionName: cc-app-worker-function
		Handler: lambda_function.lambda_handler
		Code:
			S3Bucket: cc-lambda-functions
			S3Key: worker.zip
		Runtime: python3.9
		MemorySize: 1024
		Timeout: 45
		VpcConfig:
			SecurityGroupIds:
			- sg-0abcd1234abcd1234
			SubnetIds:
			- subnet-abcd1234
			- subnet-1234abcd
		Role: !GetAtt 'FunctionExecutionRole.Arn'

Using Terraform (AWS Provider)

01 Terraform configuration file (.tf):

terraform {
	required_providers {
		aws = {
			source  = "hashicorp/aws"
			version = "~> 4.0"
		}
	}

	required_version = ">= 0.14.9"
}

provider "aws" {
	profile = "default"
	region  = "us-east-1"
}

resource "aws_iam_role" "lambda-execution-role" {
	name = "LambdaExecutionRole"
	path = "/"
	assume_role_policy = <<EOF
	{
		"Version": "2012-10-17",
		"Statement": [
			{
				"Action": "sts:AssumeRole",
				"Principal": {
				"Service": "lambda.amazonaws.com"
				},
				"Effect": "Allow"
			}
		]
	}
	EOF
	managed_policy_arns = ["arn:aws:iam::aws:policy/AdministratorAccess"]
	managed_policy_arns = ["arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]
	managed_policy_arns = ["arn:aws:iam::aws:policy/service-role/AWSXRayDaemonWriteAccess"]
}

resource "aws_lambda_function" "lambda-function" {
	function_name    = "cc-app-worker-function"
	s3_bucket        = "cc-lambda-functions"
	s3_key           = "worker.zip" 
	handler          = "lambda_function.lambda_handler"
	runtime          = "python3.9"
	memory_size      = 1024
	timeout          = 45   
	vpc_config {
		subnet_ids         = [ "subnet-01234abcd1234abcd", "subnet-0abcd1234abcd1234" ]
		security_group_ids = [ "sg-0abcd1234abcd1234" ]
	}
	role = aws_iam_role.lambda-execution-role.arn
}

Using AWS CLI

01 Sign in to the AWS Management Console.

02 Navigate to Amazon Lambda console at https://console.aws.amazon.com/lambda/.

03 In the left navigation panel, under AWS Lambda, choose Functions.

04 Click on the name of the function that you want to reconfigure.

05 Select the Configuration tab and choose Permissions from the left menu.

06 In the Execution role section, choose Edit to change the execution role that defines the permissions for the selected function.

07 On the Edit basic settings configuration**page, perform one of the following operations:

  1. To associate the function with an existing, compliant IAM role, choose Use an existing role from the Execution role, and select the required role from the Existing role dropdown list. The chosen IAM role must follow the Principle of Least Privilege and provide only the access required by the selected function. Choose Save to apply the changes.
  2. To apply a new execution role to your Lambda function, choose Create a new role from AWS policy templates to create a new execution role for the selected Amazon Lambda function. Provide a unique name for the new role in the Role name box and select one or more policy templates from the Policy templates dropdown list. Based on your function's access requirements, select only the necessary permission set(s) from the Policy templates - optional dropdown list. Choose Save to apply the changes.

08 Repeat steps no. 4 – 7 to change the permissions for each Amazon Lambda function with admin privileges, available within the current AWS region.

09 Change the AWS cloud region from the navigation bar and repeat the Remediation process for the other regions.

Using AWS CLI

01 Create the trust relationship policy required for the new execution role. This trust policy allows Amazon Lambda to use the role's permissions by giving the service principal "lambda.amazonaws.com" permission to call the AWS Security Token Service "AssumeRole" action. To create the required trust policy for the new IAM role, save the following policy document to a JSON file named cc-execution-role-trust-policy.json:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Principal": {
				"Service": "lambda.amazonaws.com"
			},
			"Action": "sts:AssumeRole"
		}
	]
}

02 Run create-role command (OSX/Linux/UNIX) to create a new IAM execution role using the trust relationship policy defined at the previous step:

aws iam create-role
  --role-name cc-new-app-function-role
  --assume-role-policy-document file://cc-execution-role-trust-policy.json.json

03 The command output should return the metadata available for the new IAM role:

{
	"Role": {
		"AssumeRolePolicyDocument": {
			"Version": "2012-10-17",
			"Statement": [
				{
					"Action": "sts:AssumeRole",
					"Effect": "Allow",
					"Principal": {
						"Service": "lambda.amazonaws.com"
					}
				}
			]
		},
		"RoleId": "AAAABBBBCCCCDDDDEEEEF",
		"CreateDate": "2021-08-30T11:00:00Z ",
		"RoleName": "cc-new-app-function-role",
		"Path": "/",
		"Arn": "arn:aws:iam::123456789012:role/cc-new-app-function-role"
	}
}

04 The following AWS-managed policies provide permissions that are required to use Amazon Lambda features (see the official documentation for the updated list of managed policies):

  • "AWSLambdaBasicExecutionRole" – permission to upload logs to Amazon CloudWatch Logs.
  • "AWSLambdaDynamoDBExecutionRole" – permission to read records from an Amazon DynamoDB stream.
  • "AWSLambdaKinesisExecutionRole" – permission to read events from an Amazon Kinesis data stream or consumer.
  • "AWSLambdaMQExecutionRole" – permission to read records from an Amazon MQ broker.
  • "AWSLambdaMSKExecutionRole" – permission to read records from an Amazon Managed Streaming for Apache Kafka (Amazon MSK) cluster.
  • "AWSLambdaSQSQueueExecutionRole" – permission to read a message from an Amazon Simple Queue Service (Amazon SQS) queue.
  • "AWSLambdaVPCAccessExecutionRole" – permission to manage elastic network interfaces to connect your function to a virtual private cloud (VPC).
  • "AWSXRayDaemonWriteAccess" – permission to upload trace data to X-Ray.
  • "CloudWatchLambdaInsightsExecutionRolePolicy" – permission to write runtime metrics to CloudWatch Lambda Insights.

05 Run attach-role-policy command (OSX/Linux/UNIX) to attach an AWS-managed policy to the newly created execution role. Based on your function's access requirements, choose the appropriate policy from the list of managed policies described at the previous step. Make sure that the execution role has the right set of permissions in order to follow the Principle of Least Privilege (POLP). In the following command request example, the "AWSLambdaBasicExecutionRole" managed policy provides permission to upload Amazon Lambda function logs to Amazon CloudWatch Logs (the command does not produce an output):

aws iam attach-role-policy
  --role-name cc-new-app-function-role
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

06 Run update-function-configuration command (OSX/Linux/UNIX) using the name of the Amazon Lambda function that you want to reconfigure as the identifier parameter, to replace the shared execution role with the new IAM role created and configured at the previous steps:

aws lambda update-function-configuration
  --region us-east-1
  --function-name cc-process-app-queue
  --role arn:aws:iam::123456789012:role/cc-new-app-function-role

07 The command output should return the metadata available for the reconfigured function:

{
	"LastUpdateStatus": "Successful",
	"FunctionName": "cc-process-app-queue",
	"LastModified": "2021-08-30T11:00:00.000+0000",
	"RevisionId": "abcdabcd-1234-abcd-1234-abcd1234abcd",
	"MemorySize": 128,
	"State": "Active",
	"Version": "$LATEST",
	"Role": "arn:aws:iam::123456789012:role/cc-new-app-function-role",
	"Timeout": 45,
	"Runtime": "nodejs12.x",
	"TracingConfig": {
		"Mode": "PassThrough"
	},
	"CodeSha256": "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
	"Description": "",
	"CodeSize": 403,
	"FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:cc-process-app-queue",
	"Handler": "index.handler"
}

08 Repeat steps no. 1 – 7 to change the permissions for each Amazon Lambda function with admin privileges, available in the selected AWS region.

09 Change the AWS cloud region by updating the --region command parameter value and repeat steps no. 1 – 8 to perform the Remediation process for other regions.

References

Publication date Oct 14, 2017