DEV Community

Himanshu Maheshwari
Himanshu Maheshwari

Posted on

AWS IAM Policies-Simple & Easy

Imagine you're running a company building, and you need to control who can access different rooms. Some employees can only view the conference room schedule, while others can book rooms, and managers can access the server room. AWS IAM Policies work exactly like this - they're the security system that controls who can do what in your AWS environment.

In this guide, I'll break down IAM policies in simple terms, so even if you're new to AWS, you'll understand how to control access to your cloud resources.


What are IAM Policies?

Think of IAM policies as permission slips in AWS. Just like a parent gives permission to a teacher to take their child on a field trip, IAM policies give permission to users or applications to access AWS resources.

The Structure of an IAM Policy

An IAM policy is like a recipe card with specific ingredients:

{
  "Version": "2012-10-17",
  "Id": "s3-account-permissions",
  "Statement": [
    {
      "Sid": "1",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::mybucket/*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Breaking It Down (in Simple Terms)

1. Version - Like a Date Stamp on a Document

  • Always use "2012-10-17" (the latest version)
  • Think of it as the "policy format version"
  • This tells AWS which rules to follow when reading your policy

2. Id (Optional) - A Nickname for Your Policy

  • Example: "s3-account-permissions"
  • Helps you identify what this policy does
  • Like naming a document "Sales_Team_Permissions" instead of "Document1"

3. Statement - The Actual Rules (The Important Part!)

  • This is where you define WHO can do WHAT
  • You can have multiple statements in one policy
  • Each statement is like a separate rule

4. Sid (Optional) - Statement ID

  • A label for each individual permission rule
  • Example: "AllowReadAccess" or "DenyDeleteOperations"
  • Useful when you have multiple rules and need to identify them

5. Effect - The Decision: Allow or Deny

  • "Allow" = Yes, you can do this βœ…
  • "Deny" = No, you cannot do this ❌
  • Deny always wins if there's a conflict

6. Principal - WHO Gets the Permission

  • The person, role, or service getting access
  • Example: "arn:aws:iam::123456789012:root" (an AWS account)
  • Think of it as the "name on the permission slip"

7. Action - WHAT They Can Do

  • Specific tasks allowed/denied
  • Example: "s3:GetObject" (download files), "s3:PutObject" (upload files)
  • You can use wildcards: "s3:*" means all S3 actions

8. Resource - WHERE They Can Do It

  • Which AWS resources this applies to
  • Example: "arn:aws:s3:::mybucket/*" (all files in "mybucket")
  • Like saying "only in this specific room"

9. Condition (Optional) - WHEN This Applies

  • Extra rules like time of day, IP address, etc.
  • Example: Only allow access from the office IP
  • Adds an extra layer of security

Real-World Example: Photo Storage App

Let's say you're managing a photo storage app. You want photographers to upload and download photos, but only from your office network:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowUserToUploadPhotos",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::987654321098:user/photographer"
      },
      "Action": [
        "s3:PutObject",
        "s3:GetObject"
      ],
      "Resource": "arn:aws:s3:::customer-photos/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "203.0.113.0/24"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Translation in Plain English:

  • Who: The photographer user
  • Can do what: Upload (PutObject) and download (GetObject) photos
  • Where: In the customer-photos bucket
  • When: Only when connected from the office IP address (203.0.113.0/24)

More Policy Examples

Example 1: Read-Only Access to EC2 Instances

Scenario: You want your intern to view all EC2 instances but not make any changes.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EC2ReadOnly",
      "Effect": "Allow",
      "Action": [
        "ec2:Describe*",
        "ec2:Get*"
      ],
      "Resource": "*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

What it means:

  • The intern can see (Describe and Get) all EC2 information
  • They cannot create, modify, or delete instances
  • The * wildcard means all EC2 resources

Use case: Perfect for team members who need to monitor servers but shouldn't change anything.


Example 2: Developer Access with Restrictions

Scenario: You want developers to work freely in the development environment but stay away from production.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowDevelopmentEnvironment",
      "Effect": "Allow",
      "Action": [
        "ec2:*",
        "s3:*",
        "lambda:*"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": "us-west-2"
        }
      }
    },
    {
      "Sid": "DenyProductionAccess",
      "Effect": "Deny",
      "Action": "*",
      "Resource": [
        "arn:aws:s3:::production-*",
        "arn:aws:ec2:*:*:instance/i-prod*"
      ]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

What it means:

  • First statement: Developers can do anything with EC2, S3, and Lambda in the us-west-2 region
  • Second statement: But they are explicitly blocked from any production resources (buckets starting with "production-" and instances starting with "i-prod")
  • Deny wins, so even if allowed elsewhere, production is off-limits

Use case: Gives developers freedom to experiment while protecting critical production systems.


Example 3: Time-Based Access

Scenario: Contractors should only access resources during business hours.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "BusinessHoursOnly",
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::project-files/*",
      "Condition": {
        "DateGreaterThan": {
          "aws:CurrentTime": "2024-01-01T09:00:00Z"
        },
        "DateLessThan": {
          "aws:CurrentTime": "2024-12-31T17:00:00Z"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

What it means:

  • Contractors can access project files
  • Only between 9 AM and 5 PM
  • Automatically enforced by AWS

Example 4: Multi-Factor Authentication (MFA) Required

Scenario: For sensitive operations, require MFA.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowWithMFA",
      "Effect": "Allow",
      "Action": [
        "ec2:StopInstances",
        "ec2:TerminateInstances"
      ],
      "Resource": "*",
      "Condition": {
        "BoolIfExists": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

What it means:

  • Users can stop or terminate EC2 instances
  • Only if they've authenticated with MFA
  • Prevents accidental or unauthorized shutdowns

Common IAM Policy Patterns

Pattern 1: Least Privilege Principle

Concept: Give users the minimum permissions they need to do their job.

Bad Example ❌:

{
  "Effect": "Allow",
  "Action": "*",
  "Resource": "*"
}
Enter fullscreen mode Exit fullscreen mode

This gives full access to everything - dangerous!

Good Example βœ…:

{
  "Effect": "Allow",
  "Action": [
    "s3:GetObject",
    "s3:ListBucket"
  ],
  "Resource": [
    "arn:aws:s3:::my-bucket",
    "arn:aws:s3:::my-bucket/*"
  ]
}
Enter fullscreen mode Exit fullscreen mode

This gives only read access to a specific bucket.


Pattern 2: Using Deny for Extra Security

Concept: Explicitly deny critical actions to prevent accidents.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowMostS3Actions",
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::my-bucket/*"
    },
    {
      "Sid": "NeverAllowDelete",
      "Effect": "Deny",
      "Action": [
        "s3:DeleteBucket",
        "s3:DeleteObject"
      ],
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

What it means: Users can do most S3 operations, but deletion is always blocked.


Understanding Policy Evaluation

When you make a request to AWS, here's how it decides if you're allowed:

  1. By default, everything is denied 🚫
  2. Check for explicit Allow βœ…
  3. Check for explicit Deny ❌
  4. Deny always wins πŸ†

Example Decision Flow:

Request: Delete S3 object
   ↓
Is there an Allow? β†’ Yes (s3:* is allowed)
   ↓
Is there a Deny? β†’ Yes (s3:DeleteObject is denied)
   ↓
Result: DENIED ❌ (Deny wins)
Enter fullscreen mode Exit fullscreen mode

Policy Variables for Dynamic Permissions

You can use variables to create flexible policies:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowUserToAccessTheirOwnFolder",
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::shared-bucket/${aws:username}/*"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

What it means:

  • Each user can only access their own folder
  • ${aws:username} automatically inserts the user's name
  • John can access /shared-bucket/john/*
  • Sarah can access /shared-bucket/sarah/*

Testing Your Policies

Use the IAM Policy Simulator

AWS provides a tool to test policies before applying them:

  1. Go to IAM Policy Simulator
  2. Select a user or role
  3. Choose a service (like S3)
  4. Select an action (like GetObject)
  5. Click "Run Simulation"

This shows you if the action would be allowed or denied.


Common Mistakes to Avoid

Mistake 1: Using * Too Broadly

{
  "Effect": "Allow",
  "Action": "*",
  "Resource": "*"
}
Enter fullscreen mode Exit fullscreen mode

Problem: Gives full access to everything in AWS
Solution: Be specific about actions and resources

Mistake 2: Forgetting Resource ARNs

{
  "Effect": "Allow",
  "Action": "s3:GetObject"
  // Missing "Resource" field!
}
Enter fullscreen mode Exit fullscreen mode

Problem: Policy won't work without specifying resources
Solution: Always include the Resource field

Mistake 3: Not Testing Policies

Problem: Policies might not work as expected
Solution: Always test with IAM Policy Simulator before applying


Best Practices

1. Start Small, Then Expand

  • Begin with minimal permissions
  • Add more as needed
  • Don't start with full access

2. Use Groups for Common Permissions

  • Create groups like "Developers", "Admins", "Readers"
  • Assign policies to groups
  • Add users to groups

3. Regular Audits

  • Review policies quarterly
  • Remove unused permissions
  • Update for new requirements

4. Document Your Policies

  • Add comments explaining why policies exist
  • Use descriptive Sid values
  • Keep a change log

5. Use Managed Policies When Possible

  • AWS provides pre-built policies
  • Examples: ReadOnlyAccess, PowerUserAccess
  • Easier to maintain

Quick Reference

Policy Template

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DescriptiveName",
      "Effect": "Allow|Deny",
      "Principal": { "AWS": "arn:..." },
      "Action": ["service:Action"],
      "Resource": "arn:...",
      "Condition": { ... }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Common Actions

  • S3: s3:GetObject, s3:PutObject, s3:DeleteObject, s3:ListBucket
  • EC2: ec2:RunInstances, ec2:StopInstances, ec2:DescribeInstances
  • Lambda: lambda:InvokeFunction, lambda:CreateFunction, lambda:UpdateFunctionCode
  • IAM: iam:CreateUser, iam:AttachUserPolicy, iam:GetUser

Conclusion

IAM policies are the foundation of AWS security. By understanding how to structure and apply them, you can:

βœ… Control who accesses your resources

βœ… Specify exactly what actions are allowed

βœ… Add conditions for extra security

βœ… Follow the principle of least privilege

βœ… Keep your AWS environment secure

Key Takeaways:

  1. Version: Always use "2012-10-17"
  2. Effect: Allow or Deny
  3. Principal: Who gets access
  4. Action: What they can do
  5. Resource: Where they can do it
  6. Condition: When it applies
  7. Deny always wins in conflicts

Remember: Good IAM policies are specific, tested, and regularly reviewed. Start with minimal permissions and add more only when needed.


Additional Resources


Pro Tip: Always test your policies in a non-production environment first. Use the IAM Policy Simulator to verify they work as expected before applying them to real users!

Stay secure! πŸ”’

Top comments (0)