iam-policy-validator 1.7.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.
Potentially problematic release.
This version of iam-policy-validator might be problematic. Click here for more details.
- iam_policy_validator-1.7.0.dist-info/METADATA +1057 -0
- iam_policy_validator-1.7.0.dist-info/RECORD +83 -0
- iam_policy_validator-1.7.0.dist-info/WHEEL +4 -0
- iam_policy_validator-1.7.0.dist-info/entry_points.txt +2 -0
- iam_policy_validator-1.7.0.dist-info/licenses/LICENSE +21 -0
- iam_validator/__init__.py +27 -0
- iam_validator/__main__.py +11 -0
- iam_validator/__version__.py +7 -0
- iam_validator/checks/__init__.py +43 -0
- iam_validator/checks/action_condition_enforcement.py +884 -0
- iam_validator/checks/action_resource_matching.py +441 -0
- iam_validator/checks/action_validation.py +72 -0
- iam_validator/checks/condition_key_validation.py +92 -0
- iam_validator/checks/condition_type_mismatch.py +259 -0
- iam_validator/checks/full_wildcard.py +71 -0
- iam_validator/checks/mfa_condition_check.py +112 -0
- iam_validator/checks/policy_size.py +147 -0
- iam_validator/checks/policy_type_validation.py +305 -0
- iam_validator/checks/principal_validation.py +776 -0
- iam_validator/checks/resource_validation.py +138 -0
- iam_validator/checks/sensitive_action.py +254 -0
- iam_validator/checks/service_wildcard.py +107 -0
- iam_validator/checks/set_operator_validation.py +157 -0
- iam_validator/checks/sid_uniqueness.py +170 -0
- 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 +294 -0
- iam_validator/checks/utils/wildcard_expansion.py +87 -0
- iam_validator/checks/wildcard_action.py +67 -0
- iam_validator/checks/wildcard_resource.py +135 -0
- iam_validator/commands/__init__.py +25 -0
- iam_validator/commands/analyze.py +531 -0
- iam_validator/commands/base.py +48 -0
- iam_validator/commands/cache.py +392 -0
- iam_validator/commands/download_services.py +255 -0
- iam_validator/commands/post_to_pr.py +86 -0
- iam_validator/commands/validate.py +600 -0
- iam_validator/core/__init__.py +14 -0
- iam_validator/core/access_analyzer.py +671 -0
- iam_validator/core/access_analyzer_report.py +640 -0
- iam_validator/core/aws_fetcher.py +940 -0
- iam_validator/core/check_registry.py +607 -0
- iam_validator/core/cli.py +134 -0
- iam_validator/core/condition_validators.py +626 -0
- iam_validator/core/config/__init__.py +81 -0
- iam_validator/core/config/aws_api.py +35 -0
- iam_validator/core/config/aws_global_conditions.py +160 -0
- iam_validator/core/config/category_suggestions.py +104 -0
- iam_validator/core/config/condition_requirements.py +155 -0
- iam_validator/core/config/config_loader.py +472 -0
- iam_validator/core/config/defaults.py +523 -0
- iam_validator/core/config/principal_requirements.py +421 -0
- iam_validator/core/config/sensitive_actions.py +672 -0
- iam_validator/core/config/service_principals.py +95 -0
- iam_validator/core/config/wildcards.py +124 -0
- iam_validator/core/constants.py +74 -0
- iam_validator/core/formatters/__init__.py +27 -0
- iam_validator/core/formatters/base.py +147 -0
- iam_validator/core/formatters/console.py +59 -0
- iam_validator/core/formatters/csv.py +170 -0
- iam_validator/core/formatters/enhanced.py +440 -0
- iam_validator/core/formatters/html.py +672 -0
- iam_validator/core/formatters/json.py +33 -0
- iam_validator/core/formatters/markdown.py +63 -0
- iam_validator/core/formatters/sarif.py +251 -0
- iam_validator/core/models.py +327 -0
- iam_validator/core/policy_checks.py +656 -0
- iam_validator/core/policy_loader.py +396 -0
- iam_validator/core/pr_commenter.py +424 -0
- iam_validator/core/report.py +872 -0
- iam_validator/integrations/__init__.py +28 -0
- iam_validator/integrations/github_integration.py +815 -0
- iam_validator/integrations/ms_teams.py +442 -0
- iam_validator/sdk/__init__.py +187 -0
- iam_validator/sdk/arn_matching.py +382 -0
- iam_validator/sdk/context.py +222 -0
- iam_validator/sdk/exceptions.py +48 -0
- iam_validator/sdk/helpers.py +177 -0
- iam_validator/sdk/policy_utils.py +425 -0
- iam_validator/sdk/shortcuts.py +283 -0
- iam_validator/utils/__init__.py +31 -0
- iam_validator/utils/cache.py +105 -0
- iam_validator/utils/regex.py +206 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Wildcard action check - detects Action: '*' in IAM policies."""
|
|
2
|
+
|
|
3
|
+
from iam_validator.core.aws_fetcher import AWSServiceFetcher
|
|
4
|
+
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
5
|
+
from iam_validator.core.models import Statement, ValidationIssue
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class WildcardActionCheck(PolicyCheck):
|
|
9
|
+
"""Checks for wildcard actions (Action: '*') which grant all permissions."""
|
|
10
|
+
|
|
11
|
+
@property
|
|
12
|
+
def check_id(self) -> str:
|
|
13
|
+
return "wildcard_action"
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def description(self) -> str:
|
|
17
|
+
return "Checks for wildcard actions (*)"
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def default_severity(self) -> str:
|
|
21
|
+
return "medium"
|
|
22
|
+
|
|
23
|
+
async def execute(
|
|
24
|
+
self,
|
|
25
|
+
statement: Statement,
|
|
26
|
+
statement_idx: int,
|
|
27
|
+
fetcher: AWSServiceFetcher,
|
|
28
|
+
config: CheckConfig,
|
|
29
|
+
) -> list[ValidationIssue]:
|
|
30
|
+
"""Execute wildcard action check on a statement."""
|
|
31
|
+
issues = []
|
|
32
|
+
|
|
33
|
+
# Only check Allow statements
|
|
34
|
+
if statement.effect != "Allow":
|
|
35
|
+
return issues
|
|
36
|
+
|
|
37
|
+
actions = statement.get_actions()
|
|
38
|
+
|
|
39
|
+
# Check for wildcard action (Action: "*")
|
|
40
|
+
if "*" in actions:
|
|
41
|
+
message = config.config.get("message", "Statement allows all actions (*)")
|
|
42
|
+
suggestion_text = config.config.get(
|
|
43
|
+
"suggestion",
|
|
44
|
+
"Replace wildcard with specific actions needed for your use case",
|
|
45
|
+
)
|
|
46
|
+
example = config.config.get("example", "")
|
|
47
|
+
|
|
48
|
+
# Combine suggestion + example
|
|
49
|
+
suggestion = (
|
|
50
|
+
f"{suggestion_text}\nExample:\n```json\n{example}\n```"
|
|
51
|
+
if example
|
|
52
|
+
else suggestion_text
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
issues.append(
|
|
56
|
+
ValidationIssue(
|
|
57
|
+
severity=self.get_severity(config),
|
|
58
|
+
statement_sid=statement.sid,
|
|
59
|
+
statement_index=statement_idx,
|
|
60
|
+
issue_type="overly_permissive",
|
|
61
|
+
message=message,
|
|
62
|
+
suggestion=suggestion,
|
|
63
|
+
line_number=statement.line_number,
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return issues
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Wildcard resource check - detects Resource: '*' in IAM policies."""
|
|
2
|
+
|
|
3
|
+
from iam_validator.checks.utils.wildcard_expansion import expand_wildcard_actions
|
|
4
|
+
from iam_validator.core.aws_fetcher import AWSServiceFetcher
|
|
5
|
+
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
6
|
+
from iam_validator.core.models import Statement, ValidationIssue
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WildcardResourceCheck(PolicyCheck):
|
|
10
|
+
"""Checks for wildcard resources (Resource: '*') which grant access to all resources."""
|
|
11
|
+
|
|
12
|
+
@property
|
|
13
|
+
def check_id(self) -> str:
|
|
14
|
+
return "wildcard_resource"
|
|
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"
|
|
23
|
+
|
|
24
|
+
async def execute(
|
|
25
|
+
self,
|
|
26
|
+
statement: Statement,
|
|
27
|
+
statement_idx: int,
|
|
28
|
+
fetcher: AWSServiceFetcher,
|
|
29
|
+
config: CheckConfig,
|
|
30
|
+
) -> list[ValidationIssue]:
|
|
31
|
+
"""Execute wildcard resource check on a statement."""
|
|
32
|
+
issues = []
|
|
33
|
+
|
|
34
|
+
# Only check Allow statements
|
|
35
|
+
if statement.effect != "Allow":
|
|
36
|
+
return issues
|
|
37
|
+
|
|
38
|
+
actions = statement.get_actions()
|
|
39
|
+
resources = statement.get_resources()
|
|
40
|
+
|
|
41
|
+
# Check for wildcard resource (Resource: "*")
|
|
42
|
+
if "*" in resources:
|
|
43
|
+
# Check if all actions are in the allowed_wildcards list
|
|
44
|
+
# allowed_wildcards works by expanding wildcard patterns (like "ec2:Describe*")
|
|
45
|
+
# to all matching AWS actions using the AWS API, then checking if the policy's
|
|
46
|
+
# actions are in that expanded list. This ensures only validated AWS actions
|
|
47
|
+
# are allowed with Resource: "*".
|
|
48
|
+
allowed_wildcards_expanded = await self._get_expanded_allowed_wildcards(config, fetcher)
|
|
49
|
+
|
|
50
|
+
# Check if ALL actions (excluding full wildcard "*") are in the expanded list
|
|
51
|
+
non_wildcard_actions = [a for a in actions if a != "*"]
|
|
52
|
+
|
|
53
|
+
if allowed_wildcards_expanded and non_wildcard_actions:
|
|
54
|
+
# Check if all actions are in the expanded allowed list (exact match)
|
|
55
|
+
all_actions_allowed = all(
|
|
56
|
+
action in allowed_wildcards_expanded for action in non_wildcard_actions
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# If all actions are in the expanded list, skip the wildcard resource warning
|
|
60
|
+
if all_actions_allowed:
|
|
61
|
+
# All actions are safe, Resource: "*" is acceptable
|
|
62
|
+
return issues
|
|
63
|
+
|
|
64
|
+
# Flag the issue if actions are not all allowed or no allowed_wildcards configured
|
|
65
|
+
message = config.config.get("message", "Statement applies to all resources (*)")
|
|
66
|
+
suggestion_text = config.config.get(
|
|
67
|
+
"suggestion", "Replace wildcard with specific resource ARNs"
|
|
68
|
+
)
|
|
69
|
+
example = config.config.get("example", "")
|
|
70
|
+
|
|
71
|
+
# Combine suggestion + example
|
|
72
|
+
suggestion = (
|
|
73
|
+
f"{suggestion_text}\nExample:\n```json\n{example}\n```"
|
|
74
|
+
if example
|
|
75
|
+
else suggestion_text
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
issues.append(
|
|
79
|
+
ValidationIssue(
|
|
80
|
+
severity=self.get_severity(config),
|
|
81
|
+
statement_sid=statement.sid,
|
|
82
|
+
statement_index=statement_idx,
|
|
83
|
+
issue_type="overly_permissive",
|
|
84
|
+
message=message,
|
|
85
|
+
suggestion=suggestion,
|
|
86
|
+
line_number=statement.line_number,
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
return issues
|
|
91
|
+
|
|
92
|
+
async def _get_expanded_allowed_wildcards(
|
|
93
|
+
self, config: CheckConfig, fetcher: AWSServiceFetcher
|
|
94
|
+
) -> frozenset[str]:
|
|
95
|
+
"""Get and expand allowed_wildcards configuration.
|
|
96
|
+
|
|
97
|
+
This method retrieves wildcard patterns from the allowed_wildcards config
|
|
98
|
+
and expands them using the AWS API to get all matching actual AWS actions.
|
|
99
|
+
|
|
100
|
+
How it works:
|
|
101
|
+
1. Retrieves patterns from config (e.g., ["ec2:Describe*", "s3:List*"])
|
|
102
|
+
2. Expands each pattern using AWS API:
|
|
103
|
+
- "ec2:Describe*" → ["ec2:DescribeInstances", "ec2:DescribeImages", ...]
|
|
104
|
+
- "s3:List*" → ["s3:ListBucket", "s3:ListObjects", ...]
|
|
105
|
+
3. Returns a set of all expanded actions
|
|
106
|
+
|
|
107
|
+
This allows you to:
|
|
108
|
+
- Specify patterns like "ec2:Describe*" in config
|
|
109
|
+
- Have the validator allow specific actions like "ec2:DescribeInstances" with Resource: "*"
|
|
110
|
+
- Ensure only real AWS actions (validated via API) are allowed
|
|
111
|
+
|
|
112
|
+
Example:
|
|
113
|
+
Config: allowed_wildcards: ["ec2:Describe*"]
|
|
114
|
+
Expands to: ["ec2:DescribeInstances", "ec2:DescribeImages", ...]
|
|
115
|
+
Policy: "Action": ["ec2:DescribeInstances"], "Resource": "*"
|
|
116
|
+
Result: ✅ Allowed (ec2:DescribeInstances is in expanded list)
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
config: The check configuration
|
|
120
|
+
fetcher: AWS service fetcher for expanding wildcards via AWS API
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
A frozenset of all expanded action names from the configured patterns
|
|
124
|
+
"""
|
|
125
|
+
patterns_to_expand = config.config.get("allowed_wildcards", [])
|
|
126
|
+
|
|
127
|
+
# If no patterns configured, return empty set
|
|
128
|
+
if not patterns_to_expand or not isinstance(patterns_to_expand, list):
|
|
129
|
+
return frozenset()
|
|
130
|
+
|
|
131
|
+
# Expand the wildcard patterns using the AWS API
|
|
132
|
+
# This converts patterns like "ec2:Describe*" to actual AWS actions
|
|
133
|
+
expanded_actions = await expand_wildcard_actions(patterns_to_expand, fetcher)
|
|
134
|
+
|
|
135
|
+
return frozenset(expanded_actions)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""CLI commands for IAM Policy Validator."""
|
|
2
|
+
|
|
3
|
+
from .analyze import AnalyzeCommand
|
|
4
|
+
from .cache import CacheCommand
|
|
5
|
+
from .download_services import DownloadServicesCommand
|
|
6
|
+
from .post_to_pr import PostToPRCommand
|
|
7
|
+
from .validate import ValidateCommand
|
|
8
|
+
|
|
9
|
+
# All available commands
|
|
10
|
+
ALL_COMMANDS = [
|
|
11
|
+
ValidateCommand(),
|
|
12
|
+
PostToPRCommand(),
|
|
13
|
+
AnalyzeCommand(),
|
|
14
|
+
CacheCommand(),
|
|
15
|
+
DownloadServicesCommand(),
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"ValidateCommand",
|
|
20
|
+
"PostToPRCommand",
|
|
21
|
+
"AnalyzeCommand",
|
|
22
|
+
"CacheCommand",
|
|
23
|
+
"DownloadServicesCommand",
|
|
24
|
+
"ALL_COMMANDS",
|
|
25
|
+
]
|