Introduction
AWS security starts with one fundamental service: Identity and Access Management (IAM).
Whether you’re working with Amazon S3, EC2, Lambda, or API Gateway, IAM policies determine:
- Who can access AWS resources
- What actions they can perform
- Which resources they can access
- Under what conditions access is granted
For many beginners, IAM policies look intimidating because of their JSON format. However, once you understand the building blocks, writing and troubleshooting IAM policies becomes much easier.
In this guide, we’ll learn AWS IAM policies using practical examples.
What is an AWS IAM Policy?
An IAM policy is a JSON document that defines permissions in AWS.
A simple policy looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::your-bucket-name"
}
]
}
Components of an IAM Policy
| Component | Description |
|---|---|
| Version | Policy language version |
| Statement | Container holding permissions |
| Effect | Allow or Deny |
| Action | Operation that can be performed |
| Resource | AWS resource on which action is performed |
A More Advanced IAM Policy Example
As environments become more secure, policies often contain additional elements.
{
"Version": "2012-10-17",
"Id": "S3-Bucket-Security-Policy-2026",
"Statement": [
{
"Sid": "AllowSpecificIPsAdminAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/AdminUser"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-secure-bucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
}
]
}
Additional Elements Explained
Sid
A friendly identifier used to describe a policy statement.
Principal
Specifies who receives permission.
Condition
Adds restrictions such as IP address, MFA requirements, tags, etc.
Id
An optional identifier for the entire policy document.
Types of AWS IAM Policies
As beginners, you should focus on two important policy types:
- Identity-Based Policies
- Resource-Based Policies
Identity-Based Policies
Identity-based policies are attached directly to:
- IAM Users
- IAM Groups
- IAM Roles
These policies answer:
What can I do?
Real Example
Imagine a Lambda function needs permission to upload files into an S3 bucket.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowLambdaToWriteToHyderabadFolder",
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::Pallab-S3-Bucket-India/Hyderabad/*"
}
]
}
Because AWS already knows which role or user this policy is attached to.
Real Workflow
- Create an IAM Role.
- Assign the role to Lambda.
- Attach this policy to the role.
AWS now understands:
Lambda is allowed to write files into this S3 location.
Resource-Based Policies
Resource-based policies are attached directly to AWS resources.
Examples include:
- S3 Bucket Policies
- Lambda Resource Policies
- API Gateway Policies
These policies answer:
Who can access me?
Resource Policy Example
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAPIGatewayInvokeDispatcher",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:ap-south-1:123456789012:function:dispatcher-lambda"
}
]
}
Because the resource itself needs to know who can access or invoke it.
In this example:
API Gateway is explicitly allowed to invoke the Lambda function.
AWS Policy Evaluation Logic
This is probably the single most important IAM concept.
AWS Always Starts With Deny
AWS evaluates permissions in the following order:
Step 1
Default Deny
Step 2
Check for Allow
Step 3
Check for Explicit Deny
Step 4
If Explicit Deny exists, access is denied
Example
Allow all S3 actions:
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
Explicitly deny S3 delete operations:
{
"Effect": "Deny",
"Action": "s3:DeleteObject",
"Resource": "*"
}
❌ Delete requests are denied.
Even though an Allow exists, the Explicit Deny takes priority.
Remember: Explicit Deny Always Wins.
IAM Conditions
Conditions provide additional security controls.
Example:
{
"IpAddress": {
"aws:SourceIp": "203.0.113.0/24"
}
}
This means:
✅ Requests from the specified IP range are allowed.
❌ Requests from other locations are denied.
Common Uses
- Restrict office network access
- Allow access only through VPN
- Restrict administrative actions
- Enforce MFA authentication
What is a Trust Policy?
Trust policies answer a different question:
Who can use this role?
Example:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
What This Means
AWS allows the Lambda service to assume this IAM role.
Without a trust policy:
❌ Lambda cannot use the role.
Even if permissions are present.
Understanding AWS Authorization Flow
Let’s connect everything together.
Imagine this common architecture:
API Gateway ↓ Lambda Function ↓ S3 Bucket
Resource Policy
Checks:
Who can invoke Lambda?
Trust Policy
Checks:
Who can assume the role?
Permission Policy
Checks:
What actions can that role perform?
For example:
✅ Read S3 Objects
✅ Write S3 Objects
❌ Delete S3 Objects
Only when all policy evaluations succeed does AWS allow access.
Key Takeaways
Before working with AWS in production, remember these facts:
✅ IAM policies are written in JSON
✅ Identity policies answer “What can I do?”
✅ Resource policies answer “Who can access me?”
✅ Trust policies answer “Who can use this role?”
✅ Conditions add extra security restrictions
✅ Explicit Deny always overrides Allow
Final Thoughts
AWS IAM is the backbone of AWS security.
Once you understand:
- Identity-Based Policies
- Resource-Based Policies
- Trust Policies
- Conditions
- Authorization Flow
you can confidently secure cloud environments and troubleshoot permission issues faster.
If you’re preparing for AWS certifications, DevOps interviews, or real-world cloud projects, IAM is a topic you simply cannot skip.