Skip to main content
Skip to main content
Still in beta — questions, comments or suggestions? aramb@aramb.dev

Tighten IAM Permissions with Least Privilege

Learn how to apply the principle of least privilege by scoping Lambda execution roles to specific AWS actions and resources.

30 min
Introductory
AWS Free TierFREE TIER

All services used in this lesson are covered by the AWS Free Tier.

AWS Services Used

IAMAlways free

Learning Outcomes

By the end of this lesson, you will be able to:

  1. Explain what least privilege means for this project.
  2. Identify which Lambda function needs which AWS actions.
  3. Replace overly broad permissions with narrower, resource-scoped policies.
  4. Explain why S3 object actions and DynamoDB table actions should be limited to specific resources.
  5. Understand the lifecycle of permissions from development to production.

The Core Idea

Now that the dashboard works, the next hardening step is to stop relying on permissions that are broader than necessary. AWS IAM and Lambda guidance both recommend least privilege: grant only the permissions required to do the task, and restrict those permissions to the specific resources the workload actually needs.

Broad vs. Least-Privilege Permissions

Mapping Functions to Permissions

In this project, each Lambda function has a narrow job. Their IAM permissions should reflect that:

1) Upload-Ticket Lambda

  • Action: s3:PutObject (required to generate a presigned upload request).
  • Resource: arn:aws:s3:::YOUR_BUCKET/incoming/*.

2) Metadata-Writer Lambda

  • Action: dynamodb:PutItem.
  • Resource: arn:aws:dynamodb:REGION:ACCOUNT:table/upload_metadata.

3) Metadata-Detail Lambda

  • Actions: dynamodb:GetItem and s3:GetObject (for download links).
  • Resources: Specific table and specific bucket prefix.

4) Metadata-List Lambda

  • Action: dynamodb:Query (not Scan, and definitely not Put/Delete).
  • Resource: Specific table.

The One Permission Every Function Needs

Your Lambda functions always need permission to write logs to CloudWatch. Least privilege does not mean removing logging; it means keeping everything else as narrow as possible.

Standard logging actions:

  • logs:CreateLogGroup
  • logs:CreateLogStream
  • logs:PutLogEvents

Example: Narrow Policy for Upload Ticket

Instead of using s3:* on all resources, use a policy like this:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowUploadPrefixOnly",
      "Effect": "Allow",
      "Action": ["s3:PutObject"],
      "Resource": "arn:aws:s3:::YOUR_UPLOAD_BUCKET/incoming/*"
    },
    {
      "Sid": "WriteLogs",
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "*"
    }
  ]
}

What to Remove

If you see these in your production roles, they are candidates for tightening:

  • "Action": "s3:*"
  • "Action": "dynamodb:*"
  • "Resource": "*" (except for logging where * is often required for the log group creation).

Lab Checklist

StepSuccess Condition
Audit RolesEvery Lambda has its own execution role
Scope S3Object actions are limited to a specific bucket and prefix
Scope DynamoDBTable actions are limited to the metadata table only
Remove Wildcards* is removed from non-logging Actions
Verify FunctionFunctions still work after tightening permissions

Micro-activity 1: Audit Your Project

Least Privilege Audit
0 / 5 filled

For each function, write the narrowest permission it actually needs and the specific resource ARN it should be scoped to.


Micro-activity 2: Reflection

Think about it

Why is s3:GetObject on a specific prefix better than s3:* on all resources? Why is dynamodb:Query preferred over broader permissions for a list function?


Summary

Least privilege is the most important security habit in the cloud. By stopping the use of shared, broad roles and moving to narrow, per-function permissions, you significantly reduce the "blast radius" of any potential security event.


Quiz

Knowledge Check
1 / 5

What does least privilege mean in this project?