iam-policy-validator 1.5.0__py3-none-any.whl → 1.6.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.5.0.dist-info → iam_policy_validator-1.6.0.dist-info}/METADATA +89 -60
  2. {iam_policy_validator-1.5.0.dist-info → iam_policy_validator-1.6.0.dist-info}/RECORD +40 -25
  3. iam_validator/__version__.py +1 -1
  4. iam_validator/checks/__init__.py +9 -3
  5. iam_validator/checks/action_condition_enforcement.py +164 -2
  6. iam_validator/checks/action_resource_matching.py +424 -0
  7. iam_validator/checks/condition_key_validation.py +3 -1
  8. iam_validator/checks/condition_type_mismatch.py +259 -0
  9. iam_validator/checks/mfa_condition_check.py +112 -0
  10. iam_validator/checks/sensitive_action.py +78 -6
  11. iam_validator/checks/set_operator_validation.py +157 -0
  12. iam_validator/checks/utils/sensitive_action_matcher.py +35 -1
  13. iam_validator/commands/cache.py +1 -1
  14. iam_validator/commands/validate.py +44 -11
  15. iam_validator/core/aws_fetcher.py +89 -52
  16. iam_validator/core/check_registry.py +165 -21
  17. iam_validator/core/condition_validators.py +626 -0
  18. iam_validator/core/config/__init__.py +13 -15
  19. iam_validator/core/config/aws_global_conditions.py +160 -0
  20. iam_validator/core/config/category_suggestions.py +104 -0
  21. iam_validator/core/config/condition_requirements.py +5 -385
  22. iam_validator/core/{config_loader.py → config/config_loader.py} +3 -0
  23. iam_validator/core/config/defaults.py +187 -54
  24. iam_validator/core/config/sensitive_actions.py +620 -81
  25. iam_validator/core/models.py +14 -1
  26. iam_validator/core/policy_checks.py +4 -4
  27. iam_validator/core/pr_commenter.py +1 -1
  28. iam_validator/sdk/__init__.py +187 -0
  29. iam_validator/sdk/arn_matching.py +274 -0
  30. iam_validator/sdk/context.py +222 -0
  31. iam_validator/sdk/exceptions.py +48 -0
  32. iam_validator/sdk/helpers.py +177 -0
  33. iam_validator/sdk/policy_utils.py +425 -0
  34. iam_validator/sdk/shortcuts.py +283 -0
  35. iam_validator/utils/__init__.py +31 -0
  36. iam_validator/utils/cache.py +105 -0
  37. iam_validator/utils/regex.py +206 -0
  38. iam_validator/checks/action_resource_constraint.py +0 -151
  39. iam_validator/core/aws_global_conditions.py +0 -137
  40. {iam_policy_validator-1.5.0.dist-info → iam_policy_validator-1.6.0.dist-info}/WHEEL +0 -0
  41. {iam_policy_validator-1.5.0.dist-info → iam_policy_validator-1.6.0.dist-info}/entry_points.txt +0 -0
  42. {iam_policy_validator-1.5.0.dist-info → iam_policy_validator-1.6.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.5.0
3
+ Version: 1.6.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://github.com/boogy/iam-policy-validator/tree/main/docs
@@ -58,7 +58,7 @@ Description-Content-Type: text/markdown
58
58
 
59
59
  **This tool prevents these issues** by:
60
60
  - ✅ **Validating early** - Catch errors in PRs before merge
61
- - ✅ **Comprehensive checks** - AWS Access Analyzer + 15+ security checks
61
+ - ✅ **Comprehensive checks** - AWS Access Analyzer + 18 built-in security checks
62
62
  - ✅ **Smart filtering** - Auto-detects IAM policies from mixed JSON/YAML files
63
63
  - ✅ **Developer-friendly** - Clear error messages with fix suggestions
64
64
  - ✅ **Zero setup** - Works as a GitHub Action out of the box
@@ -67,7 +67,7 @@ Description-Content-Type: text/markdown
67
67
 
68
68
  ### 🔍 Multi-Layer Validation
69
69
  - **AWS IAM Access Analyzer** - Official AWS validation (syntax, permissions, security)
70
- - **Custom Security Checks** - 15+ specialized checks for best practices
70
+ - **18 Built-in Security Checks** - Comprehensive validation across AWS requirements and security best practices
71
71
  - **Policy Comparison** - Detect new permissions vs baseline (prevent scope creep)
72
72
  - **Public Access Detection** - Check 29+ AWS resource types for public exposure
73
73
  - **Privilege Escalation Detection** - Identify dangerous action combinations
@@ -748,7 +748,7 @@ iam-validator analyze \
748
748
  - **API**: API Gateway REST API
749
749
  - **DevOps**: CodeArtifact Domain, Backup Vault, CloudTrail
750
750
 
751
- See [docs/custom-policy-checks.md](docs/custom-policy-checks.md) for complete documentation.
751
+ See [docs/custom-checks.md](docs/custom-checks.md) for complete documentation.
752
752
 
753
753
  ### As a Python Package
754
754
 
@@ -782,70 +782,96 @@ asyncio.run(main())
782
782
 
783
783
  ## Validation Checks
784
784
 
785
- ### 1. Action Validation
786
-
787
- Verifies that IAM actions exist in AWS services:
788
-
785
+ IAM Policy Validator performs **18 built-in checks** to ensure your policies are secure and valid.
786
+
787
+ **📖 For detailed check documentation with configuration examples and pass/fail scenarios:**
788
+ - **[Check Reference Guide](docs/check-reference.md)** - Complete reference for all 18 checks
789
+ - **[Condition Requirements](docs/condition-requirements.md)** - Action condition enforcement
790
+ - **[Privilege Escalation Detection](docs/privilege-escalation.md)** - Detecting escalation paths
791
+
792
+ ### Quick Overview
793
+
794
+ **AWS IAM Validation (12 checks)** - Ensure policies work correctly in AWS:
795
+ - Statement ID uniqueness and format
796
+ - Policy size limits
797
+ - Action and condition key validation
798
+ - Condition operator and value type checking
799
+ - Set operator validation
800
+ - MFA anti-pattern detection
801
+ - Resource ARN format validation
802
+ - Principal validation (resource policies)
803
+ - Policy type validation
804
+ - Action-resource constraint and matching
805
+
806
+ **Security Best Practices (6 checks)** - Identify security risks:
807
+ - Wildcard actions (`Action: "*"`)
808
+ - Wildcard resources (`Resource: "*"`)
809
+ - Full wildcard (CRITICAL: both wildcards together)
810
+ - Service-level wildcards (`iam:*`, `s3:*`, etc.)
811
+ - Sensitive actions without conditions (490 actions across 4 risk categories)
812
+ - Action condition enforcement (MFA, IP restrictions, tags, etc.)
813
+
814
+ ### Quick Examples
815
+
816
+ **Action Validation:**
789
817
  ```json
818
+ // ✅ PASS: Valid S3 action
790
819
  {
791
820
  "Effect": "Allow",
792
- "Action": "s3:GetObject", // ✅ Valid
793
- "Resource": "*"
821
+ "Action": "s3:GetObject",
822
+ "Resource": "arn:aws:s3:::my-bucket/*"
794
823
  }
795
- ```
796
824
 
797
- ```json
825
+ // ❌ FAIL: Invalid action name
798
826
  {
799
827
  "Effect": "Allow",
800
- "Action": "s3:InvalidAction", // Invalid - action doesn't exist
828
+ "Action": "s3:InvalidAction", // ERROR: Action doesn't exist
801
829
  "Resource": "*"
802
830
  }
803
831
  ```
804
832
 
805
- ### 2. Condition Key Validation
833
+ **Full Wildcard (Critical):**
834
+ ```json
835
+ // ✅ PASS: Specific actions and resources
836
+ {
837
+ "Effect": "Allow",
838
+ "Action": ["s3:GetObject", "s3:PutObject"],
839
+ "Resource": "arn:aws:s3:::my-bucket/*"
840
+ }
806
841
 
807
- Checks that condition keys are valid for the specified actions:
842
+ // FAIL: Administrative access
843
+ {
844
+ "Effect": "Allow",
845
+ "Action": "*", // CRITICAL: All actions
846
+ "Resource": "*" // CRITICAL: All resources
847
+ }
848
+ ```
808
849
 
850
+ **Action Condition Enforcement:**
809
851
  ```json
852
+ // ✅ PASS: iam:PassRole with required condition
810
853
  {
811
854
  "Effect": "Allow",
812
- "Action": "s3:GetObject",
855
+ "Action": "iam:PassRole",
813
856
  "Resource": "*",
814
857
  "Condition": {
815
858
  "StringEquals": {
816
- "aws:RequestedRegion": "us-east-1" // ✅ Valid global condition key
859
+ "iam:PassedToService": ["lambda.amazonaws.com"]
817
860
  }
818
861
  }
819
862
  }
820
- ```
821
-
822
- ### 3. Resource ARN Validation
823
-
824
- Ensures ARNs follow proper AWS format:
825
-
826
- ```json
827
- {
828
- "Effect": "Allow",
829
- "Action": "s3:GetObject",
830
- "Resource": "arn:aws:s3:::my-bucket/*" // ✅ Valid ARN
831
- }
832
- ```
833
863
 
834
- ```json
864
+ // ❌ FAIL: iam:PassRole without condition
835
865
  {
836
866
  "Effect": "Allow",
837
- "Action": "s3:GetObject",
838
- "Resource": "not-a-valid-arn" // ❌ Invalid ARN format
867
+ "Action": "iam:PassRole", // HIGH: Missing iam:PassedToService condition
868
+ "Resource": "*"
839
869
  }
840
870
  ```
841
871
 
842
- ### 4. Security Best Practices
872
+ **📚 For complete documentation of all 18 checks with detailed examples, see [Check Reference Guide](docs/check-reference.md)**
843
873
 
844
- Identifies potential security risks:
845
-
846
- - Overly permissive wildcard usage (`*` for both Action and Resource)
847
- - Sensitive actions without conditions
848
- - Administrative permissions without restrictions
874
+ _Note: The old [CHECKS.md](docs/CHECKS.md) has been deprecated in favor of the new check-reference.md with better organization and examples._
849
875
 
850
876
  ## GitHub Integration Features
851
877
 
@@ -956,28 +982,27 @@ Result: PR always shows current state, no stale comments
956
982
 
957
983
  ## 📚 Documentation
958
984
 
959
- **[📖 Complete Documentation →](DOCS.md)**
960
-
961
- The comprehensive [DOCS.md](DOCS.md) file contains everything you need:
962
- - Installation & Quick Start
963
- - GitHub Actions Integration
964
- - CLI Reference & Examples
965
- - Custom Policy Checks (CheckAccessNotGranted, CheckNoNewAccess, CheckNoPublicAccess)
966
- - Configuration Guide
967
- - Creating Custom Validation Rules
968
- - Performance Optimization
969
- - Troubleshooting
970
-
971
- **Additional Resources:**
972
- - **[Examples Directory](examples/)** - Real-world examples:
973
- - [GitHub Actions Workflows](examples/github-actions/)
974
- - [Custom Checks](examples/custom_checks/)
975
- - [Configuration Files](examples/configs/)
976
- - [Test IAM Policies](examples/iam-test-policies/)
985
+ ### Core Documentation
986
+ - **[📖 Complete Usage Guide (DOCS.md)](DOCS.md)** - Installation, CLI reference, GitHub Actions, configuration
987
+ - **[✅ Validation Checks Reference](docs/check-reference.md)** - All 18 checks with pass/fail examples
988
+ - **[🐍 Python SDK Guide (SDK.md)](docs/SDK.md)** - Use as a Python library in your applications
989
+ - **[🤝 Contributing Guide (CONTRIBUTING.md)](CONTRIBUTING.md)** - How to contribute to the project
990
+
991
+ ### Examples & Resources
992
+ - **[Configuration Examples](examples/configs/)** - 9 configuration files for different use cases
993
+ - **[GitHub Actions Workflows](examples/github-actions/)** - Ready-to-use workflow examples
994
+ - **[Custom Checks](examples/custom_checks/)** - Example custom validation rules
995
+ - **[Library Usage Examples](examples/library-usage/)** - Python SDK examples
996
+ - **[Test IAM Policies](examples/iam-test-policies/)** - Example policies for testing
997
+
998
+ ### Advanced Topics
977
999
  - **[Roadmap](docs/ROADMAP.md)** - Planned features and improvements
978
- - **[AWS Services Backup Guide](docs/aws-services-backup.md)** - Offline validation
979
- - **[Contributing Guide](CONTRIBUTING.md)** - Contribution guidelines
980
- - **[Publishing Guide](docs/development/PUBLISHING.md)** - Release process
1000
+ - **[AWS Services Backup Guide](docs/aws-services-backup.md)** - Offline validation setup
1001
+ - **[Publishing Guide](docs/development/PUBLISHING.md)** - Release process for maintainers
1002
+
1003
+ ### Quick Links
1004
+ - **[GitHub Issues](https://github.com/boogy/iam-policy-validator/issues)** - Report bugs or request features
1005
+ - **[GitHub Discussions](https://github.com/boogy/iam-policy-validator/discussions)** - Ask questions and share ideas
981
1006
 
982
1007
  ## 🤝 Contributing
983
1008
 
@@ -1014,6 +1039,10 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed instructions.
1014
1039
 
1015
1040
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
1016
1041
 
1042
+ ### Third-Party Code
1043
+
1044
+ Portions of the ARN pattern matching code in [`iam_validator/sdk/arn_matching.py`](iam_validator/sdk/arn_matching.py) are derived from [Parliament](https://github.com/duo-labs/parliament) (Copyright 2019 Duo Security, [BSD 3-Clause License](https://github.com/duo-labs/parliament/blob/master/LICENSE)). See file header for details.
1045
+
1017
1046
  ## 🆘 Support
1018
1047
 
1019
1048
  - **Documentation**: Check the [docs/](docs/) directory
@@ -1,51 +1,56 @@
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=aNFKvgY68bb-MhUFw2OC-8_0VmwOTwY6_J5GPtri6os,206
4
- iam_validator/checks/__init__.py,sha256=OSgwk2WO_lLYOgSrTAycUNgRHw0NSU33Rse39thvVSk,1456
5
- iam_validator/checks/action_condition_enforcement.py,sha256=bKQEkD7PJYA0g9CwfrgfQSAKcVJkQgqfSnpXKE3Rz_0,29588
6
- iam_validator/checks/action_resource_constraint.py,sha256=p-gP7S9QYR6M7vffrnJY6LOlMUTn0kpEbrxQ8pTY5rs,6031
3
+ iam_validator/__version__.py,sha256=U-2GASzFF5PD483Cth0LG6biXahUQLBsW4BrfQVnGhw,206
4
+ iam_validator/checks/__init__.py,sha256=eDiDlVon0CwWGSBnZgM-arn1i5R5ZSG89pgR-ifETxE,1782
5
+ iam_validator/checks/action_condition_enforcement.py,sha256=qE2ae6vzOG2LqYGrvxeDdKyXtfdtqgfCBBceTpIGqNY,36573
6
+ iam_validator/checks/action_resource_matching.py,sha256=KyF9GgZrfSLy-DR_iaj9J9fOTOaj8G5BvBYqHEiSnkg,16577
7
7
  iam_validator/checks/action_validation.py,sha256=IpxtTsk58f2zEZ-xzAoyHw4QK8BCRV43OffP-8ydf9E,2578
8
- iam_validator/checks/condition_key_validation.py,sha256=XmlwSDHq7p48dEDxjUJiRtaqtfAiFgpBJnj2jY_25LU,3796
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
9
10
  iam_validator/checks/full_wildcard.py,sha256=8zkmkQo2TkflgNgbclThH73mIBRHbuiob0YO2HwQhuE,2371
11
+ iam_validator/checks/mfa_condition_check.py,sha256=s7K2r9hxlJI1KWk8qXl-JOWE6jLIhpxooK26Pr7acKs,4915
10
12
  iam_validator/checks/policy_size.py,sha256=gJD8rFHa1CstKaZ2Dj9B5XEI3o0wsGv7ksqjqZXoSXI,5771
11
13
  iam_validator/checks/policy_type_validation.py,sha256=w85W4zdZ6ZrDy0DmHxxnAXbJGfN8peRDjLfJ4Bp1dWc,15009
12
14
  iam_validator/checks/principal_validation.py,sha256=DLmqX_QbfuV8O5XtcuocBeR_Vwa50_3RBx35XuLQob8,29837
13
15
  iam_validator/checks/resource_validation.py,sha256=AEIoiR6AKYLuVaA8ne3QE5qy6NCMDe98_2JAiwE9-JU,4261
14
- iam_validator/checks/sensitive_action.py,sha256=mGxUELAuzsY_zK382WgJeeRGJDl8lumIsWgGIm_tmPs,6852
16
+ iam_validator/checks/sensitive_action.py,sha256=gxPhxMxQzsj7xrvRfMZlfh1o67B2s1ddSLF_KQ0FKOw,9716
15
17
  iam_validator/checks/service_wildcard.py,sha256=1O3NF8_T1LsCzpm8SFViv1KTh9NYQSqXN8-D3xx6Erw,4156
18
+ iam_validator/checks/set_operator_validation.py,sha256=1XjOdf-xk-m6m1bODuHsELZccriGqOJTDI-HCcuId80,7464
16
19
  iam_validator/checks/sid_uniqueness.py,sha256=1Ux9W1hPPhzgdCzfxwxvD-nSBRo1SyrxFWlnTXDcOys,6887
17
20
  iam_validator/checks/wildcard_action.py,sha256=KsAej_GP6qL2XpmvGnS56SIJw3Z-5xyvZ7VDfsERFrU,2045
18
21
  iam_validator/checks/wildcard_resource.py,sha256=V5aBmb1pr8KhbVv2G4nzjBlZWz0kCOCgW6jKnb2_U60,5504
19
22
  iam_validator/checks/utils/__init__.py,sha256=j0X4ibUB6RGx2a-kNoJnlVZwHfoEvzZsIeTmJIAoFzA,45
20
23
  iam_validator/checks/utils/policy_level_checks.py,sha256=2V60C0zhKfsFPjQ-NMlD3EemtwA9S6-4no8nETgXdQE,5274
21
- iam_validator/checks/utils/sensitive_action_matcher.py,sha256=Wl_YHktQR1LthkePaLMVF5iCeBpax2QgNRN0_azgfD8,9295
24
+ iam_validator/checks/utils/sensitive_action_matcher.py,sha256=e67RIi-zg7ssFwq6x4kt4wsTF-brNz91KaBxgV-23jg,10687
22
25
  iam_validator/checks/utils/wildcard_expansion.py,sha256=V3V_KRpapOzPBhpUObJjGHoMhvCH90QvDxppeEHIG_U,3152
23
26
  iam_validator/commands/__init__.py,sha256=M-5bo8w0TCWydK0cXgJyPD2fmk8bpQs-3b26YbgLzlc,565
24
27
  iam_validator/commands/analyze.py,sha256=TWlDaZ8gVOdNv6__KQQfzeLVW36qLiL5IzlhGYfvq_g,16501
25
28
  iam_validator/commands/base.py,sha256=5baCCMwxz7pdQ6XMpWfXFNz7i1l5dB8Qv9dKKR04Gzs,1074
26
- iam_validator/commands/cache.py,sha256=NHfbIDWI8tj-3o-4fIZJQS-Vvd9bxIH3Lk6kBtNuiUU,14212
29
+ iam_validator/commands/cache.py,sha256=p4ucRVuh42sbK3Lk0b610L3ofAR5TnUreF00fpO6VFg,14219
27
30
  iam_validator/commands/download_services.py,sha256=KKz3ybMLT8DQUf9aFZ0tilJ-o1b6PE8Pf1pC4K6cT8I,9175
28
31
  iam_validator/commands/post_to_pr.py,sha256=CvUXs2xvO-UhluxdfNM6F0TCWD8hDBEOiYw60fm1Dms,2363
29
- iam_validator/commands/validate.py,sha256=Nz6nC8UoRSLjnxTjv5n1qc5SOC88vK1ZwV04nH4oPDI,22333
32
+ iam_validator/commands/validate.py,sha256=vyPsEenHoQPc_ftaVv0Ek5i52OvoqHaRCpVLLjCU5As,23508
30
33
  iam_validator/core/__init__.py,sha256=1FvJPMrbzJfS9YbRUJCshJLd5gzWwR9Fd_slS0Aq9c8,416
31
34
  iam_validator/core/access_analyzer.py,sha256=poeT1i74jXpKr1B3UmvqiTvCTbq82zffWgZHwiFUwoo,24337
32
35
  iam_validator/core/access_analyzer_report.py,sha256=IrQVszlhFfQ6WykYLpig7TU3hf8dnQTegPDsOvHjR5Q,24873
33
- iam_validator/core/aws_fetcher.py,sha256=raEnvUi3rFaE1Bf9h6Am0bKeDSUN0WI6MPuVt4LSQzg,34169
34
- iam_validator/core/aws_global_conditions.py,sha256=ADVcMEWhgvDZWdBmRUQN3HB7a9OycbTLecXFAy3LPbo,5837
35
- iam_validator/core/check_registry.py,sha256=-3MDcJvzN07cyMbi9UTzw_JcPJCcB-tXGl5hKX-Y2ZY,16067
36
+ iam_validator/core/aws_fetcher.py,sha256=NEXS7w6M5_EIXAm6OyyUEenpPU6p2Aj_a_p93aR9vAI,36147
37
+ iam_validator/core/check_registry.py,sha256=cMjtJROkZOLzXxl-mTdLYHdxyajNnOsaHGs-EeaSZ7k,21741
36
38
  iam_validator/core/cli.py,sha256=PkXiZjlgrQ21QustBbspefYsdbxst4gxoClyG2_HQR8,3843
37
- iam_validator/core/config_loader.py,sha256=qPdRokl8Hdc1t1vX--JQjOC_colgnnq1MrKsGtcW56s,17609
38
- iam_validator/core/models.py,sha256=8v-b8Z8PFqpbdEpkZZ33kuZ_5D81Z2lIHzlFLu3i5mE,11094
39
- iam_validator/core/policy_checks.py,sha256=zmA1GupD5jE1avCdaYLdZ7WA7CVG0CWjmgkd_2F-p7A,26429
39
+ iam_validator/core/condition_validators.py,sha256=7zBjlcf2xGFKGbcFrXSLvWT5tFhWxoqwzhsJqS2E8uY,21524
40
+ iam_validator/core/models.py,sha256=spL5USsDFNfzQ_7R6yaTo-fcoRANkKS-zCwn88XYjYQ,11544
41
+ iam_validator/core/policy_checks.py,sha256=Uz2yCsqRaoIja31F4ZM-39a1pHv51yZqKyWWkGUZKNY,26489
40
42
  iam_validator/core/policy_loader.py,sha256=TR7SpzlRG3TwH4HBGEFUuhNOmxIR8Cud2SQ-AmHWBpM,14040
41
- iam_validator/core/pr_commenter.py,sha256=7wt1q1rQE3bozNfrynWaE2RVkyRxu4CUNKX7u1_Ii1c,11593
43
+ iam_validator/core/pr_commenter.py,sha256=EDE8lWsabkHYrOw2ApIUrPbjI5K3-Z_QxJkjakaVsTk,11600
42
44
  iam_validator/core/report.py,sha256=Yeh_u9jQvTyDV3ignyPcWEQVfFcxNZNrxf4T0fjeWb4,33283
43
- iam_validator/core/config/__init__.py,sha256=e9Dh-NtUtW6-Kk_RwLiOzLn8X09E4_VqgNp0Cuva7y0,2655
45
+ iam_validator/core/config/__init__.py,sha256=CWSyIA7kEyzrskEenjYbs9Iih10BXRpiY9H2dHg61rU,2671
44
46
  iam_validator/core/config/aws_api.py,sha256=HLIzOItQ0A37wxHcgWck6ZFO0wmNY8JNTiWMMK6JKYU,1248
45
- iam_validator/core/config/condition_requirements.py,sha256=45HITvpClti453CgrMLlV1AwoZVUbSTVVhflaxapJTM,17021
46
- iam_validator/core/config/defaults.py,sha256=_GcVnGkMMqqG1OCxQy4lsS5pM7rDD3phXHTq1w3ECJU,19334
47
+ iam_validator/core/config/aws_global_conditions.py,sha256=gdmMxXGBy95B3uYUG-J7rnM6Ixgc6L7Y9Pcd2XAMb60,7170
48
+ iam_validator/core/config/category_suggestions.py,sha256=QlrYi4BTkxDSTlL7NZGE9BWN-atWetZ6XjkI9F_7YzI,4370
49
+ iam_validator/core/config/condition_requirements.py,sha256=1PuADTB9pLqh-kNUGC7kSU6LMLtXMSc003tvI7qKeAY,5170
50
+ iam_validator/core/config/config_loader.py,sha256=MjO9SJ3HSXl6gnv_Qy0d906pX9iW8cONM8alOotUaKI,17749
51
+ iam_validator/core/config/defaults.py,sha256=w5ievxkqki3zYr7NaREoWtVx5rTfxBpZlgoNdovcILs,27112
47
52
  iam_validator/core/config/principal_requirements.py,sha256=VCX7fBDgeDTJQyoz7_x7GI7Kf9O1Eu-sbihoHOrKv6o,15105
48
- iam_validator/core/config/sensitive_actions.py,sha256=J03x_Y3z2gqU4QmeQF2iDWEZfeWKoNls1qL2VgtwtOU,4464
53
+ iam_validator/core/config/sensitive_actions.py,sha256=uATDIp_TD3OQQlsYTZp79qd1mSK2Bf9hJ0JwcqLBr84,25344
49
54
  iam_validator/core/config/service_principals.py,sha256=gQSROsxUWBD6P2F9qP320UZV4lHGlsyvHSkMyy0njrU,2685
50
55
  iam_validator/core/config/wildcards.py,sha256=H_v6hb-rZ0UUz4cul9lxkVI39e6knaK4Y-MbWz2Ebpw,3228
51
56
  iam_validator/core/formatters/__init__.py,sha256=fnCKAEBXItnOf2m4rhVs7zwMaTxbG6ESh3CF8V5j5ec,868
@@ -60,8 +65,18 @@ iam_validator/core/formatters/sarif.py,sha256=O3pn7whqFq5xxk-tuoqSb2k4Fk5ai_A2SK
60
65
  iam_validator/integrations/__init__.py,sha256=7Hlor_X9j0NZaEjFuSvoXAAuSKQ-zgY19Rk-Dz3JpKo,616
61
66
  iam_validator/integrations/github_integration.py,sha256=bKs94vNT4PmcmUPUeuY2WJFhCYpUY2SWiBP1vj-andA,25673
62
67
  iam_validator/integrations/ms_teams.py,sha256=t2PlWuTDb6GGH-eDU1jnOKd8D1w4FCB68bahGA7MJcE,14475
63
- iam_policy_validator-1.5.0.dist-info/METADATA,sha256=D5TTVNQDeankIcLYRBT_UzysyZgWTZtaHzby0CHH_Vc,34222
64
- iam_policy_validator-1.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
65
- iam_policy_validator-1.5.0.dist-info/entry_points.txt,sha256=8HtWd8O7mvPiPdZR5YbzY8or_qcqLM4-pKaFdhtFT8M,62
66
- iam_policy_validator-1.5.0.dist-info/licenses/LICENSE,sha256=AMnbFTBDcK4_MITe2wiQBkj0vg-jjBBhsc43ydC7tt4,1098
67
- iam_policy_validator-1.5.0.dist-info/RECORD,,
68
+ iam_validator/sdk/__init__.py,sha256=fRDSXAclGmCU3KDft4StL8JUcpAsdzwIRf8mVj461q0,5306
69
+ iam_validator/sdk/arn_matching.py,sha256=we70RM2sriCcsd5GAUj7gL0iGKZt3oa0kle2VLF-X2E,8841
70
+ iam_validator/sdk/context.py,sha256=SBFeedu8rhCzFA-zC2cH4wLZxEJT6XOW30hIZAyXPVU,6826
71
+ iam_validator/sdk/exceptions.py,sha256=tm91TxIwU157U_UHN7w5qICf_OhU11agj6pV5W_YP-4,1023
72
+ iam_validator/sdk/helpers.py,sha256=OVBg4xrW95LT74wXCg1LQkba9kw5RfFqeCLuTqhgL-A,5697
73
+ iam_validator/sdk/policy_utils.py,sha256=CZS1OGSdiWsd2lsCwg0BDcUNWa61tUwgvn-P5rKqeN8,12987
74
+ iam_validator/sdk/shortcuts.py,sha256=EVNSYV7rv4TFH03ulsZ3mS1UVmTSp2jKpc2AXs4j1q4,8531
75
+ iam_validator/utils/__init__.py,sha256=V8u-SSdnL4a7NwF-yg9x0JRl5epKAXEs2f5RiwK2qPo,856
76
+ iam_validator/utils/cache.py,sha256=wOQKOBeoG6QqC5f0oXcHz63Cjtu_-SsSS-0pTSwyAiM,3254
77
+ iam_validator/utils/regex.py,sha256=PMVCYxjlVa2zLNEnIU3upQCSIhPazlXWg_sJClIiqiM,6221
78
+ iam_policy_validator-1.6.0.dist-info/METADATA,sha256=rghXQo_4hFarMkPFzCmWFgD_1yMW1dwtwGIId_MsBdc,36586
79
+ iam_policy_validator-1.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
80
+ iam_policy_validator-1.6.0.dist-info/entry_points.txt,sha256=8HtWd8O7mvPiPdZR5YbzY8or_qcqLM4-pKaFdhtFT8M,62
81
+ iam_policy_validator-1.6.0.dist-info/licenses/LICENSE,sha256=AMnbFTBDcK4_MITe2wiQBkj0vg-jjBBhsc43ydC7tt4,1098
82
+ iam_policy_validator-1.6.0.dist-info/RECORD,,
@@ -3,5 +3,5 @@
3
3
  This file is the single source of truth for the package version.
4
4
  """
5
5
 
6
- __version__ = "1.5.0"
6
+ __version__ = "1.6.0"
7
7
  __version_info__ = tuple(int(part) for part in __version__.split("."))
@@ -5,32 +5,38 @@ Built-in policy checks for IAM Policy Validator.
5
5
  from iam_validator.checks.action_condition_enforcement import (
6
6
  ActionConditionEnforcementCheck,
7
7
  )
8
- from iam_validator.checks.action_resource_constraint import (
9
- ActionResourceConstraintCheck,
8
+ from iam_validator.checks.action_resource_matching import (
9
+ ActionResourceMatchingCheck,
10
10
  )
11
11
  from iam_validator.checks.action_validation import ActionValidationCheck
12
12
  from iam_validator.checks.condition_key_validation import ConditionKeyValidationCheck
13
+ from iam_validator.checks.condition_type_mismatch import ConditionTypeMismatchCheck
13
14
  from iam_validator.checks.full_wildcard import FullWildcardCheck
15
+ from iam_validator.checks.mfa_condition_check import MFAConditionCheck
14
16
  from iam_validator.checks.policy_size import PolicySizeCheck
15
17
  from iam_validator.checks.principal_validation import PrincipalValidationCheck
16
18
  from iam_validator.checks.resource_validation import ResourceValidationCheck
17
19
  from iam_validator.checks.sensitive_action import SensitiveActionCheck
18
20
  from iam_validator.checks.service_wildcard import ServiceWildcardCheck
21
+ from iam_validator.checks.set_operator_validation import SetOperatorValidationCheck
19
22
  from iam_validator.checks.sid_uniqueness import SidUniquenessCheck
20
23
  from iam_validator.checks.wildcard_action import WildcardActionCheck
21
24
  from iam_validator.checks.wildcard_resource import WildcardResourceCheck
22
25
 
23
26
  __all__ = [
24
27
  "ActionConditionEnforcementCheck",
25
- "ActionResourceConstraintCheck",
28
+ "ActionResourceMatchingCheck",
26
29
  "ActionValidationCheck",
27
30
  "ConditionKeyValidationCheck",
31
+ "ConditionTypeMismatchCheck",
28
32
  "FullWildcardCheck",
33
+ "MFAConditionCheck",
29
34
  "PolicySizeCheck",
30
35
  "PrincipalValidationCheck",
31
36
  "ResourceValidationCheck",
32
37
  "SensitiveActionCheck",
33
38
  "ServiceWildcardCheck",
39
+ "SetOperatorValidationCheck",
34
40
  "SidUniquenessCheck",
35
41
  "WildcardActionCheck",
36
42
  "WildcardResourceCheck",
@@ -5,6 +5,7 @@ This built-in check ensures that specific actions have required conditions.
5
5
  Supports ALL types of conditions: MFA, IP, VPC, time, tags, encryption, etc.
6
6
 
7
7
  Supports advanced "all_of" and "any_of" logic for both actions and conditions.
8
+ Supports both STATEMENT-LEVEL and POLICY-LEVEL enforcement.
8
9
 
9
10
  Common use cases:
10
11
  - iam:PassRole must have iam:PassedToService condition
@@ -12,6 +13,7 @@ Common use cases:
12
13
  - Actions must have source IP restrictions
13
14
  - Resources must have required tags
14
15
  - Combine multiple conditions (MFA + IP + Tags)
16
+ - Policy-level: Ensure ALL statements granting certain actions have MFA
15
17
 
16
18
  Configuration in iam-validator.yaml:
17
19
 
@@ -21,6 +23,7 @@ Configuration in iam-validator.yaml:
21
23
  severity: error
22
24
  description: "Enforce specific conditions for specific actions"
23
25
 
26
+ # STATEMENT-LEVEL: Check individual statements (default)
24
27
  action_condition_requirements:
25
28
  # BASIC: Simple action with required condition
26
29
  - actions:
@@ -90,15 +93,56 @@ Configuration in iam-validator.yaml:
90
93
  - "iam:*"
91
94
  - "s3:DeleteBucket"
92
95
  description: "These dangerous actions should never be used"
96
+
97
+ # POLICY-LEVEL: Scan entire policy and enforce conditions across all matching statements
98
+ policy_level_requirements:
99
+ # Example: If ANY statement grants privilege escalation actions,
100
+ # then ALL such statements must have MFA
101
+ - actions:
102
+ any_of:
103
+ - "iam:CreateUser"
104
+ - "iam:AttachUserPolicy"
105
+ - "iam:PutUserPolicy"
106
+ scope: "policy"
107
+ required_conditions:
108
+ - condition_key: "aws:MultiFactorAuthPresent"
109
+ expected_value: true
110
+ description: "Privilege escalation actions require MFA across entire policy"
111
+ severity: "critical"
112
+
113
+ # Example: All admin actions across the policy must have MFA
114
+ - actions:
115
+ any_of:
116
+ - "iam:*"
117
+ - "s3:*"
118
+ scope: "policy"
119
+ required_conditions:
120
+ all_of:
121
+ - condition_key: "aws:MultiFactorAuthPresent"
122
+ expected_value: true
123
+ - condition_key: "aws:SourceIp"
124
+ apply_to: "all_matching_statements"
125
+
126
+ # Example: Ensure no statement in the policy allows dangerous combinations
127
+ - actions:
128
+ all_of:
129
+ - "iam:CreateAccessKey"
130
+ - "iam:UpdateAccessKey"
131
+ scope: "policy"
132
+ severity: "critical"
133
+ description: "Dangerous combination of actions detected in policy"
93
134
  """
94
135
 
95
136
  import re
96
- from typing import Any
137
+ from typing import TYPE_CHECKING, Any
97
138
 
98
139
  from iam_validator.core.aws_fetcher import AWSServiceFetcher
99
140
  from iam_validator.core.check_registry import CheckConfig, PolicyCheck
100
141
  from iam_validator.core.models import Statement, ValidationIssue
101
142
 
143
+ if TYPE_CHECKING:
144
+ from iam_validator.core.models import IAMPolicy
145
+
102
146
 
103
147
  class ActionConditionEnforcementCheck(PolicyCheck):
104
148
  """Enforces specific condition requirements for specific actions with all_of/any_of support."""
@@ -122,7 +166,7 @@ class ActionConditionEnforcementCheck(PolicyCheck):
122
166
  fetcher: AWSServiceFetcher,
123
167
  config: CheckConfig,
124
168
  ) -> list[ValidationIssue]:
125
- """Execute condition enforcement check."""
169
+ """Execute statement-level condition enforcement check."""
126
170
  issues = []
127
171
 
128
172
  # Only check Allow statements
@@ -186,6 +230,124 @@ class ActionConditionEnforcementCheck(PolicyCheck):
186
230
 
187
231
  return issues
188
232
 
233
+ async def execute_policy(
234
+ self,
235
+ policy: "IAMPolicy",
236
+ policy_file: str,
237
+ fetcher: AWSServiceFetcher,
238
+ config: CheckConfig,
239
+ **kwargs,
240
+ ) -> list[ValidationIssue]:
241
+ """
242
+ Execute policy-level condition enforcement check.
243
+
244
+ This method scans the entire policy and enforces that ALL statements granting
245
+ certain actions must have specific conditions. This is useful for ensuring
246
+ consistent security controls across the entire policy.
247
+
248
+ Example use case:
249
+ - "If ANY statement in the policy grants iam:CreateUser, iam:AttachUserPolicy,
250
+ or iam:PutUserPolicy, then ALL such statements must have MFA condition."
251
+
252
+ Args:
253
+ policy: The complete IAM policy to check
254
+ policy_file: Path to the policy file (for context/reporting)
255
+ fetcher: AWS service fetcher for validation against AWS APIs
256
+ config: Configuration for this check instance
257
+ **kwargs: Additional context (policy_type, etc.)
258
+
259
+ Returns:
260
+ List of ValidationIssue objects found by this check
261
+ """
262
+ del policy_file, kwargs # Not used in current implementation
263
+ issues = []
264
+
265
+ # Get policy-level requirements from config
266
+ policy_level_requirements = config.config.get("policy_level_requirements", [])
267
+ if not policy_level_requirements:
268
+ return issues
269
+
270
+ # Process each policy-level requirement
271
+ for requirement in policy_level_requirements:
272
+ # Collect all statements that match the action criteria
273
+ matching_statements: list[tuple[int, Statement, list[str]]] = []
274
+
275
+ for idx, statement in enumerate(policy.statement):
276
+ # Only check Allow statements
277
+ if statement.effect != "Allow":
278
+ continue
279
+
280
+ statement_actions = statement.get_actions()
281
+
282
+ # Check if this statement matches the action requirement
283
+ actions_match, matching_actions = await self._check_action_match(
284
+ statement_actions, requirement, fetcher
285
+ )
286
+
287
+ if actions_match and matching_actions:
288
+ matching_statements.append((idx, statement, matching_actions))
289
+
290
+ # If no statements match, skip this requirement
291
+ if not matching_statements:
292
+ continue
293
+
294
+ # Now validate that ALL matching statements have the required conditions
295
+ required_conditions_config = requirement.get("required_conditions", [])
296
+ if not required_conditions_config:
297
+ # No conditions specified, just report that actions were found
298
+ description = requirement.get("description", "")
299
+ severity = requirement.get("severity", self.get_severity(config))
300
+
301
+ # Create a summary issue for all matching statements
302
+ all_actions = set()
303
+ statement_refs = []
304
+ for idx, stmt, actions in matching_statements:
305
+ all_actions.update(actions)
306
+ sid_info = f" (SID: {stmt.sid})" if stmt.sid else ""
307
+ statement_refs.append(f"Statement #{idx + 1}{sid_info}")
308
+
309
+ # Use the first matching statement's index for the issue
310
+ first_idx, first_stmt, _ = matching_statements[0]
311
+
312
+ issues.append(
313
+ ValidationIssue(
314
+ severity=severity,
315
+ statement_sid=first_stmt.sid,
316
+ statement_index=first_idx,
317
+ issue_type="policy_level_action_detected",
318
+ message=f"POLICY-LEVEL: Actions {sorted(all_actions)} found in {len(matching_statements)} statement(s). {description}",
319
+ action=", ".join(sorted(all_actions)),
320
+ suggestion=f"Review these statements: {', '.join(statement_refs)}. {description}",
321
+ line_number=first_stmt.line_number,
322
+ )
323
+ )
324
+ continue
325
+
326
+ # Validate conditions for each matching statement
327
+ for idx, statement, matching_actions in matching_statements:
328
+ condition_issues = self._validate_conditions(
329
+ statement,
330
+ idx,
331
+ required_conditions_config,
332
+ matching_actions,
333
+ config,
334
+ requirement,
335
+ )
336
+
337
+ # Add policy-level context to each issue
338
+ for issue in condition_issues:
339
+ # Modify the message to indicate this is part of policy-level enforcement
340
+ issue.message = f"POLICY-LEVEL: {issue.message}"
341
+ issue.suggestion = (
342
+ f"{issue.suggestion}\n\n"
343
+ f"Note: This is enforced at the policy level. "
344
+ f"Found {len(matching_statements)} statement(s) with these actions in the policy."
345
+ )
346
+
347
+ issues.extend(condition_issues)
348
+
349
+ return issues
350
+
189
351
  async def _check_action_match(
190
352
  self, statement_actions: list[str], requirement: dict[str, Any], fetcher: AWSServiceFetcher
191
353
  ) -> tuple[bool, list[str]]: