With Lambda functions, you should follow least-privileged access and only allow the access needed to perform a given operation. Attaching a role with more permissions than necessary can open up your systems for abuse.
Limitations on policies
This rule only works with inline IAM policy documents: policies defined as part of an IAM role resource and, for AWS::Serverless::Function resources without an explicit Role, inline policy documents in the function's Policies property. It will not check managed policies, policies defined as separate resources, or SAM policy templates such as DynamoDBWritePolicy, which are not expanded into effective permissions.
IAM Statement elements written either as a single object or as a list are both supported. The rule checks wildcard actions (for example * or s3:*); a wildcard in a Resource ARN, such as arn:aws:s3:::my-bucket/*, does not by itself trigger this rule.
Resources:MyRole:Type:AWS::IAM::RoleProperties:AssumeRolePolicyDocument:Version:"2012-10-17"Statement:-Effect:AllowPrincipal:Service:-lambda.amazonaws.comAction:-sts:AssumeRole# The rule will check this policyPolicies:-PolicyName:rootPolicyDocument:Version:"2012-10-17"Statement:-Effect:AllowAction:dynamodb:QueryResource:"*"# It will not check this policyMyPolicy:Type:AWS::IAM::PolicyProperties:PolicyDocument:Version:"2012-10-17"Statement:-Effect:AllowAction:dynamodb:*Resource:"*"Roles:-!GetAttMyRole.Arn
resource"aws_iam_role""this"{name="my-function-role"assume_role_policy=data.aws_iam_policy_document.assume.json # The rule will check this policyinline_policy{name="FunctionPolicy"policy=data.aws_iam_policy_document.valid.json}}# It will not check this policyresource"aws_iam_policy""this"{policy=data.aws_iam_policy_document.invalid.json}resource"aws_iam_policy_attachment""this"{roles=[aws_iam_role.this.name]policy_arn=aws_iam_policy.this.arn}data"aws_iam_policy_document""assume"{statement{actions=["sts:AssumeRole"]principals{type="Service"identifiers=["lambda.amazonaws.com"]}}}data"aws_iam_policy_document""valid"{statement{actions=["dynamodb:Query"]resources=["arn:aws:dynamodb:eu-west-1:111122223333:table/my-table"]}}data"aws_iam_policy_document""invalid"{statement{actions=["dynamodb:*"]resources=["*"]}}
If your Lambda function needs a broad range of permissions, you do not know ahead of time which permissions you will need, and you have evaluated the risks of using broad permissions for this function, you might ignore this rule.
AWS SAM templates
For AWS::Serverless::Function resources without an explicit Role, this rule checks inline IAM policy documents in the function's effective Policies property. Named managed policies and SAM policy templates such as DynamoDBWritePolicy are not expanded into effective permissions.
import{AttributeType,Table}from'@aws-cdk/aws-dynamodb';import{Code,Function,Runtime}from'@aws-cdk/aws-lambda';exportclassMyStackextendscdk.Stack{constructor(scope:cdk.Construct,id:string,props?:cdk.StackProps){super(scope,id,props);constmyTable=newTable(scope,'MyTable',{partitionKey:{name:'id',type:AttributeType.STRING,}},);constmyFunction=newFunction(scope,'MyFunction',{code:Code.fromAsset('src/hello/'),handler:'main.handler',runtime:Runtime.PYTHON_3_8,});// Grant read access to the DynamoDB tabletable.grantReadData(myFunction);}}
1 2 3 4 5 6 7 8 91011121314151617181920212223
{"Resources":{"MyFunction":{"Type":"AWS::Serverless::Function","Properties":{"CodeUri":".","Runtime":"python3.8","Handler":"main.handler","Policies":[{"Version":"2012-10-17","Statement":[{"Effect":"Allow",// Tightly scoped permissions to just 's3:GetObject'// instead of 's3:*' or '*'"Action":"s3:GetObject","Resource":"arn:aws:s3:::my-bucket/*"}]}]}}}}
1 2 3 4 5 6 7 8 910111213141516
Resources:MyFunction:Type:AWS::Serverless::FunctionProperties:CodeUri:.Runtime:python3.12Handler:main.handlerPolicies:-Version:"2012-10-17"Statement:-Effect:Allow# Tightly scoped permissions to just 's3:GetObject'# instead of 's3:*' or '*'Action:s3:GetObjectResource:"arn:aws:s3:::my-bucket/*"
1 2 3 4 5 6 7 8 9101112131415
provider:name:awsiam:role:name:my-function-rolestatements:-Effect:Allow# Tightly scoped permissions to just 's3:GetObject'# instead of 's3:*' or '*'Action:s3:GetObjectResource:"arn:aws:s3:::my-bucket/*"functions:hello:handler:handler.hello
resource"aws_iam_role""this"{name="my-function-role"assume_role_policy=data.aws_iam_policy_document.assume.jsoninline_policy{name="FunctionPolicy"policy=data.aws_iam_policy_document.this.json}}data"aws_iam_policy_document""assume"{statement{actions=["sts:AssumeRole"]principals{type="Service"identifiers=["lambda.amazonaws.com"]}}}data"aws_iam_policy_document""this"{statement{ # Tightly scoped permissions to just 'dynamodb:Query' # instead of 'dynamodb:*' or '*'actions=["dynamodb:Query"]resources=["arn:aws:dynamodb:eu-west-1:111122223333:table/my-table"]}}resource"aws_lambda_function""this"{function_name="my-function"handler="main.handler"runtime="python3.8"filename="function.zip"role=aws_iam_role.this.arn}