iam-policy-validator 1.1.0__py3-none-any.whl → 1.1.1__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.
Potentially problematic release.
This version of iam-policy-validator might be problematic. Click here for more details.
- {iam_policy_validator-1.1.0.dist-info → iam_policy_validator-1.1.1.dist-info}/METADATA +2 -2
- {iam_policy_validator-1.1.0.dist-info → iam_policy_validator-1.1.1.dist-info}/RECORD +25 -19
- iam_validator/__version__.py +1 -1
- iam_validator/checks/__init__.py +2 -0
- iam_validator/checks/action_resource_constraint.py +151 -0
- iam_validator/checks/action_validation.py +18 -138
- iam_validator/checks/security_best_practices.py +152 -402
- iam_validator/checks/utils/__init__.py +1 -0
- iam_validator/checks/utils/policy_level_checks.py +143 -0
- iam_validator/checks/utils/sensitive_action_matcher.py +252 -0
- iam_validator/checks/utils/wildcard_expansion.py +89 -0
- iam_validator/commands/__init__.py +3 -1
- iam_validator/commands/cache.py +402 -0
- iam_validator/core/access_analyzer_report.py +2 -1
- iam_validator/core/aws_fetcher.py +79 -19
- iam_validator/core/check_registry.py +3 -0
- iam_validator/core/cli.py +1 -1
- iam_validator/core/config_loader.py +1 -0
- iam_validator/core/defaults.py +103 -73
- iam_validator/core/formatters/enhanced.py +6 -1
- iam_validator/core/policy_checks.py +21 -2
- iam_validator/core/report.py +8 -1
- {iam_policy_validator-1.1.0.dist-info → iam_policy_validator-1.1.1.dist-info}/WHEEL +0 -0
- {iam_policy_validator-1.1.0.dist-info → iam_policy_validator-1.1.1.dist-info}/entry_points.txt +0 -0
- {iam_policy_validator-1.1.0.dist-info → iam_policy_validator-1.1.1.dist-info}/licenses/LICENSE +0 -0
iam_validator/core/defaults.py
CHANGED
|
@@ -37,8 +37,7 @@ DEFAULT_CONFIG = {
|
|
|
37
37
|
"enable_builtin_checks": True,
|
|
38
38
|
"parallel_execution": True,
|
|
39
39
|
"cache_enabled": True,
|
|
40
|
-
"
|
|
41
|
-
"cache_ttl_hours": 24,
|
|
40
|
+
"cache_ttl_hours": 168,
|
|
42
41
|
"fail_on_severity": ["error", "critical"],
|
|
43
42
|
},
|
|
44
43
|
"sid_uniqueness_check": {
|
|
@@ -56,12 +55,11 @@ DEFAULT_CONFIG = {
|
|
|
56
55
|
"enabled": True,
|
|
57
56
|
"severity": "error",
|
|
58
57
|
"description": "Validates that actions exist in AWS services",
|
|
59
|
-
"disable_wildcard_warnings": True,
|
|
60
58
|
},
|
|
61
59
|
"condition_key_validation_check": {
|
|
62
60
|
"enabled": True,
|
|
63
61
|
"severity": "error",
|
|
64
|
-
"description": "Validates condition keys against AWS service definitions",
|
|
62
|
+
"description": "Validates condition keys against AWS service definitions for specified actions",
|
|
65
63
|
"validate_aws_global_keys": True,
|
|
66
64
|
},
|
|
67
65
|
"resource_validation_check": {
|
|
@@ -70,9 +68,41 @@ DEFAULT_CONFIG = {
|
|
|
70
68
|
"description": "Validates ARN format for resources",
|
|
71
69
|
"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*]*:.+$",
|
|
72
70
|
},
|
|
71
|
+
"action_resource_constraint_check": {
|
|
72
|
+
"enabled": True,
|
|
73
|
+
"severity": "error",
|
|
74
|
+
"description": "Validates that actions without required resource types use Resource: '*'",
|
|
75
|
+
},
|
|
73
76
|
"security_best_practices_check": {
|
|
74
77
|
"enabled": True,
|
|
75
78
|
"description": "Checks for common security anti-patterns",
|
|
79
|
+
"allowed_wildcards": [
|
|
80
|
+
"autoscaling:Describe*",
|
|
81
|
+
"cloudwatch:Describe*",
|
|
82
|
+
"cloudwatch:Get*",
|
|
83
|
+
"cloudwatch:List*",
|
|
84
|
+
"dynamodb:Describe*",
|
|
85
|
+
"ec2:Describe*",
|
|
86
|
+
"elasticloadbalancing:Describe*",
|
|
87
|
+
"iam:Get*",
|
|
88
|
+
"iam:List*",
|
|
89
|
+
"kms:Describe*",
|
|
90
|
+
"lambda:Get*",
|
|
91
|
+
"lambda:List*",
|
|
92
|
+
"logs:Describe*",
|
|
93
|
+
"logs:Filter*",
|
|
94
|
+
"logs:Get*",
|
|
95
|
+
"rds:Describe*",
|
|
96
|
+
"route53:Get*",
|
|
97
|
+
"route53:List*",
|
|
98
|
+
"s3:Describe*",
|
|
99
|
+
"s3:GetBucket*",
|
|
100
|
+
"s3:GetM*",
|
|
101
|
+
"s3:List*",
|
|
102
|
+
"sqs:Get*",
|
|
103
|
+
"sqs:List*",
|
|
104
|
+
"apigateway:GET",
|
|
105
|
+
],
|
|
76
106
|
"wildcard_action_check": {
|
|
77
107
|
"enabled": True,
|
|
78
108
|
"severity": "medium",
|
|
@@ -126,29 +156,83 @@ With specific values:
|
|
|
126
156
|
"service_wildcard_check": {
|
|
127
157
|
"enabled": True,
|
|
128
158
|
"severity": "high",
|
|
129
|
-
"allowed_services": ["logs", "cloudwatch"],
|
|
159
|
+
"allowed_services": ["logs", "cloudwatch", "xray"],
|
|
130
160
|
},
|
|
131
161
|
"sensitive_action_check": {
|
|
132
162
|
"enabled": True,
|
|
133
163
|
"severity": "medium",
|
|
134
164
|
"sensitive_actions": [
|
|
135
|
-
"iam:
|
|
136
|
-
"iam:CreateRole",
|
|
137
|
-
"iam:PutUserPolicy",
|
|
138
|
-
"iam:PutRolePolicy",
|
|
139
|
-
"iam:AttachUserPolicy",
|
|
165
|
+
"iam:AddClientIDToOpenIDConnectProvider",
|
|
140
166
|
"iam:AttachRolePolicy",
|
|
167
|
+
"iam:AttachUserPolicy",
|
|
141
168
|
"iam:CreateAccessKey",
|
|
142
|
-
"iam:
|
|
169
|
+
"iam:CreateOpenIDConnectProvider",
|
|
170
|
+
"iam:CreatePolicyVersion",
|
|
171
|
+
"iam:CreateRole",
|
|
172
|
+
"iam:CreateSAMLProvider",
|
|
173
|
+
"iam:CreateUser",
|
|
174
|
+
"iam:DeleteAccessKey",
|
|
175
|
+
"iam:DeleteLoginProfile",
|
|
176
|
+
"iam:DeleteOpenIDConnectProvider",
|
|
143
177
|
"iam:DeleteRole",
|
|
144
|
-
"
|
|
145
|
-
"
|
|
146
|
-
"
|
|
147
|
-
"
|
|
178
|
+
"iam:DeleteRolePolicy",
|
|
179
|
+
"iam:DeleteSAMLProvider",
|
|
180
|
+
"iam:DeleteUser",
|
|
181
|
+
"iam:DeleteUserPolicy",
|
|
182
|
+
"iam:DetachRolePolicy",
|
|
183
|
+
"iam:DetachUserPolicy",
|
|
184
|
+
"iam:PutRolePolicy",
|
|
185
|
+
"iam:PutUserPolicy",
|
|
186
|
+
"iam:SetDefaultPolicyVersion",
|
|
187
|
+
"iam:UpdateAccessKey",
|
|
188
|
+
"iam:UpdateAssumeRolePolicy",
|
|
189
|
+
"kms:DisableKey",
|
|
190
|
+
"kms:PutKeyPolicy",
|
|
191
|
+
"kms:ScheduleKeyDeletion",
|
|
192
|
+
"secretsmanager:DeleteSecret",
|
|
193
|
+
"secretsmanager:GetSecretValue",
|
|
194
|
+
"secretsmanager:PutSecretValue",
|
|
195
|
+
"ssm:DeleteParameter",
|
|
196
|
+
"ssm:PutParameter",
|
|
197
|
+
"ec2:DeleteSnapshot",
|
|
148
198
|
"ec2:DeleteVolume",
|
|
149
|
-
"
|
|
150
|
-
"
|
|
199
|
+
"ec2:DeleteVpc",
|
|
200
|
+
"ec2:ModifyInstanceAttribute",
|
|
201
|
+
"ec2:TerminateInstances",
|
|
202
|
+
"ecr:DeleteRepository",
|
|
203
|
+
"ecs:DeleteCluster",
|
|
204
|
+
"ecs:DeleteService",
|
|
151
205
|
"eks:DeleteCluster",
|
|
206
|
+
"lambda:DeleteFunction",
|
|
207
|
+
"lambda:DeleteFunctionConcurrency",
|
|
208
|
+
"lambda:PutFunctionConcurrency",
|
|
209
|
+
"dynamodb:DeleteTable",
|
|
210
|
+
"efs:DeleteFileSystem",
|
|
211
|
+
"elasticache:DeleteCacheCluster",
|
|
212
|
+
"fsx:DeleteFileSystem",
|
|
213
|
+
"rds:DeleteDBCluster",
|
|
214
|
+
"rds:DeleteDBInstance",
|
|
215
|
+
"redshift:DeleteCluster",
|
|
216
|
+
"backup:DeleteBackupVault",
|
|
217
|
+
"glacier:DeleteArchive",
|
|
218
|
+
"s3:DeleteBucket",
|
|
219
|
+
"s3:DeleteBucketPolicy",
|
|
220
|
+
"s3:DeleteObject",
|
|
221
|
+
"s3:PutBucketPolicy",
|
|
222
|
+
"s3:PutLifecycleConfiguration",
|
|
223
|
+
"ec2:AuthorizeSecurityGroupIngress",
|
|
224
|
+
"ec2:DeleteSecurityGroup",
|
|
225
|
+
"ec2:DisassociateRouteTable",
|
|
226
|
+
"ec2:RevokeSecurityGroupEgress",
|
|
227
|
+
"cloudtrail:DeleteTrail",
|
|
228
|
+
"cloudtrail:StopLogging",
|
|
229
|
+
"cloudwatch:DeleteLogGroup",
|
|
230
|
+
"config:DeleteConfigurationRecorder",
|
|
231
|
+
"guardduty:DeleteDetector",
|
|
232
|
+
"account:CloseAccount",
|
|
233
|
+
"account:CreateAccount",
|
|
234
|
+
"organizations:LeaveOrganization",
|
|
235
|
+
"organizations:RemoveAccountFromOrganization",
|
|
152
236
|
],
|
|
153
237
|
"sensitive_action_patterns": ["^iam:Delete.*"],
|
|
154
238
|
},
|
|
@@ -209,25 +293,14 @@ With specific values:
|
|
|
209
293
|
},
|
|
210
294
|
],
|
|
211
295
|
},
|
|
212
|
-
{
|
|
213
|
-
"actions": ["s3:DeleteBucket", "s3:DeleteBucketPolicy", "s3:PutBucketPolicy"],
|
|
214
|
-
"severity": "high",
|
|
215
|
-
"required_conditions": [
|
|
216
|
-
{
|
|
217
|
-
"condition_key": "aws:MultiFactorAuthPresent",
|
|
218
|
-
"description": "Require MFA for S3 destructive operations",
|
|
219
|
-
"expected_value": True,
|
|
220
|
-
},
|
|
221
|
-
],
|
|
222
|
-
},
|
|
223
296
|
{
|
|
224
297
|
"action_patterns": [
|
|
225
298
|
"^ssm:StartSession$",
|
|
226
299
|
"^ssm:Run.*$",
|
|
227
300
|
"^s3:GetObject$",
|
|
228
|
-
"^rds
|
|
301
|
+
"^rds-db:Connect$",
|
|
229
302
|
],
|
|
230
|
-
"severity": "
|
|
303
|
+
"severity": "low",
|
|
231
304
|
"required_conditions": [
|
|
232
305
|
{
|
|
233
306
|
"condition_key": "aws:SourceIp",
|
|
@@ -244,49 +317,6 @@ With specific values:
|
|
|
244
317
|
},
|
|
245
318
|
],
|
|
246
319
|
},
|
|
247
|
-
{
|
|
248
|
-
"actions": ["ec2:RunInstances"],
|
|
249
|
-
"required_conditions": {
|
|
250
|
-
"all_of": [
|
|
251
|
-
{
|
|
252
|
-
"condition_key": "aws:ResourceTag/owner",
|
|
253
|
-
"operator": "StringEquals",
|
|
254
|
-
"expected_value": "${aws:PrincipalTag/owner}",
|
|
255
|
-
"description": "Resource owner must match the principal's owner tag",
|
|
256
|
-
},
|
|
257
|
-
{
|
|
258
|
-
"condition_key": "aws:RequestTag/env",
|
|
259
|
-
"operator": "StringEquals",
|
|
260
|
-
"expected_value": [
|
|
261
|
-
"prod",
|
|
262
|
-
"pre",
|
|
263
|
-
"dev",
|
|
264
|
-
"sandbox",
|
|
265
|
-
],
|
|
266
|
-
"description": "Must specify a valid Environment tag",
|
|
267
|
-
},
|
|
268
|
-
],
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
"action_patterns": ["^rds:Create.*", "^rds:Modify.*"],
|
|
273
|
-
"required_conditions": {
|
|
274
|
-
"all_of": [
|
|
275
|
-
{
|
|
276
|
-
"condition_key": "aws:RequestTag/DataClassification",
|
|
277
|
-
"description": "Must specify data classification",
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
"condition_key": "aws:RequestTag/BackupPolicy",
|
|
281
|
-
"description": "Must specify backup policy",
|
|
282
|
-
},
|
|
283
|
-
{
|
|
284
|
-
"condition_key": "aws:RequestTag/Owner",
|
|
285
|
-
"description": "Must specify resource owner",
|
|
286
|
-
},
|
|
287
|
-
],
|
|
288
|
-
},
|
|
289
|
-
},
|
|
290
320
|
],
|
|
291
321
|
},
|
|
292
322
|
}
|
|
@@ -9,6 +9,7 @@ from rich.table import Table
|
|
|
9
9
|
from rich.text import Text
|
|
10
10
|
from rich.tree import Tree
|
|
11
11
|
|
|
12
|
+
from iam_validator.__version__ import __version__
|
|
12
13
|
from iam_validator.core.formatters.base import OutputFormatter
|
|
13
14
|
from iam_validator.core.models import PolicyValidationResult, ValidationReport
|
|
14
15
|
|
|
@@ -49,7 +50,11 @@ class EnhancedFormatter(OutputFormatter):
|
|
|
49
50
|
|
|
50
51
|
# Header with title
|
|
51
52
|
console.print()
|
|
52
|
-
title = Text(
|
|
53
|
+
title = Text(
|
|
54
|
+
f"IAM Policy Validation Report (v{__version__})",
|
|
55
|
+
style="bold cyan",
|
|
56
|
+
justify="center",
|
|
57
|
+
)
|
|
53
58
|
console.print(Panel(title, border_style="bright_blue", padding=(1, 0)))
|
|
54
59
|
console.print()
|
|
55
60
|
|
|
@@ -474,7 +474,18 @@ async def validate_policies(
|
|
|
474
474
|
"""
|
|
475
475
|
if not use_registry:
|
|
476
476
|
# Legacy path - use old PolicyValidator
|
|
477
|
-
|
|
477
|
+
# Load config for cache settings even in legacy mode
|
|
478
|
+
from iam_validator.core.config_loader import ConfigLoader
|
|
479
|
+
|
|
480
|
+
config = ConfigLoader.load_config(explicit_path=config_path, allow_missing=True)
|
|
481
|
+
cache_enabled = config.get_setting("cache_enabled", True)
|
|
482
|
+
cache_ttl_hours = config.get_setting("cache_ttl_hours", 168)
|
|
483
|
+
cache_directory = config.get_setting("cache_directory", None)
|
|
484
|
+
cache_ttl_seconds = cache_ttl_hours * 3600
|
|
485
|
+
|
|
486
|
+
async with AWSServiceFetcher(
|
|
487
|
+
enable_cache=cache_enabled, cache_ttl=cache_ttl_seconds, cache_dir=cache_directory
|
|
488
|
+
) as fetcher:
|
|
478
489
|
validator = PolicyValidator(fetcher)
|
|
479
490
|
|
|
480
491
|
tasks = [validator.validate_policy(policy, file_path) for file_path, policy in policies]
|
|
@@ -530,8 +541,16 @@ async def validate_policies(
|
|
|
530
541
|
# Get fail_on_severity setting from config
|
|
531
542
|
fail_on_severities = config.get_setting("fail_on_severity", ["error"])
|
|
532
543
|
|
|
544
|
+
# Get cache settings from config
|
|
545
|
+
cache_enabled = config.get_setting("cache_enabled", True)
|
|
546
|
+
cache_ttl_hours = config.get_setting("cache_ttl_hours", 168) # 7 days default
|
|
547
|
+
cache_directory = config.get_setting("cache_directory", None)
|
|
548
|
+
cache_ttl_seconds = cache_ttl_hours * 3600
|
|
549
|
+
|
|
533
550
|
# Validate policies using registry
|
|
534
|
-
async with AWSServiceFetcher(
|
|
551
|
+
async with AWSServiceFetcher(
|
|
552
|
+
enable_cache=cache_enabled, cache_ttl=cache_ttl_seconds, cache_dir=cache_directory
|
|
553
|
+
) as fetcher:
|
|
535
554
|
tasks = [
|
|
536
555
|
_validate_policy_with_registry(policy, file_path, registry, fetcher, fail_on_severities)
|
|
537
556
|
for file_path, policy in policies
|
iam_validator/core/report.py
CHANGED
|
@@ -11,6 +11,7 @@ from rich.panel import Panel
|
|
|
11
11
|
from rich.table import Table
|
|
12
12
|
from rich.text import Text
|
|
13
13
|
|
|
14
|
+
from iam_validator.__version__ import __version__
|
|
14
15
|
from iam_validator.core.formatters import (
|
|
15
16
|
ConsoleFormatter,
|
|
16
17
|
CSVFormatter,
|
|
@@ -143,7 +144,13 @@ class ReportGenerator:
|
|
|
143
144
|
summary_text.append(")")
|
|
144
145
|
summary_text.append("\n")
|
|
145
146
|
|
|
146
|
-
self.console.print(
|
|
147
|
+
self.console.print(
|
|
148
|
+
Panel(
|
|
149
|
+
summary_text,
|
|
150
|
+
title=f"Validation Summary (iam-validator v{__version__})",
|
|
151
|
+
border_style="blue",
|
|
152
|
+
)
|
|
153
|
+
)
|
|
147
154
|
|
|
148
155
|
# Detailed results
|
|
149
156
|
for result in report.results:
|
|
File without changes
|
{iam_policy_validator-1.1.0.dist-info → iam_policy_validator-1.1.1.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{iam_policy_validator-1.1.0.dist-info → iam_policy_validator-1.1.1.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|