iam-policy-validator 1.4.0__py3-none-any.whl → 1.5.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 (33) hide show
  1. {iam_policy_validator-1.4.0.dist-info → iam_policy_validator-1.5.0.dist-info}/METADATA +18 -19
  2. {iam_policy_validator-1.4.0.dist-info → iam_policy_validator-1.5.0.dist-info}/RECORD +31 -20
  3. iam_validator/__version__.py +1 -1
  4. iam_validator/checks/__init__.py +13 -3
  5. iam_validator/checks/action_condition_enforcement.py +1 -6
  6. iam_validator/checks/condition_key_validation.py +21 -1
  7. iam_validator/checks/full_wildcard.py +67 -0
  8. iam_validator/checks/principal_validation.py +497 -3
  9. iam_validator/checks/sensitive_action.py +178 -0
  10. iam_validator/checks/service_wildcard.py +105 -0
  11. iam_validator/checks/utils/sensitive_action_matcher.py +39 -31
  12. iam_validator/checks/wildcard_action.py +62 -0
  13. iam_validator/checks/wildcard_resource.py +131 -0
  14. iam_validator/commands/download_services.py +3 -8
  15. iam_validator/commands/validate.py +28 -2
  16. iam_validator/core/aws_fetcher.py +25 -12
  17. iam_validator/core/check_registry.py +15 -21
  18. iam_validator/core/config/__init__.py +83 -0
  19. iam_validator/core/config/aws_api.py +35 -0
  20. iam_validator/core/config/condition_requirements.py +535 -0
  21. iam_validator/core/config/defaults.py +390 -0
  22. iam_validator/core/config/principal_requirements.py +421 -0
  23. iam_validator/core/config/sensitive_actions.py +133 -0
  24. iam_validator/core/config/service_principals.py +95 -0
  25. iam_validator/core/config/wildcards.py +124 -0
  26. iam_validator/core/config_loader.py +29 -9
  27. iam_validator/core/formatters/enhanced.py +11 -5
  28. iam_validator/core/formatters/sarif.py +78 -14
  29. iam_validator/checks/security_best_practices.py +0 -536
  30. iam_validator/core/defaults.py +0 -393
  31. {iam_policy_validator-1.4.0.dist-info → iam_policy_validator-1.5.0.dist-info}/WHEEL +0 -0
  32. {iam_policy_validator-1.4.0.dist-info → iam_policy_validator-1.5.0.dist-info}/entry_points.txt +0 -0
  33. {iam_policy_validator-1.4.0.dist-info → iam_policy_validator-1.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,393 +0,0 @@
1
- """
2
- Default configuration for IAM Policy Validator.
3
-
4
- This module contains the default configuration that is used when no user
5
- configuration file is provided. User configuration files will override
6
- these defaults.
7
-
8
- This configuration is synced with the default-config.yaml file.
9
- """
10
-
11
- # ============================================================================
12
- # SEVERITY LEVELS
13
- # ============================================================================
14
- # The validator uses two types of severity levels:
15
- #
16
- # 1. IAM VALIDITY SEVERITIES (for AWS IAM policy correctness):
17
- # - error: Policy violates AWS IAM rules (invalid actions, ARNs, etc.)
18
- # - warning: Policy may have IAM-related issues but is technically valid
19
- # - info: Informational messages about the policy structure
20
- #
21
- # 2. SECURITY SEVERITIES (for security best practices):
22
- # - critical: Critical security risk (e.g., wildcard action + resource)
23
- # - high: High security risk (e.g., missing required conditions)
24
- # - medium: Medium security risk (e.g., overly permissive wildcards)
25
- # - low: Low security risk (e.g., minor best practice violations)
26
- #
27
- # Use 'error' for policy validity issues, and 'critical/high/medium/low' for
28
- # security best practices. This distinction helps separate "broken policies"
29
- # from "insecure but valid policies".
30
- # ============================================================================
31
-
32
- # Default configuration dictionary
33
- DEFAULT_CONFIG = {
34
- "settings": {
35
- "fail_fast": False,
36
- "max_concurrent": 10,
37
- "enable_builtin_checks": True,
38
- "parallel_execution": True,
39
- "aws_services_dir": None,
40
- "cache_enabled": True,
41
- "cache_ttl_hours": 168,
42
- "fail_on_severity": ["error", "critical", "high"],
43
- },
44
- "sid_uniqueness_check": {
45
- "enabled": True,
46
- "severity": "error",
47
- "description": "Validates that Statement IDs (Sids) are unique and follow AWS naming requirements",
48
- },
49
- "policy_size_check": {
50
- "enabled": True,
51
- "severity": "error",
52
- "description": "Validates that IAM policies don't exceed AWS size limits",
53
- "policy_type": "managed",
54
- },
55
- "action_validation_check": {
56
- "enabled": True,
57
- "severity": "error",
58
- "description": "Validates that actions exist in AWS services",
59
- },
60
- "condition_key_validation_check": {
61
- "enabled": True,
62
- "severity": "error",
63
- "description": "Validates condition keys against AWS service definitions for specified actions",
64
- "validate_aws_global_keys": True,
65
- },
66
- "resource_validation_check": {
67
- "enabled": True,
68
- "severity": "error",
69
- "description": "Validates ARN format for resources",
70
- "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*]*:.+$",
71
- },
72
- "principal_validation_check": {
73
- "enabled": True,
74
- "severity": "high",
75
- "description": "Validates Principal elements in resource policies for security best practices",
76
- "blocked_principals": ["*"],
77
- "allowed_principals": [],
78
- "require_conditions_for": {
79
- "*": ["aws:SourceArn", "aws:SourceAccount"],
80
- },
81
- "allowed_service_principals": [
82
- "cloudfront.amazonaws.com",
83
- "s3.amazonaws.com",
84
- "sns.amazonaws.com",
85
- "lambda.amazonaws.com",
86
- "logs.amazonaws.com",
87
- "events.amazonaws.com",
88
- ],
89
- },
90
- "action_resource_constraint_check": {
91
- "enabled": True,
92
- "severity": "error",
93
- "description": "Validates that actions without required resource types use Resource: '*'",
94
- },
95
- "security_best_practices_check": {
96
- "enabled": True,
97
- "description": "Checks for common security anti-patterns",
98
- "allowed_wildcards": [
99
- "autoscaling:Describe*",
100
- "cloudwatch:Describe*",
101
- "cloudwatch:Get*",
102
- "cloudwatch:List*",
103
- "dynamodb:Describe*",
104
- "ec2:Describe*",
105
- "elasticloadbalancing:Describe*",
106
- "iam:Get*",
107
- "iam:List*",
108
- "kms:Describe*",
109
- "lambda:Get*",
110
- "lambda:List*",
111
- "logs:Describe*",
112
- "logs:Filter*",
113
- "logs:Get*",
114
- "rds:Describe*",
115
- "route53:Get*",
116
- "route53:List*",
117
- "s3:Describe*",
118
- "s3:GetBucket*",
119
- "s3:GetM*",
120
- "s3:List*",
121
- "sqs:Get*",
122
- "sqs:List*",
123
- "apigateway:GET",
124
- ],
125
- "wildcard_action_check": {
126
- "enabled": True,
127
- "severity": "medium",
128
- "message": "Statement allows all actions (*)",
129
- "suggestion": "Replace wildcard with specific actions needed for your use case",
130
- "example": """Replace:
131
- "Action": ["*"]
132
-
133
- With specific actions:
134
- "Action": [
135
- "s3:GetObject",
136
- "s3:PutObject",
137
- "s3:ListBucket"
138
- ]
139
- """,
140
- },
141
- "wildcard_resource_check": {
142
- "enabled": True,
143
- "severity": "medium",
144
- "message": "Statement applies to all resources (*)",
145
- "suggestion": "Replace wildcard with specific resource ARNs",
146
- "example": """Replace:
147
- "Resource": "*"
148
-
149
- With specific ARNs:
150
- "Resource": [
151
- "arn:aws:service:region:account-id:resource-type/resource-id",
152
- "arn:aws:service:region:account-id:resource-type/*"
153
- ]
154
- """,
155
- },
156
- "full_wildcard_check": {
157
- "enabled": True,
158
- "severity": "critical",
159
- "message": "Statement allows all actions on all resources - CRITICAL SECURITY RISK",
160
- "suggestion": "This grants full administrative access. Replace both wildcards with specific actions and resources to follow least-privilege principle",
161
- "example": """Replace:
162
- "Action": "*",
163
- "Resource": "*"
164
-
165
- With specific values:
166
- "Action": [
167
- "s3:GetObject",
168
- "s3:PutObject"
169
- ],
170
- "Resource": [
171
- "arn:aws:s3:::my-bucket/*"
172
- ]
173
- """,
174
- },
175
- "service_wildcard_check": {
176
- "enabled": True,
177
- "severity": "high",
178
- "allowed_services": ["logs", "cloudwatch", "xray"],
179
- },
180
- "sensitive_action_check": {
181
- "enabled": True,
182
- "severity": "medium",
183
- "message_single": "Sensitive action '{action}' should have conditions to limit when it can be used",
184
- "message_multiple": "Sensitive actions '{actions}' should have conditions to limit when they can be used",
185
- "suggestion": "Add IAM conditions to limit when this action can be used. Consider: ABAC (ResourceTag OR RequestTag must match PrincipalTag), IP restrictions (aws:SourceIp), MFA requirements (aws:MultiFactorAuthPresent), or time-based restrictions (aws:CurrentTime)",
186
- "example": """"Condition": {
187
- "StringEquals": {
188
- "aws:ResourceTag/owner": "${aws:PrincipalTag/owner}"
189
- }
190
- }
191
- """,
192
- "sensitive_actions": [
193
- "iam:AddClientIDToOpenIDConnectProvider",
194
- "iam:AttachRolePolicy",
195
- "iam:AttachUserPolicy",
196
- "iam:CreateAccessKey",
197
- "iam:CreateOpenIDConnectProvider",
198
- "iam:CreatePolicyVersion",
199
- "iam:CreateRole",
200
- "iam:CreateSAMLProvider",
201
- "iam:CreateUser",
202
- "iam:DeleteAccessKey",
203
- "iam:DeleteLoginProfile",
204
- "iam:DeleteOpenIDConnectProvider",
205
- "iam:DeleteRole",
206
- "iam:DeleteRolePolicy",
207
- "iam:DeleteSAMLProvider",
208
- "iam:DeleteUser",
209
- "iam:DeleteUserPolicy",
210
- "iam:DetachRolePolicy",
211
- "iam:DetachUserPolicy",
212
- "iam:PutRolePolicy",
213
- "iam:PutUserPolicy",
214
- "iam:SetDefaultPolicyVersion",
215
- "iam:UpdateAccessKey",
216
- "iam:UpdateAssumeRolePolicy",
217
- "kms:DisableKey",
218
- "kms:PutKeyPolicy",
219
- "kms:ScheduleKeyDeletion",
220
- "secretsmanager:DeleteSecret",
221
- "secretsmanager:GetSecretValue",
222
- "secretsmanager:PutSecretValue",
223
- "ssm:DeleteParameter",
224
- "ssm:PutParameter",
225
- "ec2:DeleteSnapshot",
226
- "ec2:DeleteVolume",
227
- "ec2:DeleteVpc",
228
- "ec2:ModifyInstanceAttribute",
229
- "ec2:TerminateInstances",
230
- "ecr:DeleteRepository",
231
- "ecs:DeleteCluster",
232
- "ecs:DeleteService",
233
- "eks:DeleteCluster",
234
- "lambda:DeleteFunction",
235
- "lambda:DeleteFunctionConcurrency",
236
- "lambda:PutFunctionConcurrency",
237
- "dynamodb:DeleteTable",
238
- "efs:DeleteFileSystem",
239
- "elasticache:DeleteCacheCluster",
240
- "fsx:DeleteFileSystem",
241
- "rds:DeleteDBCluster",
242
- "rds:DeleteDBInstance",
243
- "redshift:DeleteCluster",
244
- "backup:DeleteBackupVault",
245
- "glacier:DeleteArchive",
246
- "s3:DeleteBucket",
247
- "s3:DeleteBucketPolicy",
248
- "s3:DeleteObject",
249
- "s3:PutBucketPolicy",
250
- "s3:PutLifecycleConfiguration",
251
- "ec2:AuthorizeSecurityGroupIngress",
252
- "ec2:DeleteSecurityGroup",
253
- "ec2:DisassociateRouteTable",
254
- "ec2:RevokeSecurityGroupEgress",
255
- "cloudtrail:DeleteTrail",
256
- "cloudtrail:StopLogging",
257
- "cloudwatch:DeleteLogGroup",
258
- "config:DeleteConfigurationRecorder",
259
- "guardduty:DeleteDetector",
260
- "account:CloseAccount",
261
- "account:CreateAccount",
262
- "organizations:LeaveOrganization",
263
- "organizations:RemoveAccountFromOrganization",
264
- ],
265
- },
266
- },
267
- "action_condition_enforcement_check": {
268
- "enabled": True,
269
- "severity": "high",
270
- "description": "Enforce specific IAM condition requirements (unified: MFA, IP, tags, etc.)",
271
- "action_condition_requirements": [
272
- {
273
- "actions": ["iam:PassRole"],
274
- "severity": "high",
275
- "required_conditions": [
276
- {
277
- "condition_key": "iam:PassedToService",
278
- "description": "Specify which AWS services are allowed to use the passed role to prevent privilege escalation",
279
- "example": """"Condition": {
280
- "StringEquals": {
281
- "iam:PassedToService": [
282
- "lambda.amazonaws.com",
283
- "ecs-tasks.amazonaws.com",
284
- "ec2.amazonaws.com",
285
- "glue.amazonaws.com",
286
- "lambda.amazonaws.com"
287
- ]
288
- }
289
- }
290
- """,
291
- },
292
- ],
293
- },
294
- {
295
- "actions": [
296
- "iam:CreateRole",
297
- "iam:PutRolePolicy*",
298
- "iam:PutUserPolicy",
299
- "iam:PutRolePolicy",
300
- "iam:Attach*Policy*",
301
- "iam:AttachUserPolicy",
302
- "iam:AttachRolePolicy",
303
- ],
304
- "severity": "high",
305
- "required_conditions": [
306
- {
307
- "condition_key": "iam:PermissionsBoundary",
308
- "description": "Require permissions boundary for sensitive IAM operations to prevent privilege escalation",
309
- "expected_value": "arn:aws:iam::*:policy/DeveloperBoundary",
310
- "example": """# See: https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html
311
- "Condition": {
312
- "StringEquals": {
313
- "iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/XCompanyBoundaries"
314
- }
315
- }
316
- """,
317
- },
318
- ],
319
- },
320
- {
321
- "actions": ["s3:PutObject"],
322
- "severity": "medium",
323
- "required_conditions": [
324
- {
325
- "condition_key": "aws:ResourceOrgId",
326
- "description": "Require aws:ResourceOrgId condition for S3 write actions to enforce organization-level access control",
327
- "example": """"Condition": {
328
- "StringEquals": {
329
- "aws:ResourceOrgId": "${aws:PrincipalOrgID}"
330
- }
331
- }
332
- """,
333
- },
334
- ],
335
- },
336
- {
337
- "action_patterns": [
338
- "^ssm:StartSession$",
339
- "^ssm:Run.*$",
340
- "^s3:GetObject$",
341
- "^rds-db:Connect$",
342
- ],
343
- "severity": "low",
344
- "required_conditions": [
345
- {
346
- "condition_key": "aws:SourceIp",
347
- "description": "Restrict access to corporate IP ranges",
348
- "example": """"Condition": {
349
- "IpAddress": {
350
- "aws:SourceIp": [
351
- "10.0.0.0/8",
352
- "172.16.0.0/12"
353
- ]
354
- }
355
- }
356
- """,
357
- },
358
- ],
359
- },
360
- {
361
- "actions": ["s3:GetObject", "s3:PutObject"],
362
- "required_conditions": {
363
- "none_of": [
364
- {
365
- "condition_key": "aws:SecureTransport",
366
- "expected_value": False,
367
- "description": "Never allow insecure transport to be explicitly permitted",
368
- "example": """# Set this condition to true to enforce secure transport or remove it entirely
369
- "Condition": {
370
- "Bool": {
371
- "aws:SecureTransport": "true"
372
- }
373
- }
374
- """,
375
- },
376
- ],
377
- },
378
- },
379
- ],
380
- },
381
- }
382
-
383
-
384
- def get_default_config() -> dict:
385
- """
386
- Get a deep copy of the default configuration.
387
-
388
- Returns:
389
- A deep copy of the default configuration dictionary
390
- """
391
- import copy
392
-
393
- return copy.deepcopy(DEFAULT_CONFIG)