iam-policy-validator 1.10.2__py3-none-any.whl → 1.11.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. iam_policy_validator-1.11.0.dist-info/METADATA +782 -0
  2. {iam_policy_validator-1.10.2.dist-info → iam_policy_validator-1.11.0.dist-info}/RECORD +26 -22
  3. iam_validator/__version__.py +1 -1
  4. iam_validator/checks/action_condition_enforcement.py +27 -14
  5. iam_validator/checks/sensitive_action.py +123 -11
  6. iam_validator/checks/utils/policy_level_checks.py +47 -10
  7. iam_validator/checks/wildcard_resource.py +29 -7
  8. iam_validator/commands/__init__.py +6 -0
  9. iam_validator/commands/completion.py +420 -0
  10. iam_validator/commands/query.py +485 -0
  11. iam_validator/commands/validate.py +21 -26
  12. iam_validator/core/config/category_suggestions.py +77 -0
  13. iam_validator/core/config/condition_requirements.py +105 -54
  14. iam_validator/core/config/defaults.py +110 -6
  15. iam_validator/core/config/wildcards.py +3 -0
  16. iam_validator/core/diff_parser.py +321 -0
  17. iam_validator/core/formatters/enhanced.py +34 -27
  18. iam_validator/core/models.py +2 -0
  19. iam_validator/core/pr_commenter.py +179 -51
  20. iam_validator/core/report.py +19 -17
  21. iam_validator/integrations/github_integration.py +250 -1
  22. iam_validator/sdk/__init__.py +33 -0
  23. iam_validator/sdk/query_utils.py +454 -0
  24. iam_policy_validator-1.10.2.dist-info/METADATA +0 -549
  25. {iam_policy_validator-1.10.2.dist-info → iam_policy_validator-1.11.0.dist-info}/WHEEL +0 -0
  26. {iam_policy_validator-1.10.2.dist-info → iam_policy_validator-1.11.0.dist-info}/entry_points.txt +0 -0
  27. {iam_policy_validator-1.10.2.dist-info → iam_policy_validator-1.11.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,782 @@
1
+ Metadata-Version: 2.4
2
+ Name: iam-policy-validator
3
+ Version: 1.11.0
4
+ Summary: Validate AWS IAM policies for correctness and security using AWS Service Reference API
5
+ Project-URL: Homepage, https://github.com/boogy/iam-policy-validator
6
+ Project-URL: Documentation, https://github.com/boogy/iam-policy-validator/tree/main/docs
7
+ Project-URL: Repository, https://github.com/boogy/iam-policy-validator
8
+ Project-URL: Issues, https://github.com/boogy/iam-policy-validator/issues
9
+ Project-URL: Changelog, https://github.com/boogy/iam-policy-validator/blob/main/docs/CHANGELOG.md
10
+ Author-email: boogy <0xboogy@gmail.com>
11
+ License: MIT
12
+ License-File: LICENSE
13
+ Keywords: aws,github-action,iam,policy,security,validation
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Intended Audience :: System Administrators
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Security
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Topic :: System :: Systems Administration
25
+ Requires-Python: >=3.10
26
+ Requires-Dist: boto3>=1.28.0
27
+ Requires-Dist: botocore>=1.40.55
28
+ Requires-Dist: httpx[http2]>=0.27.0
29
+ Requires-Dist: pydantic>=2.0.0
30
+ Requires-Dist: pyyaml>=6.0
31
+ Requires-Dist: rich>=13.0.0
32
+ Provides-Extra: dev
33
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
34
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
35
+ Requires-Dist: pytest-benchmark>=4.0.0; extra == 'dev'
36
+ Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
37
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
38
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
39
+ Requires-Dist: types-boto3; extra == 'dev'
40
+ Requires-Dist: types-pyyaml; extra == 'dev'
41
+ Description-Content-Type: text/markdown
42
+
43
+ # IAM Policy Validator
44
+
45
+ **Catch IAM policy errors before they reach AWS** — Validate syntax, security misconfigurations, and dangerous permission combinations in CI/CD pipelines.
46
+
47
+ [![GitHub Actions](https://img.shields.io/badge/GitHub%20Actions-Ready-blue)](https://github.com/marketplace/actions/iam-policy-validator)
48
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
49
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
50
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/boogy/iam-policy-validator/badge)](https://scorecard.dev/viewer/?uri=github.com/boogy/iam-policy-validator)
51
+
52
+ ---
53
+
54
+ ## Why This Tool Exists
55
+
56
+ Security teams need to **enforce organization-specific IAM requirements** and **catch dangerous patterns** before policies reach production. Manual review doesn't scale, and AWS's built-in validation in IAM console only checks more syntax and less security.
57
+
58
+ **Real problems this detects:**
59
+
60
+ 1. **Privilege escalation chains** - Scattered actions that together grant admin access
61
+ 2. **Broken automation** - Syntactically valid but functionally wrong policies (`s3:GetObject` on bucket ARN)
62
+ 3. **Missing security controls** - No IAM conditions for sensitive AWS API actions
63
+ 4. **Overly permissive access** - Wildcard actions and resources that violate least privilege
64
+ 5. **Trust policy vulnerabilities** - Incorrect principals, missing OIDC audience, SAML misconfiguration
65
+ 6. **Typos and invalid syntax** - Invalid actions (`s3:GetObjekt`), condition keys, or ARN formats before deployment
66
+ 7. **Your own detection** - Set custom configuration file for custom detections
67
+
68
+ ---
69
+
70
+ ## Quick Start
71
+
72
+ ```bash
73
+ pip install iam-policy-validator
74
+
75
+ # Try it with the example policies (from repository root)
76
+ iam-validator validate --path examples/quick-start/ --format enhanced
77
+ ```
78
+
79
+ **Example output:**
80
+
81
+ <details>
82
+ <summary>See the example policies used (examples/quick-start/)</summary>
83
+
84
+ **user-policy.json** - Contains typo and missing condition:
85
+
86
+ ```json
87
+ {
88
+ "Version": "2012-10-17",
89
+ "Statement": [
90
+ {"Effect": "Allow", "Action": "s3:GetObjekt", "Resource": "arn:aws:s3:::my-bucket/*"},
91
+ {"Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::123456789012:role/lambda-role"}
92
+ ]
93
+ }
94
+ ```
95
+
96
+ **s3-policy.json** - Sensitive action without conditions:
97
+
98
+ ```json
99
+ {
100
+ "Version": "2012-10-17",
101
+ "Statement": [
102
+ {"Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::my-bucket/*"}
103
+ ]
104
+ }
105
+ ```
106
+
107
+ **lambda-policy.json** - Valid policy:
108
+
109
+ ```json
110
+ {
111
+ "Version": "2012-10-17",
112
+ "Statement": [
113
+ {"Effect": "Allow", "Action": "lambda:InvokeFunction", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function"}
114
+ ]
115
+ }
116
+ ```
117
+
118
+ </details>
119
+
120
+ ```
121
+ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
122
+ │ │
123
+ │ IAM Policy Validation Report (v1.10.3) │
124
+ │ │
125
+ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
126
+ ───────────────────────────────────────── Detailed Results ─────────────────────────────────────────
127
+ ❌ [1/3] examples/quick-start/user-policy.json • INVALID (IAM errors + security issues)
128
+ 2 issue(s) found
129
+
130
+ Issues (2)
131
+ ├── 🔴 High
132
+ │ └── [Statement 2 @L10] missing_required_condition
133
+ │ └── Required: Action(s) ``iam:PassRole`` require condition `iam:PassedToService`
134
+ │ ├── Action: iam:PassRole • Condition: iam:PassedToService
135
+ │ └── 💡 Restrict which AWS services can assume the passed role to prevent privilege escalation
136
+
137
+ │ Note: Found 1 statement(s) with these actions in the policy.
138
+ │ Example:
139
+ │ "Condition": {
140
+ │ "StringEquals": {
141
+ │ "iam:PassedToService": [
142
+ │ "lambda.amazonaws.com",
143
+ │ "ecs-tasks.amazonaws.com",
144
+ │ "ec2.amazonaws.com",
145
+ │ "glue.amazonaws.com"
146
+ │ ]
147
+ │ }
148
+ │ }
149
+ └── 🔴 Error
150
+ └── [Statement 1 @L5] invalid_action
151
+ └── Action `GetObjekt` not found in service `s3`.
152
+ └── Action: s3:GetObjekt
153
+
154
+ ❌ [2/3] examples/quick-start/s3-policy.json • FAILED (critical security issues)
155
+ 1 issue(s) found
156
+
157
+ Issues (1)
158
+ └── 🔴 High
159
+ └── [Statement 1 @L5] missing_required_condition_any_of
160
+ └── Actions `s3:GetObject` require at least ONE of these conditions: `aws:ResourceOrgID` OR `aws:ResourceOrgPaths` OR `aws:SourceIp` OR
161
+ `aws:SourceVpc` OR `aws:SourceVpce` OR `aws:ResourceAccount`
162
+ ├── Action: s3:GetObject
163
+ └── 💡 Add at least ONE of these conditions:
164
+ - **Option 1**: `aws:ResourceOrgID` - Restrict S3 operations to resources within your AWS Organization (value:
165
+ `${aws:PrincipalOrgID}`)
166
+ - **Option 2**: `aws:ResourceOrgPaths` - Restrict S3 operations to resources within your AWS Organization path (value:
167
+ `${aws:PrincipalOrgPaths}`)
168
+ - **Option 3**: `aws:SourceIp` - Restrict S3 operations by source IP address and same account
169
+ - **Option 4**: `aws:SourceVpc` - Restrict S3 operations by source VPC and same account
170
+ - **Option 5**: `aws:SourceVpce` - Restrict S3 operations by VPC endpoint and same account
171
+ - **Option 6**: `aws:ResourceAccount` - Restrict S3 operations to resources within the same AWS account (value:
172
+ `${aws:PrincipalAccount}`)
173
+
174
+ Note: Found 1 statement(s) with these actions in the policy.
175
+
176
+ ✅ [3/3] examples/quick-start/lambda-policy.json • VALID
177
+ No issues detected
178
+
179
+ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
180
+ │ │
181
+ │ ❌ VALIDATION FAILED │
182
+ │ 2 of 3 policies have critical issues that must be resolved. │
183
+ │ │
184
+ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
185
+ ```
186
+
187
+ ### In GitHub PRs
188
+
189
+ ```yaml
190
+ # .github/workflows/iam-validator.yml
191
+ - uses: boogy/iam-policy-validator@v1
192
+ with:
193
+ path: policies/
194
+ github-review: true
195
+ ```
196
+
197
+ **Result:** Line-specific comments on policy files showing what's wrong and how to fix it.
198
+
199
+ ---
200
+
201
+ ## What Makes This Different
202
+
203
+ ### 🎯 **1. Enforce Your Organization's Security Rules**
204
+
205
+ Define security requirements as code—the validator becomes your organization's policy gatekeeper:
206
+
207
+ ```yaml
208
+ # .iam-validator.yaml - Your security requirements as code
209
+ action_condition_enforcement:
210
+ enabled: true
211
+ action_condition_requirements:
212
+ # Require service-specific PassRole
213
+ - actions: ["iam:PassRole"]
214
+ required_conditions:
215
+ - condition_key: "iam:PassedToService"
216
+ description: "Restrict which services can use passed roles"
217
+
218
+ # Enforce IP restrictions for privileged actions (automation from CI/CD)
219
+ - actions: ["iam:AttachUserPolicy", "iam:PutUserPolicy", "iam:CreateAccessKey"]
220
+ required_conditions:
221
+ - condition_key: "aws:SourceIp"
222
+ expected_value: ["10.0.0.0/8", "172.16.0.0/12"]
223
+ description: "Only allow from corporate network or CI/CD"
224
+
225
+ # Require encryption for S3 uploads
226
+ - actions: ["s3:PutObject"]
227
+ required_conditions:
228
+ - condition_key: "s3:x-amz-server-side-encryption"
229
+ operator: "StringEquals"
230
+ expected_value: "AES256"
231
+
232
+ # Enforce tagging requirements
233
+ - actions: ["ec2:RunInstances"]
234
+ required_conditions:
235
+ all_of:
236
+ - condition_key: "aws:RequestTag/CostCenter"
237
+ - condition_key: "aws:RequestTag/Environment"
238
+ - condition_key: "aws:RequestTag/Owner"
239
+ ```
240
+
241
+ **Real-world use cases:**
242
+
243
+ - 🏢 **Corporate network only**: Require `aws:SourceIp` for admin actions (automation from CI/CD IPs)
244
+ - 🏷️ **Cost tracking**: Enforce resource tagging before creation
245
+ - 🔐 **Encryption mandates**: Require encryption conditions on data operations
246
+ - ⏰ **Time-based access**: Require `aws:CurrentTime` conditions for temporary access
247
+ - 🔒 **Service restrictions**: Limit `iam:PassRole` to specific AWS services
248
+ - 🌐 **VPC restrictions**: Require `aws:SourceVpc` for sensitive operations
249
+
250
+ **Why this matters:** Other tools perform AWS-standard security checks but lack the flexibility to codify your organization's specific security requirements (IP restrictions, tagging mandates, encryption requirements, etc.).
251
+
252
+ ---
253
+
254
+ ### 🔍 **2. Detect Cross-Statement Privilege Escalation**
255
+
256
+ Privilege escalation often occurs when multiple actions are scattered across different statements. This validator uses `all_of` logic to detect when ALL actions in a dangerous combination exist somewhere in the policy:
257
+
258
+ ```json
259
+ {
260
+ "Statement": [
261
+ {"Sid": "AllowUserManagement", "Action": "iam:CreateUser", "Resource": "*"},
262
+ {"Sid": "AllowS3Read", "Action": "s3:GetObject", "Resource": "*"},
263
+ {"Sid": "AllowPolicyAttachment", "Action": "iam:AttachUserPolicy", "Resource": "*"}
264
+ ]
265
+ }
266
+ ```
267
+
268
+ **🚨 Detected:** Statements 1 and 3 enable privilege escalation:
269
+
270
+ 1. Create new IAM user
271
+ 2. Attach `AdministratorAccess` policy to that user
272
+ 3. Escalate to full account access
273
+
274
+ **Built-in escalation patterns** (enabled by default):
275
+
276
+ - User privilege escalation (`iam:CreateUser` + `iam:AttachUserPolicy`)
277
+ - Role privilege escalation (`iam:CreateRole` + `iam:AttachRolePolicy`)
278
+ - Lambda function backdoor (`lambda:CreateFunction` + `lambda:InvokeFunction`)
279
+ - Lambda code injection (`lambda:UpdateFunctionCode` + `lambda:InvokeFunction`)
280
+ - Policy version manipulation (`iam:CreatePolicyVersion` + `iam:SetDefaultPolicyVersion`)
281
+ - EC2 instance privilege escalation (`ec2:RunInstances` + `iam:PassRole`)
282
+
283
+ Additionally detects **[hundreds of sensitive actions](iam_validator/core/config/sensitive_actions.py)** across 4 categories (credential exposure, data access, privilege escalation, resource exposure) that should have IAM conditions.
284
+ List of actions copied from [primeharbor/sensitive_iam_actions](https://github.com/primeharbor/sensitive_iam_actions).
285
+
286
+ **Extend with custom patterns:**
287
+
288
+ ```yaml
289
+ sensitive_action:
290
+ sensitive_actions:
291
+ # Add your own cross-statement patterns
292
+ - all_of: ["cloudformation:CreateStack", "iam:PassRole"]
293
+ severity: critical
294
+ message: "CloudFormation + PassRole enables infrastructure privilege escalation"
295
+ ```
296
+
297
+ See [docs/privilege-escalation.md](docs/privilege-escalation.md) for all built-in patterns and custom configuration.
298
+
299
+ **Comparison:**
300
+
301
+ - **This tool**: 6 built-in escalation patterns + hundreds of sensitive actions + extensible
302
+ - **IAM Lens**: Runtime permission evaluator ("what can this principal do?"), not policy validator
303
+ - **Policy Sentry**: Generates policies, doesn't scan for escalation
304
+ - **IAMSpy**: Enumerates permissions, different use case
305
+
306
+ ---
307
+
308
+ ### ⚙️ **3. Catch Functionally Broken Policies**
309
+
310
+ Validates that actions and resources are **compatible**—catches policies that pass AWS validation but fail at runtime:
311
+
312
+ ```json
313
+ {
314
+ "Effect": "Allow",
315
+ "Action": "s3:GetObject",
316
+ "Resource": "arn:aws:s3:::mybucket"
317
+ }
318
+ ```
319
+
320
+ **🚨 Detected:** `s3:GetObject` operates on **objects**, not buckets. This policy does nothing.
321
+ **💡 Fix:** `"Resource": "arn:aws:s3:::mybucket/*"`
322
+
323
+ **More examples:**
324
+
325
+ ```json
326
+ // BAD: s3:ListBucket with object ARN
327
+ {"Action": "s3:ListBucket", "Resource": "arn:aws:s3:::bucket/*"}
328
+ // ✅ FIX: s3:ListBucket needs bucket ARN
329
+ {"Action": "s3:ListBucket", "Resource": "arn:aws:s3:::bucket"}
330
+
331
+ // BAD: iam:ListUsers with user-specific ARN
332
+ {"Action": "iam:ListUsers", "Resource": "arn:aws:iam::*:user/bob"}
333
+ // ✅ FIX: iam:ListUsers is global, needs wildcard
334
+ {"Action": "iam:ListUsers", "Resource": "*"}
335
+
336
+ // BAD: ec2:DescribeInstances with specific instance
337
+ {"Action": "ec2:DescribeInstances", "Resource": "arn:aws:ec2:*:*:instance/i-1234"}
338
+ // ✅ FIX: Describe actions don't support resource-level permissions
339
+ {"Action": "ec2:DescribeInstances", "Resource": "*"}
340
+ ```
341
+
342
+ **Why this matters:** These policies look correct but fail silently in production. AWS validates syntax, not action-resource compatibility.
343
+
344
+ ---
345
+
346
+ ### 🔧 **4. Uses Official AWS Service Definitions**
347
+
348
+ Fetches **real AWS service data** from AWS's official IAM service definition API (JSON endpoint)—always accurate and up-to-date:
349
+
350
+ - **Actions**: Validates against 250+ AWS services with complete action lists
351
+ - **Condition keys**: Checks valid keys for each action
352
+ - **Resource types**: Validates ARN formats and resource compatibility
353
+ - **Auto-updating**: Fetches latest definitions on-demand or use cached versions
354
+
355
+ ```bash
356
+ # Query AWS service definitions (like Policy Sentry)
357
+ iam-validator query action --service s3 --access-level write
358
+ iam-validator query condition --service s3 --name s3:prefix
359
+ iam-validator query arn --service lambda --name function
360
+
361
+ # Download for offline use
362
+ iam-validator sync-services --output-dir ./aws-services
363
+ iam-validator validate --path policies/ --aws-services-dir ./aws-services
364
+ ```
365
+
366
+ **Comparison:**
367
+
368
+ - **This tool**: Official AWS API, auto-updates, offline mode
369
+ - **Policy Sentry**: Official AWS API, excellent query capabilities
370
+ - **IAM Lens**: Uses actual AWS account data (runtime analysis)
371
+ - **IAMSpy**: Static database, may lag behind AWS updates
372
+
373
+ ---
374
+
375
+ ### 🎨 **5. Built for CI/CD and Developer Workflows**
376
+
377
+ **GitHub PR Integration:**
378
+
379
+ - **Diff-aware filtering**: Only comments on lines you actually changed
380
+ - **Line-specific feedback**: Inline comments on policy files with exact line numbers
381
+ - **Smart cleanup**: Updates existing comments, removes stale ones
382
+ - **Severity-based reviews**: Auto-approve or request changes based on findings
383
+
384
+ **Multiple output formats:**
385
+
386
+ - Console (colored terminal)
387
+ - JSON (automation/API)
388
+ - SARIF (GitHub Code Scanning)
389
+ - Markdown (documentation)
390
+ - HTML (interactive reports)
391
+ - CSV (spreadsheet analysis)
392
+
393
+ **Example GitHub Action:**
394
+
395
+ ```yaml
396
+ - uses: boogy/iam-policy-validator@v1
397
+ with:
398
+ path: policies/
399
+ github-review: true # Inline PR comments
400
+ github-summary: true # Actions summary tab
401
+ fail-on-severity: high # Block merge on high/critical
402
+ ```
403
+
404
+ ---
405
+
406
+ ## What Does It Check?
407
+
408
+ ### ✅ **AWS Correctness (12 checks)**
409
+
410
+ Validates against official AWS IAM requirements:
411
+
412
+ | Check | What It Does |
413
+ | ---------------------------- | ----------------------------------------------------------------------------------- |
414
+ | **Policy Structure** | Required fields (Version, Statement, Effect), valid JSON/YAML |
415
+ | **Action Validation** | Actions exist in AWS services (detects typos: `s3:GetObjekt`) |
416
+ | **Condition Keys** | Valid condition keys for actions (e.g., `s3:prefix` valid for `s3:ListBucket`) |
417
+ | **Condition Types** | Values match expected types (IP for `aws:SourceIp`, Bool for `aws:SecureTransport`) |
418
+ | **Resource ARNs** | Correct ARN format and patterns |
419
+ | **Principal Validation** | Valid principals in resource/trust policies |
420
+ | **Policy Size** | AWS limits (6144 bytes managed, 10240 inline, 20480 resource) |
421
+ | **SID Uniqueness** | Statement IDs unique within policy |
422
+ | **Set Operators** | Correct `ForAllValues`/`ForAnyValue` usage with arrays |
423
+ | **MFA Conditions** | Detect insecure MFA patterns (`!= false` instead of `== true`) |
424
+ | **Policy Type** | RCP/SCP-specific requirements |
425
+ | **Action-Resource Matching** | Actions compatible with resources (catches functional errors) |
426
+
427
+ ### 🔒 **Security Best Practices (6 checks)**
428
+
429
+ Identifies overly permissive configurations:
430
+
431
+ | Check | What It Catches |
432
+ | ------------------------------------- | ------------------------------------------------------ |
433
+ | **Wildcard Action** | `Action: "*"` grants all AWS permissions |
434
+ | **Wildcard Resource** | `Resource: "*"` applies to all resources |
435
+ | **Full Wildcard** | Both `Action: "*"` AND `Resource: "*"` (admin access) |
436
+ | **Service Wildcards** | `s3:*`, `iam:*`, `ec2:*` (overly broad) |
437
+ | **Sensitive Actions (Policy-Wide)** | **Cross-statement** privilege escalation patterns |
438
+ | **Sensitive Actions (Per-Statement)** | Dangerous actions in single statement |
439
+ | **Condition Enforcement** | Organization-specific requirements (your custom rules) |
440
+
441
+ **Note on Sensitive Actions:** This check has two modes:
442
+
443
+ - `all_of`: **Policy-wide** detection (e.g., `iam:CreateUser` in statement 0 + `iam:AttachUserPolicy` in statement 2)
444
+ - `any_of`: **Per-statement** detection (e.g., any statement with `iam:PutUserPolicy`)
445
+
446
+ ### 🔐 **Trust Policy Validation (opt-in)**
447
+
448
+ Specialized checks for role assumption:
449
+
450
+ - Correct principal types (`AssumeRoleWithSAML` needs `Federated` principal)
451
+ - SAML/OIDC provider ARN validation
452
+ - Required conditions (`SAML:aud`, OIDC audience)
453
+ - Federated identity best practices
454
+
455
+ ---
456
+
457
+ ## Installation & Usage
458
+
459
+ ### CLI
460
+
461
+ ```bash
462
+ pip install iam-policy-validator
463
+
464
+ # Validate (no AWS credentials needed)
465
+ iam-validator validate --path policies/
466
+
467
+ # With AWS Access Analyzer (requires AWS credentials)
468
+ iam-validator analyze --path policies/ --run-all-checks
469
+
470
+ # Different policy types
471
+ iam-validator validate --path trust-policies/ --policy-type TRUST_POLICY
472
+
473
+ # Output formats
474
+ iam-validator validate --path policies/ --format json --output report.json
475
+ iam-validator validate --path policies/ --format sarif --output code-scanning.sarif
476
+ ```
477
+
478
+ ### Python Library
479
+
480
+ ```python
481
+ from iam_validator.core.policy_loader import PolicyLoader
482
+ from iam_validator.core.policy_checks import validate_policies
483
+
484
+ loader = PolicyLoader()
485
+ policies = loader.load_from_path("./policies")
486
+ results = await validate_policies(policies)
487
+
488
+ for result in results:
489
+ if not result.is_valid:
490
+ for issue in result.issues:
491
+ print(f"{issue.severity}: {issue.message} at line {issue.line_number}")
492
+ ```
493
+
494
+ ### Configuration
495
+
496
+ All checks are customizable via `.iam-validator.yaml`:
497
+
498
+ ```yaml
499
+ settings:
500
+ enable_builtin_checks: true
501
+ fail_on_severity: high
502
+
503
+ # Detect cross-statement privilege escalation
504
+ sensitive_action:
505
+ enabled: true
506
+ sensitive_actions:
507
+ # Policy-wide: ALL actions must exist somewhere in policy
508
+ - all_of:
509
+ - "iam:CreateUser"
510
+ - "iam:AttachUserPolicy"
511
+ - all_of:
512
+ - "lambda:CreateFunction"
513
+ - "iam:PassRole"
514
+
515
+ # Per-statement: ANY action in a single statement
516
+ - any_of:
517
+ - "iam:PutUserPolicy"
518
+ - "iam:PutGroupPolicy"
519
+
520
+ # Enforce your organization's conditions
521
+ action_condition_enforcement:
522
+ enabled: true
523
+ action_condition_requirements:
524
+ - actions: ["iam:PassRole"]
525
+ required_conditions:
526
+ - condition_key: "iam:PassedToService"
527
+
528
+ # IP restrictions for admin actions (automation from CI/CD IPs)
529
+ - actions: ["iam:CreateUser", "iam:DeleteUser", "iam:CreateAccessKey"]
530
+ required_conditions:
531
+ - condition_key: "aws:SourceIp"
532
+ expected_value: ["10.0.0.0/8", "52.94.76.0/24"] # Corporate + GitHub Actions
533
+
534
+ # Ignore patterns
535
+ ignore_patterns:
536
+ - filepath: "terraform/modules/admin/*.json"
537
+ reason: "Admin policies reviewed separately"
538
+ ```
539
+
540
+ #### Understanding Configuration: Two Ways to Control Action Validation
541
+
542
+ The validator provides two complementary approaches for action-specific validation:
543
+
544
+ **Option 1: Enforce Required Conditions** (`action_condition_enforcement`)
545
+
546
+ Use this when you want to **mandate specific conditions** for certain actions:
547
+
548
+ ```yaml
549
+ action_condition_enforcement:
550
+ enabled: true
551
+ requirements:
552
+ # Enforce that iam:PassRole must specify which service can use the role
553
+ - actions: ["iam:PassRole"]
554
+ required_conditions:
555
+ - condition_key: "iam:PassedToService"
556
+ description: "Prevent privilege escalation by restricting service access"
557
+
558
+ # Enforce MFA for credential creation
559
+ - actions: ["iam:CreateAccessKey"]
560
+ required_conditions:
561
+ - condition_key: "aws:MultiFactorAuthPresent"
562
+ expected_value: true
563
+ ```
564
+
565
+ **What this does:**
566
+
567
+ - ✅ **Validates** that required conditions exist in the policy
568
+ - ✅ **Fails validation** when conditions are missing
569
+ - ✅ **Prevents duplicate warnings** (automatically filters from `sensitive_action` check)
570
+ - ✅ **Specific guidance** per action about which conditions are required
571
+
572
+ **Option 2: Suggest Best Practices** (`sensitive_action`)
573
+
574
+ Use this when you want to **flag actions without conditions** and provide ABAC guidance:
575
+
576
+ ```yaml
577
+ sensitive_action:
578
+ enabled: true
579
+ # Uses built-in list of 490+ sensitive actions across 4 categories:
580
+ # - credential_exposure: Actions that expose credentials/secrets
581
+ # - data_access: Actions that retrieve sensitive data
582
+ # - priv_esc: Actions that enable privilege escalation
583
+ # - resource_exposure: Actions that modify resource policies
584
+
585
+ # Optionally add your own sensitive actions
586
+ sensitive_actions:
587
+ - "custom:SensitiveAction"
588
+ ```
589
+
590
+ **What this does:**
591
+
592
+ - ⚠️ **Suggests** that actions should have conditions (doesn't enforce specific ones)
593
+ - ⚠️ **Generic ABAC guidance** (tag matching, MFA, IP restrictions)
594
+ - ✅ **Automatic filtering** (skips actions already validated by `action_condition_enforcement`)
595
+
596
+ **Decision Matrix:**
597
+
598
+ | Your Goal | Use This | Config Example |
599
+ | --------------------------------------------------- | ------------------------------ | ------------------------------------------------ |
600
+ | **Must enforce** specific conditions for compliance | `action_condition_enforcement` | Require `iam:PassedToService` for `iam:PassRole` |
601
+ | **Want to suggest** general security improvements | `sensitive_action` | Flag `s3:GetObject` without any conditions |
602
+ | **Organization-specific** rules (IP, tags, MFA) | `action_condition_enforcement` | Require corporate IPs for admin actions |
603
+ | **General best practices** (ABAC) | `sensitive_action` | Suggest tag-based access control |
604
+
605
+ **How They Work Together:**
606
+
607
+ 1. `action_condition_enforcement` validates **specific required conditions** (strict enforcement)
608
+ 2. `sensitive_action` suggests **ABAC best practices** for actions without conditions (general guidance)
609
+ 3. **Automatic deduplication** prevents showing both warnings for the same action
610
+ 4. Actions in `action_condition_enforcement` are automatically filtered from `sensitive_action`
611
+
612
+ **Example - Complete Configuration:**
613
+
614
+ ```yaml
615
+ # Strict enforcement for critical actions
616
+ action_condition_enforcement:
617
+ enabled: true
618
+ requirements:
619
+ - actions: ["iam:PassRole"]
620
+ required_conditions:
621
+ - condition_key: "iam:PassedToService"
622
+
623
+ - actions: ["s3:GetObject", "s3:GetObjectVersion"]
624
+ required_conditions:
625
+ any_of:
626
+ - condition_key: "aws:ResourceOrgID"
627
+ - condition_key: "aws:SourceVpc"
628
+
629
+ # General suggestions for other sensitive actions
630
+ sensitive_action:
631
+ enabled: true
632
+ # Will NOT warn about iam:PassRole or s3:GetObject (already covered above)
633
+ # Will warn about other sensitive actions like iam:CreateUser, s3:DeleteObject, etc.
634
+ ```
635
+
636
+ For more details, see:
637
+
638
+ - [docs/condition-requirements.md](docs/condition-requirements.md) - How to configure condition requirements
639
+ - [examples/configs/full-reference-config.yaml](examples/configs/full-reference-config.yaml) - Complete configuration reference
640
+
641
+ ---
642
+
643
+ ## AWS Access Analyzer (Optional)
644
+
645
+ Optionally enable AWS Access Analyzer to validate policy syntax, then perform security checks on top of that validation:
646
+
647
+ ```bash
648
+ # Check for public access (S3, SNS, SQS, etc.)
649
+ iam-validator analyze --path bucket-policy.json \
650
+ --policy-type RESOURCE_POLICY \
651
+ --check-no-public-access \
652
+ --public-access-resource-type "AWS::S3::Bucket"
653
+
654
+ # Prevent specific actions
655
+ iam-validator analyze --path policy.json \
656
+ --check-access-not-granted "s3:DeleteBucket iam:DeleteUser"
657
+
658
+ # Compare against baseline (detect permission creep)
659
+ iam-validator analyze --path new-policy.json \
660
+ --check-no-new-access baseline-policy.json
661
+ ```
662
+
663
+ **Note:** Access Analyzer requires AWS credentials. Built-in checks work offline.
664
+
665
+ ---
666
+
667
+ ## Comparison Matrix
668
+
669
+ | Feature | IAM Policy Validator | IAM Lens | IAMSpy | Policy Sentry |
670
+ | ------------------------------ | -------------------------------- | ----------------------------- | ---------------------- | -------------------------- |
671
+ | **Primary Purpose** | Pre-deployment validation | Runtime permission analysis | Permission enumeration | Least-privilege generation |
672
+ | **Use Case** | CI/CD policy scanning | "What can this principal do?" | Pentesting/audit | Policy creation |
673
+ | **Custom Security Rules** | ✅ Full support | ❌ No | ❌ No | ❌ No |
674
+ | **Cross-Statement Patterns** | ✅ Privilege escalation detection | N/A (different purpose) | N/A | N/A |
675
+ | **Action-Resource Validation** | ✅ Catches incompatible pairs | N/A | ❌ No | ✅ Generates correct |
676
+ | **Organization Conditions** | ✅ IP, tags, encryption, etc. | ❌ No | ❌ No | ❌ No |
677
+ | **CI/CD Ready** | ✅ GitHub Actions native | ⚠️ Manual setup | ⚠️ Manual | ⚠️ Manual |
678
+ | **PR Line Comments** | ✅ Diff-aware | ❌ No | ❌ No | ❌ No |
679
+ | **AWS Service Data** | ✅ Official API (auto-update) | ✅ Real AWS account data | ⚠️ Static | ✅ Official API |
680
+ | **Offline Mode** | ✅ Yes | ❌ Needs AWS account | ✅ Yes | ❌ Needs internet |
681
+ | **Query Permissions** | ✅ Yes | ✅ Yes (different approach) | ⚠️ Enumerate only | ✅ Excellent |
682
+
683
+ **Choose this tool if you:**
684
+
685
+ - Need **pre-deployment validation** in CI/CD
686
+ - Want to **enforce organization-specific security requirements**
687
+ - Need to catch **privilege escalation patterns**
688
+ - Want to validate **action-resource compatibility**
689
+ - Need **PR integration with line comments**
690
+
691
+ **Choose IAM Lens if you:**
692
+
693
+ - Need **runtime permission analysis** ("can this user do X?")
694
+ - Want to **simulate real AWS requests**
695
+ - Need to understand **effective permissions across policies**
696
+
697
+ **Choose Policy Sentry if you:**
698
+
699
+ - Need to **generate least-privilege policies** from scratch
700
+ - Want to **query AWS permissions** for policy writing
701
+
702
+ **IAMSpy is for:**
703
+
704
+ - **Enumerating existing permissions** in AWS accounts
705
+ - **Security assessment** (pentesting, not validation)
706
+
707
+ ---
708
+
709
+ ## Documentation
710
+
711
+ **Guides:**
712
+
713
+ - [Check Reference](docs/check-reference.md) - All 19 checks with examples
714
+ - [Configuration Guide](docs/configuration.md) - Customize checks and behavior
715
+ - [GitHub Actions Guide](docs/github-actions-workflows.md) - CI/CD integration
716
+ - [Python Library Guide](docs/python-library-usage.md) - Use as Python package
717
+ - [Trust Policy Guide](examples/trust-policies/README.md) - Trust policy validation
718
+ - [Query Command](docs/query-command.md) - Query AWS service definitions
719
+
720
+ **Examples:**
721
+
722
+ - [Configuration Examples](examples/configs/) - Config file templates
723
+ - [Workflow Examples](examples/github-actions/) - GitHub Actions workflows
724
+ - [Custom Checks](examples/custom_checks/) - Add your own validation rules
725
+
726
+ ---
727
+
728
+ ## Related Tools & Resources
729
+
730
+ Other tools in the IAM security ecosystem that serve different purposes:
731
+
732
+ ### Policy Analysis & Generation
733
+
734
+ - **[Parliament](https://github.com/duo-labs/parliament)** - IAM policy linter that checks for syntax errors and basic security issues. This validator uses Parliament's ARN pattern matching logic.
735
+ - **[Policy Sentry](https://github.com/salesforce/policy_sentry)** - Generates least-privilege IAM policies from AWS service definitions. Great for policy creation; this validator focuses on policy validation.
736
+ - **[Cloudsplaining](https://github.com/salesforce/cloudsplaining)** - Scans existing AWS account policies for security issues. Runtime analysis vs. pre-deployment validation.
737
+
738
+ ### Permission Analysis
739
+
740
+ - **[IAM Dataset](https://github.com/glassechidna/iam-dataset)** - Curated dataset of AWS IAM actions, resources, and conditions scraped from AWS documentation. Useful reference for policy authors.
741
+ - **[IAMSpy](https://github.com/WithSecureLabs/IAMSpy)** - Enumerates IAM permissions for roles/users in an AWS account. Pentesting/audit tool, not a validator.
742
+ - **[IAM Lens](https://github.com/welldone-cloud/aws-iam-lens)** - Runtime permission evaluator that answers "what can this principal do?". Complements pre-deployment validation.
743
+
744
+ ### AWS Official Tools
745
+
746
+ - **[AWS Access Analyzer](https://aws.amazon.com/iam/access-analyzer/)** - AWS's built-in policy validation and external access detection. This validator can optionally integrate with it.
747
+ - **[AWS IAM Policy Simulator](https://policysim.aws.amazon.com/)** - Test policies against AWS resources to see if actions are allowed.
748
+
749
+ **When to use this validator vs. others:**
750
+
751
+ - Use this for **pre-deployment CI/CD validation** with custom security rules
752
+ - Use Policy Sentry for **generating** least-privilege policies
753
+ - Use Cloudsplaining/IAMSpy for **auditing existing** AWS accounts
754
+ - Use IAM Lens for **runtime permission analysis**
755
+ - Use Parliament if you only need basic syntax/ARN validation
756
+
757
+ ---
758
+
759
+ ## Contributing
760
+
761
+ Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md).
762
+
763
+ ```bash
764
+ git clone https://github.com/boogy/iam-policy-validator.git
765
+ cd iam-policy-validator
766
+ uv sync --extra dev
767
+ uv run pytest
768
+ ```
769
+
770
+ ---
771
+
772
+ ## License
773
+
774
+ MIT License - see [LICENSE](LICENSE).
775
+
776
+ - **Third-party code:** ARN pattern matching derived from [Parliament](https://github.com/duo-labs/parliament) (BSD 3-Clause).
777
+
778
+ ---
779
+
780
+ ## Support
781
+
782
+ - **Issues**: [GitHub Issues](https://github.com/boogy/iam-policy-validator/issues)