Developing least privilege IAM roles
As you develop a Lambda function, you expand the scope of this policy to enable access to other resources. For example, for a function that processes objects put into an S3 bucket, it requires read access to objects stored in that bucket. Do not grant the function broader permissions to write or delete data, or operate in other buckets.
Determining the exact permissions can be challenging, since IAM permissions are very granular and they control access to both the data plane and control plane. The following references are useful for developing IAM policies:
-
All IAM actions, resources, and condition keys available for AWS services are listed in this documentation page.
-
Build policies with the AWS Policy Generator
to help formulate the syntax. -
Test your policies with the IAM Policy Simulator
, and see the documentation for this tool. -
Using the AWS IAM role-comparison tool
to extract and compare IAM roles from different AWS accounts.
One of the fastest ways to scope permissions appropriately is to use AWS SAM policy templates. You can reference these templates directly in the AWS SAM template for your application, providing custom parameters as required:

Example AWS SAM template from https://github.com/aws-samples/s3-to-lambda-patterns/blob/master/translation/v1/template.yaml
In this example, the S3CrudPolicy template provides full create, read, update, and delete permissions to one bucket, and the S3ReadPolicy template provides read-only access to another bucket. AWS SAM named templates expand into more verbose CloudFormation policy definitions that show how the principle of least privilege is applied. The S3ReadPolicy is defined as:
"Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject", "s3:ListBucket", "s3:GetBucketLocation", "s3:GetObjectVersion", "s3:GetLifecycleConfiguration" ], "Resource": [ { "Fn::Sub": [ "arn:${AWS::Partition}:s3:::${bucketName}", { "bucketName": { "Ref": "BucketName" } } ] }, { "Fn::Sub": [ "arn:${AWS::Partition}:s3:::${bucketName}/*", { "bucketName": { "Ref": "BucketName" } } ] } ] } ]
It includes the necessary, minimal permissions to retrieve the S3 object, including getting the bucket location, object version, and lifecycle configuration.