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.
Files changed (49) hide show
  1. {iam_policy_validator-1.8.0.dist-info → iam_policy_validator-1.10.0.dist-info}/METADATA +106 -1
  2. iam_policy_validator-1.10.0.dist-info/RECORD +96 -0
  3. iam_validator/__init__.py +1 -1
  4. iam_validator/__version__.py +1 -1
  5. iam_validator/checks/action_condition_enforcement.py +504 -190
  6. iam_validator/checks/action_resource_matching.py +8 -15
  7. iam_validator/checks/action_validation.py +6 -12
  8. iam_validator/checks/condition_key_validation.py +6 -12
  9. iam_validator/checks/condition_type_mismatch.py +9 -16
  10. iam_validator/checks/full_wildcard.py +9 -13
  11. iam_validator/checks/mfa_condition_check.py +8 -17
  12. iam_validator/checks/policy_size.py +6 -39
  13. iam_validator/checks/policy_structure.py +10 -40
  14. iam_validator/checks/policy_type_validation.py +18 -19
  15. iam_validator/checks/principal_validation.py +11 -20
  16. iam_validator/checks/resource_validation.py +5 -12
  17. iam_validator/checks/sensitive_action.py +8 -15
  18. iam_validator/checks/service_wildcard.py +6 -12
  19. iam_validator/checks/set_operator_validation.py +11 -18
  20. iam_validator/checks/sid_uniqueness.py +8 -38
  21. iam_validator/checks/trust_policy_validation.py +8 -14
  22. iam_validator/checks/utils/wildcard_expansion.py +1 -1
  23. iam_validator/checks/wildcard_action.py +6 -12
  24. iam_validator/checks/wildcard_resource.py +6 -12
  25. iam_validator/commands/cache.py +4 -3
  26. iam_validator/commands/validate.py +26 -4
  27. iam_validator/core/__init__.py +1 -1
  28. iam_validator/core/aws_fetcher.py +24 -1030
  29. iam_validator/core/aws_service/__init__.py +21 -0
  30. iam_validator/core/aws_service/cache.py +108 -0
  31. iam_validator/core/aws_service/client.py +205 -0
  32. iam_validator/core/aws_service/fetcher.py +612 -0
  33. iam_validator/core/aws_service/parsers.py +149 -0
  34. iam_validator/core/aws_service/patterns.py +51 -0
  35. iam_validator/core/aws_service/storage.py +291 -0
  36. iam_validator/core/aws_service/validators.py +379 -0
  37. iam_validator/core/check_registry.py +82 -14
  38. iam_validator/core/config/defaults.py +10 -0
  39. iam_validator/core/constants.py +17 -0
  40. iam_validator/core/label_manager.py +197 -0
  41. iam_validator/core/policy_checks.py +7 -3
  42. iam_validator/core/pr_commenter.py +34 -7
  43. iam_validator/sdk/__init__.py +1 -1
  44. iam_validator/sdk/context.py +1 -1
  45. iam_validator/sdk/helpers.py +1 -1
  46. iam_policy_validator-1.8.0.dist-info/RECORD +0 -87
  47. {iam_policy_validator-1.8.0.dist-info → iam_policy_validator-1.10.0.dist-info}/WHEEL +0 -0
  48. {iam_policy_validator-1.8.0.dist-info → iam_policy_validator-1.10.0.dist-info}/entry_points.txt +0 -0
  49. {iam_policy_validator-1.8.0.dist-info → iam_policy_validator-1.10.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,197 @@
1
+ """Label Manager for GitHub PR Labels based on Severity Findings.
2
+
3
+ This module manages GitHub PR labels based on IAM policy validation severity findings.
4
+ When validation finds issues with specific severities, it applies corresponding labels.
5
+ When those severities are not found, it removes the labels if present.
6
+ """
7
+
8
+ import logging
9
+ from typing import TYPE_CHECKING
10
+
11
+ if TYPE_CHECKING:
12
+ from iam_validator.core.models import PolicyValidationResult, ValidationReport
13
+ from iam_validator.integrations.github_integration import GitHubIntegration
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class LabelManager:
19
+ """Manages GitHub PR labels based on severity findings."""
20
+
21
+ def __init__(
22
+ self,
23
+ github: "GitHubIntegration",
24
+ severity_labels: dict[str, str | list[str]] | None = None,
25
+ ):
26
+ """Initialize label manager.
27
+
28
+ Args:
29
+ github: GitHubIntegration instance for API calls
30
+ severity_labels: Mapping of severity levels to label name(s)
31
+ Supports both single labels and lists of labels per severity.
32
+ Examples:
33
+ - Single label per severity:
34
+ {"error": "iam-validity-error", "critical": "security-critical"}
35
+ - Multiple labels per severity:
36
+ {"error": ["iam-error", "needs-fix"], "critical": ["security-critical", "needs-security-review"]}
37
+ - Mixed:
38
+ {"error": "iam-validity-error", "critical": ["security-critical", "needs-review"]}
39
+ """
40
+ self.github = github
41
+ self.severity_labels = severity_labels or {}
42
+
43
+ def is_enabled(self) -> bool:
44
+ """Check if label management is enabled.
45
+
46
+ Returns:
47
+ True if severity_labels is configured and GitHub is configured
48
+ """
49
+ return bool(self.severity_labels) and self.github.is_configured()
50
+
51
+ def _get_severities_in_results(self, results: list["PolicyValidationResult"]) -> set[str]:
52
+ """Extract all severity levels found in validation results.
53
+
54
+ Args:
55
+ results: List of PolicyValidationResult objects
56
+
57
+ Returns:
58
+ Set of severity levels found (e.g., {"error", "critical", "high"})
59
+ """
60
+ severities = set()
61
+ for result in results:
62
+ for issue in result.issues:
63
+ severities.add(issue.severity)
64
+ return severities
65
+
66
+ def _get_severities_in_report(self, report: "ValidationReport") -> set[str]:
67
+ """Extract all severity levels found in validation report.
68
+
69
+ Args:
70
+ report: ValidationReport object
71
+
72
+ Returns:
73
+ Set of severity levels found (e.g., {"error", "critical", "high"})
74
+ """
75
+ return self._get_severities_in_results(report.results)
76
+
77
+ def _determine_labels_to_apply(self, found_severities: set[str]) -> set[str]:
78
+ """Determine which labels should be applied based on found severities.
79
+
80
+ Args:
81
+ found_severities: Set of severity levels found in validation
82
+
83
+ Returns:
84
+ Set of label names to apply
85
+ """
86
+ labels_to_apply = set()
87
+ for severity, labels in self.severity_labels.items():
88
+ if severity in found_severities:
89
+ # Support both single labels and lists of labels
90
+ if isinstance(labels, list):
91
+ labels_to_apply.update(labels)
92
+ else:
93
+ labels_to_apply.add(labels)
94
+ return labels_to_apply
95
+
96
+ def _determine_labels_to_remove(self, found_severities: set[str]) -> set[str]:
97
+ """Determine which labels should be removed based on missing severities.
98
+
99
+ Args:
100
+ found_severities: Set of severity levels found in validation
101
+
102
+ Returns:
103
+ Set of label names to remove
104
+ """
105
+ labels_to_remove = set()
106
+ for severity, labels in self.severity_labels.items():
107
+ if severity not in found_severities:
108
+ # Support both single labels and lists of labels
109
+ if isinstance(labels, list):
110
+ labels_to_remove.update(labels)
111
+ else:
112
+ labels_to_remove.add(labels)
113
+ return labels_to_remove
114
+
115
+ async def manage_labels_from_results(
116
+ self, results: list["PolicyValidationResult"]
117
+ ) -> tuple[bool, int, int]:
118
+ """Manage PR labels based on validation results.
119
+
120
+ This method will:
121
+ 1. Determine which severity levels are present in the results
122
+ 2. Add labels for severities that are found
123
+ 3. Remove labels for severities that are not found
124
+
125
+ Args:
126
+ results: List of PolicyValidationResult objects
127
+
128
+ Returns:
129
+ Tuple of (success, labels_added, labels_removed)
130
+ """
131
+ if not self.is_enabled():
132
+ logger.debug("Label management not enabled (no severity_labels configured)")
133
+ return (True, 0, 0)
134
+
135
+ # Get all severities found in results
136
+ found_severities = self._get_severities_in_results(results)
137
+ logger.debug(f"Found severities in results: {found_severities}")
138
+
139
+ # Determine which labels to apply/remove
140
+ labels_to_apply = self._determine_labels_to_apply(found_severities)
141
+ labels_to_remove = self._determine_labels_to_remove(found_severities)
142
+
143
+ logger.debug(f"Labels to apply: {labels_to_apply}")
144
+ logger.debug(f"Labels to remove: {labels_to_remove}")
145
+
146
+ # Get current labels on PR
147
+ current_labels = set(await self.github.get_labels())
148
+ logger.debug(f"Current PR labels: {current_labels}")
149
+
150
+ # Filter: only add labels that aren't already present
151
+ labels_to_add = labels_to_apply - current_labels
152
+
153
+ # Filter: only remove labels that are currently present
154
+ labels_to_actually_remove = labels_to_remove & current_labels
155
+
156
+ success = True
157
+ added_count = 0
158
+ removed_count = 0
159
+
160
+ # Add new labels
161
+ if labels_to_add:
162
+ logger.info(f"Adding labels to PR: {labels_to_add}")
163
+ if await self.github.add_labels(list(labels_to_add)):
164
+ added_count = len(labels_to_add)
165
+ else:
166
+ logger.error("Failed to add labels to PR")
167
+ success = False
168
+
169
+ # Remove old labels
170
+ for label in labels_to_actually_remove:
171
+ logger.info(f"Removing label from PR: {label}")
172
+ if await self.github.remove_label(label):
173
+ removed_count += 1
174
+ else:
175
+ logger.error(f"Failed to remove label: {label}")
176
+ success = False
177
+
178
+ if added_count > 0 or removed_count > 0:
179
+ logger.info(f"Label management complete: added {added_count}, removed {removed_count}")
180
+ else:
181
+ logger.debug("No label changes needed")
182
+
183
+ return (success, added_count, removed_count)
184
+
185
+ async def manage_labels_from_report(self, report: "ValidationReport") -> tuple[bool, int, int]:
186
+ """Manage PR labels based on validation report.
187
+
188
+ This is a convenience method that extracts results from the report
189
+ and calls manage_labels_from_results().
190
+
191
+ Args:
192
+ report: ValidationReport object
193
+
194
+ Returns:
195
+ Tuple of (success, labels_added, labels_removed)
196
+ """
197
+ return await self.manage_labels_from_results(report.results)
@@ -12,7 +12,7 @@ import logging
12
12
  from pathlib import Path
13
13
 
14
14
  from iam_validator.core import constants
15
- from iam_validator.core.aws_fetcher import AWSServiceFetcher
15
+ from iam_validator.core.aws_service import AWSServiceFetcher
16
16
  from iam_validator.core.check_registry import CheckRegistry, create_default_registry
17
17
  from iam_validator.core.config.config_loader import ConfigLoader
18
18
  from iam_validator.core.models import (
@@ -51,6 +51,7 @@ async def validate_policies(
51
51
  config_path: str | None = None,
52
52
  custom_checks_dir: str | None = None,
53
53
  policy_type: PolicyType = "IDENTITY_POLICY",
54
+ aws_services_dir: str | None = None,
54
55
  ) -> list[PolicyValidationResult]:
55
56
  """Validate multiple policies concurrently.
56
57
 
@@ -59,6 +60,8 @@ async def validate_policies(
59
60
  config_path: Optional path to configuration file
60
61
  custom_checks_dir: Optional path to directory containing custom checks for auto-discovery
61
62
  policy_type: Type of policy (IDENTITY_POLICY, RESOURCE_POLICY, SERVICE_CONTROL_POLICY)
63
+ aws_services_dir: Optional path to directory containing pre-downloaded AWS service definitions
64
+ (enables offline mode, overrides config setting)
62
65
 
63
66
  Returns:
64
67
  List of validation results
@@ -110,7 +113,8 @@ async def validate_policies(
110
113
  cache_enabled = config.get_setting("cache_enabled", True)
111
114
  cache_ttl_hours = config.get_setting("cache_ttl_hours", constants.DEFAULT_CACHE_TTL_HOURS)
112
115
  cache_directory = config.get_setting("cache_directory", None)
113
- aws_services_dir = config.get_setting("aws_services_dir", None)
116
+ # CLI argument takes precedence over config file
117
+ services_dir = aws_services_dir or config.get_setting("aws_services_dir", None)
114
118
  cache_ttl_seconds = cache_ttl_hours * constants.SECONDS_PER_HOUR
115
119
 
116
120
  # Validate policies using registry
@@ -118,7 +122,7 @@ async def validate_policies(
118
122
  enable_cache=cache_enabled,
119
123
  cache_ttl=cache_ttl_seconds,
120
124
  cache_dir=cache_directory,
121
- aws_services_dir=aws_services_dir,
125
+ aws_services_dir=services_dir,
122
126
  ) as fetcher:
123
127
  tasks = [
124
128
  _validate_policy_with_registry(
@@ -13,7 +13,9 @@ from iam_validator.core.constants import (
13
13
  REVIEW_IDENTIFIER,
14
14
  SUMMARY_IDENTIFIER,
15
15
  )
16
+ from iam_validator.core.label_manager import LabelManager
16
17
  from iam_validator.core.models import ValidationIssue, ValidationReport
18
+ from iam_validator.core.report import ReportGenerator
17
19
  from iam_validator.integrations.github_integration import GitHubIntegration, ReviewEvent
18
20
 
19
21
  logger = logging.getLogger(__name__)
@@ -32,6 +34,7 @@ class PRCommenter:
32
34
  github: GitHubIntegration | None = None,
33
35
  cleanup_old_comments: bool = True,
34
36
  fail_on_severities: list[str] | None = None,
37
+ severity_labels: dict[str, str | list[str]] | None = None,
35
38
  ):
36
39
  """Initialize PR commenter.
37
40
 
@@ -40,16 +43,24 @@ class PRCommenter:
40
43
  cleanup_old_comments: Whether to clean up old bot comments before posting new ones
41
44
  fail_on_severities: List of severity levels that should trigger REQUEST_CHANGES
42
45
  (e.g., ["error", "critical", "high"])
46
+ severity_labels: Mapping of severity levels to label name(s) for automatic label management
47
+ Supports both single labels and lists of labels per severity.
48
+ Examples:
49
+ - Single: {"error": "iam-validity-error", "critical": "security-critical"}
50
+ - Multiple: {"error": ["iam-error", "needs-fix"], "critical": ["security-critical", "needs-review"]}
51
+ - Mixed: {"error": "iam-validity-error", "critical": ["security-critical", "needs-review"]}
43
52
  """
44
53
  self.github = github
45
54
  self.cleanup_old_comments = cleanup_old_comments
46
55
  self.fail_on_severities = fail_on_severities or ["error", "critical"]
56
+ self.severity_labels = severity_labels or {}
47
57
 
48
58
  async def post_findings_to_pr(
49
59
  self,
50
60
  report: ValidationReport,
51
61
  create_review: bool = True,
52
62
  add_summary_comment: bool = True,
63
+ manage_labels: bool = True,
53
64
  ) -> bool:
54
65
  """Post validation findings to a PR.
55
66
 
@@ -57,6 +68,7 @@ class PRCommenter:
57
68
  report: Validation report with findings
58
69
  create_review: Whether to create a PR review with line comments
59
70
  add_summary_comment: Whether to add a summary comment
71
+ manage_labels: Whether to manage PR labels based on severity findings
60
72
 
61
73
  Returns:
62
74
  True if successful, False otherwise
@@ -81,8 +93,6 @@ class PRCommenter:
81
93
 
82
94
  # Post summary comment (potentially as multiple parts)
83
95
  if add_summary_comment:
84
- from iam_validator.core.report import ReportGenerator
85
-
86
96
  generator = ReportGenerator()
87
97
  comment_parts = generator.generate_github_comment_parts(report)
88
98
 
@@ -104,6 +114,18 @@ class PRCommenter:
104
114
  logger.error("Failed to post review comments")
105
115
  success = False
106
116
 
117
+ # Manage PR labels based on severity findings
118
+ if manage_labels and self.severity_labels:
119
+ label_manager = LabelManager(self.github, self.severity_labels)
120
+ label_success, added, removed = await label_manager.manage_labels_from_report(report)
121
+
122
+ if not label_success:
123
+ logger.error("Failed to manage PR labels")
124
+ success = False
125
+ else:
126
+ if added > 0 or removed > 0:
127
+ logger.info(f"Label management: added {added}, removed {removed}")
128
+
107
129
  return success
108
130
 
109
131
  async def _post_review_comments(self, report: ValidationReport) -> bool:
@@ -288,7 +310,7 @@ class PRCommenter:
288
310
 
289
311
  return mapping
290
312
 
291
- except Exception as e:
313
+ except Exception as e: # pylint: disable=broad-exception-caught
292
314
  logger.warning(f"Could not parse {policy_file} for line mapping: {e}")
293
315
  return {}
294
316
 
@@ -369,7 +391,7 @@ class PRCommenter:
369
391
 
370
392
  return None
371
393
 
372
- except Exception as e:
394
+ except Exception as e: # pylint: disable=broad-exception-caught
373
395
  logger.debug(f"Could not search {policy_file}: {e}")
374
396
  return None
375
397
 
@@ -398,15 +420,20 @@ async def post_report_to_pr(
398
420
 
399
421
  report = ValidationReport.model_validate(report_data)
400
422
 
401
- # Load config to get fail_on_severity setting
423
+ # Load config to get fail_on_severity and severity_labels settings
402
424
  from iam_validator.core.config.config_loader import ConfigLoader
403
425
 
404
426
  config = ConfigLoader.load_config(config_path)
405
427
  fail_on_severities = config.get_setting("fail_on_severity", ["error", "critical"])
428
+ severity_labels = config.get_setting("severity_labels", {})
406
429
 
407
430
  # Post to PR
408
431
  async with GitHubIntegration() as github:
409
- commenter = PRCommenter(github, fail_on_severities=fail_on_severities)
432
+ commenter = PRCommenter(
433
+ github,
434
+ fail_on_severities=fail_on_severities,
435
+ severity_labels=severity_labels,
436
+ )
410
437
  return await commenter.post_findings_to_pr(
411
438
  report,
412
439
  create_review=create_review,
@@ -419,6 +446,6 @@ async def post_report_to_pr(
419
446
  except json.JSONDecodeError as e:
420
447
  logger.error(f"Invalid JSON in report file: {e}")
421
448
  return False
422
- except Exception as e:
449
+ except Exception as e: # pylint: disable=broad-exception-caught
423
450
  logger.error(f"Failed to post report to PR: {e}")
424
451
  return False
@@ -37,7 +37,7 @@ Quick Start:
37
37
 
38
38
  # === High-level validation functions (shortcuts) ===
39
39
  # === AWS utilities ===
40
- from iam_validator.core.aws_fetcher import AWSServiceFetcher
40
+ from iam_validator.core.aws_service import AWSServiceFetcher
41
41
 
42
42
  # === Core validation components (for advanced usage) ===
43
43
  from iam_validator.core.check_registry import CheckRegistry, PolicyCheck
@@ -8,7 +8,7 @@ and make the validation API more convenient to use.
8
8
  from contextlib import asynccontextmanager
9
9
  from pathlib import Path
10
10
 
11
- from iam_validator.core.aws_fetcher import AWSServiceFetcher
11
+ from iam_validator.core.aws_service import AWSServiceFetcher
12
12
  from iam_validator.core.models import PolicyValidationResult
13
13
  from iam_validator.core.policy_checks import validate_policies
14
14
  from iam_validator.core.policy_loader import PolicyLoader
@@ -6,7 +6,7 @@ easy to develop custom IAM policy checks.
6
6
  """
7
7
 
8
8
  from iam_validator.checks.utils.wildcard_expansion import expand_wildcard_actions
9
- from iam_validator.core.aws_fetcher import AWSServiceFetcher
9
+ from iam_validator.core.aws_service import AWSServiceFetcher
10
10
  from iam_validator.core.models import ValidationIssue
11
11
  from iam_validator.sdk.arn_matching import arn_matches, arn_strictly_valid
12
12
 
@@ -1,87 +0,0 @@
1
- iam_validator/__init__.py,sha256=APnMR3Fu4fHhxfsHBvUM2dJIwazgvLKQbfOsSgFPidg,693
2
- iam_validator/__main__.py,sha256=to_nz3n_IerJpVVZZ6WSFlFR5s_06J0csfPOTfQZG8g,197
3
- iam_validator/__version__.py,sha256=3gyLuIf6oV1A2rFZSmXco3rdq2hmgGAYEB2we_Su_TU,361
4
- iam_validator/checks/__init__.py,sha256=OTkPnmlelu4YjMO8krjhu2wXiTV72RzopA5u1SfPQA0,1990
5
- iam_validator/checks/action_condition_enforcement.py,sha256=XztLhckc3Xc5RwxlMM2U2M81TNyt9M5xgBwn5fqHK1M,39141
6
- iam_validator/checks/action_resource_matching.py,sha256=BTrweeD1SNy9hcsfIDEN4L1E7oLNiVLyg-yerlZ5eC0,19356
7
- iam_validator/checks/action_validation.py,sha256=t8JPbvLiQb0Lx7SF_gruxehVgy0WU5uWppDJhhsSnI0,2580
8
- iam_validator/checks/condition_key_validation.py,sha256=VaOo1CLrMVRi23oUE1nMlKAgzNY9_jrnnEfGbdfF53g,3982
9
- iam_validator/checks/condition_type_mismatch.py,sha256=VK7KxkdeX2FmKWJUaZwJXSFQUxqtnqGj5sigOuhGCWo,10707
10
- iam_validator/checks/full_wildcard.py,sha256=ywD762BOV8WxFuTTARkaGMJn27f3ZZVuZUjKo8URnTc,2281
11
- iam_validator/checks/mfa_condition_check.py,sha256=YCBX3tFTQRmVTAed_W-Tu1b6WqD2LBYyom53P7lBjh4,4935
12
- iam_validator/checks/policy_size.py,sha256=ibgmrErpkz6OfUAN6bFuHe1KHzpzzra9gHwNtVAkPWc,5729
13
- iam_validator/checks/policy_structure.py,sha256=CQh1FsqVOFENAQe7mbyRzlIntjMs0gAwv6wUUqsdXqc,22636
14
- iam_validator/checks/policy_type_validation.py,sha256=8wnaCmvFb_q4ToqPR8B1exwFdwwqXYEf-Dw8YUgnj0s,15873
15
- iam_validator/checks/principal_validation.py,sha256=HYxcUtTWDvWh9AZbqtUSWrZOJrNGALRu1jrDydNF3xk,27895
16
- iam_validator/checks/resource_validation.py,sha256=8FAVPxAsralAPlao5GeJNSutqKC7DLWYZaI7CHhLs_E,6052
17
- iam_validator/checks/sensitive_action.py,sha256=1-Bumsk_fPHTCW0iRmIHaqMaQY-1uYI5vH2uO3YGvf0,9765
18
- iam_validator/checks/service_wildcard.py,sha256=brdm4cm7bOgpHB8jyAzGEGPQzoytaFIy5CgfUVgamv8,4012
19
- iam_validator/checks/set_operator_validation.py,sha256=AnOC7Ywd3tk7zdqNkQXAAdtsiCxKwVQ6pGsbpsopZfY,7465
20
- iam_validator/checks/sid_uniqueness.py,sha256=ZScVKa1RROhrY2uSOUSeeIK4xXNVzfnp9hn5Jr-TVHk,6984
21
- iam_validator/checks/trust_policy_validation.py,sha256=q3YFqMk3MYa4pEr1CPCCPvMcbv8-6rzT74EfsgZ6k0k,17880
22
- iam_validator/checks/wildcard_action.py,sha256=-yS4o2SgDRMEp_SA_kcwmmf6do0gWppkP1rpg7IP9Zg,2023
23
- iam_validator/checks/wildcard_resource.py,sha256=zsz7nfvvqnOYLMUfM1w7E46267Y4SrBF4x1Nvgg-B7U,5467
24
- iam_validator/checks/utils/__init__.py,sha256=j0X4ibUB6RGx2a-kNoJnlVZwHfoEvzZsIeTmJIAoFzA,45
25
- iam_validator/checks/utils/policy_level_checks.py,sha256=2V60C0zhKfsFPjQ-NMlD3EemtwA9S6-4no8nETgXdQE,5274
26
- iam_validator/checks/utils/sensitive_action_matcher.py,sha256=qDXcJa_2sCJu9pBbjDlI7x5lPtLRc6jQCpKPMheCOJQ,11215
27
- iam_validator/checks/utils/wildcard_expansion.py,sha256=JK8iYcYpOzi5RN4IvIMBCbzkCEhVRJxZDKLZIKgD8nY,3131
28
- iam_validator/commands/__init__.py,sha256=M-5bo8w0TCWydK0cXgJyPD2fmk8bpQs-3b26YbgLzlc,565
29
- iam_validator/commands/analyze.py,sha256=rvLBJ5_A3HB530xtixhaIsC19QON68olEQnn8TievgI,20784
30
- iam_validator/commands/base.py,sha256=5baCCMwxz7pdQ6XMpWfXFNz7i1l5dB8Qv9dKKR04Gzs,1074
31
- iam_validator/commands/cache.py,sha256=p4ucRVuh42sbK3Lk0b610L3ofAR5TnUreF00fpO6VFg,14219
32
- iam_validator/commands/download_services.py,sha256=KKz3ybMLT8DQUf9aFZ0tilJ-o1b6PE8Pf1pC4K6cT8I,9175
33
- iam_validator/commands/post_to_pr.py,sha256=CvUXs2xvO-UhluxdfNM6F0TCWD8hDBEOiYw60fm1Dms,2363
34
- iam_validator/commands/validate.py,sha256=hau8oPCNGya8gAUrvbhQxAlR4fhaGKzl7MQSryBgQfQ,23381
35
- iam_validator/core/__init__.py,sha256=JyeUUjuVsXFPkxLjsZ9omLPAFudWR-lQ_8oBX9jTY70,376
36
- iam_validator/core/access_analyzer.py,sha256=mtMaY-FnKjKEVITky_9ywZe1FaCAm61ElRv5Z_ZeC7E,24562
37
- iam_validator/core/access_analyzer_report.py,sha256=UMm2RNGj2rAKav1zsCw_htQZZRwRC0jjayd2zvKma1A,24896
38
- iam_validator/core/aws_fetcher.py,sha256=U9aE1kJ6HqJYYFpT8bq90dAAKGvmy8wKV6v_1aQCno4,41741
39
- iam_validator/core/check_registry.py,sha256=5hmhKiF45cenLYviGMAEhb08_Fqvu9PFxXzBmLEQuqk,22639
40
- iam_validator/core/cli.py,sha256=PkXiZjlgrQ21QustBbspefYsdbxst4gxoClyG2_HQR8,3843
41
- iam_validator/core/condition_validators.py,sha256=7zBjlcf2xGFKGbcFrXSLvWT5tFhWxoqwzhsJqS2E8uY,21524
42
- iam_validator/core/constants.py,sha256=H3eH0yddn5Dk-xZxJWtuvluRIpuXKYGiiteBSHPpJoI,5560
43
- iam_validator/core/ignore_patterns.py,sha256=pZqDJBtkbck-85QK5eFPM5ZOPEKs3McRh3avqiCT5z0,10398
44
- iam_validator/core/models.py,sha256=f5d9ovtO1xMSwhyBrKIgc2psEq0eugnd3S3ioqurqEE,13242
45
- iam_validator/core/policy_checks.py,sha256=le1ovFm3qcgq3JG-L336h4nCSfol0PzL65RC3Beslwk,8520
46
- iam_validator/core/policy_loader.py,sha256=2KJnXzGg3g9pDXWZHk3DO0xpZnZZ-wXWFEOdQ_naJ8s,17862
47
- iam_validator/core/pr_commenter.py,sha256=MU-t7SfdHUpSc6BDbh8_dNAbxDiG-bZBCry-jUXivAc,15066
48
- iam_validator/core/report.py,sha256=kzSeWnT1LqWZVA5pqKKz-maVowXVj0djdoShfRhhpz4,35899
49
- iam_validator/core/config/__init__.py,sha256=CWSyIA7kEyzrskEenjYbs9Iih10BXRpiY9H2dHg61rU,2671
50
- iam_validator/core/config/aws_api.py,sha256=HLIzOItQ0A37wxHcgWck6ZFO0wmNY8JNTiWMMK6JKYU,1248
51
- iam_validator/core/config/aws_global_conditions.py,sha256=gdmMxXGBy95B3uYUG-J7rnM6Ixgc6L7Y9Pcd2XAMb60,7170
52
- iam_validator/core/config/category_suggestions.py,sha256=QlrYi4BTkxDSTlL7NZGE9BWN-atWetZ6XjkI9F_7YzI,4370
53
- iam_validator/core/config/condition_requirements.py,sha256=qauIP73HFnOw1dchUeFpg1x7Y7QWkILo3GfxV_dxdQo,7696
54
- iam_validator/core/config/config_loader.py,sha256=qKD8aR8YAswaFf68pnYJLFNwKznvcc6lNxSQWU3i6SY,17713
55
- iam_validator/core/config/defaults.py,sha256=rWzDrlw0AAudtm_If6zjNFvruLg71jpLJEdRgKYSKMQ,27917
56
- iam_validator/core/config/principal_requirements.py,sha256=VCX7fBDgeDTJQyoz7_x7GI7Kf9O1Eu-sbihoHOrKv6o,15105
57
- iam_validator/core/config/sensitive_actions.py,sha256=uATDIp_TD3OQQlsYTZp79qd1mSK2Bf9hJ0JwcqLBr84,25344
58
- iam_validator/core/config/service_principals.py,sha256=8pys5H_yycVJ9KTyimAKFYBg83Aol2Iri53wiHjtnEM,3959
59
- iam_validator/core/config/wildcards.py,sha256=H_v6hb-rZ0UUz4cul9lxkVI39e6knaK4Y-MbWz2Ebpw,3228
60
- iam_validator/core/formatters/__init__.py,sha256=fnCKAEBXItnOf2m4rhVs7zwMaTxbG6ESh3CF8V5j5ec,868
61
- iam_validator/core/formatters/base.py,sha256=SShDeDiy5mYQnS6BpA8xYg91N-KX1EObkOtlrVHqx1Q,4451
62
- iam_validator/core/formatters/console.py,sha256=FdTp7AzeILCWrUynSvSew8QJKGOMJaAA9_YiQJd-uco,2196
63
- iam_validator/core/formatters/csv.py,sha256=pPqgvGh4KtD5Qm36xnMaDAavXYR6MlQhs4zbcrxT550,5941
64
- iam_validator/core/formatters/enhanced.py,sha256=TVtkcTIow8NGoLhG45-5ms-_PTxyxMcAHxf_uPMyKAc,18155
65
- iam_validator/core/formatters/html.py,sha256=j4sQi-wXiD9kCHldW5JCzbJe0frhiP5uQI9KlH3Sj_g,22994
66
- iam_validator/core/formatters/json.py,sha256=A7gZ8P32GEdbDvrSn6v56yQ4fOP_kyMaoFVXG2bgnew,939
67
- iam_validator/core/formatters/markdown.py,sha256=dk4STeY-tOEZsVrlmolIEqZvWYP9JhRtygxxNA49DEE,2293
68
- iam_validator/core/formatters/sarif.py,sha256=O3pn7whqFq5xxk-tuoqSb2k4Fk5ai_A2SKX_ph8GLV4,10469
69
- iam_validator/integrations/__init__.py,sha256=7Hlor_X9j0NZaEjFuSvoXAAuSKQ-zgY19Rk-Dz3JpKo,616
70
- iam_validator/integrations/github_integration.py,sha256=EnrolMq3uZbKWPxUMhYnqcKAfic6Fb8qJzieDruKqsc,26485
71
- iam_validator/integrations/ms_teams.py,sha256=t2PlWuTDb6GGH-eDU1jnOKd8D1w4FCB68bahGA7MJcE,14475
72
- iam_validator/sdk/__init__.py,sha256=fRDSXAclGmCU3KDft4StL8JUcpAsdzwIRf8mVj461q0,5306
73
- iam_validator/sdk/arn_matching.py,sha256=HSDpLltOYISq-SoPebAlM89mKOaUaghq_04urchEFDA,12778
74
- iam_validator/sdk/context.py,sha256=SBFeedu8rhCzFA-zC2cH4wLZxEJT6XOW30hIZAyXPVU,6826
75
- iam_validator/sdk/exceptions.py,sha256=tm91TxIwU157U_UHN7w5qICf_OhU11agj6pV5W_YP-4,1023
76
- iam_validator/sdk/helpers.py,sha256=OVBg4xrW95LT74wXCg1LQkba9kw5RfFqeCLuTqhgL-A,5697
77
- iam_validator/sdk/policy_utils.py,sha256=CZS1OGSdiWsd2lsCwg0BDcUNWa61tUwgvn-P5rKqeN8,12987
78
- iam_validator/sdk/shortcuts.py,sha256=EVNSYV7rv4TFH03ulsZ3mS1UVmTSp2jKpc2AXs4j1q4,8531
79
- iam_validator/utils/__init__.py,sha256=NveA2F3G1E6-ANZzFr7J6Q6u5mogvMp862iFokmYuCs,1021
80
- iam_validator/utils/cache.py,sha256=wOQKOBeoG6QqC5f0oXcHz63Cjtu_-SsSS-0pTSwyAiM,3254
81
- iam_validator/utils/regex.py,sha256=xHoMECttb7qaMhts-c9b0GIxdhHNZTt-UBr7wNhWfzg,6219
82
- iam_validator/utils/terminal.py,sha256=FsRaRMH_JAyDgXWBCOgOEhbS89cs17HCmKYoughq5io,724
83
- iam_policy_validator-1.8.0.dist-info/METADATA,sha256=vccDFxkghziff8eO-K7hIVreQjE5gkLsWrIS5b61EwY,16174
84
- iam_policy_validator-1.8.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
85
- iam_policy_validator-1.8.0.dist-info/entry_points.txt,sha256=8HtWd8O7mvPiPdZR5YbzY8or_qcqLM4-pKaFdhtFT8M,62
86
- iam_policy_validator-1.8.0.dist-info/licenses/LICENSE,sha256=AMnbFTBDcK4_MITe2wiQBkj0vg-jjBBhsc43ydC7tt4,1098
87
- iam_policy_validator-1.8.0.dist-info/RECORD,,