iam-policy-validator 1.8.0__py3-none-any.whl → 1.10.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.8.0.dist-info → iam_policy_validator-1.10.0.dist-info}/METADATA +106 -1
- iam_policy_validator-1.10.0.dist-info/RECORD +96 -0
- iam_validator/__init__.py +1 -1
- iam_validator/__version__.py +1 -1
- iam_validator/checks/action_condition_enforcement.py +504 -190
- iam_validator/checks/action_resource_matching.py +8 -15
- iam_validator/checks/action_validation.py +6 -12
- iam_validator/checks/condition_key_validation.py +6 -12
- iam_validator/checks/condition_type_mismatch.py +9 -16
- 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 +10 -40
- iam_validator/checks/policy_type_validation.py +18 -19
- iam_validator/checks/principal_validation.py +11 -20
- iam_validator/checks/resource_validation.py +5 -12
- iam_validator/checks/sensitive_action.py +8 -15
- iam_validator/checks/service_wildcard.py +6 -12
- iam_validator/checks/set_operator_validation.py +11 -18
- iam_validator/checks/sid_uniqueness.py +8 -38
- iam_validator/checks/trust_policy_validation.py +8 -14
- iam_validator/checks/utils/wildcard_expansion.py +1 -1
- iam_validator/checks/wildcard_action.py +6 -12
- iam_validator/checks/wildcard_resource.py +6 -12
- iam_validator/commands/cache.py +4 -3
- iam_validator/commands/validate.py +26 -4
- iam_validator/core/__init__.py +1 -1
- iam_validator/core/aws_fetcher.py +24 -1030
- 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 +82 -14
- iam_validator/core/config/defaults.py +10 -0
- iam_validator/core/constants.py +17 -0
- iam_validator/core/label_manager.py +197 -0
- iam_validator/core/policy_checks.py +7 -3
- iam_validator/core/pr_commenter.py +34 -7
- 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.8.0.dist-info/RECORD +0 -87
- {iam_policy_validator-1.8.0.dist-info → iam_policy_validator-1.10.0.dist-info}/WHEEL +0 -0
- {iam_policy_validator-1.8.0.dist-info → iam_policy_validator-1.10.0.dist-info}/entry_points.txt +0 -0
- {iam_policy_validator-1.8.0.dist-info → iam_policy_validator-1.10.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Sensitive action check - detects sensitive actions without IAM conditions."""
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
4
4
|
|
|
5
5
|
from iam_validator.checks.utils.policy_level_checks import check_policy_level_actions
|
|
6
6
|
from iam_validator.checks.utils.sensitive_action_matcher import (
|
|
@@ -8,7 +8,7 @@ from iam_validator.checks.utils.sensitive_action_matcher import (
|
|
|
8
8
|
check_sensitive_actions,
|
|
9
9
|
)
|
|
10
10
|
from iam_validator.checks.utils.wildcard_expansion import expand_wildcard_actions
|
|
11
|
-
from iam_validator.core.
|
|
11
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
12
12
|
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
13
13
|
from iam_validator.core.config.sensitive_actions import get_category_for_action
|
|
14
14
|
from iam_validator.core.models import Statement, ValidationIssue
|
|
@@ -20,17 +20,9 @@ if TYPE_CHECKING:
|
|
|
20
20
|
class SensitiveActionCheck(PolicyCheck):
|
|
21
21
|
"""Checks for sensitive actions without IAM conditions to limit their use."""
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@property
|
|
28
|
-
def description(self) -> str:
|
|
29
|
-
return "Checks for sensitive actions without conditions"
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def default_severity(self) -> str:
|
|
33
|
-
return "medium"
|
|
23
|
+
check_id: ClassVar[str] = "sensitive_action"
|
|
24
|
+
description: ClassVar[str] = "Checks for sensitive actions without conditions"
|
|
25
|
+
default_severity: ClassVar[str] = "medium"
|
|
34
26
|
|
|
35
27
|
def _get_severity_for_action(self, action: str, config: CheckConfig) -> str:
|
|
36
28
|
"""
|
|
@@ -86,6 +78,7 @@ class SensitiveActionCheck(PolicyCheck):
|
|
|
86
78
|
return (
|
|
87
79
|
"Add IAM conditions to limit when this action can be used. Use ABAC for scalability:\n"
|
|
88
80
|
"• Match principal tags to resource tags (`aws:PrincipalTag/<tag-name>` = `aws:ResourceTag/<tag-name>`)\n"
|
|
81
|
+
"• Match organization principal tags to resource tags (`aws:PrincipalOrgID` = `aws:ResourceOrgID`)\n"
|
|
89
82
|
"• Require MFA (`aws:MultiFactorAuthPresent` = `true`)\n"
|
|
90
83
|
"• Restrict by IP (`aws:SourceIp`) or VPC (`aws:SourceVpc`)",
|
|
91
84
|
'"Condition": {\n'
|
|
@@ -125,14 +118,14 @@ class SensitiveActionCheck(PolicyCheck):
|
|
|
125
118
|
if len(matched_actions) == 1:
|
|
126
119
|
message_template = config.config.get(
|
|
127
120
|
"message_single",
|
|
128
|
-
"Sensitive action
|
|
121
|
+
"Sensitive action `{action}` should have conditions to limit when it can be used",
|
|
129
122
|
)
|
|
130
123
|
message = message_template.format(action=matched_actions[0])
|
|
131
124
|
else:
|
|
132
125
|
action_list = "', '".join(matched_actions)
|
|
133
126
|
message_template = config.config.get(
|
|
134
127
|
"message_multiple",
|
|
135
|
-
"Sensitive actions
|
|
128
|
+
"Sensitive actions `{actions}` should have conditions to limit when they can be used",
|
|
136
129
|
)
|
|
137
130
|
message = message_template.format(actions=action_list)
|
|
138
131
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""Service wildcard check - detects service-level wildcards like 'iam:*', 's3:*'."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from typing import ClassVar
|
|
4
|
+
|
|
5
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
4
6
|
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
5
7
|
from iam_validator.core.models import Statement, ValidationIssue
|
|
6
8
|
|
|
@@ -8,17 +10,9 @@ from iam_validator.core.models import Statement, ValidationIssue
|
|
|
8
10
|
class ServiceWildcardCheck(PolicyCheck):
|
|
9
11
|
"""Checks for service-level wildcards (e.g., 'iam:*', 's3:*') which grant all permissions for a service."""
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@property
|
|
16
|
-
def description(self) -> str:
|
|
17
|
-
return "Checks for service-level wildcards (e.g., 'iam:*', 's3:*')"
|
|
18
|
-
|
|
19
|
-
@property
|
|
20
|
-
def default_severity(self) -> str:
|
|
21
|
-
return "high"
|
|
13
|
+
check_id: ClassVar[str] = "service_wildcard"
|
|
14
|
+
description: ClassVar[str] = "Checks for service-level wildcards (e.g., 'iam:*', 's3:*')"
|
|
15
|
+
default_severity: ClassVar[str] = "high"
|
|
22
16
|
|
|
23
17
|
async def execute(
|
|
24
18
|
self,
|
|
@@ -6,7 +6,9 @@ Based on AWS IAM best practices:
|
|
|
6
6
|
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
from
|
|
9
|
+
from typing import ClassVar
|
|
10
|
+
|
|
11
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
10
12
|
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
11
13
|
from iam_validator.core.condition_validators import (
|
|
12
14
|
is_multivalued_context_key,
|
|
@@ -18,20 +20,11 @@ from iam_validator.core.models import Statement, ValidationIssue
|
|
|
18
20
|
class SetOperatorValidationCheck(PolicyCheck):
|
|
19
21
|
"""Check for proper usage of ForAllValues and ForAnyValue set operators."""
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@property
|
|
27
|
-
def description(self) -> str:
|
|
28
|
-
"""Description of what this check does."""
|
|
29
|
-
return "Validates proper usage of ForAllValues and ForAnyValue set operators"
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def default_severity(self) -> str:
|
|
33
|
-
"""Default severity level for issues found by this check."""
|
|
34
|
-
return "error"
|
|
23
|
+
check_id: ClassVar[str] = "set_operator_validation"
|
|
24
|
+
description: ClassVar[str] = (
|
|
25
|
+
"Validates proper usage of ForAllValues and ForAnyValue set operators"
|
|
26
|
+
)
|
|
27
|
+
default_severity: ClassVar[str] = "error"
|
|
35
28
|
|
|
36
29
|
async def execute(
|
|
37
30
|
self,
|
|
@@ -120,8 +113,8 @@ class SetOperatorValidationCheck(PolicyCheck):
|
|
|
120
113
|
ValidationIssue(
|
|
121
114
|
severity="warning",
|
|
122
115
|
message=(
|
|
123
|
-
f"Security risk: ForAllValues with Allow effect on `{condition_key}` "
|
|
124
|
-
f"should include a Null condition check. Without it, requests with missing "
|
|
116
|
+
f"Security risk: `ForAllValues` with `Allow` effect on `{condition_key}` "
|
|
117
|
+
f"should include a `Null` condition check. Without it, requests with missing "
|
|
125
118
|
f'`{condition_key}` will be granted access. Add: `"Null": {{"{condition_key}": "false"}}`. '
|
|
126
119
|
f"See: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html"
|
|
127
120
|
),
|
|
@@ -141,7 +134,7 @@ class SetOperatorValidationCheck(PolicyCheck):
|
|
|
141
134
|
severity="warning",
|
|
142
135
|
message=(
|
|
143
136
|
f"Unpredictable behavior: `ForAnyValue` with `Deny` effect on `{condition_key}` "
|
|
144
|
-
f"should include a Null condition check. Without it, requests with missing "
|
|
137
|
+
f"should include a `Null` condition check. Without it, requests with missing "
|
|
145
138
|
f"`{condition_key}` will evaluate to `No match` instead of denying access. "
|
|
146
139
|
f'Add: `"Null": {{"{condition_key}": "false"}}`. '
|
|
147
140
|
f"See: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-single-vs-multi-valued-context-keys.html"
|
|
@@ -13,10 +13,11 @@ statement, examining all statements in the policy to find duplicates and format
|
|
|
13
13
|
|
|
14
14
|
import re
|
|
15
15
|
from collections import Counter
|
|
16
|
+
from typing import ClassVar
|
|
16
17
|
|
|
17
|
-
from iam_validator.core.
|
|
18
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
18
19
|
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
19
|
-
from iam_validator.core.models import IAMPolicy,
|
|
20
|
+
from iam_validator.core.models import IAMPolicy, ValidationIssue
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def _check_sid_uniqueness_impl(policy: IAMPolicy, severity: str) -> list[ValidationIssue]:
|
|
@@ -111,42 +112,11 @@ class SidUniquenessCheck(PolicyCheck):
|
|
|
111
112
|
It only runs once when processing the first statement to avoid duplicate work.
|
|
112
113
|
"""
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def description(self) -> str:
|
|
120
|
-
return "Validates that Statement IDs (Sids) are unique and follow AWS naming requirements (no spaces)"
|
|
121
|
-
|
|
122
|
-
@property
|
|
123
|
-
def default_severity(self) -> str:
|
|
124
|
-
return "warning"
|
|
125
|
-
|
|
126
|
-
async def execute(
|
|
127
|
-
self,
|
|
128
|
-
statement: Statement,
|
|
129
|
-
statement_idx: int,
|
|
130
|
-
fetcher: AWSServiceFetcher,
|
|
131
|
-
config: CheckConfig,
|
|
132
|
-
) -> list[ValidationIssue]:
|
|
133
|
-
"""Execute the SID uniqueness check at statement level.
|
|
134
|
-
|
|
135
|
-
This is a policy-level check, so statement-level execution returns empty.
|
|
136
|
-
The actual check runs in execute_policy() which has access to all statements.
|
|
137
|
-
|
|
138
|
-
Args:
|
|
139
|
-
statement: The IAM policy statement (unused)
|
|
140
|
-
statement_idx: Index of the statement in the policy (unused)
|
|
141
|
-
fetcher: AWS service fetcher (unused for this check)
|
|
142
|
-
config: Configuration for this check instance (unused)
|
|
143
|
-
|
|
144
|
-
Returns:
|
|
145
|
-
Empty list (actual check runs in execute_policy())
|
|
146
|
-
"""
|
|
147
|
-
del statement, statement_idx, fetcher, config # Unused
|
|
148
|
-
# This is a policy-level check - execution happens in execute_policy()
|
|
149
|
-
return []
|
|
115
|
+
check_id: ClassVar[str] = "sid_uniqueness"
|
|
116
|
+
description: ClassVar[str] = (
|
|
117
|
+
"Validates that Statement IDs (Sids) are unique and follow AWS naming requirements (no spaces)"
|
|
118
|
+
)
|
|
119
|
+
default_severity: ClassVar[str] = "warning"
|
|
150
120
|
|
|
151
121
|
async def execute_policy(
|
|
152
122
|
self,
|
|
@@ -34,9 +34,9 @@ This check is DISABLED by default. Enable it for trust policy validation:
|
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
36
|
import re
|
|
37
|
-
from typing import TYPE_CHECKING, Any
|
|
37
|
+
from typing import TYPE_CHECKING, Any, ClassVar
|
|
38
38
|
|
|
39
|
-
from iam_validator.core.
|
|
39
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
40
40
|
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
41
41
|
from iam_validator.core.models import Statement, ValidationIssue
|
|
42
42
|
|
|
@@ -79,17 +79,11 @@ class TrustPolicyValidationCheck(PolicyCheck):
|
|
|
79
79
|
},
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def description(self) -> str:
|
|
88
|
-
return "Validates trust policies for role assumption security and action-principal coupling"
|
|
89
|
-
|
|
90
|
-
@property
|
|
91
|
-
def default_severity(self) -> str:
|
|
92
|
-
return "high"
|
|
82
|
+
check_id: ClassVar[str] = "trust_policy_validation"
|
|
83
|
+
description: ClassVar[str] = (
|
|
84
|
+
"Validates trust policies for role assumption security and action-principal coupling"
|
|
85
|
+
)
|
|
86
|
+
default_severity: ClassVar[str] = "high"
|
|
93
87
|
|
|
94
88
|
async def execute(
|
|
95
89
|
self,
|
|
@@ -256,7 +250,7 @@ class TrustPolicyValidationCheck(PolicyCheck):
|
|
|
256
250
|
ValidationIssue(
|
|
257
251
|
severity=self.get_severity(config),
|
|
258
252
|
issue_type="invalid_principal_type_for_assume_action",
|
|
259
|
-
message=f"Action `{action}` should not use Principal type `{principal_type}`. "
|
|
253
|
+
message=f"Action `{action}` should not use `Principal` type `{principal_type}`. "
|
|
260
254
|
f"Expected principal types: {allowed_list}",
|
|
261
255
|
statement_index=statement_idx,
|
|
262
256
|
statement_sid=statement.sid,
|
|
@@ -7,7 +7,7 @@ to their actual action names using the AWS Service Reference API.
|
|
|
7
7
|
import re
|
|
8
8
|
from functools import lru_cache
|
|
9
9
|
|
|
10
|
-
from iam_validator.core.
|
|
10
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
# Global cache for compiled wildcard patterns (shared across checks)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""Wildcard action check - detects Action: '*' in IAM policies."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from typing import ClassVar
|
|
4
|
+
|
|
5
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
4
6
|
from iam_validator.core.check_registry import CheckConfig, PolicyCheck
|
|
5
7
|
from iam_validator.core.models import Statement, ValidationIssue
|
|
6
8
|
|
|
@@ -8,17 +10,9 @@ from iam_validator.core.models import Statement, ValidationIssue
|
|
|
8
10
|
class WildcardActionCheck(PolicyCheck):
|
|
9
11
|
"""Checks for wildcard actions (Action: '*') which grant all permissions."""
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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"
|
|
13
|
+
check_id: ClassVar[str] = "wildcard_action"
|
|
14
|
+
description: ClassVar[str] = "Checks for wildcard actions (*)"
|
|
15
|
+
default_severity: ClassVar[str] = "medium"
|
|
22
16
|
|
|
23
17
|
async def execute(
|
|
24
18
|
self,
|
|
@@ -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,
|
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
|
|
|
@@ -163,6 +166,13 @@ Examples:
|
|
|
163
166
|
help="Path to directory containing custom checks for auto-discovery",
|
|
164
167
|
)
|
|
165
168
|
|
|
169
|
+
parser.add_argument(
|
|
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.",
|
|
174
|
+
)
|
|
175
|
+
|
|
166
176
|
parser.add_argument(
|
|
167
177
|
"--stream",
|
|
168
178
|
action="store_true",
|
|
@@ -242,12 +252,14 @@ Examples:
|
|
|
242
252
|
# Validate policies
|
|
243
253
|
config_path = getattr(args, "config", None)
|
|
244
254
|
custom_checks_dir = getattr(args, "custom_checks_dir", None)
|
|
255
|
+
aws_services_dir = getattr(args, "aws_services_dir", None)
|
|
245
256
|
policy_type = cast(PolicyType, getattr(args, "policy_type", "IDENTITY_POLICY"))
|
|
246
257
|
results = await validate_policies(
|
|
247
258
|
policies,
|
|
248
259
|
config_path=config_path,
|
|
249
260
|
custom_checks_dir=custom_checks_dir,
|
|
250
261
|
policy_type=policy_type,
|
|
262
|
+
aws_services_dir=aws_services_dir,
|
|
251
263
|
)
|
|
252
264
|
|
|
253
265
|
# Generate report (include parsing errors if any)
|
|
@@ -290,12 +302,17 @@ Examples:
|
|
|
290
302
|
from iam_validator.core.config.config_loader import ConfigLoader
|
|
291
303
|
from iam_validator.core.pr_commenter import PRCommenter
|
|
292
304
|
|
|
293
|
-
# Load config to get fail_on_severity
|
|
305
|
+
# Load config to get fail_on_severity and severity_labels settings
|
|
294
306
|
config = ConfigLoader.load_config(config_path)
|
|
295
307
|
fail_on_severities = config.get_setting("fail_on_severity", ["error", "critical"])
|
|
308
|
+
severity_labels = config.get_setting("severity_labels", {})
|
|
296
309
|
|
|
297
310
|
async with GitHubIntegration() as github:
|
|
298
|
-
commenter = PRCommenter(
|
|
311
|
+
commenter = PRCommenter(
|
|
312
|
+
github,
|
|
313
|
+
fail_on_severities=fail_on_severities,
|
|
314
|
+
severity_labels=severity_labels,
|
|
315
|
+
)
|
|
299
316
|
success = await commenter.post_findings_to_pr(
|
|
300
317
|
report,
|
|
301
318
|
create_review=getattr(args, "github_review", False),
|
|
@@ -414,12 +431,17 @@ Examples:
|
|
|
414
431
|
from iam_validator.core.config.config_loader import ConfigLoader
|
|
415
432
|
from iam_validator.core.pr_commenter import PRCommenter
|
|
416
433
|
|
|
417
|
-
# Load config to get fail_on_severity
|
|
434
|
+
# Load config to get fail_on_severity and severity_labels settings
|
|
418
435
|
config = ConfigLoader.load_config(config_path)
|
|
419
436
|
fail_on_severities = config.get_setting("fail_on_severity", ["error", "critical"])
|
|
437
|
+
severity_labels = config.get_setting("severity_labels", {})
|
|
420
438
|
|
|
421
439
|
async with GitHubIntegration() as github:
|
|
422
|
-
commenter = PRCommenter(
|
|
440
|
+
commenter = PRCommenter(
|
|
441
|
+
github,
|
|
442
|
+
fail_on_severities=fail_on_severities,
|
|
443
|
+
severity_labels=severity_labels,
|
|
444
|
+
)
|
|
423
445
|
success = await commenter.post_findings_to_pr(
|
|
424
446
|
report,
|
|
425
447
|
create_review=False, # Already posted per-file reviews in streaming mode
|
iam_validator/core/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Core validation modules."""
|
|
2
2
|
|
|
3
|
-
from iam_validator.core.
|
|
3
|
+
from iam_validator.core.aws_service import AWSServiceFetcher
|
|
4
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
|