iam-policy-validator 1.14.7__py3-none-any.whl → 1.15.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 (42) hide show
  1. {iam_policy_validator-1.14.7.dist-info → iam_policy_validator-1.15.0.dist-info}/METADATA +16 -11
  2. {iam_policy_validator-1.14.7.dist-info → iam_policy_validator-1.15.0.dist-info}/RECORD +41 -28
  3. iam_policy_validator-1.15.0.dist-info/entry_points.txt +4 -0
  4. iam_validator/__version__.py +1 -1
  5. iam_validator/checks/__init__.py +2 -0
  6. iam_validator/checks/action_validation.py +91 -27
  7. iam_validator/checks/not_action_not_resource.py +163 -0
  8. iam_validator/checks/resource_validation.py +132 -81
  9. iam_validator/checks/wildcard_resource.py +136 -6
  10. iam_validator/commands/__init__.py +3 -0
  11. iam_validator/commands/cache.py +66 -24
  12. iam_validator/commands/completion.py +94 -15
  13. iam_validator/commands/mcp.py +210 -0
  14. iam_validator/commands/query.py +489 -65
  15. iam_validator/core/aws_service/__init__.py +5 -1
  16. iam_validator/core/aws_service/cache.py +20 -0
  17. iam_validator/core/aws_service/fetcher.py +180 -11
  18. iam_validator/core/aws_service/storage.py +14 -6
  19. iam_validator/core/aws_service/validators.py +32 -41
  20. iam_validator/core/check_registry.py +100 -35
  21. iam_validator/core/config/aws_global_conditions.py +13 -0
  22. iam_validator/core/config/check_documentation.py +104 -51
  23. iam_validator/core/config/config_loader.py +39 -3
  24. iam_validator/core/config/defaults.py +6 -0
  25. iam_validator/core/constants.py +11 -4
  26. iam_validator/core/models.py +39 -14
  27. iam_validator/mcp/__init__.py +162 -0
  28. iam_validator/mcp/models.py +118 -0
  29. iam_validator/mcp/server.py +2928 -0
  30. iam_validator/mcp/session_config.py +319 -0
  31. iam_validator/mcp/templates/__init__.py +79 -0
  32. iam_validator/mcp/templates/builtin.py +856 -0
  33. iam_validator/mcp/tools/__init__.py +72 -0
  34. iam_validator/mcp/tools/generation.py +888 -0
  35. iam_validator/mcp/tools/org_config_tools.py +263 -0
  36. iam_validator/mcp/tools/query.py +395 -0
  37. iam_validator/mcp/tools/validation.py +376 -0
  38. iam_validator/sdk/__init__.py +2 -0
  39. iam_validator/sdk/policy_utils.py +31 -5
  40. iam_policy_validator-1.14.7.dist-info/entry_points.txt +0 -2
  41. {iam_policy_validator-1.14.7.dist-info → iam_policy_validator-1.15.0.dist-info}/WHEEL +0 -0
  42. {iam_policy_validator-1.14.7.dist-info → iam_policy_validator-1.15.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iam-policy-validator
3
- Version: 1.14.7
3
+ Version: 1.15.0
4
4
  Summary: Validate AWS IAM policies for correctness and security using AWS Service Reference API
5
5
  Project-URL: Homepage, https://github.com/boogy/iam-policy-validator
6
6
  Project-URL: Documentation, https://boogy.github.io/iam-policy-validator
@@ -11,7 +11,7 @@ Author-email: boogy <0xboogy@gmail.com>
11
11
  License: MIT
12
12
  License-File: LICENSE
13
13
  Keywords: aws,github-action,iam,policy,security,validation
14
- Classifier: Development Status :: 4 - Beta
14
+ Classifier: Development Status :: 5 - Production/Stable
15
15
  Classifier: Intended Audience :: Developers
16
16
  Classifier: Intended Audience :: System Administrators
17
17
  Classifier: License :: OSI Approved :: MIT License
@@ -19,6 +19,8 @@ Classifier: Programming Language :: Python :: 3
19
19
  Classifier: Programming Language :: Python :: 3.10
20
20
  Classifier: Programming Language :: Python :: 3.11
21
21
  Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
22
24
  Classifier: Topic :: Security
23
25
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
26
  Classifier: Topic :: System :: Systems Administration
@@ -44,6 +46,8 @@ Requires-Dist: mkdocs-literate-nav>=0.6.0; extra == 'docs'
44
46
  Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
45
47
  Requires-Dist: mkdocs>=1.6.0; extra == 'docs'
46
48
  Requires-Dist: mkdocstrings[python]>=0.24.0; extra == 'docs'
49
+ Provides-Extra: mcp
50
+ Requires-Dist: fastmcp>=2.14.1; extra == 'mcp'
47
51
  Description-Content-Type: text/markdown
48
52
 
49
53
  # IAM Policy Validator
@@ -55,6 +59,8 @@ Description-Content-Type: text/markdown
55
59
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
56
60
  [![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)
57
61
 
62
+ **[📖 Full Documentation](https://boogy.github.io/iam-policy-validator/)**
63
+
58
64
  ---
59
65
 
60
66
  ## Why This Tool Exists
@@ -434,15 +440,14 @@ Validates against official AWS IAM requirements:
434
440
 
435
441
  Identifies overly permissive configurations:
436
442
 
437
- | Check | What It Catches |
438
- | ------------------------------------- | ------------------------------------------------------ |
439
- | **Wildcard Action** | `Action: "*"` grants all AWS permissions |
440
- | **Wildcard Resource** | `Resource: "*"` applies to all resources |
441
- | **Full Wildcard** | Both `Action: "*"` AND `Resource: "*"` (admin access) |
442
- | **Service Wildcards** | `s3:*`, `iam:*`, `ec2:*` (overly broad) |
443
- | **Sensitive Actions (Policy-Wide)** | **Cross-statement** privilege escalation patterns |
444
- | **Sensitive Actions (Per-Statement)** | Dangerous actions in single statement |
445
- | **Condition Enforcement** | Organization-specific requirements (your custom rules) |
443
+ | Check | What It Catches |
444
+ | ------------------------- | ------------------------------------------------------ |
445
+ | **Wildcard Action** | `Action: "*"` grants all AWS permissions |
446
+ | **Wildcard Resource** | `Resource: "*"` applies to all resources |
447
+ | **Full Wildcard** | Both `Action: "*"` AND `Resource: "*"` (admin access) |
448
+ | **Service Wildcards** | `s3:*`, `iam:*`, `ec2:*` (overly broad) |
449
+ | **Sensitive Actions** | 490+ privilege escalation patterns and dangerous actions |
450
+ | **Condition Enforcement** | Organization-specific condition requirements |
446
451
 
447
452
  **Note on Sensitive Actions:** This check has two modes:
448
453
 
@@ -1,76 +1,78 @@
1
1
  iam_validator/__init__.py,sha256=xHdUASOxFHwEXfT_GSr_KrkLlnxZ-pAAr1wW1PwAGko,693
2
2
  iam_validator/__main__.py,sha256=to_nz3n_IerJpVVZZ6WSFlFR5s_06J0csfPOTfQZG8g,197
3
- iam_validator/__version__.py,sha256=gzNFhw4Ir0RuOpe7hw6D6K-mQnE1zvBtL7jSlcAUnrE,374
4
- iam_validator/checks/__init__.py,sha256=OTkPnmlelu4YjMO8krjhu2wXiTV72RzopA5u1SfPQA0,1990
3
+ iam_validator/__version__.py,sha256=nBQw8c9_j3cm0AjlGzltWfPi7BYKIJlC0VQImhHNMGQ,374
4
+ iam_validator/checks/__init__.py,sha256=wFU5Lz-ZIQBcn2y1u0Kl88B--vEO3btOOaTGPPSjJ74,2106
5
5
  iam_validator/checks/action_condition_enforcement.py,sha256=2-XUMbof9tQ7SHZNmAHMkR1DgbOIzY2eFWlp9S9dwLk,60625
6
6
  iam_validator/checks/action_resource_matching.py,sha256=qND0hfDgNoxFEdLWwrxOPVDfdj3k50nzedT2qF7nK7o,19428
7
- iam_validator/checks/action_validation.py,sha256=glA2F3iQBU-d8rruiyB9IdzVOESC2Kb-91SnwRCdQF0,2562
7
+ iam_validator/checks/action_validation.py,sha256=gy9_mujYbojBboLk0WwuJYJjggrY2sRwHAFvJnoLTYE,4823
8
8
  iam_validator/checks/condition_key_validation.py,sha256=5i8LqqV78SjWK6pLrbttWmeMAD4pDC12_FjTjx5dFSU,4024
9
9
  iam_validator/checks/condition_type_mismatch.py,sha256=KJp7zQHDd8VeTcfjcD-ur3S4070cXEDTWkFtxfp7CuE,10652
10
10
  iam_validator/checks/full_wildcard.py,sha256=0TkkHtV0MZ6nZtJRtGdn3wwOMM96TRyGO7l7mmdHNUo,2325
11
11
  iam_validator/checks/mfa_condition_check.py,sha256=y1LbqcvQ_fL2BPTNaKRQoBYM5hM7JET9cDPUOWKFEVs,4814
12
+ iam_validator/checks/not_action_not_resource.py,sha256=WWKOCLCq7yxOG9tgi1n5xPpphTLZ9RfcfPwZ-TP6n9Y,8097
12
13
  iam_validator/checks/policy_size.py,sha256=eJd36Nj4gqWLIkQ5imhHR1hGtQ6T-iJsC22Wd1VSUf0,4681
13
14
  iam_validator/checks/policy_structure.py,sha256=LExdm93JeqsyhikWrh9lfJ9sBiZ4818Ts0-N3MwUrtk,22089
14
15
  iam_validator/checks/policy_type_validation.py,sha256=-Q2Yn_sa7Cba_Fb9ESxSL5qNbRpncuC7NQy7R_fdJtY,16521
15
16
  iam_validator/checks/principal_validation.py,sha256=TthgDW5YXFfv5li1u4nn56k0Feqt5HeOEtQgo5pBKqo,27911
16
- iam_validator/checks/resource_validation.py,sha256=RIBMiCMwX45wwnDwSzpvF1mIught5QSbSbmTQSVa1wI,6192
17
+ iam_validator/checks/resource_validation.py,sha256=k7qHIwX7IDf4MCWIvl9G17aINzTuZLOHDHRWrujbCaM,7787
17
18
  iam_validator/checks/sensitive_action.py,sha256=LHicl6dd5E1JV19cLKvFAMGzLzYr5h_Y7QvS8s57kvA,18952
18
19
  iam_validator/checks/service_wildcard.py,sha256=1epcET5oDclAmzxhtmQfKBg3Q5Rl4VXBMoZouxCJLpM,4114
19
20
  iam_validator/checks/set_operator_validation.py,sha256=GMZ1OWqySptYWV7565-K4R5ODs1eYgWXDozwtU-3sgY,7422
20
21
  iam_validator/checks/sid_uniqueness.py,sha256=MPQwALBjcvbY4Q55mpxDrGMqmVCMb13YSg621YbQYF8,6048
21
22
  iam_validator/checks/trust_policy_validation.py,sha256=r3fM2hU7W0yCFS6hbd4ZSlD8y2tm0zk99mUVlIt0LsI,17956
22
23
  iam_validator/checks/wildcard_action.py,sha256=VhWezb1JXmFnwV9WKgVu-48ythScGfZasg8fFd6tAG4,2001
23
- iam_validator/checks/wildcard_resource.py,sha256=5nswLCYvjgiZvv64y3OOywVwmTZMlpYBRSC94FS3X8M,16801
24
+ iam_validator/checks/wildcard_resource.py,sha256=YO2I4q0QssOyjFrG62Yz148n3yRUJPTm_LD-bkVQj28,22351
24
25
  iam_validator/checks/utils/__init__.py,sha256=iI9jHIDlDuuPK2vxjJA-qc927PaWC9zVJb9z3vBRUsQ,356
25
26
  iam_validator/checks/utils/action_parser.py,sha256=zA_NGknc5gJvsmIlf4aC14eHFIkBLyL9if5ad80gHwY,4421
26
27
  iam_validator/checks/utils/policy_level_checks.py,sha256=pr-uLo-otB612YLZ-rd8W5Kl9ENaTHuzTNOUhQaULKc,7593
27
28
  iam_validator/checks/utils/sensitive_action_matcher.py,sha256=qDXcJa_2sCJu9pBbjDlI7x5lPtLRc6jQCpKPMheCOJQ,11215
28
29
  iam_validator/checks/utils/wildcard_expansion.py,sha256=3W13hlyWcP2wJ6w-BwM887VOnRzglK6Bk3eHMjUtOco,3131
29
- iam_validator/commands/__init__.py,sha256=RBEz-Kgt3aRVn_9B1HRy_XgQMIKzlSSQs4Gtg2jQEv8,729
30
+ iam_validator/commands/__init__.py,sha256=BgtZqCIazIhCpQIw49J8hOG853Y-sltg4w-SsSEDr14,793
30
31
  iam_validator/commands/analyze.py,sha256=rtXZmevC7GCXrADoGrxihRkrLbma59wMAMP2yBhqWPU,21752
31
32
  iam_validator/commands/base.py,sha256=5baCCMwxz7pdQ6XMpWfXFNz7i1l5dB8Qv9dKKR04Gzs,1074
32
- iam_validator/commands/cache.py,sha256=llfyQzPE5Azd5YcW0ohYcYjF_OCyiQ1GoJQ982t71lQ,14294
33
- iam_validator/commands/completion.py,sha256=cnQf3qcV5WSNpwJlPyl_hMNB1z3TkeeXCxj8K2FmEBw,19320
33
+ iam_validator/commands/cache.py,sha256=ZMfNe1HfKlCKESqa-9OkBcgZUqAIcV6m7rDrBxLq700,16162
34
+ iam_validator/commands/completion.py,sha256=mrvGoOOYJVC68SJbqmEJYBvqDHsDVm_4kLRbl15TtHY,23265
34
35
  iam_validator/commands/download_services.py,sha256=KKz3ybMLT8DQUf9aFZ0tilJ-o1b6PE8Pf1pC4K6cT8I,9175
36
+ iam_validator/commands/mcp.py,sha256=ttJXeWvV9GIK7ipa5xjS0gMjRjw3qcuRhJajF_8_rrU,6315
35
37
  iam_validator/commands/post_to_pr.py,sha256=CvUXs2xvO-UhluxdfNM6F0TCWD8hDBEOiYw60fm1Dms,2363
36
- iam_validator/commands/query.py,sha256=ft8ptWfsNUK4Wprq_A11txdV_chBgqkoAo7SQfzEwK0,17079
38
+ iam_validator/commands/query.py,sha256=6EQc3mGRqTZ8k8-yMNMBzV6vLCI0NaP-1P5zeAL1Vvo,35948
37
39
  iam_validator/commands/validate.py,sha256=4wk-eSwhgqnQvyUre426S831JadVUctb0FDeCZD4RTk,34176
38
40
  iam_validator/core/__init__.py,sha256=hYXkSbxplKzhM6dqrVzV4M3k7GKLsZbgExypxKq74gs,376
39
41
  iam_validator/core/access_analyzer.py,sha256=mtMaY-FnKjKEVITky_9ywZe1FaCAm61ElRv5Z_ZeC7E,24562
40
42
  iam_validator/core/access_analyzer_report.py,sha256=UMm2RNGj2rAKav1zsCw_htQZZRwRC0jjayd2zvKma1A,24896
41
43
  iam_validator/core/aws_fetcher.py,sha256=op93QvtGmeLF9dHobl2IuoPDeunn33pBLb8h7XjtmoQ,920
42
- iam_validator/core/check_registry.py,sha256=oRCdWoCGQ8VZERVYd821u9r5NdKQ9FMC54e6dRWJfqw,25475
44
+ iam_validator/core/check_registry.py,sha256=cRvFko_cTrip94VgVqwkxgrjR6oz3JfSiwertESicRc,28567
43
45
  iam_validator/core/cli.py,sha256=PkXiZjlgrQ21QustBbspefYsdbxst4gxoClyG2_HQR8,3843
44
46
  iam_validator/core/codeowners.py,sha256=dfRjYTpcTVmc-h95i4EoPXCXlcblD8yryeJBaTKQfjM,7530
45
47
  iam_validator/core/condition_validators.py,sha256=7zBjlcf2xGFKGbcFrXSLvWT5tFhWxoqwzhsJqS2E8uY,21524
46
- iam_validator/core/constants.py,sha256=YRT_uOUs1Dnt9J1hE-zG6Ja0numsH4Mf7RNNXNJWZIY,7447
48
+ iam_validator/core/constants.py,sha256=O80dQ6AtgsCJPempRtNlKaSIVE61rg6YDPV5vgaSnAY,7771
47
49
  iam_validator/core/diff_parser.py,sha256=5Jxa6WvQZtG5grblZeUH2OQ2R46tFLK-h8tvkHOSfLk,12110
48
50
  iam_validator/core/finding_fingerprint.py,sha256=NJIlu8NhdenWbLS7ww8LyWFasJgpKWN63-DprrNW7Zs,4353
49
51
  iam_validator/core/ignore_patterns.py,sha256=pZqDJBtkbck-85QK5eFPM5ZOPEKs3McRh3avqiCT5z0,10398
50
52
  iam_validator/core/ignore_processor.py,sha256=zgWfS-4BU4c_W6VxUxHIHorMtB5XzB410wZ3bbzVgH8,10686
51
53
  iam_validator/core/ignored_findings.py,sha256=b4PySz46so1rGKNt4prg2dkysHPfTJP4wsHYorVn1FA,12756
52
54
  iam_validator/core/label_manager.py,sha256=qKQ60shsW8yJELkHgd9rXgzLW9oKErPd4hFTTQkHjbI,8776
53
- iam_validator/core/models.py,sha256=lXUadIsTpp_j0Vt89Ez7aJkTKs2GD2ty3Ukl2NeY9Zo,15680
55
+ iam_validator/core/models.py,sha256=QgL1p5-GEPOSEi6VB-eqHR0dHH4Akq0bI_r-yVa2V9c,17060
54
56
  iam_validator/core/policy_checks.py,sha256=FNVuS2GTffwCjjrlupVIazC172gSxKYAAT_ObV6Apbo,8803
55
57
  iam_validator/core/policy_loader.py,sha256=iid3mGfDzSXASzKDqbLnrqJHBdVQvvebofVqNImsGKM,29201
56
58
  iam_validator/core/pr_commenter.py,sha256=IZu2FQqzw73U_8ugTUq197ECLqk9mRCQpTWXPu5qk0k,35490
57
59
  iam_validator/core/report.py,sha256=IDjBjSrzrE_JdkA8eTiSxyUL3g36sJMhTkxehEYzuBQ,45476
58
- iam_validator/core/aws_service/__init__.py,sha256=UqMh4HUdGlx2QF5OoueJJ2UlCnhX4QW_x3KeE_bxRQc,735
59
- iam_validator/core/aws_service/cache.py,sha256=DPuOOPPJC867KAYgV1e0RyQs_k3mtefMdYli3jPaN64,3589
60
+ iam_validator/core/aws_service/__init__.py,sha256=vSmYBn6GGeEcRxxyBmeKcBHFioZlWWBEwbvXmE6ZXVk,800
61
+ iam_validator/core/aws_service/cache.py,sha256=HkxBLCkgf9VYOZKVZd_MidR_TOlUkwbvX3D421ADFZ8,4421
60
62
  iam_validator/core/aws_service/client.py,sha256=Zv7rIpEFdUCDXKGp3migPDkj8L5eZltgrGe64M2t2Ko,7336
61
- iam_validator/core/aws_service/fetcher.py,sha256=TD9qQ4tQF4xdEGhVVADGgF8QlXe15R3nAc2hWZnVoUw,23996
63
+ iam_validator/core/aws_service/fetcher.py,sha256=TqaCp6yKOEXCJdcQIFVBB5RW0pxLMOmQXjJFHZsrBr4,31209
62
64
  iam_validator/core/aws_service/parsers.py,sha256=gJzR7HCD8ItCWCCbguTQIZpPEdj2rdMwC7LPhu7ve14,5174
63
65
  iam_validator/core/aws_service/patterns.py,sha256=gGc55Tn-EJ3cmcWtmYAZROUajKYz7DaMchYWGEhHpC0,1726
64
- iam_validator/core/aws_service/storage.py,sha256=PrfKdvF60IL7E_8xYs_XwFoAJPRcVYw57FVLHCoqwVk,10429
65
- iam_validator/core/aws_service/validators.py,sha256=7izAvL92TsWpQePU7g9qvegT_F2xz8CqpbrnSgE40Xg,19890
66
+ iam_validator/core/aws_service/storage.py,sha256=A98ui_THAyZ86ik-t6HWB22vOqwmbFklG10uhdf26p4,10881
67
+ iam_validator/core/aws_service/validators.py,sha256=qWMB4iQi9Oc0SGXOJVrlyjnsMwmPlqhUaywyRL4d-hM,19385
66
68
  iam_validator/core/config/__init__.py,sha256=CWSyIA7kEyzrskEenjYbs9Iih10BXRpiY9H2dHg61rU,2671
67
69
  iam_validator/core/config/aws_api.py,sha256=HLIzOItQ0A37wxHcgWck6ZFO0wmNY8JNTiWMMK6JKYU,1248
68
- iam_validator/core/config/aws_global_conditions.py,sha256=PO3zMdzM_QWZduxL3lV2nrmpcMEEwKASCUYHcqX0LBg,7363
70
+ iam_validator/core/config/aws_global_conditions.py,sha256=Ny20rnwp0OGxW8NdrHw8d3Lv3wh8YbL5vCIFQw7ZQh4,8006
69
71
  iam_validator/core/config/category_suggestions.py,sha256=fopaZ9kXDrsLgi_r0pERrLwgdPPJl5VIiKvXtQK9tj0,8583
70
- iam_validator/core/config/check_documentation.py,sha256=Adyt3Q4JSRlVNPWulXVlRIEorxXG_nt0mkPz_ySa8y4,15931
72
+ iam_validator/core/config/check_documentation.py,sha256=-wK6-wfU7SEHX3h2Jj5pOFqgxD9ULW-NvEkSVp_66WA,18718
71
73
  iam_validator/core/config/condition_requirements.py,sha256=1CeQJfWV-Y2ImW0Mq9YdrgvH-hj9IXe0gVOm3B36Rc8,10655
72
- iam_validator/core/config/config_loader.py,sha256=M51apOv_JwRXC8VM0Spghu8ns-_qnbSoYQZWmgBP3Ww,24059
73
- iam_validator/core/config/defaults.py,sha256=poREMGKiDLWy9hSWfuWLPy6xXNLf9bkROUQ2A_cJIn4,38502
74
+ iam_validator/core/config/config_loader.py,sha256=Fohz9R-H5edYMYXoT3HkjmsmZE32rjLWlAjnZaz1Xrc,25649
75
+ iam_validator/core/config/defaults.py,sha256=EKlmfX04IGPb4Qs9ctqrStoJ-_LAGEr2PWTJX9fjenk,38920
74
76
  iam_validator/core/config/principal_requirements.py,sha256=VCX7fBDgeDTJQyoz7_x7GI7Kf9O1Eu-sbihoHOrKv6o,15105
75
77
  iam_validator/core/config/sensitive_actions.py,sha256=uATDIp_TD3OQQlsYTZp79qd1mSK2Bf9hJ0JwcqLBr84,25344
76
78
  iam_validator/core/config/service_principals.py,sha256=8pys5H_yycVJ9KTyimAKFYBg83Aol2Iri53wiHjtnEM,3959
@@ -87,20 +89,31 @@ iam_validator/core/formatters/sarif.py,sha256=03MHSyuZm9FlzaPeWg7wH-UTzzCDhSy6vM
87
89
  iam_validator/integrations/__init__.py,sha256=7Hlor_X9j0NZaEjFuSvoXAAuSKQ-zgY19Rk-Dz3JpKo,616
88
90
  iam_validator/integrations/github_integration.py,sha256=0aeQ_RPTZf5ij7dsBjmtIDz4oHl0BXLno9GperFzTbc,69004
89
91
  iam_validator/integrations/ms_teams.py,sha256=t2PlWuTDb6GGH-eDU1jnOKd8D1w4FCB68bahGA7MJcE,14475
90
- iam_validator/sdk/__init__.py,sha256=1voMXldzhLJ0mZ4AxwYPXwJd_kKFjQ-zp_tN8eWvkP4,6209
92
+ iam_validator/mcp/__init__.py,sha256=dHCPuxLNKG3EMDYTBum8FTdskoebWJN6TaC03rkcnYQ,4927
93
+ iam_validator/mcp/models.py,sha256=EJaDHaGdVvNzSauxYH3L4hmfbtBLLyzuHX_CbXOZr8Q,4473
94
+ iam_validator/mcp/server.py,sha256=V_d4SmNSNMsPG6nul6II0G9GyvWiAvfnMX5B9_U3RQw,108422
95
+ iam_validator/mcp/session_config.py,sha256=dtzPqHVycpMUQH7qG68LW7ZikUz6APJrzttyFZkXwak,10336
96
+ iam_validator/mcp/templates/__init__.py,sha256=OY1C7Af9O46W5-A2TEuZb3jB7gwrG6N-dZ-LQS6FHpw,2408
97
+ iam_validator/mcp/templates/builtin.py,sha256=3cSPOqAzSQSWY2rBEwQ_sTHHKxur64NVASe0kVErbS8,31032
98
+ iam_validator/mcp/tools/__init__.py,sha256=JqFaQaBpavPpGEWF_GIY6YIXWhIL4kDcKCZQvUzmZyE,2040
99
+ iam_validator/mcp/tools/generation.py,sha256=R_pSLv5uxMyg6Pj-TEY2fY5UV9Pd1mh-P9A44Nvws-I,37124
100
+ iam_validator/mcp/tools/org_config_tools.py,sha256=Y13srYplK3SRIxpK3Sat9TocanThcrF8hWblcS7sJhI,7754
101
+ iam_validator/mcp/tools/query.py,sha256=05X0dhNGY0KcmyKJIn9vYw2ed3yGlFnRC2rqOoyVMLQ,13316
102
+ iam_validator/mcp/tools/validation.py,sha256=XrG7rBGbHnpeZSgNZdfNWyD3XeZwmdBTj-w5ErLOt2c,13219
103
+ iam_validator/sdk/__init__.py,sha256=rfWkijjIA8iKrHE2Wd1HnXAl0jJWHHwYgUFZeISQGiI,6297
91
104
  iam_validator/sdk/arn_matching.py,sha256=HSDpLltOYISq-SoPebAlM89mKOaUaghq_04urchEFDA,12778
92
105
  iam_validator/sdk/context.py,sha256=b2XXlvsnqxl42d1wsdoynTqsZOy8nRjV73RgxIdKdPQ,6940
93
106
  iam_validator/sdk/exceptions.py,sha256=tm91TxIwU157U_UHN7w5qICf_OhU11agj6pV5W_YP-4,1023
94
107
  iam_validator/sdk/helpers.py,sha256=sjfK0na_Fo7O8GhEVhl44rVHqOdw6nAKkBL4FVL-QdU,5697
95
- iam_validator/sdk/policy_utils.py,sha256=bGdJ1X1aC72dVXXpAnAwyBpAiiX-qXvblpetY5BsjKU,13658
108
+ iam_validator/sdk/policy_utils.py,sha256=zSn3UFdwr5pik-n1Y4pv_AZheyCuFqaGlSIt403L0is,14386
96
109
  iam_validator/sdk/query_utils.py,sha256=kp1sORVnouRMt7kvzyZo1569l7j20jJGmHICR7O8Cqs,14455
97
110
  iam_validator/sdk/shortcuts.py,sha256=EVNSYV7rv4TFH03ulsZ3mS1UVmTSp2jKpc2AXs4j1q4,8531
98
111
  iam_validator/utils/__init__.py,sha256=NveA2F3G1E6-ANZzFr7J6Q6u5mogvMp862iFokmYuCs,1021
99
112
  iam_validator/utils/cache.py,sha256=wOQKOBeoG6QqC5f0oXcHz63Cjtu_-SsSS-0pTSwyAiM,3254
100
113
  iam_validator/utils/regex.py,sha256=xHoMECttb7qaMhts-c9b0GIxdhHNZTt-UBr7wNhWfzg,6219
101
114
  iam_validator/utils/terminal.py,sha256=FsRaRMH_JAyDgXWBCOgOEhbS89cs17HCmKYoughq5io,724
102
- iam_policy_validator-1.14.7.dist-info/METADATA,sha256=l4PstdoYzO1kqFBTI2M7UDbvoQMAcVC9sHamKl43x9Y,34741
103
- iam_policy_validator-1.14.7.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
104
- iam_policy_validator-1.14.7.dist-info/entry_points.txt,sha256=8HtWd8O7mvPiPdZR5YbzY8or_qcqLM4-pKaFdhtFT8M,62
105
- iam_policy_validator-1.14.7.dist-info/licenses/LICENSE,sha256=AMnbFTBDcK4_MITe2wiQBkj0vg-jjBBhsc43ydC7tt4,1098
106
- iam_policy_validator-1.14.7.dist-info/RECORD,,
115
+ iam_policy_validator-1.15.0.dist-info/METADATA,sha256=CkJmAGo-FcnQ0qpEb0_EDjNcbKRzTErYiIic3gUyHD8,34808
116
+ iam_policy_validator-1.15.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
117
+ iam_policy_validator-1.15.0.dist-info/entry_points.txt,sha256=VXAcx1evo9fuxX0Gtj3J2HnzWcBHSXugiZwBtQ1BXE0,162
118
+ iam_policy_validator-1.15.0.dist-info/licenses/LICENSE,sha256=AMnbFTBDcK4_MITe2wiQBkj0vg-jjBBhsc43ydC7tt4,1098
119
+ iam_policy_validator-1.15.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ iam-policy-validator = iam_validator.core.cli:main
3
+ iam-validator = iam_validator.core.cli:main
4
+ iam-validator-mcp = iam_validator.mcp:run_server
@@ -3,7 +3,7 @@
3
3
  This file is the single source of truth for the package version.
4
4
  """
5
5
 
6
- __version__ = "1.14.7"
6
+ __version__ = "1.15.0"
7
7
  # Parse version, handling pre-release suffixes like -rc, -alpha, -beta
8
8
  _version_base = __version__.split("-", maxsplit=1)[0] # Remove pre-release suffix if present
9
9
  __version_info__ = tuple(int(part) for part in _version_base.split("."))
@@ -11,6 +11,7 @@ from iam_validator.checks.condition_key_validation import ConditionKeyValidation
11
11
  from iam_validator.checks.condition_type_mismatch import ConditionTypeMismatchCheck
12
12
  from iam_validator.checks.full_wildcard import FullWildcardCheck
13
13
  from iam_validator.checks.mfa_condition_check import MFAConditionCheck
14
+ from iam_validator.checks.not_action_not_resource import NotActionNotResourceCheck
14
15
  from iam_validator.checks.policy_size import PolicySizeCheck
15
16
  from iam_validator.checks.policy_structure import PolicyStructureCheck
16
17
  from iam_validator.checks.principal_validation import PrincipalValidationCheck
@@ -31,6 +32,7 @@ __all__ = [
31
32
  "ConditionTypeMismatchCheck",
32
33
  "FullWildcardCheck",
33
34
  "MFAConditionCheck",
35
+ "NotActionNotResourceCheck",
34
36
  "PolicySizeCheck",
35
37
  "PolicyStructureCheck",
36
38
  "PrincipalValidationCheck",
@@ -9,6 +9,7 @@ validations. However, it can be useful in environments where Access Analyzer is
9
9
  not available or for pre-deployment policy validation to catch errors early.
10
10
  """
11
11
 
12
+ import asyncio
12
13
  from typing import ClassVar
13
14
 
14
15
  from iam_validator.core.aws_service import AWSServiceFetcher
@@ -23,6 +24,51 @@ class ActionValidationCheck(PolicyCheck):
23
24
  description: ClassVar[str] = "Validates that actions exist in AWS service definitions"
24
25
  default_severity: ClassVar[str] = "error"
25
26
 
27
+ async def _validate_action(
28
+ self,
29
+ action: str,
30
+ fetcher: AWSServiceFetcher,
31
+ config: CheckConfig,
32
+ statement_sid: str | None,
33
+ statement_idx: int,
34
+ line_number: int | None,
35
+ field_name: str,
36
+ ) -> ValidationIssue | None:
37
+ """Validate a single action and return an issue if invalid.
38
+
39
+ Args:
40
+ action: The action string to validate (e.g., "s3:GetObject")
41
+ fetcher: AWS service fetcher for validation
42
+ config: Check configuration
43
+ statement_sid: Statement ID for error reporting
44
+ statement_idx: Statement index for error reporting
45
+ line_number: Line number for error reporting
46
+ field_name: Field name ("action" or "not_action") for error reporting
47
+
48
+ Returns:
49
+ ValidationIssue if action is invalid, None otherwise
50
+ """
51
+ # Skip full wildcard - it's valid but handled by security checks
52
+ if action == "*":
53
+ return None
54
+
55
+ # Validate the action exists in AWS (handles both exact and wildcard patterns)
56
+ is_valid, error_msg, _is_wildcard = await fetcher.validate_action(action)
57
+
58
+ if not is_valid:
59
+ return ValidationIssue(
60
+ severity=self.get_severity(config),
61
+ statement_sid=statement_sid,
62
+ statement_index=statement_idx,
63
+ issue_type="invalid_action",
64
+ message=error_msg or f"Invalid action: `{action}`",
65
+ action=action,
66
+ line_number=line_number,
67
+ field_name=field_name,
68
+ )
69
+
70
+ return None
71
+
26
72
  async def execute(
27
73
  self,
28
74
  statement: Statement,
@@ -32,36 +78,54 @@ class ActionValidationCheck(PolicyCheck):
32
78
  ) -> list[ValidationIssue]:
33
79
  """Execute action validation on a statement.
34
80
 
35
- This check ONLY validates that actions exist in AWS service definitions.
36
- Wildcard security checks are handled by security_best_practices_check.
37
- """
38
- issues = []
81
+ Validates both Action and NotAction fields to ensure all specified
82
+ actions exist in AWS service definitions. Wildcard patterns like
83
+ "s3:Get*" are validated to ensure they match at least one real action.
84
+
85
+ Actions are validated in parallel for better performance.
39
86
 
40
- # Get actions from statement
41
- actions = statement.get_actions()
87
+ Security implications of wildcards are handled by separate checks
88
+ (wildcard_action, service_wildcard, etc.).
89
+ """
42
90
  statement_sid = statement.sid
43
91
  line_number = statement.line_number
44
92
 
45
- for action in actions:
46
- # Skip wildcard actions - they're handled by security_best_practices_check
47
- if action == "*" or "*" in action:
48
- continue
49
-
50
- # Validate the action exists in AWS
51
- is_valid, error_msg, _is_wildcard = await fetcher.validate_action(action)
52
-
53
- if not is_valid:
54
- issues.append(
55
- ValidationIssue(
56
- severity=self.get_severity(config),
57
- statement_sid=statement_sid,
58
- statement_index=statement_idx,
59
- issue_type="invalid_action",
60
- message=error_msg or f"Invalid action: `{action}`",
61
- action=action,
62
- line_number=line_number,
63
- field_name="action",
64
- )
93
+ # Build list of validation tasks for parallel execution
94
+ tasks = []
95
+
96
+ # Validate Action field
97
+ for action in statement.get_actions():
98
+ tasks.append(
99
+ self._validate_action(
100
+ action=action,
101
+ fetcher=fetcher,
102
+ config=config,
103
+ statement_sid=statement_sid,
104
+ statement_idx=statement_idx,
105
+ line_number=line_number,
106
+ field_name="action",
65
107
  )
108
+ )
109
+
110
+ # Validate NotAction field (same validation - typos in NotAction are equally problematic)
111
+ for action in statement.get_not_actions():
112
+ tasks.append(
113
+ self._validate_action(
114
+ action=action,
115
+ fetcher=fetcher,
116
+ config=config,
117
+ statement_sid=statement_sid,
118
+ statement_idx=statement_idx,
119
+ line_number=line_number,
120
+ field_name="not_action",
121
+ )
122
+ )
123
+
124
+ # Execute all validations in parallel
125
+ if not tasks:
126
+ return []
127
+
128
+ results = await asyncio.gather(*tasks)
66
129
 
67
- return issues
130
+ # Filter out None results (valid actions)
131
+ return [issue for issue in results if issue is not None]
@@ -0,0 +1,163 @@
1
+ """NotAction/NotResource check - detects dangerous Not* patterns in IAM policies.
2
+
3
+ NotAction and NotResource are powerful IAM features that can be misused to
4
+ grant overly broad permissions. This check detects patterns that violate
5
+ the principle of least privilege.
6
+ """
7
+
8
+ from typing import ClassVar
9
+
10
+ from iam_validator.core.aws_service import AWSServiceFetcher
11
+ from iam_validator.core.check_registry import CheckConfig, PolicyCheck
12
+ from iam_validator.core.models import Statement, ValidationIssue
13
+
14
+
15
+ class NotActionNotResourceCheck(PolicyCheck):
16
+ """Checks for dangerous NotAction/NotResource patterns.
17
+
18
+ Patterns detected:
19
+ 1. NotAction with Effect: Allow - grants everything EXCEPT listed actions
20
+ 2. NotResource with wildcards - grants access to all resources except listed
21
+ 3. NotAction in Allow without strict conditions - missing safeguards
22
+
23
+ These patterns are particularly dangerous because they grant permissions
24
+ by exclusion rather than explicit inclusion, making it easy to accidentally
25
+ grant more access than intended.
26
+ """
27
+
28
+ check_id: ClassVar[str] = "not_action_not_resource"
29
+ description: ClassVar[str] = "Checks for dangerous NotAction/NotResource patterns"
30
+ default_severity: ClassVar[str] = "high"
31
+
32
+ async def execute(
33
+ self,
34
+ statement: Statement,
35
+ statement_idx: int,
36
+ fetcher: AWSServiceFetcher,
37
+ config: CheckConfig,
38
+ ) -> list[ValidationIssue]:
39
+ """Execute NotAction/NotResource check on a statement."""
40
+ del fetcher # Unused
41
+
42
+ issues = []
43
+
44
+ not_actions = statement.get_not_actions()
45
+ not_resources = statement.get_not_resources()
46
+ effect = statement.effect
47
+
48
+ # Check 1: NotAction with Effect: Allow
49
+ # This grants ALL actions EXCEPT the listed ones - extremely dangerous
50
+ if not_actions and effect == "Allow":
51
+ has_conditions = bool(statement.condition)
52
+
53
+ if has_conditions:
54
+ # NotAction with conditions is still risky but less severe
55
+ issues.append(
56
+ ValidationIssue(
57
+ severity="medium",
58
+ statement_sid=statement.sid,
59
+ statement_index=statement_idx,
60
+ issue_type="not_action_allow",
61
+ message=(
62
+ "Statement uses NotAction with Allow effect. "
63
+ "This grants ALL actions except the listed ones. "
64
+ "While conditions are present, this pattern is still risky."
65
+ ),
66
+ suggestion=(
67
+ "Consider using explicit Action lists instead of NotAction. "
68
+ "If NotAction is required, ensure conditions are comprehensive."
69
+ ),
70
+ example='{\n "Effect": "Allow",\n "Action": ["s3:GetObject", "s3:ListBucket"],\n "Resource": "*"\n}',
71
+ line_number=statement.line_number,
72
+ field_name="action",
73
+ action=", ".join(not_actions[:3]) + ("..." if len(not_actions) > 3 else ""),
74
+ )
75
+ )
76
+ else:
77
+ # NotAction Allow without conditions is critical
78
+ issues.append(
79
+ ValidationIssue(
80
+ severity=self.get_severity(config),
81
+ statement_sid=statement.sid,
82
+ statement_index=statement_idx,
83
+ issue_type="not_action_allow_no_condition",
84
+ message=(
85
+ "Statement uses NotAction with Allow effect and NO conditions. "
86
+ f"This grants ALL AWS actions except: {', '.join(not_actions[:5])}"
87
+ f"{'...' if len(not_actions) > 5 else ''}. "
88
+ "This is equivalent to granting near-administrator access."
89
+ ),
90
+ suggestion=(
91
+ "Replace NotAction with explicit Action list. "
92
+ "If NotAction is required, add strict conditions like "
93
+ "aws:SourceIp, aws:PrincipalArn, or aws:MultiFactorAuthPresent."
94
+ ),
95
+ example='{\n "Effect": "Allow",\n "Action": ["specific:Action"],\n "Resource": "*",\n "Condition": {\n "Bool": {"aws:MultiFactorAuthPresent": "true"}\n }\n}',
96
+ line_number=statement.line_number,
97
+ field_name="action",
98
+ action=", ".join(not_actions[:3]) + ("..." if len(not_actions) > 3 else ""),
99
+ )
100
+ )
101
+
102
+ # Check 2: NotResource with wildcards or broad patterns
103
+ if not_resources and effect == "Allow":
104
+ # Check if NotResource is used with wildcard Resource
105
+ resources = statement.get_resources()
106
+ has_wildcard_resource = "*" in resources or any("*" in r for r in resources)
107
+
108
+ if has_wildcard_resource or not resources:
109
+ issues.append(
110
+ ValidationIssue(
111
+ severity=self.get_severity(config),
112
+ statement_sid=statement.sid,
113
+ statement_index=statement_idx,
114
+ issue_type="not_resource_broad",
115
+ message=(
116
+ "Statement uses NotResource with Allow effect and broad Resource. "
117
+ f"This grants access to ALL resources except: {', '.join(not_resources[:3])}"
118
+ f"{'...' if len(not_resources) > 3 else ''}."
119
+ ),
120
+ suggestion=(
121
+ "Replace NotResource with explicit Resource ARNs. "
122
+ "Using NotResource grants access to all current and future resources "
123
+ "except those explicitly excluded."
124
+ ),
125
+ example='{\n "Effect": "Allow",\n "Action": ["s3:GetObject"],\n "Resource": "arn:aws:s3:::my-bucket/*"\n}',
126
+ line_number=statement.line_number,
127
+ field_name="resource",
128
+ resource=", ".join(not_resources[:3])
129
+ + ("..." if len(not_resources) > 3 else ""),
130
+ )
131
+ )
132
+
133
+ # Check 3: NotAction with Deny - less dangerous but worth noting
134
+ # NotAction with Deny means "deny everything except these actions"
135
+ # which is actually a valid deny pattern but should be reviewed
136
+ if not_actions and effect == "Deny":
137
+ resources = statement.get_resources()
138
+ has_wildcard_resource = "*" in resources
139
+
140
+ if has_wildcard_resource:
141
+ issues.append(
142
+ ValidationIssue(
143
+ severity="low",
144
+ statement_sid=statement.sid,
145
+ statement_index=statement_idx,
146
+ issue_type="not_action_deny_review",
147
+ message=(
148
+ "Statement uses NotAction with Deny effect on all resources. "
149
+ f"This denies everything except: {', '.join(not_actions[:5])}"
150
+ f"{'...' if len(not_actions) > 5 else ''}. "
151
+ "Review to ensure this is the intended behavior."
152
+ ),
153
+ suggestion=(
154
+ "Verify that allowing only these specific actions is intended. "
155
+ "Consider if an explicit Allow list would be clearer."
156
+ ),
157
+ line_number=statement.line_number,
158
+ field_name="action",
159
+ action=", ".join(not_actions[:3]) + ("..." if len(not_actions) > 3 else ""),
160
+ )
161
+ )
162
+
163
+ return issues