DEV Community

Cover image for AWS IAM basics explained with real examples
Sahinur
Sahinur

Posted on

AWS IAM basics explained with real examples

When you first start working with Amazon Web Services, one of the most critical services you'll encounter is Identity and Access Management (IAM). Think of IAM as the security guard of your AWS account—it controls who can enter, what rooms they can access, and what actions they can perform.

In this guide, we'll break down IAM concepts with practical examples that you can immediately apply to your projects.


What is AWS IAM?

AWS Identity and Access Management (IAM) is a free service that allows you to securely manage access to AWS resources. With IAM, you can control:

  • Who can access your resources (authentication)
  • What they can do with those resources (authorization)

Every interaction with AWS—whether through the console, CLI, or SDK—goes through IAM for permission checks.


Core IAM Components

1. Users

An IAM user represents a person or application that interacts with AWS. Each user has unique credentials.

Real Example: Creating a Developer User

Imagine you're onboarding a new developer named Sarah to your team. She needs access to deploy applications to EC2 and view logs in CloudWatch.

{
  "UserName": "sarah-developer",
  "Tags": [
    {
      "Key": "Department",
      "Value": "Engineering"
    },
    {
      "Key": "Role",
      "Value": "Backend Developer"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Best Practice: Never use the root account for daily tasks. Create individual IAM users for each team member.


2. Groups

Groups are collections of users. Instead of attaching policies to each user individually, you attach them to a group, and all members inherit those permissions.

Real Example: Team-Based Access Structure

├── Developers (Group)
│   ├── sarah-developer
│   ├── john-developer
│   └── Policy: DeveloperAccess
│
├── DevOps (Group)
│   ├── mike-devops
│   └── Policy: DevOpsFullAccess
│
└── Finance (Group)
    ├── lisa-finance
    └── Policy: BillingReadOnly
Enter fullscreen mode Exit fullscreen mode

When Sarah moves from Development to DevOps, you simply remove her from the Developers group and add her to DevOps. No policy changes needed.


3. Roles

Roles are similar to users but are meant to be assumed temporarily by users, applications, or AWS services. They don't have permanent credentials.

Real Example: EC2 Instance Accessing S3

Your application running on EC2 needs to upload images to an S3 bucket. Instead of storing AWS credentials in your code (a security risk), you create a role:

{
  "RoleName": "EC2-S3-Upload-Role",
  "AssumeRolePolicyDocument": {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Service": "ec2.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

The EC2 instance automatically gets temporary credentials to access S3—no hardcoded keys required.


4. Policies

Policies are JSON documents that define permissions. They specify what actions are allowed or denied on which resources.

Policy Structure:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow | Deny",
      "Action": "service:action",
      "Resource": "arn:aws:service:region:account:resource",
      "Condition": { }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Real-World Policy Examples

Example 1: S3 Read-Only Access to a Specific Bucket

A mobile app needs to read images from a bucket called my-app-images:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::my-app-images",
        "arn:aws:s3:::my-app-images/*"
      ]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Example 2: Developer Access with Restrictions

Developers can manage EC2 instances but cannot terminate production servers:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ec2:*",
      "Resource": "*"
    },
    {
      "Effect": "Deny",
      "Action": "ec2:TerminateInstances",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "ec2:ResourceTag/Environment": "production"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Example 3: Time-Based Access

Contractors can only access resources during business hours:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "*",
      "Condition": {
        "DateGreaterThan": {
          "aws:CurrentTime": "2025-01-01T09:00:00Z"
        },
        "DateLessThan": {
          "aws:CurrentTime": "2025-12-31T18:00:00Z"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Example 4: Lambda Function Accessing DynamoDB

A Lambda function that reads and writes to a specific DynamoDB table:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:GetItem",
        "dynamodb:PutItem",
        "dynamodb:UpdateItem",
        "dynamodb:Query"
      ],
      "Resource": "arn:aws:dynamodb:ap-south-1:123456789012:table/UserProfiles"
    },
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Understanding Policy Evaluation

When a request is made, AWS evaluates policies in this order:

  1. Explicit Deny — If any policy explicitly denies the action, access is denied (highest priority)
  2. Explicit Allow — If a policy allows the action and nothing denies it, access is granted
  3. Implicit Deny — If no policy mentions the action, access is denied by default
Request → Check Deny → Check Allow → Default Deny
              ↓             ↓              ↓
           DENIED       ALLOWED        DENIED
Enter fullscreen mode Exit fullscreen mode

Types of IAM Policies

Policy Type Description Use Case
AWS Managed Created and maintained by AWS Quick setup with common permissions
Customer Managed Created by you Custom permissions for your organization
Inline Embedded directly in a user, group, or role Strict one-to-one relationship

Recommendation: Use customer managed policies for reusability and easier maintenance.


Security Best Practices

1. Enable Multi-Factor Authentication (MFA)

Always enable MFA for the root account and privileged users.

2. Follow the Principle of Least Privilege

Grant only the permissions required to perform a task—nothing more.

//  Bad: Too permissive
{
  "Effect": "Allow",
  "Action": "*",
  "Resource": "*"
}

//  Good: Specific and limited
{
  "Effect": "Allow",
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::my-bucket/public/*"
}
Enter fullscreen mode Exit fullscreen mode

3. Use Roles Instead of Access Keys

For applications running on AWS services, always use IAM roles instead of embedding access keys.

4. Rotate Credentials Regularly

Set up automatic rotation for access keys and review unused credentials.

5. Use IAM Access Analyzer

This tool helps identify resources shared with external entities and validates policies.


Common IAM Scenarios

Scenario 1: Cross-Account Access

Your production and development accounts are separate. Developers need to access production S3 for debugging.

Solution: Create a role in production that developers can assume from the development account.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::DEV_ACCOUNT_ID:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Scenario 2: Service-Linked Roles

Some AWS services create roles automatically to perform actions on your behalf. For example, when you use Elastic Load Balancing, AWS creates AWSServiceRoleForElasticLoadBalancing.

Scenario 3: Federated Access

Your company uses Google Workspace or Microsoft Azure AD. Instead of creating IAM users, you can federate identity:

Corporate Identity Provider → AWS STS → Temporary Credentials → AWS Access
Enter fullscreen mode Exit fullscreen mode

Debugging IAM Issues

When access is denied, check these areas:

  1. Policy Simulator — Test policies before applying them
  2. CloudTrail Logs — See exactly what was denied and why
  3. IAM Access Advisor — View which services a user actually accessed

Common Error:

An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
Enter fullscreen mode Exit fullscreen mode

Debugging Steps:

  • Verify the policy is attached to the user/role
  • Check for explicit deny statements
  • Ensure the resource ARN matches exactly
  • Verify the correct region is specified

Quick Reference: Common IAM Actions

Service Common Actions
S3 s3:GetObject, s3:PutObject, s3:DeleteObject, s3:ListBucket
EC2 ec2:RunInstances, ec2:StopInstances, ec2:TerminateInstances
Lambda lambda:InvokeFunction, lambda:CreateFunction, lambda:UpdateFunctionCode
DynamoDB dynamodb:GetItem, dynamodb:PutItem, dynamodb:Query, dynamodb:Scan
RDS rds:CreateDBInstance, rds:DeleteDBInstance, rds:DescribeDBInstances

Conclusion

AWS IAM is the foundation of security in the cloud. By understanding users, groups, roles, and policies, you can build secure applications that follow the principle of least privilege.

Start with these steps:

  1. Create individual users for your team members
  2. Organize users into groups based on job functions
  3. Use roles for applications and cross-account access
  4. Write specific policies that grant only necessary permissions
  5. Enable MFA and regularly audit your IAM configuration

Security isn't a one-time setup—it's an ongoing practice. Regularly review your IAM policies and adjust as your application evolves.


Happy building on AWS!

Top comments (0)