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
@@ -16,7 +16,8 @@ Benefits of code-first approach:
16
16
  - 5-10x faster than YAML parsing
17
17
  """
18
18
 
19
- from iam_validator.core.config.condition_requirements import get_default_requirements
19
+ from iam_validator.core.config.category_suggestions import get_category_suggestions
20
+ from iam_validator.core.config.condition_requirements import CONDITION_REQUIREMENTS
20
21
  from iam_validator.core.config.principal_requirements import (
21
22
  get_default_principal_requirements,
22
23
  )
@@ -76,9 +77,12 @@ DEFAULT_CONFIG = {
76
77
  "fail_on_severity": ["error", "critical", "high"],
77
78
  },
78
79
  # ========================================================================
79
- # AWS IAM Validation Checks
80
+ # AWS IAM Validation Checks (17 checks total)
80
81
  # These validate that policies conform to AWS IAM requirements
81
82
  # ========================================================================
83
+ # ========================================================================
84
+ # 1. SID UNIQUENESS
85
+ # ========================================================================
82
86
  # Validate Statement ID (Sid) uniqueness as per AWS IAM requirements
83
87
  # AWS requires:
84
88
  # - Sids must be unique within the policy (duplicate_sid error)
@@ -89,6 +93,9 @@ DEFAULT_CONFIG = {
89
93
  "severity": "error", # IAM validity error
90
94
  "description": "Validates that Statement IDs (Sids) are unique and follow AWS naming requirements",
91
95
  },
96
+ # ========================================================================
97
+ # 2. POLICY SIZE
98
+ # ========================================================================
92
99
  # Validate policy size against AWS limits
93
100
  # Policy type determines which AWS limit to enforce:
94
101
  # - managed: 6144 characters (excluding whitespace)
@@ -101,6 +108,9 @@ DEFAULT_CONFIG = {
101
108
  "description": "Validates that IAM policies don't exceed AWS size limits",
102
109
  "policy_type": "managed", # Change based on your policy type
103
110
  },
111
+ # ========================================================================
112
+ # 3. ACTION VALIDATION
113
+ # ========================================================================
104
114
  # Validate IAM actions against AWS service definitions
105
115
  # Uses AWS Service Authorization Reference to validate action names
106
116
  # Catches typos like "s3:GetObjekt" or non-existent actions
@@ -109,6 +119,9 @@ DEFAULT_CONFIG = {
109
119
  "severity": "error", # IAM validity error
110
120
  "description": "Validates that actions exist in AWS services",
111
121
  },
122
+ # ========================================================================
123
+ # 4. CONDITION KEY VALIDATION
124
+ # ========================================================================
112
125
  # Validate condition keys for actions against AWS service definitions
113
126
  # Ensures condition keys are valid for the specified actions
114
127
  # Examples:
@@ -124,8 +137,49 @@ DEFAULT_CONFIG = {
124
137
  # While global condition keys can be used across all AWS services, they may not be available
125
138
  # in every request context. This warning helps ensure proper validation.
126
139
  # Set to False to disable warnings for global condition keys
127
- "warn_on_global_condition_keys": True,
140
+ "warn_on_global_condition_keys": False,
141
+ },
142
+ # ========================================================================
143
+ # 5. CONDITION TYPE MISMATCH
144
+ # ========================================================================
145
+ # Validate condition type matching
146
+ # Ensures condition operators match the expected types for condition keys
147
+ # Examples:
148
+ # ✅ StringEquals with string condition key
149
+ # ❌ NumericEquals with string condition key (type mismatch)
150
+ # ✅ DateGreaterThan with date condition key
151
+ # ❌ StringLike with date condition key (type mismatch)
152
+ "condition_type_mismatch": {
153
+ "enabled": True,
154
+ "severity": "error", # IAM validity error
155
+ "description": "Validates that condition operators match the expected types for condition keys",
128
156
  },
157
+ # ========================================================================
158
+ # 6. SET OPERATOR VALIDATION
159
+ # ========================================================================
160
+ # Validate set operator usage (ForAllValues/ForAnyValue)
161
+ # Ensures set operators are only used with multi-value condition keys
162
+ # Using them with single-value keys can cause unexpected behavior
163
+ "set_operator_validation": {
164
+ "enabled": True,
165
+ "severity": "error", # IAM validity error
166
+ "description": "Validates that set operators are used with multi-value condition keys",
167
+ },
168
+ # ========================================================================
169
+ # 7. MFA CONDITION ANTIPATTERN
170
+ # ========================================================================
171
+ # Detect MFA condition anti-patterns
172
+ # Identifies dangerous MFA-related patterns that may not enforce MFA as intended:
173
+ # 1. Bool with aws:MultiFactorAuthPresent = false (key may not exist)
174
+ # 2. Null with aws:MultiFactorAuthPresent = false (only checks existence)
175
+ "mfa_condition_antipattern": {
176
+ "enabled": True,
177
+ "severity": "warning", # Security concern, not an IAM validity error
178
+ "description": "Detects dangerous MFA-related condition patterns",
179
+ },
180
+ # ========================================================================
181
+ # 8. RESOURCE VALIDATION
182
+ # ========================================================================
129
183
  # Validate resource ARN formats
130
184
  # Ensures ARNs follow the correct format:
131
185
  # arn:partition:service:region:account-id:resource-type/resource-id
@@ -137,7 +191,7 @@ DEFAULT_CONFIG = {
137
191
  "arn_pattern": "^arn:(aws|aws-cn|aws-us-gov|aws-eusc|aws-iso|aws-iso-b|aws-iso-e|aws-iso-f):[a-z0-9\\-]+:[a-z0-9\\-*]*:[0-9*]*:.+$",
138
192
  },
139
193
  # ========================================================================
140
- # Principal Validation (Resource Policies)
194
+ # 9. PRINCIPAL VALIDATION
141
195
  # ========================================================================
142
196
  # Validates Principal elements in resource-based policies
143
197
  # (S3 buckets, SNS topics, SQS queues, etc.)
@@ -193,17 +247,44 @@ DEFAULT_CONFIG = {
193
247
  # See: iam_validator/core/config/service_principals.py
194
248
  "allowed_service_principals": list(DEFAULT_SERVICE_PRINCIPALS),
195
249
  },
196
- # Validate resource constraints for actions
197
- # Ensures that actions without required resource types (account-level operations)
198
- # use Resource: "*" as they cannot target specific resources
199
- # Example: iam:ListUsers cannot target a specific user, must use "*"
200
- "action_resource_constraint": {
250
+ # ========================================================================
251
+ # 10. POLICY TYPE VALIDATION
252
+ # ========================================================================
253
+ # Validate policy type requirements (new in v1.3.0)
254
+ # Ensures policies conform to the declared type (IDENTITY vs RESOURCE_POLICY)
255
+ # Also enforces RCP (Resource Control Policy) specific requirements
256
+ # RCP validation includes:
257
+ # - Must have Effect: Deny (RCPs are deny-only)
258
+ # - Must target specific resource types (no wildcards)
259
+ # - Principal must be "*" (applies to all)
260
+ "policy_type_validation": {
261
+ "enabled": True,
262
+ "severity": "error", # IAM validity error
263
+ "description": "Validates policies match declared type and enforces RCP requirements",
264
+ },
265
+ # ========================================================================
266
+ # 11. ACTION-RESOURCE MATCHING
267
+ # ========================================================================
268
+ # Validate action-resource matching
269
+ # Ensures resources match the required resource types for actions
270
+ # Handles both:
271
+ # 1. Account-level actions that require Resource: "*" (e.g., iam:ListUsers)
272
+ # 2. Resource-specific actions with correct ARN types (e.g., s3:GetObject)
273
+ # Inspired by Parliament's RESOURCE_MISMATCH check
274
+ # Examples:
275
+ # ✅ iam:ListUsers with Resource: "*"
276
+ # ❌ iam:ListUsers with arn:aws:iam::123:user/foo (account-level action)
277
+ # ✅ s3:GetObject with arn:aws:s3:::bucket/*
278
+ # ❌ s3:GetObject with arn:aws:s3:::bucket (missing /*)
279
+ # ✅ s3:ListBucket with arn:aws:s3:::bucket
280
+ # ❌ s3:ListBucket with arn:aws:s3:::bucket/* (should be bucket, not object)
281
+ "action_resource_matching": {
201
282
  "enabled": True,
202
283
  "severity": "error", # IAM validity error
203
- "description": "Validates that actions without required resource types use Resource: '*'",
284
+ "description": "Validates that resource ARNs match the required resource types for actions (including account-level actions)",
204
285
  },
205
286
  # ========================================================================
206
- # Security Best Practices Checks
287
+ # Security Best Practices Checks (6 checks)
207
288
  # ========================================================================
208
289
  # Individual checks for security anti-patterns
209
290
  #
@@ -221,6 +302,9 @@ DEFAULT_CONFIG = {
221
302
  # See: iam_validator/core/config/wildcards.py for allowed wildcards
222
303
  # See: iam_validator/core/config/sensitive_actions.py for sensitive actions
223
304
  # ========================================================================
305
+ # ========================================================================
306
+ # 12. WILDCARD ACTION
307
+ # ========================================================================
224
308
  # Check for wildcard actions (Action: "*")
225
309
  # Flags statements that allow all actions
226
310
  "wildcard_action": {
@@ -237,6 +321,9 @@ DEFAULT_CONFIG = {
237
321
  ' "Action": ["s3:GetObject", "s3:PutObject", "s3:ListBucket"]\n'
238
322
  ),
239
323
  },
324
+ # ========================================================================
325
+ # 13. WILDCARD RESOURCE
326
+ # ========================================================================
240
327
  # Check for wildcard resources (Resource: "*")
241
328
  # Flags statements that apply to all resources
242
329
  # Exception: Allowed if ALL actions are in allowed_wildcards list
@@ -261,6 +348,9 @@ DEFAULT_CONFIG = {
261
348
  " ]\n"
262
349
  ),
263
350
  },
351
+ # ========================================================================
352
+ # 14. FULL WILDCARD (CRITICAL)
353
+ # ========================================================================
264
354
  # Check for BOTH Action: "*" AND Resource: "*" (CRITICAL)
265
355
  # This grants full administrative access (AdministratorAccess equivalent)
266
356
  "full_wildcard": {
@@ -278,15 +368,13 @@ DEFAULT_CONFIG = {
278
368
  ' "Resource": "*"\n'
279
369
  "\n"
280
370
  "With specific values:\n"
281
- ' "Action": [\n'
282
- ' "s3:GetObject",\n'
283
- ' "s3:PutObject"\n'
284
- " ],\n"
285
- ' "Resource": [\n'
286
- ' "arn:aws:s3:::my-bucket/*"\n'
287
- " ]\n"
371
+ ' "Action": ["s3:GetObject", "s3:PutObject"],\n'
372
+ ' "Resource": ["arn:aws:s3:::my-bucket/*"]\n'
288
373
  ),
289
374
  },
375
+ # ========================================================================
376
+ # 15. SERVICE WILDCARD
377
+ # ========================================================================
290
378
  # Check for service-level wildcards (e.g., "iam:*", "s3:*", "ec2:*")
291
379
  # These grant ALL permissions for a service (often too permissive)
292
380
  # Exception: Some services like logs, cloudwatch are typically safe
@@ -302,16 +390,38 @@ DEFAULT_CONFIG = {
302
390
  # See: iam_validator/core/config/wildcards.py
303
391
  "allowed_services": list(DEFAULT_SERVICE_WILDCARDS),
304
392
  },
393
+ # ========================================================================
394
+ # 16. SENSITIVE ACTION
395
+ # ========================================================================
305
396
  # Check for sensitive actions without IAM conditions
306
397
  # Sensitive actions: IAM changes, secrets access, destructive operations
307
- # Default: 79 actions across 8 categories
308
- # Categories: iam_identity, secrets_credentials, compute_containers,
309
- # database_storage, s3_backup, network_security,
310
- # access_logging, account_organization
398
+ # Default: 490 actions across 4 security risk categories
399
+ #
400
+ # Categories (with action counts):
401
+ # - credential_exposure (46): Actions exposing credentials, secrets, or tokens
402
+ # - data_access (109): Actions retrieving sensitive data
403
+ # - priv_esc (27): Actions enabling privilege escalation
404
+ # - resource_exposure (321): Actions modifying resource policies/permissions
311
405
  #
312
406
  # Scans at BOTH statement-level AND policy-level for security patterns
313
407
  # See: iam_validator/core/config/sensitive_actions.py
314
- # Python API: get_actions_by_categories(['iam_identity', 'secrets_credentials'])
408
+ # Source: https://github.com/primeharbor/sensitive_iam_actions
409
+ #
410
+ # Python API:
411
+ # from iam_validator.core.config.sensitive_actions import get_sensitive_actions
412
+ # # Get all sensitive actions (default)
413
+ # all_actions = get_sensitive_actions()
414
+ # # Get only specific categories
415
+ # priv_esc_only = get_sensitive_actions(['priv_esc'])
416
+ # # Get multiple categories
417
+ # critical = get_sensitive_actions(['credential_exposure', 'priv_esc'])
418
+ #
419
+ # Avoiding Duplicate Alerts:
420
+ # If you configure specific actions in action_condition_enforcement,
421
+ # use ignore_patterns to prevent duplicate alerts from sensitive_action:
422
+ #
423
+ # ignore_patterns:
424
+ # - action_matches: "^(iam:PassRole|iam:CreateUser|s3:PutObject)$"
315
425
  #
316
426
  # Template placeholders supported:
317
427
  # - message_single uses {action}: Single action name (e.g., "iam:CreateRole")
@@ -319,61 +429,84 @@ DEFAULT_CONFIG = {
319
429
  # - suggestion and example support both {action} and {actions}
320
430
  "sensitive_action": {
321
431
  "enabled": True,
322
- "severity": "medium", # Security issue
432
+ "severity": "medium", # Security issue (can be overridden per-category)
323
433
  "description": "Checks for sensitive actions without conditions",
434
+ # Categories to check (default: all categories enabled)
435
+ # Set to specific categories to limit scope:
436
+ # categories: ['credential_exposure', 'priv_esc'] # Only check critical actions
437
+ # categories: ['data_access'] # Only check data access actions
438
+ # Set to empty list to disable: categories: []
439
+ "categories": [
440
+ "credential_exposure", # Critical: Credential/secret exposure (46 actions)
441
+ "data_access", # High: Sensitive data retrieval (109 actions)
442
+ "priv_esc", # Critical: Privilege escalation (27 actions)
443
+ "resource_exposure", # High: Resource policy modifications (321 actions)
444
+ ],
445
+ # Per-category severity overrides (optional)
446
+ # If not specified, uses the default severity above
447
+ "category_severities": {
448
+ "credential_exposure": "critical", # Override: credential exposure is critical
449
+ "priv_esc": "critical", # Override: privilege escalation is critical
450
+ "data_access": "high", # Override: data access is high
451
+ "resource_exposure": "high", # Override: resource exposure is high
452
+ },
453
+ # Category-specific ABAC suggestions and examples
454
+ # These provide tailored guidance for each security risk category
455
+ # See: iam_validator/core/config/category_suggestions.py
456
+ # Can be overridden to customize suggestions per category
457
+ "category_suggestions": get_category_suggestions(),
324
458
  # Custom message templates (support {action} and {actions} placeholders)
325
459
  "message_single": "Sensitive action '{action}' should have conditions to limit when it can be used",
326
460
  "message_multiple": "Sensitive actions '{actions}' should have conditions to limit when they can be used",
327
- "suggestion": (
328
- "Add IAM conditions to limit when this action can be used.\n"
329
- "Consider: ABAC (ResourceTag OR RequestTag matching ${aws:PrincipalTag}), "
330
- "IP restrictions (aws:SourceIp), MFA requirements (aws:MultiFactorAuthPresent), "
331
- "or time-based restrictions (aws:CurrentTime)\n"
332
- ),
333
- "example": (
334
- '"Condition": {\n'
335
- ' "StringEquals": {\n'
336
- ' "aws:ResourceTag/owner": "${aws:PrincipalTag/owner}"\n'
337
- " }\n"
338
- "}\n"
339
- ),
461
+ # Ignore patterns to prevent duplicate alerts
462
+ # Useful when you have specific condition enforcement for certain actions
463
+ # Example: Ignore iam:PassRole since it's checked by action_condition_enforcement
464
+ "ignore_patterns": [
465
+ {"action_matches": "^iam:PassRole$"},
466
+ ],
340
467
  },
341
468
  # ========================================================================
342
- # Action Condition Enforcement
469
+ # 17. ACTION CONDITION ENFORCEMENT
343
470
  # ========================================================================
344
471
  # Enforce specific IAM condition requirements for actions
345
472
  # Examples: iam:PassRole must specify iam:PassedToService,
346
473
  # S3 writes must require MFA, EC2 launches must use tags
347
474
  #
348
- # Default: 5 enabled requirements out of 13 available
475
+ # Default: 5 enabled requirements
349
476
  # Available requirements:
350
477
  # Default (enabled):
351
478
  # - iam_pass_role: Requires iam:PassedToService
352
- # - iam_permissions_boundary: Requires permissions boundary
353
479
  # - s3_org_id: Requires organization ID for S3 writes
354
480
  # - source_ip_restrictions: Restricts to corporate IPs
355
481
  # - s3_secure_transport: Prevents insecure transport
356
- # Optional (disabled by default):
357
- # - s3_destructive_mfa: Requires MFA for S3 deletes
358
- # - s3_require_https: Requires HTTPS for all S3 operations
359
- # - ec2_vpc_restriction: Restricts EC2 to specific VPCs
360
- # - ec2_tag_requirements: ABAC tag requirements for EC2
361
- # - rds_tag_requirements: Tag requirements for RDS
362
- # - s3_bucket_tag_requirements: Tag requirements for S3 buckets
363
- # - forbidden_actions: Flags forbidden actions
364
482
  # - prevent_public_ip: Prevents 0.0.0.0/0 IP ranges
365
483
  #
366
484
  # See: iam_validator/core/config/condition_requirements.py
367
485
  # Python API:
368
- # from iam_validator.core.config import get_requirements_by_names
369
- # requirements = get_requirements_by_names(['iam_pass_role', 's3_destructive_mfa'])
486
+ # from iam_validator.core.config import CONDITION_REQUIREMENTS
487
+ # import copy
488
+ # requirements = copy.deepcopy(CONDITION_REQUIREMENTS)
370
489
  "action_condition_enforcement": {
371
490
  "enabled": True,
372
491
  "severity": "high", # Default severity (can be overridden per-requirement)
373
- "description": "Enforces conditions (MFA, IP, tags, etc.) for specific actions (supports all_of/any_of)",
374
- # Load 5 default requirements from Python module
375
- # Returns a deep copy to prevent mutation of the originals
376
- "action_condition_requirements": get_default_requirements(),
492
+ "description": "Enforces conditions (MFA, IP, tags, etc.) for specific actions at both statement and policy level",
493
+ # STATEMENT-LEVEL: Load 5 requirements from Python module
494
+ # Deep copy to prevent mutation of the originals
495
+ # These check individual statements independently
496
+ "action_condition_requirements": __import__("copy").deepcopy(CONDITION_REQUIREMENTS),
497
+ # POLICY-LEVEL: Scan entire policy and enforce conditions across ALL matching statements
498
+ # Example: "If ANY statement grants iam:CreateUser, then ALL such statements must have MFA"
499
+ # Default: Empty list (opt-in feature)
500
+ # To enable, add requirements like:
501
+ # policy_level_requirements:
502
+ # - actions:
503
+ # any_of: ["iam:CreateUser", "iam:AttachUserPolicy"]
504
+ # scope: "policy"
505
+ # required_conditions:
506
+ # - condition_key: "aws:MultiFactorAuthPresent"
507
+ # expected_value: true
508
+ # severity: "critical"
509
+ "policy_level_requirements": [],
377
510
  },
378
511
  }
379
512