iam-policy-validator 1.4.0__py3-none-any.whl → 1.6.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 (57) hide show
  1. {iam_policy_validator-1.4.0.dist-info → iam_policy_validator-1.6.0.dist-info}/METADATA +106 -78
  2. iam_policy_validator-1.6.0.dist-info/RECORD +82 -0
  3. iam_validator/__version__.py +1 -1
  4. iam_validator/checks/__init__.py +20 -4
  5. iam_validator/checks/action_condition_enforcement.py +165 -8
  6. iam_validator/checks/action_resource_matching.py +424 -0
  7. iam_validator/checks/condition_key_validation.py +24 -2
  8. iam_validator/checks/condition_type_mismatch.py +259 -0
  9. iam_validator/checks/full_wildcard.py +67 -0
  10. iam_validator/checks/mfa_condition_check.py +112 -0
  11. iam_validator/checks/principal_validation.py +497 -3
  12. iam_validator/checks/sensitive_action.py +250 -0
  13. iam_validator/checks/service_wildcard.py +105 -0
  14. iam_validator/checks/set_operator_validation.py +157 -0
  15. iam_validator/checks/utils/sensitive_action_matcher.py +74 -32
  16. iam_validator/checks/wildcard_action.py +62 -0
  17. iam_validator/checks/wildcard_resource.py +131 -0
  18. iam_validator/commands/cache.py +1 -1
  19. iam_validator/commands/download_services.py +3 -8
  20. iam_validator/commands/validate.py +72 -13
  21. iam_validator/core/aws_fetcher.py +114 -64
  22. iam_validator/core/check_registry.py +167 -29
  23. iam_validator/core/condition_validators.py +626 -0
  24. iam_validator/core/config/__init__.py +81 -0
  25. iam_validator/core/config/aws_api.py +35 -0
  26. iam_validator/core/config/aws_global_conditions.py +160 -0
  27. iam_validator/core/config/category_suggestions.py +104 -0
  28. iam_validator/core/config/condition_requirements.py +155 -0
  29. iam_validator/core/{config_loader.py → config/config_loader.py} +32 -9
  30. iam_validator/core/config/defaults.py +523 -0
  31. iam_validator/core/config/principal_requirements.py +421 -0
  32. iam_validator/core/config/sensitive_actions.py +672 -0
  33. iam_validator/core/config/service_principals.py +95 -0
  34. iam_validator/core/config/wildcards.py +124 -0
  35. iam_validator/core/formatters/enhanced.py +11 -5
  36. iam_validator/core/formatters/sarif.py +78 -14
  37. iam_validator/core/models.py +14 -1
  38. iam_validator/core/policy_checks.py +4 -4
  39. iam_validator/core/pr_commenter.py +1 -1
  40. iam_validator/sdk/__init__.py +187 -0
  41. iam_validator/sdk/arn_matching.py +274 -0
  42. iam_validator/sdk/context.py +222 -0
  43. iam_validator/sdk/exceptions.py +48 -0
  44. iam_validator/sdk/helpers.py +177 -0
  45. iam_validator/sdk/policy_utils.py +425 -0
  46. iam_validator/sdk/shortcuts.py +283 -0
  47. iam_validator/utils/__init__.py +31 -0
  48. iam_validator/utils/cache.py +105 -0
  49. iam_validator/utils/regex.py +206 -0
  50. iam_policy_validator-1.4.0.dist-info/RECORD +0 -56
  51. iam_validator/checks/action_resource_constraint.py +0 -151
  52. iam_validator/checks/security_best_practices.py +0 -536
  53. iam_validator/core/aws_global_conditions.py +0 -137
  54. iam_validator/core/defaults.py +0 -393
  55. {iam_policy_validator-1.4.0.dist-info → iam_policy_validator-1.6.0.dist-info}/WHEEL +0 -0
  56. {iam_policy_validator-1.4.0.dist-info → iam_policy_validator-1.6.0.dist-info}/entry_points.txt +0 -0
  57. {iam_policy_validator-1.4.0.dist-info → iam_policy_validator-1.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,95 @@
1
+ """
2
+ Default service principals for resource policy validation.
3
+
4
+ These are AWS service principals that are commonly used and considered safe
5
+ in resource-based policies (S3 bucket policies, SNS topic policies, etc.).
6
+ """
7
+
8
+ from typing import Final
9
+
10
+ # ============================================================================
11
+ # Allowed Service Principals
12
+ # ============================================================================
13
+ # These AWS service principals are commonly used in resource policies
14
+ # and are generally considered safe to allow
15
+
16
+ DEFAULT_SERVICE_PRINCIPALS: Final[tuple[str, ...]] = (
17
+ "cloudfront.amazonaws.com",
18
+ "s3.amazonaws.com",
19
+ "sns.amazonaws.com",
20
+ "lambda.amazonaws.com",
21
+ "logs.amazonaws.com",
22
+ "events.amazonaws.com",
23
+ "elasticloadbalancing.amazonaws.com",
24
+ "cloudtrail.amazonaws.com",
25
+ "config.amazonaws.com",
26
+ "backup.amazonaws.com",
27
+ "cloudwatch.amazonaws.com",
28
+ "monitoring.amazonaws.com",
29
+ "ec2.amazonaws.com",
30
+ "ecs-tasks.amazonaws.com",
31
+ "eks.amazonaws.com",
32
+ "apigateway.amazonaws.com",
33
+ )
34
+
35
+
36
+ def get_service_principals() -> tuple[str, ...]:
37
+ """
38
+ Get tuple of allowed service principals.
39
+
40
+ Returns:
41
+ Tuple of AWS service principal names
42
+ """
43
+ return DEFAULT_SERVICE_PRINCIPALS
44
+
45
+
46
+ def is_allowed_service_principal(principal: str) -> bool:
47
+ """
48
+ Check if a principal is an allowed service principal.
49
+
50
+ Args:
51
+ principal: Principal to check (e.g., "lambda.amazonaws.com")
52
+
53
+ Returns:
54
+ True if principal is in allowed list
55
+
56
+ Performance: O(n) but small list (~16 items)
57
+ """
58
+ return principal in DEFAULT_SERVICE_PRINCIPALS
59
+
60
+
61
+ def get_service_principals_by_category() -> dict[str, tuple[str, ...]]:
62
+ """
63
+ Get service principals organized by service category.
64
+
65
+ Returns:
66
+ Dictionary mapping categories to service principal tuples
67
+ """
68
+ return {
69
+ "storage": (
70
+ "s3.amazonaws.com",
71
+ "backup.amazonaws.com",
72
+ ),
73
+ "compute": (
74
+ "lambda.amazonaws.com",
75
+ "ec2.amazonaws.com",
76
+ "ecs-tasks.amazonaws.com",
77
+ "eks.amazonaws.com",
78
+ ),
79
+ "networking": (
80
+ "cloudfront.amazonaws.com",
81
+ "elasticloadbalancing.amazonaws.com",
82
+ "apigateway.amazonaws.com",
83
+ ),
84
+ "monitoring": (
85
+ "logs.amazonaws.com",
86
+ "cloudwatch.amazonaws.com",
87
+ "monitoring.amazonaws.com",
88
+ "cloudtrail.amazonaws.com",
89
+ ),
90
+ "messaging": (
91
+ "sns.amazonaws.com",
92
+ "events.amazonaws.com",
93
+ ),
94
+ "management": ("config.amazonaws.com",),
95
+ }
@@ -0,0 +1,124 @@
1
+ """
2
+ Default wildcard configurations for security best practices checks.
3
+
4
+ These wildcards define which actions are considered "safe" to use with
5
+ Resource: "*" (e.g., read-only describe operations).
6
+
7
+ Using Python tuples instead of YAML lists provides:
8
+ - Zero parsing overhead
9
+ - Immutable by default (tuples)
10
+ - Better performance
11
+ - Easy PyPI packaging
12
+ """
13
+
14
+ from typing import Final
15
+
16
+ # ============================================================================
17
+ # Allowed Wildcards for Resource: "*"
18
+ # ============================================================================
19
+ # These action patterns are considered safe to use with wildcard resources
20
+ # They are typically read-only operations that need broad resource access
21
+
22
+ DEFAULT_ALLOWED_WILDCARDS: Final[tuple[str, ...]] = (
23
+ # Auto Scaling
24
+ "autoscaling:Describe*",
25
+ # CloudWatch
26
+ "cloudwatch:Describe*",
27
+ "cloudwatch:Get*",
28
+ "cloudwatch:List*",
29
+ # DynamoDB
30
+ "dynamodb:Describe*",
31
+ # EC2
32
+ "ec2:Describe*",
33
+ # Elastic Load Balancing
34
+ "elasticloadbalancing:Describe*",
35
+ # IAM (non-sensitive read operations)
36
+ "iam:Get*",
37
+ "iam:List*",
38
+ # KMS
39
+ "kms:Describe*",
40
+ # Lambda
41
+ "lambda:Get*",
42
+ "lambda:List*",
43
+ # CloudWatch Logs
44
+ "logs:Describe*",
45
+ "logs:Filter*",
46
+ "logs:Get*",
47
+ # RDS
48
+ "rds:Describe*",
49
+ # Route53
50
+ "route53:Get*",
51
+ "route53:List*",
52
+ # S3 (safe read operations only)
53
+ "s3:Describe*",
54
+ "s3:GetBucket*",
55
+ "s3:GetM*",
56
+ "s3:List*",
57
+ # SQS
58
+ "sqs:Get*",
59
+ "sqs:List*",
60
+ # API Gateway
61
+ "apigateway:GET",
62
+ )
63
+
64
+ # ============================================================================
65
+ # Service-Level Wildcards (Allowed Services)
66
+ # ============================================================================
67
+ # Services that are allowed to use service-level wildcards like "logs:*"
68
+ # These are typically low-risk monitoring/logging services
69
+
70
+ DEFAULT_SERVICE_WILDCARDS: Final[tuple[str, ...]] = (
71
+ "logs",
72
+ "cloudwatch",
73
+ "xray",
74
+ )
75
+
76
+
77
+ def get_allowed_wildcards() -> tuple[str, ...]:
78
+ """
79
+ Get tuple of allowed wildcard action patterns.
80
+
81
+ Returns:
82
+ Tuple of action patterns that are safe to use with Resource: "*"
83
+ """
84
+ return DEFAULT_ALLOWED_WILDCARDS
85
+
86
+
87
+ def get_allowed_service_wildcards() -> tuple[str, ...]:
88
+ """
89
+ Get tuple of services allowed to use service-level wildcards.
90
+
91
+ Returns:
92
+ Tuple of service names (e.g., "logs", "cloudwatch")
93
+ """
94
+ return DEFAULT_SERVICE_WILDCARDS
95
+
96
+
97
+ def is_allowed_wildcard(pattern: str) -> bool:
98
+ """
99
+ Check if a wildcard pattern is in the allowed list.
100
+
101
+ Args:
102
+ pattern: Action pattern to check (e.g., "s3:List*")
103
+
104
+ Returns:
105
+ True if pattern is in allowed wildcards
106
+
107
+ Performance: O(n) but typically small list (~25 items)
108
+ """
109
+ return pattern in DEFAULT_ALLOWED_WILDCARDS
110
+
111
+
112
+ def is_allowed_service_wildcard(service: str) -> bool:
113
+ """
114
+ Check if a service is allowed to use service-level wildcards.
115
+
116
+ Args:
117
+ service: Service name (e.g., "logs", "s3")
118
+
119
+ Returns:
120
+ True if service is in allowed list
121
+
122
+ Performance: O(n) but very small list (~3 items)
123
+ """
124
+ return service in DEFAULT_SERVICE_WILDCARDS
@@ -36,13 +36,18 @@ class EnhancedFormatter(OutputFormatter):
36
36
 
37
37
  Args:
38
38
  report: Validation report to format
39
- **kwargs: Additional options (color: bool = True)
39
+ **kwargs: Additional options:
40
+ - color (bool): Enable color output (default: True)
41
+ - show_summary (bool): Show Executive Summary panel (default: True)
42
+ - show_severity_breakdown (bool): Show Issue Severity Breakdown panel (default: True)
40
43
 
41
44
  Returns:
42
45
  Formatted string with ANSI codes for console display
43
46
  """
44
47
  # Allow disabling color for plain text output
45
48
  color = kwargs.get("color", True)
49
+ show_summary = kwargs.get("show_summary", True)
50
+ show_severity_breakdown = kwargs.get("show_severity_breakdown", True)
46
51
 
47
52
  # Use StringIO to capture Rich console output
48
53
  string_buffer = StringIO()
@@ -58,11 +63,12 @@ class EnhancedFormatter(OutputFormatter):
58
63
  console.print(Panel(title, border_style="bright_blue", padding=(1, 0)))
59
64
  console.print()
60
65
 
61
- # Executive Summary with progress bars
62
- self._print_summary_panel(console, report)
66
+ # Executive Summary with progress bars (optional)
67
+ if show_summary:
68
+ self._print_summary_panel(console, report)
63
69
 
64
- # Severity breakdown if there are issues
65
- if report.total_issues > 0:
70
+ # Severity breakdown if there are issues (optional)
71
+ if show_severity_breakdown and report.total_issues > 0:
66
72
  console.print()
67
73
  self._print_severity_breakdown(console, report)
68
74
 
@@ -100,7 +100,7 @@ class SARIFFormatter(OutputFormatter):
100
100
  "text": "The specified condition key is not valid for this action"
101
101
  },
102
102
  "helpUri": "https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html",
103
- "defaultConfiguration": {"level": "warning"},
103
+ "defaultConfiguration": {"level": "error"},
104
104
  },
105
105
  {
106
106
  "id": "invalid-resource",
@@ -110,18 +110,55 @@ class SARIFFormatter(OutputFormatter):
110
110
  "defaultConfiguration": {"level": "error"},
111
111
  },
112
112
  {
113
- "id": "security-wildcard",
114
- "shortDescription": {"text": "Overly Permissive Wildcard"},
113
+ "id": "duplicate-sid",
114
+ "shortDescription": {"text": "Duplicate Statement ID"},
115
+ "fullDescription": {
116
+ "text": "Multiple statements use the same Statement ID (Sid), which can cause confusion"
117
+ },
118
+ "helpUri": "https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_sid.html",
119
+ "defaultConfiguration": {"level": "error"},
120
+ },
121
+ {
122
+ "id": "overly-permissive",
123
+ "shortDescription": {"text": "Overly Permissive Policy"},
115
124
  "fullDescription": {
116
- "text": "Using wildcards in actions or resources can be a security risk"
125
+ "text": "Policy grants overly broad permissions using wildcards in actions or resources"
117
126
  },
118
- "helpUri": "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html",
127
+ "helpUri": "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege",
119
128
  "defaultConfiguration": {"level": "warning"},
120
129
  },
121
130
  {
122
- "id": "security-sensitive-action",
123
- "shortDescription": {"text": "Sensitive Action Without Conditions"},
124
- "fullDescription": {"text": "Sensitive actions should have condition restrictions"},
131
+ "id": "missing-condition",
132
+ "shortDescription": {"text": "Missing Condition Restrictions"},
133
+ "fullDescription": {
134
+ "text": "Sensitive actions should include condition restrictions to limit when they can be used"
135
+ },
136
+ "helpUri": "https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#use-policy-conditions",
137
+ "defaultConfiguration": {"level": "warning"},
138
+ },
139
+ {
140
+ "id": "missing-required-condition",
141
+ "shortDescription": {"text": "Missing Required Condition"},
142
+ "fullDescription": {
143
+ "text": "Specific actions require certain conditions to prevent privilege escalation or security issues"
144
+ },
145
+ "helpUri": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html",
146
+ "defaultConfiguration": {"level": "error"},
147
+ },
148
+ {
149
+ "id": "invalid-principal",
150
+ "shortDescription": {"text": "Invalid Principal"},
151
+ "fullDescription": {
152
+ "text": "The specified principal is invalid or improperly formatted"
153
+ },
154
+ "helpUri": "https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html",
155
+ "defaultConfiguration": {"level": "error"},
156
+ },
157
+ {
158
+ "id": "general-issue",
159
+ "shortDescription": {"text": "IAM Policy Issue"},
160
+ "fullDescription": {"text": "General IAM policy validation issue"},
161
+ "helpUri": "https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html",
125
162
  "defaultConfiguration": {"level": "warning"},
126
163
  },
127
164
  ]
@@ -170,18 +207,45 @@ class SARIFFormatter(OutputFormatter):
170
207
  return results
171
208
 
172
209
  def _get_rule_id(self, issue: ValidationIssue) -> str:
173
- """Map issue to SARIF rule ID."""
210
+ """Map issue to SARIF rule ID.
211
+
212
+ Uses the issue_type field directly, converting underscores to hyphens
213
+ for SARIF rule ID format. Falls back to heuristic matching for unknown types.
214
+ """
215
+ # Map common issue types directly
216
+ issue_type_map = {
217
+ "invalid_action": "invalid-action",
218
+ "invalid_condition_key": "invalid-condition-key",
219
+ "invalid_resource": "invalid-resource",
220
+ "duplicate_sid": "duplicate-sid",
221
+ "overly_permissive": "overly-permissive",
222
+ "missing_condition": "missing-condition",
223
+ "missing_required_condition": "missing-required-condition",
224
+ "invalid_principal": "invalid-principal",
225
+ }
226
+
227
+ # Try direct mapping from issue_type
228
+ if issue.issue_type in issue_type_map:
229
+ return issue_type_map[issue.issue_type]
230
+
231
+ # Fallback: heuristic matching based on message
174
232
  message_lower = issue.message.lower()
175
233
 
176
234
  if "action" in message_lower and "not found" in message_lower:
177
235
  return "invalid-action"
178
236
  elif "condition key" in message_lower:
179
237
  return "invalid-condition-key"
180
- elif "arn" in message_lower or "resource" in message_lower:
238
+ elif "duplicate" in message_lower and "sid" in message_lower:
239
+ return "duplicate-sid"
240
+ elif "wildcard" in message_lower or "overly permissive" in message_lower:
241
+ return "overly-permissive"
242
+ elif "missing" in message_lower and "condition" in message_lower:
243
+ if "required" in message_lower:
244
+ return "missing-required-condition"
245
+ return "missing-condition"
246
+ elif "principal" in message_lower:
247
+ return "invalid-principal"
248
+ elif "resource" in message_lower or "arn" in message_lower:
181
249
  return "invalid-resource"
182
- elif "wildcard" in message_lower or "*" in issue.message:
183
- return "security-wildcard"
184
- elif "sensitive" in message_lower:
185
- return "security-sensitive-action"
186
250
  else:
187
251
  return "general-issue"
@@ -45,9 +45,22 @@ class ResourceType(BaseModel):
45
45
  model_config = ConfigDict(populate_by_name=True)
46
46
 
47
47
  name: str = Field(alias="Name")
48
- arn_pattern: str | None = Field(default=None, alias="ARNPattern")
48
+ arn_formats: list[str] | None = Field(default=None, alias="ARNFormats")
49
49
  condition_keys: list[str] | None = Field(default_factory=list, alias="ConditionKeys")
50
50
 
51
+ @property
52
+ def arn_pattern(self) -> str | None:
53
+ """
54
+ Get the first ARN format for backwards compatibility.
55
+
56
+ AWS provides ARN formats as an array (ARNFormats), but most code
57
+ just needs a single pattern. This property returns the first one.
58
+
59
+ Returns:
60
+ First ARN format string, or None if no formats are defined
61
+ """
62
+ return self.arn_formats[0] if self.arn_formats else None
63
+
51
64
 
52
65
  class ConditionKey(BaseModel):
53
66
  """Details about an AWS condition key."""
@@ -491,7 +491,7 @@ async def validate_policies(
491
491
  if not use_registry:
492
492
  # Legacy path - use old PolicyValidator
493
493
  # Load config for cache settings even in legacy mode
494
- from iam_validator.core.config_loader import ConfigLoader
494
+ from iam_validator.core.config.config_loader import ConfigLoader
495
495
 
496
496
  config = ConfigLoader.load_config(explicit_path=config_path, allow_missing=True)
497
497
  cache_enabled = config.get_setting("cache_enabled", True)
@@ -519,7 +519,7 @@ async def validate_policies(
519
519
 
520
520
  # New path - use CheckRegistry system
521
521
  from iam_validator.core.check_registry import create_default_registry
522
- from iam_validator.core.config_loader import ConfigLoader
522
+ from iam_validator.core.config.config_loader import ConfigLoader
523
523
 
524
524
  # Load configuration
525
525
  config = ConfigLoader.load_config(explicit_path=config_path, allow_missing=True)
@@ -630,8 +630,8 @@ async def _validate_policy_with_registry(
630
630
 
631
631
  # Execute all statement-level checks for each statement
632
632
  for idx, statement in enumerate(policy.statement):
633
- # Execute all registered checks in parallel
634
- issues = await registry.execute_checks_parallel(statement, idx, fetcher)
633
+ # Execute all registered checks in parallel (with ignore_patterns filtering)
634
+ issues = await registry.execute_checks_parallel(statement, idx, fetcher, policy_file)
635
635
 
636
636
  # Add issues to result
637
637
  result.issues.extend(issues)
@@ -313,7 +313,7 @@ async def post_report_to_pr(
313
313
  report = ValidationReport.model_validate(report_data)
314
314
 
315
315
  # Load config to get fail_on_severity setting
316
- from iam_validator.core.config_loader import ConfigLoader
316
+ from iam_validator.core.config.config_loader import ConfigLoader
317
317
 
318
318
  config = ConfigLoader.load_config(config_path)
319
319
  fail_on_severities = config.get_setting("fail_on_severity", ["error", "critical"])
@@ -0,0 +1,187 @@
1
+ """
2
+ IAM Policy Validator SDK - Public API for library usage.
3
+
4
+ This module provides the complete public API for using IAM Policy Validator
5
+ as a Python library. It exposes both high-level convenience functions and
6
+ low-level components for custom integrations.
7
+
8
+ Quick Start:
9
+ Basic validation:
10
+ >>> from iam_validator.sdk import validate_file
11
+ >>> result = await validate_file("policy.json")
12
+ >>> print(f"Valid: {result.is_valid}")
13
+
14
+ With context manager:
15
+ >>> from iam_validator.sdk import validator
16
+ >>> async with validator() as v:
17
+ ... result = await v.validate_file("policy.json")
18
+ ... v.generate_report([result])
19
+
20
+ Policy manipulation:
21
+ >>> from iam_validator.sdk import parse_policy, get_policy_summary
22
+ >>> policy = parse_policy(policy_json)
23
+ >>> summary = get_policy_summary(policy)
24
+ >>> print(f"Actions: {summary['action_count']}")
25
+
26
+ Custom check development:
27
+ >>> from iam_validator.sdk import PolicyCheck, CheckHelper
28
+ >>> class MyCheck(PolicyCheck):
29
+ ... @property
30
+ ... def check_id(self) -> str:
31
+ ... return "my_check"
32
+ ... async def execute(self, statement, idx, fetcher, config):
33
+ ... helper = CheckHelper(fetcher)
34
+ ... # Use helper.arn_matches(), helper.create_issue(), etc.
35
+ ... return []
36
+ """
37
+
38
+ # === High-level validation functions (shortcuts) ===
39
+ # === AWS utilities ===
40
+ from iam_validator.core.aws_fetcher import AWSServiceFetcher
41
+
42
+ # === Core validation components (for advanced usage) ===
43
+ from iam_validator.core.check_registry import CheckRegistry, PolicyCheck
44
+
45
+ # === ValidatorConfiguration ===
46
+ from iam_validator.core.config.config_loader import ValidatorConfig, load_validator_config
47
+
48
+ # === Reporting ===
49
+ from iam_validator.core.formatters.csv import CSVFormatter
50
+ from iam_validator.core.formatters.html import HTMLFormatter
51
+ from iam_validator.core.formatters.json import JSONFormatter
52
+ from iam_validator.core.formatters.markdown import MarkdownFormatter
53
+ from iam_validator.core.formatters.sarif import SARIFFormatter
54
+
55
+ # === Models (for type hints and inspection) ===
56
+ from iam_validator.core.models import (
57
+ IAMPolicy,
58
+ PolicyValidationResult,
59
+ Statement,
60
+ ValidationIssue,
61
+ )
62
+ from iam_validator.core.policy_checks import validate_policies
63
+ from iam_validator.core.policy_loader import PolicyLoader
64
+ from iam_validator.core.report import ReportGenerator
65
+
66
+ # === ARN matching utilities ===
67
+ from iam_validator.sdk.arn_matching import (
68
+ arn_matches,
69
+ arn_strictly_valid,
70
+ convert_aws_pattern_to_wildcard,
71
+ is_glob_match,
72
+ )
73
+
74
+ # === Context managers ===
75
+ from iam_validator.sdk.context import (
76
+ ValidationContext,
77
+ validator,
78
+ validator_from_config,
79
+ )
80
+
81
+ # === Public exceptions ===
82
+ from iam_validator.sdk.exceptions import (
83
+ AWSServiceError,
84
+ ConfigurationError,
85
+ IAMValidatorError,
86
+ InvalidPolicyFormatError,
87
+ PolicyLoadError,
88
+ PolicyValidationError,
89
+ UnsupportedPolicyTypeError,
90
+ )
91
+
92
+ # === Custom check development ===
93
+ from iam_validator.sdk.helpers import CheckHelper, expand_actions
94
+
95
+ # === Policy manipulation utilities ===
96
+ from iam_validator.sdk.policy_utils import (
97
+ extract_actions,
98
+ extract_condition_keys,
99
+ extract_resources,
100
+ find_statements_with_action,
101
+ find_statements_with_resource,
102
+ get_policy_summary,
103
+ has_public_access,
104
+ is_resource_policy,
105
+ merge_policies,
106
+ normalize_policy,
107
+ parse_policy,
108
+ policy_to_dict,
109
+ policy_to_json,
110
+ )
111
+ from iam_validator.sdk.shortcuts import (
112
+ count_issues_by_severity,
113
+ get_issues,
114
+ quick_validate,
115
+ validate_directory,
116
+ validate_file,
117
+ validate_json,
118
+ )
119
+
120
+ __all__ = [
121
+ # === High-level shortcuts ===
122
+ "validate_file",
123
+ "validate_directory",
124
+ "validate_json",
125
+ "quick_validate",
126
+ "get_issues",
127
+ "count_issues_by_severity",
128
+ # === Context managers ===
129
+ "validator",
130
+ "validator_from_config",
131
+ "ValidationContext",
132
+ # === Policy utilities ===
133
+ "parse_policy",
134
+ "normalize_policy",
135
+ "extract_actions",
136
+ "extract_resources",
137
+ "extract_condition_keys",
138
+ "find_statements_with_action",
139
+ "find_statements_with_resource",
140
+ "merge_policies",
141
+ "get_policy_summary",
142
+ "policy_to_json",
143
+ "policy_to_dict",
144
+ "is_resource_policy",
145
+ "has_public_access",
146
+ # === ARN utilities ===
147
+ "arn_matches",
148
+ "arn_strictly_valid",
149
+ "is_glob_match",
150
+ "convert_aws_pattern_to_wildcard",
151
+ # === Custom check development ===
152
+ "PolicyCheck",
153
+ "CheckRegistry",
154
+ "CheckHelper",
155
+ "expand_actions",
156
+ # === Core validation (advanced) ===
157
+ "validate_policies",
158
+ "PolicyLoader",
159
+ # === Reporting ===
160
+ "ReportGenerator",
161
+ "JSONFormatter",
162
+ "HTMLFormatter",
163
+ "CSVFormatter",
164
+ "MarkdownFormatter",
165
+ "SARIFFormatter",
166
+ # === Models ===
167
+ "ValidationIssue",
168
+ "PolicyValidationResult",
169
+ "IAMPolicy",
170
+ "Statement",
171
+ # === ValidatorConfiguration ===
172
+ "ValidatorConfig",
173
+ "load_validator_config",
174
+ # === AWS utilities ===
175
+ "AWSServiceFetcher",
176
+ # === Exceptions ===
177
+ "IAMValidatorError",
178
+ "PolicyLoadError",
179
+ "PolicyValidationError",
180
+ "ConfigurationError",
181
+ "AWSServiceError",
182
+ "InvalidPolicyFormatError",
183
+ "UnsupportedPolicyTypeError",
184
+ ]
185
+
186
+ # SDK version
187
+ __version__ = "0.1.0"