
After studying this material, you should be able to:
Identity and Access Management (IAM) is AWS's system for controlling who can do what on AWS resources.
IAM Policy Example:
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject"],
"Resource": "arn:aws:s3:::my-bucket/*"
}
This policy says: "Allow reading and writing objects in my-bucket only."
Give applications only the permissions they need — nothing more.
| Permission Level | Risk |
|---|---|
| Too broad | Security vulnerability — attacker gains excessive access |
| Too narrow | Application breaks — missing required permissions |
| Just right ✓ | Secure and functional |
Why is this hard?
There are three existing approaches, each with significant drawbacks:
AWS provides pre-built policies like AmazonS3FullAccess.
AmazonS3FullAccess grants:
- s3:GetObject ✓ (you need this)
- s3:PutObject ✓ (you need this)
- s3:DeleteBucket ✗ (you DON'T need this)
- s3:DeleteObject ✗ (you DON'T need this)
- ... 50+ more permissions you don't need
Problem: Designed for common scenarios, not your specific use case → overpermissive
A security expert manually reads your code and writes precise policies.
Problem:
Ask an AI: "What IAM permissions does my code need?"
Problems:
Hand-crafted IPA fills Managed
Least-Privilege ←—— this gap ——→ Policies
(too hard) (too broad)
IPA is a deterministic static-analysis tool that:
| Property | Meaning |
|---|---|
| Deterministic | Same code → same policy, every time |
| Static Analysis | Analyzes code without executing it |
| Authoritative | Uses up-to-date AWS service metadata |
| Traceable | Every permission linked back to source code line |
This is the heart of IPA. Think of it as an assembly line:
Source Code
↓
[Phase 1: Parse]
↓
SDK Calls Identified
↓
[Phase 2: Map]
↓
Required Permissions
↓
[Phase 3: Synthesize]
↓
IAM Policy Document
Technique: Abstract Syntax Tree (AST) Pattern Matching
What is an AST? When code is parsed, it becomes a tree structure representing its grammar.
# Your Python code:
s3_client.get_object(Bucket='my-bucket', Key='file.txt')
AST representation:
Call
├── Attribute: get_object
│ └── Name: s3_client
└── Arguments:
├── Bucket = 'my-bucket'
└── Key = 'file.txt'
IPA scans this tree looking for patterns that match AWS SDK calls.
What it identifies:
get_object, put_item)Not every SDK call maps 1:1 to an IAM permission. IPA consults authoritative AWS service metadata to get the correct mapping.
SDK Call → IAM Permission Required
─────────────────────────────────────────────────
s3.get_object() → s3:GetObject
dynamodb.put_item() → dynamodb:PutItem
lambda.invoke() → lambda:InvokeFunction
Why this matters:
IPA assembles all discovered permissions into a valid IAM policy document.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"dynamodb:PutItem",
"lambda:InvokeFunction"
],
"Resource": "*",
"_provenance": {
"s3:GetObject": "app.py:line 42",
"dynamodb:PutItem": "app.py:line 87",
"lambda:InvokeFunction": "handler.py:line 15"
}
}
]
}
Key feature — Provenance: Every permission is traced back to its origin in source code.
"Why does this policy have
dynamodb:PutItem?" "Because of line 87 in app.py."
This makes the policy auditable and explainable.
The researchers tested IPA in two settings:
| Method | Result |
|---|---|
| Minimal baseline (hand-crafted) | Reference point |
| IPA-generated | ✅ Sufficient for 9/10 apps |
| AI-generated | Similar or worse than IPA |
| Managed policies | Worked but overpermissive |
Permission Count Comparison:
─────────────────────────────────────────────────────
Managed Policies (optimal selection): ~100 permissions
Expert Developer-authored: ~X permissions
IPA-generated: ~0.6X permissions
─────────────────────────────────────────────────────
IPA vs Managed Policies: ~10x fewer permissions ✓
IPA vs Expert-authored: ~40% fewer permissions ✓
Interpretation:
┌─────────────────────────────────────────────────────┐
│ YOUR APPLICATION CODE │
│ Python / Java / Go / TypeScript │
└──────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ PHASE 1: PARSE (AST) │
│ Find all AWS SDK calls in the code │
│ → s3.get_object(), dynamodb.put_item(), ... │
└──────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ PHASE 2: MAP │
│ SDK calls → IAM permissions │
│ Using authoritative AWS metadata │
└──────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ PHASE 3: SYNTHESIZE │
│ Build IAM policy document │
│ With provenance (source code tracing) │
└──────────────────────┬──────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ GENERATED IAM POLICY │
│ ✓ Deterministic ✓ Least-privilege │
│ ✓ Traceable ✓ Up-to-date │
└─────────────────────────────────────────────────────┘
IPA is not perfect. Understanding its limitations is important:
| Limitation | Why It Happens |
|---|---|
| Dynamic calls | If SDK service/method is determined at runtime, static analysis can't see it |
| 1/10 benchmark failure | Some permissions missed due to complex code patterns |
| Starting point, not final | May need manual review for production use |
| No resource-level scoping | Generates "Resource": "*" rather than specific ARNs |
| Concept | Key Point |
|---|---|
| IAM | Controls what AWS actions applications can perform |
| Least Privilege | Grant only necessary permissions |
| Problem | Managed policies = too broad; Manual = too hard; AI = unreliable |
| IPA | Deterministic static analysis tool for policy generation |
| Phase 1 | AST parsing to find SDK calls |
| Phase 2 | Map SDK calls to IAM permissions using AWS metadata |
| Phase 3 | Synthesize policy with provenance |
| Results | 9/10 benchmarks pass; 10x fewer permissions than managed policies |
| Limitation | Dynamic calls may be missed; best used as starting point |