title: “IAM Policy Structure” created: 2026-07-22 updated: 2026-07-22 type: knowledge tags:
- aws
- iam
- security
- certification
IAM Policy Structure
What It Is
An IAM Policy is a JSON document that defines permissions. It specifies what actions are allowed or denied on which AWS resources. Policies are the core mechanism for authorization in AWS.
Why It Matters
Every permission decision in AWS goes through policy evaluation. Understanding the JSON structure is critical for writing custom policies, debugging access issues, and passing certification exams.
Key Concepts
Basic Structure
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["service:ActionName"],
"Resource": ["arn:aws:service:region:account:resource"]
}
]
}
Statement Elements
| Element | Description | Required | Example |
|---|---|---|---|
| Effect | Allow or Deny | Yes | "Allow" |
| Action | API operations permitted/denied | Yes | "ec2:DescribeInstances", "s3:GetObject" |
| Resource | AWS resources the statement applies to | Yes | "arn:aws:s3:::mybucket/*", "*" |
| Condition | Conditions for when the statement applies | No | IP range, time, MFA requirement |
| Principal | Who the statement applies to (resource-based policies only) | Depends | "AWS": "arn:aws:iam::123456789012:root" |
Action Format
Actions follow the pattern: service:ActionName
ec2:DescribeInstances— describe EC2 instancess3:GetObject— retrieve an object from S3cloudwatch:ListMetrics— list CloudWatch metricsec2:*— all EC2 actions (wildcard)
Resource Scope
"*"— any resource (broad, use carefully)- Specific ARN — targets a precise resource (e.g.,
arn:aws:s3:::mybucket/reports/*)
Multiple Statements
A policy can contain multiple statements. AWS evaluates all applicable policies and statements:
- By default, everything is denied (implicit deny)
- An explicit Allow overrides the implicit deny
- An explicit Deny always wins over any Allow
Real-World Examples
Read-only EC2 (support role):
{
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"elasticloadbalancing:Describe*",
"cloudwatch:ListMetrics",
"cloudwatch:GetMetricStatistics",
"autoscaling:Describe*"
],
"Resource": "*"
}
EC2 Admin (start/stop):
{
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": "*"
}
Gotchas
"Version": "2012-10-17"is the current policy language version — always include it- An explicit Deny always overrides an Allow (deny wins)
- Wildcards in Actions (
ec2:Describe*) match any action starting with that prefix "Resource": "*"means all resources — fine for Describe actions, dangerous for write actions- Identity-based policies (attached to users/groups/roles) don’t have a Principal element — the principal is the entity the policy is attached to
See Also
- [[iam-managed-vs-inline-policies]]
- [[iam-groups]]
- [[iam-users]]
- [[aws-arns]]
- [[s3-bucket-policies]]