iam-policy-validator 1.7.0__py3-none-any.whl → 1.7.2__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 (38) hide show
  1. iam_policy_validator-1.7.2.dist-info/METADATA +428 -0
  2. {iam_policy_validator-1.7.0.dist-info → iam_policy_validator-1.7.2.dist-info}/RECORD +37 -36
  3. iam_validator/__version__.py +4 -2
  4. iam_validator/checks/action_condition_enforcement.py +22 -13
  5. iam_validator/checks/action_resource_matching.py +70 -36
  6. iam_validator/checks/condition_key_validation.py +7 -7
  7. iam_validator/checks/condition_type_mismatch.py +8 -6
  8. iam_validator/checks/full_wildcard.py +2 -8
  9. iam_validator/checks/mfa_condition_check.py +8 -8
  10. iam_validator/checks/principal_validation.py +24 -20
  11. iam_validator/checks/sensitive_action.py +3 -9
  12. iam_validator/checks/service_wildcard.py +2 -8
  13. iam_validator/checks/sid_uniqueness.py +1 -1
  14. iam_validator/checks/utils/sensitive_action_matcher.py +1 -2
  15. iam_validator/checks/utils/wildcard_expansion.py +1 -2
  16. iam_validator/checks/wildcard_action.py +2 -8
  17. iam_validator/checks/wildcard_resource.py +2 -8
  18. iam_validator/commands/validate.py +2 -2
  19. iam_validator/core/aws_fetcher.py +115 -22
  20. iam_validator/core/config/config_loader.py +1 -2
  21. iam_validator/core/config/defaults.py +16 -7
  22. iam_validator/core/constants.py +57 -0
  23. iam_validator/core/formatters/console.py +10 -1
  24. iam_validator/core/formatters/csv.py +2 -1
  25. iam_validator/core/formatters/enhanced.py +42 -8
  26. iam_validator/core/formatters/markdown.py +2 -1
  27. iam_validator/core/models.py +22 -7
  28. iam_validator/core/policy_checks.py +5 -4
  29. iam_validator/core/policy_loader.py +71 -14
  30. iam_validator/core/report.py +65 -24
  31. iam_validator/integrations/github_integration.py +4 -5
  32. iam_validator/utils/__init__.py +4 -0
  33. iam_validator/utils/regex.py +7 -8
  34. iam_validator/utils/terminal.py +22 -0
  35. iam_policy_validator-1.7.0.dist-info/METADATA +0 -1057
  36. {iam_policy_validator-1.7.0.dist-info → iam_policy_validator-1.7.2.dist-info}/WHEEL +0 -0
  37. {iam_policy_validator-1.7.0.dist-info → iam_policy_validator-1.7.2.dist-info}/entry_points.txt +0 -0
  38. {iam_policy_validator-1.7.0.dist-info → iam_policy_validator-1.7.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,428 @@
1
+ Metadata-Version: 2.4
2
+ Name: iam-policy-validator
3
+ Version: 1.7.2
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 security issues and errors before they reach production** - A comprehensive validation tool for AWS IAM policies with built-in security checks and optional AWS Access Analyzer integration.
46
+
47
+ [![GitHub Actions](https://img.shields.io/badge/GitHub%20Actions-Ready-blue)](https://github.com/marketplace/actions/iam-policy-validator)
48
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-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
+ ## 🚀 Why IAM Policy Validator?
53
+
54
+ **IAM policy errors are costly and dangerous.** A single misconfigured policy can:
55
+ - ❌ Grant unintended admin access (privilege escalation)
56
+ - ❌ Expose sensitive data to the public
57
+ - ❌ Break production deployments with invalid syntax
58
+ - ❌ Create security vulnerabilities that persist for months
59
+
60
+ **This tool prevents these issues** by:
61
+ - ✅ **Dual validation** - built-in checks + optional AWS Access Analyzer
62
+ - ✅ **Catches real threats** - Privilege escalation, wildcards, missing conditions
63
+ - ✅ **PR integration** - Automated validation in GitHub Actions
64
+ - ✅ **Saves security team time** - Catches common issues before manual review
65
+ - ✅ **Developer-friendly** - Clear errors with fix suggestions
66
+ - ✅ **Zero setup** - Works as a GitHub Action out of the box
67
+
68
+ ## ✨ What Makes It Special
69
+
70
+ ### 🔍 Two Validation Layers
71
+
72
+ **1. Built-in Checks (No AWS Credentials Required)**
73
+ - **Security & Compliance Checks** - Works offline, no AWS account needed
74
+ - **Privilege Escalation Detection** - Detects dangerous IAM actions and configurable combination patterns
75
+ - **Wildcard Analysis** - Catches overly permissive wildcards (`*`, `s3:*`)
76
+ - **Sensitive Action Enforcement** - 490 actions requiring conditions (MFA, IP, tags)
77
+ - **AWS Requirements Validation** - Actions, conditions, ARN formats, policy size
78
+
79
+ **2. AWS Access Analyzer (Optional)**
80
+ - **Official AWS Validation** - Syntax, semantics, and security checks
81
+ - **Public Access Detection** - Checks 29+ resource types (S3, Lambda, SNS, etc.)
82
+ - **Policy Comparison** - Detect new permissions vs baseline
83
+ - **Cross-account Analysis** - Validates external access
84
+
85
+ ### 🎯 Developer Experience
86
+ - **Auto-detects IAM policies** - Scans mixed JSON/YAML repos automatically
87
+ - **PR comments & reviews** - Line-specific feedback in GitHub
88
+ - **7 output formats** - Console, JSON, Markdown, SARIF, CSV, HTML, Enhanced
89
+ - **Extensible** - Add custom checks via Python plugins
90
+
91
+ **📖 See [full feature documentation](docs/README.md) for details**
92
+
93
+ ## 📈 What It Catches
94
+
95
+ ### Example 1: Privilege Escalation (Built-in Check)
96
+ ```json
97
+ {
98
+ "Statement": [
99
+ {"Effect": "Allow", "Action": "iam:CreateUser", "Resource": "*"},
100
+ {"Effect": "Allow", "Action": "iam:AttachUserPolicy", "Resource": "*"}
101
+ ]
102
+ }
103
+ ```
104
+
105
+ **Detected:**
106
+ ```
107
+ 🚨 CRITICAL: Privilege escalation risk detected!
108
+ Actions ['iam:CreateUser', 'iam:AttachUserPolicy'] enable:
109
+ 1. Create new IAM user
110
+ 2. Attach AdministratorAccess to that user
111
+ 3. Gain full AWS account access
112
+ ```
113
+
114
+ ### Example 2: Overly Permissive Wildcards (Built-in Check)
115
+ ```json
116
+ {
117
+ "Effect": "Allow",
118
+ "Action": "s3:*",
119
+ "Resource": "*"
120
+ }
121
+ ```
122
+
123
+ **Detected:**
124
+ ```
125
+ ❌ HIGH: Service wildcard 's3:*' detected
126
+ ❌ MEDIUM: Wildcard resource '*' - applies to all S3 buckets
127
+ ❌ CRITICAL: Full wildcard (Action + Resource) grants excessive access
128
+ ```
129
+
130
+ ### Example 3: Missing Required Conditions (Built-in Check)
131
+ ```json
132
+ {
133
+ "Effect": "Allow",
134
+ "Action": "iam:PassRole",
135
+ "Resource": "*"
136
+ }
137
+ ```
138
+
139
+ **Detected:**
140
+ ```
141
+ ❌ HIGH: iam:PassRole missing required condition
142
+ 💡 Add condition: iam:PassedToService to restrict role passing
143
+ ```
144
+
145
+ ### Example 4: Public Access (Access Analyzer - Optional)
146
+ ```json
147
+ {
148
+ "Principal": "*",
149
+ "Action": "s3:GetObject",
150
+ "Resource": "arn:aws:s3:::private-bucket/*"
151
+ }
152
+ ```
153
+
154
+ **Detected:**
155
+ ```
156
+ 🛑 CRITICAL: Resource policy allows public internet access
157
+ Principal "*" grants world-readable access to S3 bucket
158
+ 💡 Use specific AWS principals or add aws:SourceIp conditions
159
+ ```
160
+
161
+ ## Quick Start
162
+
163
+ ### GitHub Action (Recommended)
164
+
165
+ Create `.github/workflows/iam-validator.yml`:
166
+
167
+ ```yaml
168
+ name: IAM Policy Validation
169
+
170
+ on:
171
+ pull_request:
172
+ paths: ['policies/**/*.json']
173
+
174
+ jobs:
175
+ validate:
176
+ runs-on: ubuntu-latest
177
+ permissions:
178
+ contents: read
179
+ pull-requests: write
180
+ steps:
181
+ - uses: actions/checkout@v5
182
+ - uses: boogy/iam-policy-validator@v1
183
+ with:
184
+ path: policies/
185
+ fail-on-warnings: true
186
+ ```
187
+
188
+ **With AWS Access Analyzer (optional):**
189
+ ```yaml
190
+ - uses: aws-actions/configure-aws-credentials@v4
191
+ with:
192
+ role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
193
+ aws-region: us-east-1
194
+ - uses: boogy/iam-policy-validator@v1
195
+ with:
196
+ path: policies/
197
+ use-access-analyzer: true
198
+ run-all-checks: true # Run both Access Analyzer + built-in checks
199
+ ```
200
+
201
+ **📖 For all GitHub Action inputs and advanced workflows, see [GitHub Actions Guide](docs/github-actions-workflows.md)**
202
+
203
+ ### CLI Tool
204
+
205
+ ```bash
206
+ # Install
207
+ pip install iam-policy-validator
208
+
209
+ # Validate (built-in checks only - no AWS credentials needed)
210
+ iam-validator validate --path ./policies/
211
+
212
+ # Validate with AWS Access Analyzer (requires AWS credentials)
213
+ iam-validator analyze --path ./policies/
214
+
215
+ # With both Access Analyzer + built-in checks
216
+ iam-validator analyze --path ./policies/ --run-all-checks
217
+
218
+ # Different policy types
219
+ iam-validator validate --path ./policies/ --policy-type RESOURCE_POLICY
220
+
221
+ # Output formats
222
+ iam-validator validate --path ./policies/ --format json --output report.json
223
+ ```
224
+
225
+ **📖 See [CLI documentation](docs/README.md) for all commands and options**
226
+
227
+ ### Python Library
228
+
229
+ ```python
230
+ from iam_validator.core.policy_loader import PolicyLoader
231
+ from iam_validator.core.policy_checks import validate_policies
232
+
233
+ # Load and validate
234
+ loader = PolicyLoader()
235
+ policies = loader.load_from_path("./policies")
236
+ results = await validate_policies(policies)
237
+ ```
238
+
239
+ **📖 See [Python Library Guide](docs/python-library-usage.md) for complete examples**
240
+
241
+ ## Built-in Validation Checks
242
+
243
+ **All checks are fully configurable** - Enable/disable checks, adjust severity levels, add custom requirements, and define ignore patterns through the configuration file.
244
+
245
+ ### AWS Correctness Checks (12)
246
+ Validates policies against AWS IAM requirements:
247
+ - **Action validation** - Verify actions exist in AWS services
248
+ - **Condition key validation** - Check condition keys are valid for actions
249
+ - **Condition type matching** - Ensure condition values match expected types
250
+ - **Resource ARN validation** - Validate ARN formats and patterns
251
+ - **Principal validation** - Check principal formats (resource policies)
252
+ - **Policy size limits** - Enforce AWS size constraints
253
+ - **SID uniqueness** - Ensure statement IDs are unique
254
+ - **Set operator validation** - Validate ForAllValues/ForAnyValue usage
255
+ - **MFA condition patterns** - Detect common MFA anti-patterns
256
+ - **Policy type validation** - Enforce policy type requirements (RCP, SCP, etc.)
257
+ - **Action-resource matching** - Detect impossible action-resource combinations
258
+ - **Action-resource constraints** - Validate service-specific constraints
259
+
260
+ ### Security Best Practices (6)
261
+ Identifies security risks and overly permissive permissions:
262
+ - **Wildcard action** (`Action: "*"`)
263
+ - **Wildcard resource** (`Resource: "*"`)
264
+ - **Full wildcard** (CRITICAL: both `Action: "*"` and `Resource: "*"`)
265
+ - **Service wildcards** (`s3:*`, `iam:*`, etc.)
266
+ - **Sensitive actions** - ~490 actions across 4 risk categories requiring conditions
267
+ - **Action condition enforcement** - Enforce required conditions (MFA, IP, SourceArn, etc.)
268
+
269
+ ### Configuration & Customization
270
+
271
+ All checks can be customized via a yaml configuration file ex: `.iam-validator.yaml`:
272
+
273
+ ```yaml
274
+ settings:
275
+ enable_builtin_checks: true
276
+ fail_on_severity: high
277
+
278
+ # Customize individual checks
279
+ wildcard_action:
280
+ enabled: true
281
+ severity: critical
282
+
283
+ # Detect privilege escalation patterns
284
+ sensitive_action:
285
+ enabled: true
286
+ severity: critical
287
+ sensitive_actions:
288
+ # all_of: Detects when ALL actions exist across the entire policy
289
+ # (checks multiple statements - finds scattered dangerous combinations)
290
+ - all_of:
291
+ - "iam:CreateUser"
292
+ - "iam:AttachUserPolicy"
293
+
294
+ # any_of: Detects when ANY action exists in a single statement
295
+ # (per-statement check - flags individual dangerous actions)
296
+ - any_of:
297
+ - "iam:PutUserPolicy"
298
+ - "iam:PutGroupPolicy"
299
+ - "iam:PutRolePolicy"
300
+
301
+ # Lambda backdoor: Needs both actions somewhere in policy
302
+ - all_of:
303
+ - "lambda:CreateFunction"
304
+ - "iam:PassRole"
305
+
306
+ # Regex patterns work with all_of (policy-wide check)
307
+ - all_of:
308
+ - "iam:Create.*" # Any IAM Create action
309
+ - "iam:Attach.*" # Any IAM Attach action
310
+
311
+ # Enforce required conditions for sensitive actions
312
+ action_condition_enforcement:
313
+ enabled: true
314
+ action_condition_requirements:
315
+ - actions: ["iam:PassRole"]
316
+ severity: critical
317
+ required_conditions:
318
+ - condition_key: "iam:PassedToService"
319
+
320
+ # Ignore specific patterns
321
+ ignore_patterns:
322
+ - filepath: "terraform/modules/admin/*.json"
323
+ - action: "s3:*"
324
+ filepath: "policies/s3-admin-policy.json"
325
+ ```
326
+
327
+ **📖 Complete documentation:**
328
+ - [Check Reference Guide](docs/check-reference.md) - All 18 checks with examples
329
+ - [Configuration Guide](docs/configuration.md) - Full configuration options
330
+ - [Condition Requirements](docs/condition-requirements.md) - Action-specific requirements
331
+ - [Privilege Escalation Detection](docs/privilege-escalation.md) - How privilege escalation works
332
+
333
+ ## Output Formats & GitHub Integration
334
+
335
+ ### Output Formats
336
+ - **Console** - Clean terminal output with colors
337
+ - **Enhanced** - Visual output with progress bars
338
+ - **JSON** - Structured data for automation
339
+ - **Markdown** - GitHub PR comments
340
+ - **SARIF** - GitHub Code Scanning integration
341
+ - **CSV** - Spreadsheet analysis
342
+ - **HTML** - Interactive reports
343
+
344
+ ### GitHub PR Integration
345
+
346
+ **Three comment modes (use any combination):**
347
+ - `--github-comment` - Summary in PR conversation
348
+ - `--github-review` - Line-specific review comments on files
349
+ - `--github-summary` - Overview in GitHub Actions summary tab
350
+
351
+ **Smart comment management:**
352
+ - Automatically cleans up old comments from previous runs
353
+ - Updates summaries instead of duplicating
354
+ - No stale comments left behind
355
+
356
+ **📖 See [GitHub Integration Guide](docs/github-actions-workflows.md) for detailed examples**
357
+
358
+ ## AWS Access Analyzer (Optional)
359
+
360
+ In addition to the 18 built-in checks, optionally enable AWS Access Analyzer for additional validation capabilities that require AWS credentials:
361
+
362
+ ### Access Analyzer Capabilities
363
+
364
+ **Custom Policy Checks:**
365
+ - `check-access-not-granted` - Verify policies DON'T grant specific actions (max 100 actions)
366
+ - `check-no-new-access` - Compare against baseline to detect permission creep
367
+ - `check-no-public-access` - Validate 29+ resource types for public exposure
368
+
369
+ **Example:**
370
+ ```bash
371
+ # Prevent dangerous actions
372
+ iam-validator analyze --path policies/ \
373
+ --check-access-not-granted "s3:DeleteBucket iam:AttachUserPolicy"
374
+
375
+ # Compare against baseline
376
+ iam-validator analyze --path new-policy.json \
377
+ --check-no-new-access baseline-policy.json
378
+
379
+ # Check for public access
380
+ iam-validator analyze --path bucket-policy.json \
381
+ --policy-type RESOURCE_POLICY \
382
+ --check-no-public-access \
383
+ --public-access-resource-type "AWS::S3::Bucket"
384
+ ```
385
+
386
+ **Supported Policy Types:**
387
+ - `IDENTITY_POLICY` (default) - User/role policies
388
+ - `RESOURCE_POLICY` - S3, SNS, KMS resource policies
389
+ - `SERVICE_CONTROL_POLICY` - AWS Organizations SCPs
390
+ - `RESOURCE_CONTROL_POLICY` - AWS Organizations RCPs (2024)
391
+
392
+ **📖 See [Access Analyzer documentation](docs/custom-checks.md) for complete details**
393
+
394
+ ## 📚 Documentation
395
+
396
+ **Guides:**
397
+ - [Check Reference](docs/check-reference.md) - All 18 checks with examples
398
+ - [Configuration Guide](docs/configuration.md) - Customize checks and behavior
399
+ - [GitHub Actions Guide](docs/github-actions-workflows.md) - CI/CD integration
400
+ - [Python Library Guide](docs/python-library-usage.md) - Use as Python package
401
+ - [Contributing Guide](CONTRIBUTING.md) - How to contribute
402
+
403
+ **Examples:**
404
+ - [Configuration Examples](examples/configs/) - 9 config file templates
405
+ - [Workflow Examples](examples/github-actions/) - GitHub Actions workflows
406
+ - [Custom Checks](examples/custom_checks/) - Add your own validation rules
407
+
408
+ ## 🤝 Contributing
409
+
410
+ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
411
+
412
+ **Quick start:**
413
+ ```bash
414
+ git clone https://github.com/YOUR-USERNAME/iam-policy-validator.git
415
+ cd iam-policy-validator
416
+ uv sync --extra dev
417
+ uv run pytest
418
+ ```
419
+
420
+ ## 📄 License
421
+
422
+ MIT License - see [LICENSE](LICENSE) file for details.
423
+
424
+ **Third-party code:** ARN pattern matching in [iam_validator/sdk/arn_matching.py](iam_validator/sdk/arn_matching.py) is derived from [Parliament](https://github.com/duo-labs/parliament) (BSD 3-Clause License).
425
+
426
+ ## 🆘 Support
427
+
428
+ - **Issues**: [GitHub Issues](https://github.com/boogy/iam-policy-validator/issues)
@@ -1,70 +1,70 @@
1
1
  iam_validator/__init__.py,sha256=APnMR3Fu4fHhxfsHBvUM2dJIwazgvLKQbfOsSgFPidg,693
2
2
  iam_validator/__main__.py,sha256=to_nz3n_IerJpVVZZ6WSFlFR5s_06J0csfPOTfQZG8g,197
3
- iam_validator/__version__.py,sha256=FNrocEukG5quczKGW_qtlYvs4m4L6shLFDfOqT0Q7bE,206
3
+ iam_validator/__version__.py,sha256=0niAY6KgsXeeyFV5nTmvfvem16X3OTrO_DItEqsW74A,361
4
4
  iam_validator/checks/__init__.py,sha256=eDiDlVon0CwWGSBnZgM-arn1i5R5ZSG89pgR-ifETxE,1782
5
- iam_validator/checks/action_condition_enforcement.py,sha256=_yyWFHTNwIYYf8neSMK4EmFfqBgJvBb3nuCerZPE2a4,36587
6
- iam_validator/checks/action_resource_matching.py,sha256=X9dqWy1s_-h1rA81wZRLOxAVLmUHlGVPjxMo0WKIlwM,17433
5
+ iam_validator/checks/action_condition_enforcement.py,sha256=VhFEGbkcgkRwNRRuslvat5uib2tlH2Nr6sltbAQTs6I,36834
6
+ iam_validator/checks/action_resource_matching.py,sha256=sk67jcDF1WzW4tPgcRSdTj4UBe2stALdwHx5ViVA9dU,19207
7
7
  iam_validator/checks/action_validation.py,sha256=IpxtTsk58f2zEZ-xzAoyHw4QK8BCRV43OffP-8ydf9E,2578
8
- iam_validator/checks/condition_key_validation.py,sha256=E-doe2QjvKSkyjXZO9TBp0QS7M0Fv2oYYQQ9738QNxg,3918
9
- iam_validator/checks/condition_type_mismatch.py,sha256=qAbP6pP_vM1aBvIBRHji56XLH_5cQI4cDhpMQe19CHM,10588
10
- iam_validator/checks/full_wildcard.py,sha256=0_F6h4goWlc3DuZwo1F9YGw5hvpnkfZxYSDxhXXK50I,2449
11
- iam_validator/checks/mfa_condition_check.py,sha256=s7K2r9hxlJI1KWk8qXl-JOWE6jLIhpxooK26Pr7acKs,4915
8
+ iam_validator/checks/condition_key_validation.py,sha256=10XxTwIcr887CbgmN90jfRZabj5RHo08dGa8csM50Fo,3980
9
+ iam_validator/checks/condition_type_mismatch.py,sha256=JyiAOyUZShzXZI8dgycL4oqwRkpJYUPwoGX4zigsi5I,10613
10
+ iam_validator/checks/full_wildcard.py,sha256=ywD762BOV8WxFuTTARkaGMJn27f3ZZVuZUjKo8URnTc,2281
11
+ iam_validator/checks/mfa_condition_check.py,sha256=YCBX3tFTQRmVTAed_W-Tu1b6WqD2LBYyom53P7lBjh4,4935
12
12
  iam_validator/checks/policy_size.py,sha256=ibgmrErpkz6OfUAN6bFuHe1KHzpzzra9gHwNtVAkPWc,5729
13
13
  iam_validator/checks/policy_type_validation.py,sha256=9qmrA8CXwsVpCU4rT0RrqDXgVOzNamMEpdg3cXWAtBI,15213
14
- iam_validator/checks/principal_validation.py,sha256=Bm4pH6eiJLDa9ID7UyM63phgffh-P5DpPpSBUbYyVn8,29851
14
+ iam_validator/checks/principal_validation.py,sha256=gTv_TqJDspGEX3iJkHXrw3DyKMJeyE33uQakZ0PjNoo,29969
15
15
  iam_validator/checks/resource_validation.py,sha256=fGi9QuX-lIHDtLm8xB3VReFFhbZpQ2Yub-FKRafQCkw,5984
16
- iam_validator/checks/sensitive_action.py,sha256=mdl4g67HBioYTvAvar9CaTjxfaPvpYkNo9phL4E1c1w,9794
17
- iam_validator/checks/service_wildcard.py,sha256=CiQQoti06nqVgvH-HpBIjoW23tnTJqDU4S-ZnM1DwsA,4218
16
+ iam_validator/checks/sensitive_action.py,sha256=0vuhF1UkAH_vxhfHsC8xk68aJXHvI7c9KTLcJFNlnHM,9652
17
+ iam_validator/checks/service_wildcard.py,sha256=1ynXLG6_82SIH8aHP88qQojJf38ZH0agnSmHp0VkZ98,4010
18
18
  iam_validator/checks/set_operator_validation.py,sha256=1XjOdf-xk-m6m1bODuHsELZccriGqOJTDI-HCcuId80,7464
19
- iam_validator/checks/sid_uniqueness.py,sha256=1Ux9W1hPPhzgdCzfxwxvD-nSBRo1SyrxFWlnTXDcOys,6887
20
- iam_validator/checks/wildcard_action.py,sha256=XAVuk5L9dQqiWPgd3HJXGNmYr2bh2szJMVVcHSBXb_8,2140
21
- iam_validator/checks/wildcard_resource.py,sha256=IEpyoU4mA3t2kRxSwVavtROYIyF0Bq1xZJAL9P7XbVQ,5582
19
+ iam_validator/checks/sid_uniqueness.py,sha256=yWNHyy002aIHxJKtHeYpYds7bKgreL0BvQmRkI2UwvQ,6891
20
+ iam_validator/checks/wildcard_action.py,sha256=f1QZ68eHzQwCTeYY_9UiYaMxUaq7XYia6DaBjIspZ2A,1972
21
+ iam_validator/checks/wildcard_resource.py,sha256=GNpbk7WDExHG6Yqu4_gxeRCK6NUEL8TFjgbvaHgg7V0,5414
22
22
  iam_validator/checks/utils/__init__.py,sha256=j0X4ibUB6RGx2a-kNoJnlVZwHfoEvzZsIeTmJIAoFzA,45
23
23
  iam_validator/checks/utils/policy_level_checks.py,sha256=2V60C0zhKfsFPjQ-NMlD3EemtwA9S6-4no8nETgXdQE,5274
24
- iam_validator/checks/utils/sensitive_action_matcher.py,sha256=e67RIi-zg7ssFwq6x4kt4wsTF-brNz91KaBxgV-23jg,10687
25
- iam_validator/checks/utils/wildcard_expansion.py,sha256=V3V_KRpapOzPBhpUObJjGHoMhvCH90QvDxppeEHIG_U,3152
24
+ iam_validator/checks/utils/sensitive_action_matcher.py,sha256=tcWK4nImpSVNia0FUsN2uLK9LM5EnzjRFtaPQLHZaLw,10667
25
+ iam_validator/checks/utils/wildcard_expansion.py,sha256=fSSoquVdVZaVWS_qBxAx7LMOzxgHed4ffQ6OAZnuqos,3132
26
26
  iam_validator/commands/__init__.py,sha256=M-5bo8w0TCWydK0cXgJyPD2fmk8bpQs-3b26YbgLzlc,565
27
27
  iam_validator/commands/analyze.py,sha256=rvLBJ5_A3HB530xtixhaIsC19QON68olEQnn8TievgI,20784
28
28
  iam_validator/commands/base.py,sha256=5baCCMwxz7pdQ6XMpWfXFNz7i1l5dB8Qv9dKKR04Gzs,1074
29
29
  iam_validator/commands/cache.py,sha256=p4ucRVuh42sbK3Lk0b610L3ofAR5TnUreF00fpO6VFg,14219
30
30
  iam_validator/commands/download_services.py,sha256=KKz3ybMLT8DQUf9aFZ0tilJ-o1b6PE8Pf1pC4K6cT8I,9175
31
31
  iam_validator/commands/post_to_pr.py,sha256=CvUXs2xvO-UhluxdfNM6F0TCWD8hDBEOiYw60fm1Dms,2363
32
- iam_validator/commands/validate.py,sha256=Eik-w613zCnX7hUHziBq4k5la3e3qJ0CO1__7aw-gBk,23554
32
+ iam_validator/commands/validate.py,sha256=2v91ogbEzKfjk2u6Y4NO0yvsCOwxi9jXoqD7acBbVTE,23624
33
33
  iam_validator/core/__init__.py,sha256=1FvJPMrbzJfS9YbRUJCshJLd5gzWwR9Fd_slS0Aq9c8,416
34
34
  iam_validator/core/access_analyzer.py,sha256=8GgkR-vCkCtSxtXGywvQNBPYq-rvDLexUuLSyflq0V4,24520
35
35
  iam_validator/core/access_analyzer_report.py,sha256=O17gagknvkNMTTlq7BrLM68FjlCEm4LjIKD9oqxEbPg,24860
36
- iam_validator/core/aws_fetcher.py,sha256=cZFo5JMSoNLx1tpM6NzYr2cnq8Bvc2KQx2nJDmo69lc,36504
36
+ iam_validator/core/aws_fetcher.py,sha256=obTzxHD9pMsWo-SojSOeWyw2s2_St-LNgbmh5BGEM9c,41215
37
37
  iam_validator/core/check_registry.py,sha256=cMjtJROkZOLzXxl-mTdLYHdxyajNnOsaHGs-EeaSZ7k,21741
38
38
  iam_validator/core/cli.py,sha256=PkXiZjlgrQ21QustBbspefYsdbxst4gxoClyG2_HQR8,3843
39
39
  iam_validator/core/condition_validators.py,sha256=7zBjlcf2xGFKGbcFrXSLvWT5tFhWxoqwzhsJqS2E8uY,21524
40
- iam_validator/core/constants.py,sha256=oblMWsjoroIhwjYgZdcyLxaATsGeR99zQwRg6h59Nlo,3145
41
- iam_validator/core/models.py,sha256=59yqvHoX3nCSJyQDmWCuEsQzNz9PNiF7um7A1wti-2w,12176
42
- iam_validator/core/policy_checks.py,sha256=Uz2yCsqRaoIja31F4ZM-39a1pHv51yZqKyWWkGUZKNY,26489
43
- iam_validator/core/policy_loader.py,sha256=TR7SpzlRG3TwH4HBGEFUuhNOmxIR8Cud2SQ-AmHWBpM,14040
40
+ iam_validator/core/constants.py,sha256=H3eH0yddn5Dk-xZxJWtuvluRIpuXKYGiiteBSHPpJoI,5560
41
+ iam_validator/core/models.py,sha256=55BCSqqJiAN96SFwK3tiTy6fhu6YBL6avKo8VpCpy2A,12766
42
+ iam_validator/core/policy_checks.py,sha256=3UMLl8SQ4oJLTU1kwscvh7c7gpT5QtjITk_bJCJ_rzs,26616
43
+ iam_validator/core/policy_loader.py,sha256=HVEnaXhQwrb9WbXpu0tn8SJBvHNW9UgDO6w4zLjLsu0,16776
44
44
  iam_validator/core/pr_commenter.py,sha256=MU-t7SfdHUpSc6BDbh8_dNAbxDiG-bZBCry-jUXivAc,15066
45
- iam_validator/core/report.py,sha256=j6uWlFL6Xavl4BnpaQtQoxFOEgKEiuY0IYBq8I9DH5Q,34134
45
+ iam_validator/core/report.py,sha256=kzSeWnT1LqWZVA5pqKKz-maVowXVj0djdoShfRhhpz4,35899
46
46
  iam_validator/core/config/__init__.py,sha256=CWSyIA7kEyzrskEenjYbs9Iih10BXRpiY9H2dHg61rU,2671
47
47
  iam_validator/core/config/aws_api.py,sha256=HLIzOItQ0A37wxHcgWck6ZFO0wmNY8JNTiWMMK6JKYU,1248
48
48
  iam_validator/core/config/aws_global_conditions.py,sha256=gdmMxXGBy95B3uYUG-J7rnM6Ixgc6L7Y9Pcd2XAMb60,7170
49
49
  iam_validator/core/config/category_suggestions.py,sha256=QlrYi4BTkxDSTlL7NZGE9BWN-atWetZ6XjkI9F_7YzI,4370
50
50
  iam_validator/core/config/condition_requirements.py,sha256=1PuADTB9pLqh-kNUGC7kSU6LMLtXMSc003tvI7qKeAY,5170
51
- iam_validator/core/config/config_loader.py,sha256=7YkuPnroR-Up5CUTQOXIyS_b732WrzNn8o1EH9O6lyI,17730
52
- iam_validator/core/config/defaults.py,sha256=w5ievxkqki3zYr7NaREoWtVx5rTfxBpZlgoNdovcILs,27112
51
+ iam_validator/core/config/config_loader.py,sha256=qKD8aR8YAswaFf68pnYJLFNwKznvcc6lNxSQWU3i6SY,17713
52
+ iam_validator/core/config/defaults.py,sha256=mCOr_YgiRQp6fThtxrcjMtm-LPdZQbd6AS16gLzV17c,27589
53
53
  iam_validator/core/config/principal_requirements.py,sha256=VCX7fBDgeDTJQyoz7_x7GI7Kf9O1Eu-sbihoHOrKv6o,15105
54
54
  iam_validator/core/config/sensitive_actions.py,sha256=uATDIp_TD3OQQlsYTZp79qd1mSK2Bf9hJ0JwcqLBr84,25344
55
55
  iam_validator/core/config/service_principals.py,sha256=gQSROsxUWBD6P2F9qP320UZV4lHGlsyvHSkMyy0njrU,2685
56
56
  iam_validator/core/config/wildcards.py,sha256=H_v6hb-rZ0UUz4cul9lxkVI39e6knaK4Y-MbWz2Ebpw,3228
57
57
  iam_validator/core/formatters/__init__.py,sha256=fnCKAEBXItnOf2m4rhVs7zwMaTxbG6ESh3CF8V5j5ec,868
58
58
  iam_validator/core/formatters/base.py,sha256=SShDeDiy5mYQnS6BpA8xYg91N-KX1EObkOtlrVHqx1Q,4451
59
- iam_validator/core/formatters/console.py,sha256=lX4Yp4bTW61fxe0fCiHuO6bCZtC_6cjCwqDNQ55nT_8,1937
60
- iam_validator/core/formatters/csv.py,sha256=2FaN6Y_0TPMFOb3A3tNtj0-9bkEc5P-6eZ7eLROIqFE,5899
61
- iam_validator/core/formatters/enhanced.py,sha256=S0UgYKFOgILfOqwnBC8-WFab3F1CiEko33g0nbaswtk,17085
59
+ iam_validator/core/formatters/console.py,sha256=FdTp7AzeILCWrUynSvSew8QJKGOMJaAA9_YiQJd-uco,2196
60
+ iam_validator/core/formatters/csv.py,sha256=pPqgvGh4KtD5Qm36xnMaDAavXYR6MlQhs4zbcrxT550,5941
61
+ iam_validator/core/formatters/enhanced.py,sha256=TVtkcTIow8NGoLhG45-5ms-_PTxyxMcAHxf_uPMyKAc,18155
62
62
  iam_validator/core/formatters/html.py,sha256=j4sQi-wXiD9kCHldW5JCzbJe0frhiP5uQI9KlH3Sj_g,22994
63
63
  iam_validator/core/formatters/json.py,sha256=A7gZ8P32GEdbDvrSn6v56yQ4fOP_kyMaoFVXG2bgnew,939
64
- iam_validator/core/formatters/markdown.py,sha256=aPAY6FpZBHsVBDag3FAsB_X9CZzznFjX9dQr0ysDrTE,2251
64
+ iam_validator/core/formatters/markdown.py,sha256=dk4STeY-tOEZsVrlmolIEqZvWYP9JhRtygxxNA49DEE,2293
65
65
  iam_validator/core/formatters/sarif.py,sha256=O3pn7whqFq5xxk-tuoqSb2k4Fk5ai_A2SKX_ph8GLV4,10469
66
66
  iam_validator/integrations/__init__.py,sha256=7Hlor_X9j0NZaEjFuSvoXAAuSKQ-zgY19Rk-Dz3JpKo,616
67
- iam_validator/integrations/github_integration.py,sha256=QoPkaxdRDQTzmHN4cKEXoGcn8BRv37JW4IvD2W5jEtc,26474
67
+ iam_validator/integrations/github_integration.py,sha256=EnrolMq3uZbKWPxUMhYnqcKAfic6Fb8qJzieDruKqsc,26485
68
68
  iam_validator/integrations/ms_teams.py,sha256=t2PlWuTDb6GGH-eDU1jnOKd8D1w4FCB68bahGA7MJcE,14475
69
69
  iam_validator/sdk/__init__.py,sha256=fRDSXAclGmCU3KDft4StL8JUcpAsdzwIRf8mVj461q0,5306
70
70
  iam_validator/sdk/arn_matching.py,sha256=HSDpLltOYISq-SoPebAlM89mKOaUaghq_04urchEFDA,12778
@@ -73,11 +73,12 @@ iam_validator/sdk/exceptions.py,sha256=tm91TxIwU157U_UHN7w5qICf_OhU11agj6pV5W_YP
73
73
  iam_validator/sdk/helpers.py,sha256=OVBg4xrW95LT74wXCg1LQkba9kw5RfFqeCLuTqhgL-A,5697
74
74
  iam_validator/sdk/policy_utils.py,sha256=CZS1OGSdiWsd2lsCwg0BDcUNWa61tUwgvn-P5rKqeN8,12987
75
75
  iam_validator/sdk/shortcuts.py,sha256=EVNSYV7rv4TFH03ulsZ3mS1UVmTSp2jKpc2AXs4j1q4,8531
76
- iam_validator/utils/__init__.py,sha256=V8u-SSdnL4a7NwF-yg9x0JRl5epKAXEs2f5RiwK2qPo,856
76
+ iam_validator/utils/__init__.py,sha256=NveA2F3G1E6-ANZzFr7J6Q6u5mogvMp862iFokmYuCs,1021
77
77
  iam_validator/utils/cache.py,sha256=wOQKOBeoG6QqC5f0oXcHz63Cjtu_-SsSS-0pTSwyAiM,3254
78
- iam_validator/utils/regex.py,sha256=PMVCYxjlVa2zLNEnIU3upQCSIhPazlXWg_sJClIiqiM,6221
79
- iam_policy_validator-1.7.0.dist-info/METADATA,sha256=gPtC5f-uipnujGSzMvZdgqR4LPpOTpS-KunMejzpsIo,36979
80
- iam_policy_validator-1.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
81
- iam_policy_validator-1.7.0.dist-info/entry_points.txt,sha256=8HtWd8O7mvPiPdZR5YbzY8or_qcqLM4-pKaFdhtFT8M,62
82
- iam_policy_validator-1.7.0.dist-info/licenses/LICENSE,sha256=AMnbFTBDcK4_MITe2wiQBkj0vg-jjBBhsc43ydC7tt4,1098
83
- iam_policy_validator-1.7.0.dist-info/RECORD,,
78
+ iam_validator/utils/regex.py,sha256=xHoMECttb7qaMhts-c9b0GIxdhHNZTt-UBr7wNhWfzg,6219
79
+ iam_validator/utils/terminal.py,sha256=FsRaRMH_JAyDgXWBCOgOEhbS89cs17HCmKYoughq5io,724
80
+ iam_policy_validator-1.7.2.dist-info/METADATA,sha256=fwySi0xxZPeiRTXyYfmp8YZPNyphy8HylBzhSXkNNG0,15244
81
+ iam_policy_validator-1.7.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
82
+ iam_policy_validator-1.7.2.dist-info/entry_points.txt,sha256=8HtWd8O7mvPiPdZR5YbzY8or_qcqLM4-pKaFdhtFT8M,62
83
+ iam_policy_validator-1.7.2.dist-info/licenses/LICENSE,sha256=AMnbFTBDcK4_MITe2wiQBkj0vg-jjBBhsc43ydC7tt4,1098
84
+ iam_policy_validator-1.7.2.dist-info/RECORD,,
@@ -3,5 +3,7 @@
3
3
  This file is the single source of truth for the package version.
4
4
  """
5
5
 
6
- __version__ = "1.7.0"
7
- __version_info__ = tuple(int(part) for part in __version__.split("."))
6
+ __version__ = "1.7.2"
7
+ # Parse version, handling pre-release suffixes like -rc, -alpha, -beta
8
+ _version_base = __version__.split("-")[0] # Remove pre-release suffix if present
9
+ __version_info__ = tuple(int(part) for part in _version_base.split("."))
@@ -349,7 +349,10 @@ class ActionConditionEnforcementCheck(PolicyCheck):
349
349
  return issues
350
350
 
351
351
  async def _check_action_match(
352
- self, statement_actions: list[str], requirement: dict[str, Any], fetcher: AWSServiceFetcher
352
+ self,
353
+ statement_actions: list[str],
354
+ requirement: dict[str, Any],
355
+ fetcher: AWSServiceFetcher,
353
356
  ) -> tuple[bool, list[str]]:
354
357
  """
355
358
  Check if statement actions match the requirement.
@@ -491,6 +494,7 @@ class ActionConditionEnforcementCheck(PolicyCheck):
491
494
  if re.match(f"^{wildcard_pattern}$", statement_action):
492
495
  return True
493
496
  except re.error:
497
+ # Invalid regex pattern - skip this match attempt
494
498
  pass
495
499
 
496
500
  # AWS wildcard match in statement_action (e.g., "iam:Creat*" in policy)
@@ -507,6 +511,7 @@ class ActionConditionEnforcementCheck(PolicyCheck):
507
511
  if re.match(f"^{stmt_wildcard_pattern}$", required_action):
508
512
  return True
509
513
  except re.error:
514
+ # Invalid regex pattern - skip this match attempt
510
515
  pass
511
516
 
512
517
  # Check if statement wildcard overlaps with any of our action patterns
@@ -764,6 +769,10 @@ class ActionConditionEnforcementCheck(PolicyCheck):
764
769
  or self.get_severity(config) # Global check severity
765
770
  )
766
771
 
772
+ suggestion_text, example_code = self._build_suggestion(
773
+ condition_key, description, example, expected_value, operator
774
+ )
775
+
767
776
  return ValidationIssue(
768
777
  severity=severity,
769
778
  statement_sid=statement.sid,
@@ -772,9 +781,8 @@ class ActionConditionEnforcementCheck(PolicyCheck):
772
781
  message=f"{message_prefix} Action(s) {matching_actions} require condition '{condition_key}'",
773
782
  action=", ".join(matching_actions),
774
783
  condition_key=condition_key,
775
- suggestion=self._build_suggestion(
776
- condition_key, description, example, expected_value, operator
777
- ),
784
+ suggestion=suggestion_text,
785
+ example=example_code,
778
786
  line_number=statement.line_number,
779
787
  )
780
788
 
@@ -785,19 +793,20 @@ class ActionConditionEnforcementCheck(PolicyCheck):
785
793
  example: str,
786
794
  expected_value: Any = None,
787
795
  operator: str = "StringEquals",
788
- ) -> str:
789
- """Build a helpful suggestion for adding the missing condition."""
790
- parts = []
796
+ ) -> tuple[str, str]:
797
+ """Build suggestion and example for adding the missing condition.
791
798
 
792
- if description:
793
- parts.append(description)
799
+ Returns:
800
+ Tuple of (suggestion_text, example_code)
801
+ """
802
+ suggestion = description if description else f"Add condition: {condition_key}"
794
803
 
795
804
  # Build example based on condition key type
796
805
  if example:
797
- parts.append(f"Example:\n```json\n{example}\n```")
806
+ example_code = example
798
807
  else:
799
808
  # Auto-generate example
800
- example_lines = ['Add to "Condition" block:', f' "{operator}": {{']
809
+ example_lines = [f' "{operator}": {{']
801
810
 
802
811
  if isinstance(expected_value, list):
803
812
  value_str = (
@@ -824,9 +833,9 @@ class ActionConditionEnforcementCheck(PolicyCheck):
824
833
  example_lines.append(f' "{condition_key}": {value_str}')
825
834
  example_lines.append(" }")
826
835
 
827
- parts.append("\n".join(example_lines))
836
+ example_code = "\n".join(example_lines)
828
837
 
829
- return ". ".join(parts) if parts else f"Add condition: {condition_key}"
838
+ return suggestion, example_code
830
839
 
831
840
  def _build_any_of_suggestion(self, any_of_conditions: list[dict[str, Any]]) -> str:
832
841
  """Build suggestion for any_of conditions."""