iam-policy-validator 1.13.1__py3-none-any.whl → 1.14.1__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.13.1.dist-info → iam_policy_validator-1.14.1.dist-info}/METADATA +1 -1
- {iam_policy_validator-1.13.1.dist-info → iam_policy_validator-1.14.1.dist-info}/RECORD +45 -39
- iam_validator/__version__.py +1 -1
- iam_validator/checks/action_condition_enforcement.py +6 -0
- iam_validator/checks/action_resource_matching.py +12 -12
- iam_validator/checks/action_validation.py +1 -0
- iam_validator/checks/condition_key_validation.py +2 -0
- iam_validator/checks/condition_type_mismatch.py +3 -0
- iam_validator/checks/full_wildcard.py +1 -0
- iam_validator/checks/mfa_condition_check.py +2 -0
- iam_validator/checks/policy_structure.py +9 -0
- iam_validator/checks/policy_type_validation.py +11 -0
- iam_validator/checks/principal_validation.py +5 -0
- iam_validator/checks/resource_validation.py +4 -0
- iam_validator/checks/sensitive_action.py +1 -0
- iam_validator/checks/service_wildcard.py +6 -3
- iam_validator/checks/set_operator_validation.py +3 -0
- iam_validator/checks/sid_uniqueness.py +2 -0
- iam_validator/checks/trust_policy_validation.py +3 -0
- iam_validator/checks/utils/__init__.py +16 -0
- iam_validator/checks/utils/action_parser.py +149 -0
- iam_validator/checks/wildcard_action.py +1 -0
- iam_validator/checks/wildcard_resource.py +231 -4
- iam_validator/commands/analyze.py +19 -1
- iam_validator/commands/completion.py +6 -2
- iam_validator/commands/validate.py +231 -12
- iam_validator/core/aws_service/fetcher.py +21 -9
- iam_validator/core/codeowners.py +245 -0
- iam_validator/core/config/check_documentation.py +390 -0
- iam_validator/core/config/config_loader.py +199 -0
- iam_validator/core/config/defaults.py +25 -0
- iam_validator/core/constants.py +1 -0
- iam_validator/core/diff_parser.py +8 -4
- iam_validator/core/finding_fingerprint.py +131 -0
- iam_validator/core/formatters/sarif.py +370 -128
- iam_validator/core/ignore_processor.py +309 -0
- iam_validator/core/ignored_findings.py +400 -0
- iam_validator/core/models.py +54 -4
- iam_validator/core/policy_loader.py +313 -4
- iam_validator/core/pr_commenter.py +223 -22
- iam_validator/core/report.py +22 -6
- iam_validator/integrations/github_integration.py +881 -123
- {iam_policy_validator-1.13.1.dist-info → iam_policy_validator-1.14.1.dist-info}/WHEEL +0 -0
- {iam_policy_validator-1.13.1.dist-info → iam_policy_validator-1.14.1.dist-info}/entry_points.txt +0 -0
- {iam_policy_validator-1.13.1.dist-info → iam_policy_validator-1.14.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""Finding fingerprint generation for stable issue identification.
|
|
2
|
+
|
|
3
|
+
This module provides a way to generate unique, deterministic identifiers
|
|
4
|
+
for validation findings that survive code changes within a PR. These
|
|
5
|
+
fingerprints are used to track which findings have been ignored by CODEOWNERS.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import hashlib
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from iam_validator.core.models import ValidationIssue
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def compute_finding_hash(
|
|
19
|
+
file_path: str,
|
|
20
|
+
check_id: str | None,
|
|
21
|
+
issue_type: str,
|
|
22
|
+
statement_sid: str | None,
|
|
23
|
+
statement_index: int,
|
|
24
|
+
action: str | None = None,
|
|
25
|
+
resource: str | None = None,
|
|
26
|
+
condition_key: str | None = None,
|
|
27
|
+
) -> str:
|
|
28
|
+
"""Compute a deterministic 16-character hash for a finding.
|
|
29
|
+
|
|
30
|
+
This is a standalone function to avoid cyclic imports when called
|
|
31
|
+
from models.py.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
file_path: Relative path to the policy file
|
|
35
|
+
check_id: Check that found the issue
|
|
36
|
+
issue_type: Type of issue
|
|
37
|
+
statement_sid: Statement ID if available
|
|
38
|
+
statement_index: Statement index
|
|
39
|
+
action: Specific action (optional)
|
|
40
|
+
resource: Specific resource (optional)
|
|
41
|
+
condition_key: Condition key (optional)
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
16-character hex string uniquely identifying this finding
|
|
45
|
+
"""
|
|
46
|
+
# Use SID if available, otherwise fall back to index
|
|
47
|
+
statement_id = statement_sid if statement_sid else f"idx:{statement_index}"
|
|
48
|
+
|
|
49
|
+
components = [
|
|
50
|
+
file_path,
|
|
51
|
+
check_id or "",
|
|
52
|
+
issue_type,
|
|
53
|
+
statement_id,
|
|
54
|
+
action or "",
|
|
55
|
+
resource or "",
|
|
56
|
+
condition_key or "",
|
|
57
|
+
]
|
|
58
|
+
combined = "|".join(components)
|
|
59
|
+
return hashlib.sha256(combined.encode()).hexdigest()[:16]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass(frozen=True, slots=True)
|
|
63
|
+
class FindingFingerprint:
|
|
64
|
+
"""Unique identifier for a validation finding across runs.
|
|
65
|
+
|
|
66
|
+
The fingerprint is based on stable attributes of the finding that
|
|
67
|
+
are unlikely to change when code is modified within the same PR.
|
|
68
|
+
Uses frozen=True for immutability and slots=True for memory efficiency.
|
|
69
|
+
|
|
70
|
+
Attributes:
|
|
71
|
+
file_path: Relative path to the policy file
|
|
72
|
+
check_id: Check that found the issue (e.g., "sensitive_action")
|
|
73
|
+
issue_type: Type of issue (e.g., "invalid_action")
|
|
74
|
+
statement_sid: Statement ID if available (more stable than index)
|
|
75
|
+
statement_index: Fallback when no SID is present
|
|
76
|
+
action: Specific action (for action-related issues)
|
|
77
|
+
resource: Specific resource (for resource-related issues)
|
|
78
|
+
condition_key: Specific condition key (for condition issues)
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
file_path: str
|
|
82
|
+
check_id: str
|
|
83
|
+
issue_type: str
|
|
84
|
+
statement_sid: str | None
|
|
85
|
+
statement_index: int
|
|
86
|
+
action: str | None
|
|
87
|
+
resource: str | None
|
|
88
|
+
condition_key: str | None
|
|
89
|
+
|
|
90
|
+
def to_hash(self) -> str:
|
|
91
|
+
"""Generate deterministic 16-character hash for storage.
|
|
92
|
+
|
|
93
|
+
The hash is based on all fingerprint components joined with a
|
|
94
|
+
delimiter. Uses SHA-256 truncated to 16 characters for a good
|
|
95
|
+
balance between uniqueness and storage efficiency.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
16-character hex string uniquely identifying this finding
|
|
99
|
+
"""
|
|
100
|
+
return compute_finding_hash(
|
|
101
|
+
file_path=self.file_path,
|
|
102
|
+
check_id=self.check_id,
|
|
103
|
+
issue_type=self.issue_type,
|
|
104
|
+
statement_sid=self.statement_sid,
|
|
105
|
+
statement_index=self.statement_index,
|
|
106
|
+
action=self.action,
|
|
107
|
+
resource=self.resource,
|
|
108
|
+
condition_key=self.condition_key,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def from_issue(cls, issue: ValidationIssue, file_path: str) -> FindingFingerprint:
|
|
113
|
+
"""Create fingerprint from a ValidationIssue.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
issue: The validation issue to fingerprint
|
|
117
|
+
file_path: Relative path to the policy file
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
FindingFingerprint instance for the issue
|
|
121
|
+
"""
|
|
122
|
+
return cls(
|
|
123
|
+
file_path=file_path,
|
|
124
|
+
check_id=issue.check_id or "",
|
|
125
|
+
issue_type=issue.issue_type,
|
|
126
|
+
statement_sid=issue.statement_sid,
|
|
127
|
+
statement_index=issue.statement_index,
|
|
128
|
+
action=issue.action,
|
|
129
|
+
resource=issue.resource,
|
|
130
|
+
condition_key=issue.condition_key,
|
|
131
|
+
)
|