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/*"
}
]
}
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"
}
}
}
]
}
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": "*"
}
]
}
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*"
]
}
]
}
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"
}
}
}
]
}
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"
}
}
}
]
}
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": "*"
}
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/*"
]
}
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/*"
}
]
}
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:
- By default, everything is denied π«
- Check for explicit Allow β
- Check for explicit Deny β
- 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)
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}/*"
}
]
}
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:
- Go to IAM Policy Simulator
- Select a user or role
- Choose a service (like S3)
- Select an action (like GetObject)
- 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": "*"
}
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!
}
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": { ... }
}
]
}
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:
- Version: Always use "2012-10-17"
- Effect: Allow or Deny
- Principal: Who gets access
- Action: What they can do
- Resource: Where they can do it
- Condition: When it applies
- 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)