iam-policy-validator 1.7.2__py3-none-any.whl → 1.9.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.
- {iam_policy_validator-1.7.2.dist-info → iam_policy_validator-1.9.0.dist-info}/METADATA +127 -6
- iam_policy_validator-1.9.0.dist-info/RECORD +95 -0
- iam_validator/__init__.py +1 -1
- iam_validator/__version__.py +1 -1
- iam_validator/checks/__init__.py +5 -3
- iam_validator/checks/action_condition_enforcement.py +559 -207
- iam_validator/checks/action_resource_matching.py +12 -15
- iam_validator/checks/action_validation.py +7 -13
- iam_validator/checks/condition_key_validation.py +7 -13
- iam_validator/checks/condition_type_mismatch.py +15 -22
- iam_validator/checks/full_wildcard.py +9 -13
- iam_validator/checks/mfa_condition_check.py +8 -17
- iam_validator/checks/policy_size.py +6 -39
- iam_validator/checks/policy_structure.py +547 -0
- iam_validator/checks/policy_type_validation.py +61 -46
- iam_validator/checks/principal_validation.py +71 -148
- iam_validator/checks/resource_validation.py +13 -20
- iam_validator/checks/sensitive_action.py +15 -18
- iam_validator/checks/service_wildcard.py +8 -14
- iam_validator/checks/set_operator_validation.py +21 -28
- iam_validator/checks/sid_uniqueness.py +16 -42
- iam_validator/checks/trust_policy_validation.py +506 -0
- iam_validator/checks/utils/sensitive_action_matcher.py +26 -26
- iam_validator/checks/utils/wildcard_expansion.py +2 -2
- iam_validator/checks/wildcard_action.py +9 -13
- iam_validator/checks/wildcard_resource.py +9 -13
- iam_validator/commands/cache.py +4 -3
- iam_validator/commands/validate.py +15 -9
- iam_validator/core/__init__.py +2 -3
- iam_validator/core/access_analyzer.py +1 -1
- iam_validator/core/access_analyzer_report.py +2 -2
- iam_validator/core/aws_fetcher.py +24 -1028
- iam_validator/core/aws_service/__init__.py +21 -0
- iam_validator/core/aws_service/cache.py +108 -0
- iam_validator/core/aws_service/client.py +205 -0
- iam_validator/core/aws_service/fetcher.py +612 -0
- iam_validator/core/aws_service/parsers.py +149 -0
- iam_validator/core/aws_service/patterns.py +51 -0
- iam_validator/core/aws_service/storage.py +291 -0
- iam_validator/core/aws_service/validators.py +379 -0
- iam_validator/core/check_registry.py +165 -93
- iam_validator/core/config/condition_requirements.py +69 -17
- iam_validator/core/config/defaults.py +58 -52
- iam_validator/core/config/service_principals.py +40 -3
- iam_validator/core/constants.py +17 -0
- iam_validator/core/ignore_patterns.py +297 -0
- iam_validator/core/models.py +15 -5
- iam_validator/core/policy_checks.py +38 -475
- iam_validator/core/policy_loader.py +27 -4
- iam_validator/sdk/__init__.py +1 -1
- iam_validator/sdk/context.py +1 -1
- iam_validator/sdk/helpers.py +1 -1
- iam_policy_validator-1.7.2.dist-info/RECORD +0 -84
- {iam_policy_validator-1.7.2.dist-info → iam_policy_validator-1.9.0.dist-info}/WHEEL +0 -0
- {iam_policy_validator-1.7.2.dist-info → iam_policy_validator-1.9.0.dist-info}/entry_points.txt +0 -0
- {iam_policy_validator-1.7.2.dist-info → iam_policy_validator-1.9.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""Wildcard resource check - detects Resource: '*' in IAM policies."""
|
|
2
2
|
|
|
3
|
+
from typing import ClassVar
|
|
4
|
+
|
|
3
5
|
from iam_validator.checks.utils.wildcard_expansion import expand_wildcard_actions
|
|
4
|
-
from iam_validator.core.
|
|
6
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
5
7
|
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
6
8
|
from iam_validator.core.models import Statement, ValidationIssue
|
|
7
9
|
|
|
@@ -9,17 +11,9 @@ from iam_validator.core.models import Statement, ValidationIssue
|
|
|
9
11
|
class WildcardResourceCheck(PolicyCheck):
|
|
10
12
|
"""Checks for wildcard resources (Resource: '*') which grant access to all resources."""
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@property
|
|
17
|
-
def description(self) -> str:
|
|
18
|
-
return "Checks for wildcard resources (*)"
|
|
19
|
-
|
|
20
|
-
@property
|
|
21
|
-
def default_severity(self) -> str:
|
|
22
|
-
return "medium"
|
|
14
|
+
check_id: ClassVar[str] = "wildcard_resource"
|
|
15
|
+
description: ClassVar[str] = "Checks for wildcard resources (*)"
|
|
16
|
+
default_severity: ClassVar[str] = "medium"
|
|
23
17
|
|
|
24
18
|
async def execute(
|
|
25
19
|
self,
|
|
@@ -62,7 +56,9 @@ class WildcardResourceCheck(PolicyCheck):
|
|
|
62
56
|
return issues
|
|
63
57
|
|
|
64
58
|
# Flag the issue if actions are not all allowed or no allowed_wildcards configured
|
|
65
|
-
message = config.config.get(
|
|
59
|
+
message = config.config.get(
|
|
60
|
+
"message", 'Statement applies to all resources `"*"` (wildcard resource).'
|
|
61
|
+
)
|
|
66
62
|
suggestion = config.config.get(
|
|
67
63
|
"suggestion", "Replace wildcard with specific resource ARNs"
|
|
68
64
|
)
|
iam_validator/commands/cache.py
CHANGED
|
@@ -8,7 +8,8 @@ from rich.console import Console
|
|
|
8
8
|
from rich.table import Table
|
|
9
9
|
|
|
10
10
|
from iam_validator.commands.base import Command
|
|
11
|
-
from iam_validator.core.
|
|
11
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
12
|
+
from iam_validator.core.aws_service.storage import ServiceFileStorage
|
|
12
13
|
from iam_validator.core.config.config_loader import ConfigLoader
|
|
13
14
|
|
|
14
15
|
logger = logging.getLogger(__name__)
|
|
@@ -130,7 +131,7 @@ Examples:
|
|
|
130
131
|
cache_ttl_seconds = cache_ttl_hours * 3600
|
|
131
132
|
|
|
132
133
|
# Get cache directory (even if caching is disabled, for info purposes)
|
|
133
|
-
cache_dir =
|
|
134
|
+
cache_dir = ServiceFileStorage.get_cache_directory(cache_directory)
|
|
134
135
|
|
|
135
136
|
action = args.cache_action
|
|
136
137
|
|
|
@@ -226,7 +227,7 @@ Examples:
|
|
|
226
227
|
services.append({"name": name, "size": size, "file": f.name, "mtime": mtime})
|
|
227
228
|
|
|
228
229
|
# Sort by service name
|
|
229
|
-
services.sort(key=lambda x: x["name"])
|
|
230
|
+
services.sort(key=lambda x: str(x["name"]))
|
|
230
231
|
|
|
231
232
|
if output_format == "table":
|
|
232
233
|
self._print_services_table(services)
|
|
@@ -44,6 +44,9 @@ Examples:
|
|
|
44
44
|
# Use custom checks from a directory
|
|
45
45
|
iam-validator validate --path ./policies/ --custom-checks-dir ./my-checks
|
|
46
46
|
|
|
47
|
+
# Use offline mode with pre-downloaded AWS service definitions
|
|
48
|
+
iam-validator validate --path ./policies/ --aws-services-dir ./aws_services
|
|
49
|
+
|
|
47
50
|
# Generate JSON output
|
|
48
51
|
iam-validator validate --path ./policies/ --format json --output report.json
|
|
49
52
|
|
|
@@ -114,13 +117,17 @@ Examples:
|
|
|
114
117
|
choices=[
|
|
115
118
|
"IDENTITY_POLICY",
|
|
116
119
|
"RESOURCE_POLICY",
|
|
120
|
+
"TRUST_POLICY",
|
|
117
121
|
"SERVICE_CONTROL_POLICY",
|
|
118
122
|
"RESOURCE_CONTROL_POLICY",
|
|
119
123
|
],
|
|
120
124
|
default="IDENTITY_POLICY",
|
|
121
125
|
help="Type of IAM policy being validated (default: IDENTITY_POLICY). "
|
|
122
|
-
"
|
|
123
|
-
"
|
|
126
|
+
"IDENTITY_POLICY: Attached to users/groups/roles | "
|
|
127
|
+
"RESOURCE_POLICY: S3/SNS/SQS policies | "
|
|
128
|
+
"TRUST_POLICY: Role assumption policies | "
|
|
129
|
+
"SERVICE_CONTROL_POLICY: AWS Orgs SCPs | "
|
|
130
|
+
"RESOURCE_CONTROL_POLICY: AWS Orgs RCPs",
|
|
124
131
|
)
|
|
125
132
|
|
|
126
133
|
parser.add_argument(
|
|
@@ -160,9 +167,10 @@ Examples:
|
|
|
160
167
|
)
|
|
161
168
|
|
|
162
169
|
parser.add_argument(
|
|
163
|
-
"--
|
|
164
|
-
|
|
165
|
-
|
|
170
|
+
"--aws-services-dir",
|
|
171
|
+
help="Path to directory containing pre-downloaded AWS service definitions "
|
|
172
|
+
"(enables offline mode, avoids API rate limiting). "
|
|
173
|
+
"Use 'iam-validator download-services' to create this directory.",
|
|
166
174
|
)
|
|
167
175
|
|
|
168
176
|
parser.add_argument(
|
|
@@ -242,16 +250,16 @@ Examples:
|
|
|
242
250
|
logging.info(f"Loaded {len(policies)} policies from {len(args.paths)} path(s)")
|
|
243
251
|
|
|
244
252
|
# Validate policies
|
|
245
|
-
use_registry = not getattr(args, "no_registry", False)
|
|
246
253
|
config_path = getattr(args, "config", None)
|
|
247
254
|
custom_checks_dir = getattr(args, "custom_checks_dir", None)
|
|
255
|
+
aws_services_dir = getattr(args, "aws_services_dir", None)
|
|
248
256
|
policy_type = cast(PolicyType, getattr(args, "policy_type", "IDENTITY_POLICY"))
|
|
249
257
|
results = await validate_policies(
|
|
250
258
|
policies,
|
|
251
259
|
config_path=config_path,
|
|
252
|
-
use_registry=use_registry,
|
|
253
260
|
custom_checks_dir=custom_checks_dir,
|
|
254
261
|
policy_type=policy_type,
|
|
262
|
+
aws_services_dir=aws_services_dir,
|
|
255
263
|
)
|
|
256
264
|
|
|
257
265
|
# Generate report (include parsing errors if any)
|
|
@@ -329,7 +337,6 @@ Examples:
|
|
|
329
337
|
"""
|
|
330
338
|
loader = PolicyLoader()
|
|
331
339
|
generator = ReportGenerator()
|
|
332
|
-
use_registry = not getattr(args, "no_registry", False)
|
|
333
340
|
config_path = getattr(args, "config", None)
|
|
334
341
|
custom_checks_dir = getattr(args, "custom_checks_dir", None)
|
|
335
342
|
policy_type = cast(PolicyType, getattr(args, "policy_type", "IDENTITY_POLICY"))
|
|
@@ -354,7 +361,6 @@ Examples:
|
|
|
354
361
|
results = await validate_policies(
|
|
355
362
|
[(file_path, policy)],
|
|
356
363
|
config_path=config_path,
|
|
357
|
-
use_registry=use_registry,
|
|
358
364
|
custom_checks_dir=custom_checks_dir,
|
|
359
365
|
policy_type=policy_type,
|
|
360
366
|
)
|
iam_validator/core/__init__.py
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
"""Core validation modules."""
|
|
2
2
|
|
|
3
|
-
from iam_validator.core.
|
|
4
|
-
from iam_validator.core.policy_checks import
|
|
3
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
4
|
+
from iam_validator.core.policy_checks import validate_policies
|
|
5
5
|
from iam_validator.core.policy_loader import PolicyLoader
|
|
6
6
|
from iam_validator.core.report import ReportGenerator
|
|
7
7
|
|
|
8
8
|
__all__ = [
|
|
9
9
|
"AWSServiceFetcher",
|
|
10
|
-
"PolicyValidator",
|
|
11
10
|
"validate_policies",
|
|
12
11
|
"PolicyLoader",
|
|
13
12
|
"ReportGenerator",
|
|
@@ -577,7 +577,7 @@ class AccessAnalyzerValidator:
|
|
|
577
577
|
)
|
|
578
578
|
results.append(result)
|
|
579
579
|
|
|
580
|
-
except Exception as e:
|
|
580
|
+
except Exception as e: # pylint: disable=broad-exception-caught
|
|
581
581
|
self.logger.error(f"Failed to validate {policy_file}: {e}")
|
|
582
582
|
result = AccessAnalyzerResult(
|
|
583
583
|
policy_file=policy_file,
|
|
@@ -259,7 +259,7 @@ class AccessAnalyzerReportFormatter:
|
|
|
259
259
|
file_path: Path to save JSON report
|
|
260
260
|
"""
|
|
261
261
|
json_content = self.generate_json_report(report)
|
|
262
|
-
with open(file_path, "w") as f:
|
|
262
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
263
263
|
f.write(json_content)
|
|
264
264
|
|
|
265
265
|
def generate_markdown_report(
|
|
@@ -636,5 +636,5 @@ class AccessAnalyzerReportFormatter:
|
|
|
636
636
|
file_path: Path to save Markdown report
|
|
637
637
|
"""
|
|
638
638
|
markdown_content = self.generate_markdown_report(report)
|
|
639
|
-
with open(file_path, "w") as f:
|
|
639
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
640
640
|
f.write(markdown_content)
|