regscale-cli 6.27.3.0__py3-none-any.whl → 6.28.1.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 regscale-cli might be problematic. Click here for more details.
- regscale/_version.py +1 -1
- regscale/core/app/utils/app_utils.py +11 -2
- regscale/dev/cli.py +26 -0
- regscale/dev/version.py +72 -0
- regscale/integrations/commercial/__init__.py +15 -1
- regscale/integrations/commercial/amazon/amazon/__init__.py +0 -0
- regscale/integrations/commercial/amazon/amazon/common.py +204 -0
- regscale/integrations/commercial/amazon/common.py +48 -58
- regscale/integrations/commercial/aws/audit_manager_compliance.py +2671 -0
- regscale/integrations/commercial/aws/cli.py +3093 -55
- regscale/integrations/commercial/aws/cloudtrail_control_mappings.py +333 -0
- regscale/integrations/commercial/aws/cloudtrail_evidence.py +501 -0
- regscale/integrations/commercial/aws/cloudwatch_control_mappings.py +357 -0
- regscale/integrations/commercial/aws/cloudwatch_evidence.py +490 -0
- regscale/integrations/commercial/aws/config_compliance.py +914 -0
- regscale/integrations/commercial/aws/conformance_pack_mappings.py +198 -0
- regscale/integrations/commercial/aws/evidence_generator.py +283 -0
- regscale/integrations/commercial/aws/guardduty_control_mappings.py +340 -0
- regscale/integrations/commercial/aws/guardduty_evidence.py +1053 -0
- regscale/integrations/commercial/aws/iam_control_mappings.py +368 -0
- regscale/integrations/commercial/aws/iam_evidence.py +574 -0
- regscale/integrations/commercial/aws/inventory/__init__.py +223 -22
- regscale/integrations/commercial/aws/inventory/base.py +107 -5
- regscale/integrations/commercial/aws/inventory/resources/audit_manager.py +513 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudtrail.py +315 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudtrail_logs_metadata.py +476 -0
- regscale/integrations/commercial/aws/inventory/resources/cloudwatch.py +191 -0
- regscale/integrations/commercial/aws/inventory/resources/compute.py +66 -9
- regscale/integrations/commercial/aws/inventory/resources/config.py +464 -0
- regscale/integrations/commercial/aws/inventory/resources/containers.py +74 -9
- regscale/integrations/commercial/aws/inventory/resources/database.py +106 -31
- regscale/integrations/commercial/aws/inventory/resources/guardduty.py +286 -0
- regscale/integrations/commercial/aws/inventory/resources/iam.py +470 -0
- regscale/integrations/commercial/aws/inventory/resources/inspector.py +476 -0
- regscale/integrations/commercial/aws/inventory/resources/integration.py +175 -61
- regscale/integrations/commercial/aws/inventory/resources/kms.py +447 -0
- regscale/integrations/commercial/aws/inventory/resources/networking.py +103 -67
- regscale/integrations/commercial/aws/inventory/resources/s3.py +394 -0
- regscale/integrations/commercial/aws/inventory/resources/security.py +268 -72
- regscale/integrations/commercial/aws/inventory/resources/securityhub.py +473 -0
- regscale/integrations/commercial/aws/inventory/resources/storage.py +53 -29
- regscale/integrations/commercial/aws/inventory/resources/systems_manager.py +657 -0
- regscale/integrations/commercial/aws/inventory/resources/vpc.py +655 -0
- regscale/integrations/commercial/aws/kms_control_mappings.py +288 -0
- regscale/integrations/commercial/aws/kms_evidence.py +879 -0
- regscale/integrations/commercial/aws/ocsf/__init__.py +7 -0
- regscale/integrations/commercial/aws/ocsf/constants.py +115 -0
- regscale/integrations/commercial/aws/ocsf/mapper.py +435 -0
- regscale/integrations/commercial/aws/org_control_mappings.py +286 -0
- regscale/integrations/commercial/aws/org_evidence.py +666 -0
- regscale/integrations/commercial/aws/s3_control_mappings.py +356 -0
- regscale/integrations/commercial/aws/s3_evidence.py +632 -0
- regscale/integrations/commercial/aws/scanner.py +851 -206
- regscale/integrations/commercial/aws/security_hub.py +319 -0
- regscale/integrations/commercial/aws/session_manager.py +282 -0
- regscale/integrations/commercial/aws/ssm_control_mappings.py +291 -0
- regscale/integrations/commercial/aws/ssm_evidence.py +492 -0
- regscale/integrations/commercial/synqly/ticketing.py +27 -0
- regscale/integrations/compliance_integration.py +308 -38
- regscale/integrations/due_date_handler.py +3 -0
- regscale/integrations/scanner_integration.py +399 -84
- regscale/models/integration_models/cisa_kev_data.json +65 -5
- regscale/models/integration_models/synqly_models/capabilities.json +1 -1
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +17 -9
- regscale/models/regscale_models/assessment.py +2 -1
- regscale/models/regscale_models/control_objective.py +74 -5
- regscale/models/regscale_models/file.py +2 -0
- regscale/models/regscale_models/issue.py +2 -5
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/METADATA +1 -1
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/RECORD +113 -34
- tests/regscale/integrations/commercial/aws/__init__.py +0 -0
- tests/regscale/integrations/commercial/aws/test_audit_manager_compliance.py +1304 -0
- tests/regscale/integrations/commercial/aws/test_audit_manager_evidence_aggregation.py +341 -0
- tests/regscale/integrations/commercial/aws/test_aws_audit_manager_collector.py +1155 -0
- tests/regscale/integrations/commercial/aws/test_aws_cloudtrail_collector.py +534 -0
- tests/regscale/integrations/commercial/aws/test_aws_config_collector.py +400 -0
- tests/regscale/integrations/commercial/aws/test_aws_guardduty_collector.py +315 -0
- tests/regscale/integrations/commercial/aws/test_aws_iam_collector.py +458 -0
- tests/regscale/integrations/commercial/aws/test_aws_inspector_collector.py +353 -0
- tests/regscale/integrations/commercial/aws/test_aws_inventory_integration.py +530 -0
- tests/regscale/integrations/commercial/aws/test_aws_kms_collector.py +919 -0
- tests/regscale/integrations/commercial/aws/test_aws_s3_collector.py +722 -0
- tests/regscale/integrations/commercial/aws/test_aws_scanner_integration.py +722 -0
- tests/regscale/integrations/commercial/aws/test_aws_securityhub_collector.py +792 -0
- tests/regscale/integrations/commercial/aws/test_aws_systems_manager_collector.py +918 -0
- tests/regscale/integrations/commercial/aws/test_aws_vpc_collector.py +996 -0
- tests/regscale/integrations/commercial/aws/test_cli_evidence.py +431 -0
- tests/regscale/integrations/commercial/aws/test_cloudtrail_control_mappings.py +452 -0
- tests/regscale/integrations/commercial/aws/test_cloudtrail_evidence.py +788 -0
- tests/regscale/integrations/commercial/aws/test_config_compliance.py +298 -0
- tests/regscale/integrations/commercial/aws/test_conformance_pack_mappings.py +200 -0
- tests/regscale/integrations/commercial/aws/test_evidence_generator.py +386 -0
- tests/regscale/integrations/commercial/aws/test_guardduty_control_mappings.py +564 -0
- tests/regscale/integrations/commercial/aws/test_guardduty_evidence.py +1041 -0
- tests/regscale/integrations/commercial/aws/test_iam_control_mappings.py +718 -0
- tests/regscale/integrations/commercial/aws/test_iam_evidence.py +1375 -0
- tests/regscale/integrations/commercial/aws/test_kms_control_mappings.py +656 -0
- tests/regscale/integrations/commercial/aws/test_kms_evidence.py +1163 -0
- tests/regscale/integrations/commercial/aws/test_ocsf_mapper.py +370 -0
- tests/regscale/integrations/commercial/aws/test_org_control_mappings.py +546 -0
- tests/regscale/integrations/commercial/aws/test_org_evidence.py +1240 -0
- tests/regscale/integrations/commercial/aws/test_s3_control_mappings.py +672 -0
- tests/regscale/integrations/commercial/aws/test_s3_evidence.py +987 -0
- tests/regscale/integrations/commercial/aws/test_scanner_evidence.py +373 -0
- tests/regscale/integrations/commercial/aws/test_security_hub_config_filtering.py +539 -0
- tests/regscale/integrations/commercial/aws/test_session_manager.py +516 -0
- tests/regscale/integrations/commercial/aws/test_ssm_control_mappings.py +588 -0
- tests/regscale/integrations/commercial/aws/test_ssm_evidence.py +735 -0
- tests/regscale/integrations/commercial/test_aws.py +55 -56
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/LICENSE +0 -0
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/WHEEL +0 -0
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/entry_points.txt +0 -0
- {regscale_cli-6.27.3.0.dist-info → regscale_cli-6.28.1.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""AWS CloudTrail Control Mappings for RegScale Compliance Integration."""
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger("regscale")
|
|
9
|
+
|
|
10
|
+
# NIST 800-53 R5 Control Mappings for AWS CloudTrail
|
|
11
|
+
CLOUDTRAIL_CONTROL_MAPPINGS = {
|
|
12
|
+
"AU-2": {
|
|
13
|
+
"name": "Event Logging",
|
|
14
|
+
"description": "Identify the types of events that the system is capable of logging",
|
|
15
|
+
"checks": {
|
|
16
|
+
"trail_enabled": {
|
|
17
|
+
"weight": 100,
|
|
18
|
+
"pass_criteria": "CloudTrail trails are enabled and logging",
|
|
19
|
+
"fail_criteria": "CloudTrail trails are disabled or not configured",
|
|
20
|
+
},
|
|
21
|
+
"management_events": {
|
|
22
|
+
"weight": 95,
|
|
23
|
+
"pass_criteria": "Management events are being logged",
|
|
24
|
+
"fail_criteria": "Management events logging not configured",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
"AU-3": {
|
|
29
|
+
"name": "Content of Audit Records",
|
|
30
|
+
"description": "Ensure audit records contain information that establishes what type of event occurred",
|
|
31
|
+
"checks": {
|
|
32
|
+
"event_selectors": {
|
|
33
|
+
"weight": 100,
|
|
34
|
+
"pass_criteria": "Event selectors configured to capture necessary events",
|
|
35
|
+
"fail_criteria": "Event selectors not configured or insufficient",
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
"AU-6": {
|
|
40
|
+
"name": "Audit Record Review, Analysis, and Reporting",
|
|
41
|
+
"description": "Review and analyze system audit records for indications of inappropriate activity",
|
|
42
|
+
"checks": {
|
|
43
|
+
"cloudwatch_integration": {
|
|
44
|
+
"weight": 100,
|
|
45
|
+
"pass_criteria": "CloudTrail integrated with CloudWatch Logs for analysis",
|
|
46
|
+
"fail_criteria": "No CloudWatch Logs integration configured",
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
"AU-9": {
|
|
51
|
+
"name": "Protection of Audit Information",
|
|
52
|
+
"description": "Protect audit information and audit logging tools from unauthorized access",
|
|
53
|
+
"checks": {
|
|
54
|
+
"log_file_validation": {
|
|
55
|
+
"weight": 100,
|
|
56
|
+
"pass_criteria": "Log file validation enabled",
|
|
57
|
+
"fail_criteria": "Log file validation not enabled",
|
|
58
|
+
},
|
|
59
|
+
"s3_encryption": {
|
|
60
|
+
"weight": 95,
|
|
61
|
+
"pass_criteria": "S3 bucket storing logs has encryption enabled",
|
|
62
|
+
"fail_criteria": "S3 bucket does not have encryption",
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
"AU-11": {
|
|
67
|
+
"name": "Audit Record Retention",
|
|
68
|
+
"description": "Retain audit records for defined time period to support after-the-fact investigations",
|
|
69
|
+
"checks": {
|
|
70
|
+
"s3_lifecycle": {
|
|
71
|
+
"weight": 100,
|
|
72
|
+
"pass_criteria": "S3 bucket has lifecycle policies for retention",
|
|
73
|
+
"fail_criteria": "No lifecycle policies configured",
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
"AU-12": {
|
|
78
|
+
"name": "Audit Record Generation",
|
|
79
|
+
"description": "Provide audit record generation capability for events",
|
|
80
|
+
"checks": {
|
|
81
|
+
"multi_region": {
|
|
82
|
+
"weight": 100,
|
|
83
|
+
"pass_criteria": "Multi-region trail configured for organization-wide logging",
|
|
84
|
+
"fail_criteria": "No multi-region trail configured",
|
|
85
|
+
},
|
|
86
|
+
"data_events": {
|
|
87
|
+
"weight": 85,
|
|
88
|
+
"pass_criteria": "Data events logging configured for sensitive resources",
|
|
89
|
+
"fail_criteria": "Data events not configured",
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
"SI-4": {
|
|
94
|
+
"name": "System Monitoring",
|
|
95
|
+
"description": "Monitor the system to detect attacks and indicators of potential attacks",
|
|
96
|
+
"checks": {
|
|
97
|
+
"sns_notifications": {
|
|
98
|
+
"weight": 100,
|
|
99
|
+
"pass_criteria": "SNS notifications configured for trail activity",
|
|
100
|
+
"fail_criteria": "No SNS notifications configured",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class CloudTrailControlMapper:
|
|
108
|
+
"""Map AWS CloudTrail configurations to compliance control status."""
|
|
109
|
+
|
|
110
|
+
def __init__(self, framework: str = "NIST800-53R5"):
|
|
111
|
+
"""
|
|
112
|
+
Initialize CloudTrail control mapper.
|
|
113
|
+
|
|
114
|
+
:param str framework: Compliance framework
|
|
115
|
+
"""
|
|
116
|
+
self.framework = framework
|
|
117
|
+
self.mappings = CLOUDTRAIL_CONTROL_MAPPINGS
|
|
118
|
+
|
|
119
|
+
def assess_trail_compliance(self, trail_data: Dict) -> Dict[str, str]:
|
|
120
|
+
"""
|
|
121
|
+
Assess CloudTrail trail compliance against all mapped controls.
|
|
122
|
+
|
|
123
|
+
:param Dict trail_data: CloudTrail trail configuration data
|
|
124
|
+
:return: Dictionary mapping control IDs to compliance results (PASS/FAIL)
|
|
125
|
+
:rtype: Dict[str, str]
|
|
126
|
+
"""
|
|
127
|
+
results = {}
|
|
128
|
+
|
|
129
|
+
if self.framework == "NIST800-53R5":
|
|
130
|
+
results["AU-2"] = self._assess_au2(trail_data)
|
|
131
|
+
results["AU-3"] = self._assess_au3(trail_data)
|
|
132
|
+
results["AU-6"] = self._assess_au6(trail_data)
|
|
133
|
+
results["AU-9"] = self._assess_au9(trail_data)
|
|
134
|
+
results["AU-11"] = self._assess_au11(trail_data)
|
|
135
|
+
results["AU-12"] = self._assess_au12(trail_data)
|
|
136
|
+
results["SI-4"] = self._assess_si4(trail_data)
|
|
137
|
+
|
|
138
|
+
return results
|
|
139
|
+
|
|
140
|
+
def assess_all_trails_compliance(self, trails: List[Dict]) -> Dict[str, str]:
|
|
141
|
+
"""
|
|
142
|
+
Assess compliance across all CloudTrail trails.
|
|
143
|
+
|
|
144
|
+
:param List[Dict] trails: List of trail configurations
|
|
145
|
+
:return: Dictionary mapping control IDs to overall compliance results
|
|
146
|
+
:rtype: Dict[str, str]
|
|
147
|
+
"""
|
|
148
|
+
if not trails:
|
|
149
|
+
logger.debug("No CloudTrail trails to assess")
|
|
150
|
+
return dict.fromkeys(self.mappings.keys(), "FAIL")
|
|
151
|
+
|
|
152
|
+
# Aggregate results - if any trail passes a control, overall result is PASS
|
|
153
|
+
aggregated_results = {}
|
|
154
|
+
for control_id in self.mappings.keys():
|
|
155
|
+
control_results = []
|
|
156
|
+
for trail in trails:
|
|
157
|
+
trail_result = self.assess_trail_compliance(trail)
|
|
158
|
+
control_results.append(trail_result.get(control_id, "FAIL"))
|
|
159
|
+
|
|
160
|
+
# If any trail passes, the control passes overall
|
|
161
|
+
aggregated_results[control_id] = "PASS" if "PASS" in control_results else "FAIL"
|
|
162
|
+
|
|
163
|
+
return aggregated_results
|
|
164
|
+
|
|
165
|
+
def _assess_au2(self, trail_data: Dict) -> str:
|
|
166
|
+
"""
|
|
167
|
+
Assess AU-2 (Event Logging) compliance.
|
|
168
|
+
|
|
169
|
+
:param Dict trail_data: Trail configuration data
|
|
170
|
+
:return: Compliance result (PASS/FAIL)
|
|
171
|
+
:rtype: str
|
|
172
|
+
"""
|
|
173
|
+
trail_name = trail_data.get("Name", "unknown")
|
|
174
|
+
status = trail_data.get("Status", {})
|
|
175
|
+
event_selectors = trail_data.get("EventSelectors", [])
|
|
176
|
+
|
|
177
|
+
# Check if trail is logging
|
|
178
|
+
is_logging = status.get("IsLogging", False)
|
|
179
|
+
if not is_logging:
|
|
180
|
+
logger.debug(f"CloudTrail {trail_name} FAILS AU-2: Trail is not logging")
|
|
181
|
+
return "FAIL"
|
|
182
|
+
|
|
183
|
+
# Check if management events are being logged
|
|
184
|
+
has_management_events = any(selector.get("IncludeManagementEvents", False) for selector in event_selectors)
|
|
185
|
+
|
|
186
|
+
if not has_management_events:
|
|
187
|
+
logger.debug(f"CloudTrail {trail_name} FAILS AU-2: Management events not enabled")
|
|
188
|
+
return "FAIL"
|
|
189
|
+
|
|
190
|
+
logger.debug(f"CloudTrail {trail_name} PASSES AU-2: Trail is logging management events")
|
|
191
|
+
return "PASS"
|
|
192
|
+
|
|
193
|
+
def _assess_au3(self, trail_data: Dict) -> str:
|
|
194
|
+
"""
|
|
195
|
+
Assess AU-3 (Content of Audit Records) compliance.
|
|
196
|
+
|
|
197
|
+
:param Dict trail_data: Trail configuration data
|
|
198
|
+
:return: Compliance result (PASS/FAIL)
|
|
199
|
+
:rtype: str
|
|
200
|
+
"""
|
|
201
|
+
trail_name = trail_data.get("Name", "unknown")
|
|
202
|
+
event_selectors = trail_data.get("EventSelectors", [])
|
|
203
|
+
|
|
204
|
+
if not event_selectors:
|
|
205
|
+
logger.debug(f"CloudTrail {trail_name} FAILS AU-3: No event selectors configured")
|
|
206
|
+
return "FAIL"
|
|
207
|
+
|
|
208
|
+
logger.debug(f"CloudTrail {trail_name} PASSES AU-3: Event selectors configured")
|
|
209
|
+
return "PASS"
|
|
210
|
+
|
|
211
|
+
def _assess_au6(self, trail_data: Dict) -> str:
|
|
212
|
+
"""
|
|
213
|
+
Assess AU-6 (Audit Record Review) compliance.
|
|
214
|
+
|
|
215
|
+
:param Dict trail_data: Trail configuration data
|
|
216
|
+
:return: Compliance result (PASS/FAIL)
|
|
217
|
+
:rtype: str
|
|
218
|
+
"""
|
|
219
|
+
trail_name = trail_data.get("Name", "unknown")
|
|
220
|
+
cloud_watch_logs_log_group_arn = trail_data.get("CloudWatchLogsLogGroupArn")
|
|
221
|
+
|
|
222
|
+
if not cloud_watch_logs_log_group_arn:
|
|
223
|
+
logger.debug(f"CloudTrail {trail_name} FAILS AU-6: No CloudWatch Logs integration")
|
|
224
|
+
return "FAIL"
|
|
225
|
+
|
|
226
|
+
logger.debug(f"CloudTrail {trail_name} PASSES AU-6: CloudWatch Logs integration configured")
|
|
227
|
+
return "PASS"
|
|
228
|
+
|
|
229
|
+
def _assess_au9(self, trail_data: Dict) -> str:
|
|
230
|
+
"""
|
|
231
|
+
Assess AU-9 (Protection of Audit Information) compliance.
|
|
232
|
+
|
|
233
|
+
:param Dict trail_data: Trail configuration data
|
|
234
|
+
:return: Compliance result (PASS/FAIL)
|
|
235
|
+
:rtype: str
|
|
236
|
+
"""
|
|
237
|
+
trail_name = trail_data.get("Name", "unknown")
|
|
238
|
+
log_file_validation = trail_data.get("LogFileValidationEnabled", False)
|
|
239
|
+
kms_key_id = trail_data.get("KmsKeyId")
|
|
240
|
+
|
|
241
|
+
if not log_file_validation:
|
|
242
|
+
logger.debug(f"CloudTrail {trail_name} FAILS AU-9: Log file validation not enabled")
|
|
243
|
+
return "FAIL"
|
|
244
|
+
|
|
245
|
+
# Encryption is recommended but not required for passing
|
|
246
|
+
if kms_key_id:
|
|
247
|
+
logger.debug(f"CloudTrail {trail_name} PASSES AU-9: Log validation and encryption enabled")
|
|
248
|
+
else:
|
|
249
|
+
logger.debug(f"CloudTrail {trail_name} PASSES AU-9: Log validation enabled (encryption recommended)")
|
|
250
|
+
|
|
251
|
+
return "PASS"
|
|
252
|
+
|
|
253
|
+
def _assess_au11(self, trail_data: Dict) -> str:
|
|
254
|
+
"""
|
|
255
|
+
Assess AU-11 (Audit Record Retention) compliance.
|
|
256
|
+
|
|
257
|
+
:param Dict trail_data: Trail configuration data
|
|
258
|
+
:return: Compliance result (PASS/FAIL)
|
|
259
|
+
:rtype: str
|
|
260
|
+
"""
|
|
261
|
+
trail_name = trail_data.get("Name", "unknown")
|
|
262
|
+
s3_bucket_name = trail_data.get("S3BucketName")
|
|
263
|
+
|
|
264
|
+
if not s3_bucket_name:
|
|
265
|
+
logger.debug(f"CloudTrail {trail_name} FAILS AU-11: No S3 bucket configured")
|
|
266
|
+
return "FAIL"
|
|
267
|
+
|
|
268
|
+
# We can't directly check S3 lifecycle policies from CloudTrail data
|
|
269
|
+
# This would require additional S3 API calls
|
|
270
|
+
logger.debug(f"CloudTrail {trail_name} PASSES AU-11: Logs stored in S3 bucket {s3_bucket_name}")
|
|
271
|
+
return "PASS"
|
|
272
|
+
|
|
273
|
+
def _assess_au12(self, trail_data: Dict) -> str:
|
|
274
|
+
"""
|
|
275
|
+
Assess AU-12 (Audit Record Generation) compliance.
|
|
276
|
+
|
|
277
|
+
:param Dict trail_data: Trail configuration data
|
|
278
|
+
:return: Compliance result (PASS/FAIL)
|
|
279
|
+
:rtype: str
|
|
280
|
+
"""
|
|
281
|
+
trail_name = trail_data.get("Name", "unknown")
|
|
282
|
+
is_multi_region = trail_data.get("IsMultiRegionTrail", False)
|
|
283
|
+
event_selectors = trail_data.get("EventSelectors", [])
|
|
284
|
+
|
|
285
|
+
if not is_multi_region:
|
|
286
|
+
logger.debug(f"CloudTrail {trail_name} FAILS AU-12: Not a multi-region trail")
|
|
287
|
+
return "FAIL"
|
|
288
|
+
|
|
289
|
+
# Check for data events (optional but recommended)
|
|
290
|
+
has_data_events = any(selector.get("DataResources", []) for selector in event_selectors)
|
|
291
|
+
|
|
292
|
+
if has_data_events:
|
|
293
|
+
logger.debug(f"CloudTrail {trail_name} PASSES AU-12: Multi-region trail with data events")
|
|
294
|
+
else:
|
|
295
|
+
logger.debug(f"CloudTrail {trail_name} PASSES AU-12: Multi-region trail (data events recommended)")
|
|
296
|
+
|
|
297
|
+
return "PASS"
|
|
298
|
+
|
|
299
|
+
def _assess_si4(self, trail_data: Dict) -> str:
|
|
300
|
+
"""
|
|
301
|
+
Assess SI-4 (System Monitoring) compliance.
|
|
302
|
+
|
|
303
|
+
:param Dict trail_data: Trail configuration data
|
|
304
|
+
:return: Compliance result (PASS/FAIL)
|
|
305
|
+
:rtype: str
|
|
306
|
+
"""
|
|
307
|
+
trail_name = trail_data.get("Name", "unknown")
|
|
308
|
+
sns_topic_arn = trail_data.get("SnsTopicARN")
|
|
309
|
+
|
|
310
|
+
if not sns_topic_arn:
|
|
311
|
+
logger.debug(f"CloudTrail {trail_name} FAILS SI-4: No SNS notifications configured")
|
|
312
|
+
return "FAIL"
|
|
313
|
+
|
|
314
|
+
logger.debug(f"CloudTrail {trail_name} PASSES SI-4: SNS notifications configured")
|
|
315
|
+
return "PASS"
|
|
316
|
+
|
|
317
|
+
def get_control_description(self, control_id: str) -> Optional[str]:
|
|
318
|
+
"""Get human-readable description for a control."""
|
|
319
|
+
control_data = self.mappings.get(control_id)
|
|
320
|
+
if control_data:
|
|
321
|
+
return f"{control_data.get('name')}: {control_data.get('description', '')}"
|
|
322
|
+
return None
|
|
323
|
+
|
|
324
|
+
def get_mapped_controls(self) -> List[str]:
|
|
325
|
+
"""Get list of all control IDs mapped for this framework."""
|
|
326
|
+
return list(self.mappings.keys())
|
|
327
|
+
|
|
328
|
+
def get_check_details(self, control_id: str) -> Optional[Dict]:
|
|
329
|
+
"""Get detailed check criteria for a control."""
|
|
330
|
+
control_data = self.mappings.get(control_id)
|
|
331
|
+
if control_data:
|
|
332
|
+
return control_data.get("checks", {})
|
|
333
|
+
return None
|