runbooks 0.7.9__py3-none-any.whl → 0.9.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.
- runbooks/__init__.py +1 -1
- runbooks/cfat/README.md +12 -1
- runbooks/cfat/__init__.py +1 -1
- runbooks/cfat/assessment/compliance.py +4 -1
- runbooks/cfat/assessment/runner.py +42 -34
- runbooks/cfat/models.py +1 -1
- runbooks/cloudops/__init__.py +123 -0
- runbooks/cloudops/base.py +385 -0
- runbooks/cloudops/cost_optimizer.py +811 -0
- runbooks/cloudops/infrastructure_optimizer.py +29 -0
- runbooks/cloudops/interfaces.py +828 -0
- runbooks/cloudops/lifecycle_manager.py +29 -0
- runbooks/cloudops/mcp_cost_validation.py +678 -0
- runbooks/cloudops/models.py +251 -0
- runbooks/cloudops/monitoring_automation.py +29 -0
- runbooks/cloudops/notebook_framework.py +676 -0
- runbooks/cloudops/security_enforcer.py +449 -0
- runbooks/common/__init__.py +152 -0
- runbooks/common/accuracy_validator.py +1039 -0
- runbooks/common/context_logger.py +440 -0
- runbooks/common/cross_module_integration.py +594 -0
- runbooks/common/enhanced_exception_handler.py +1108 -0
- runbooks/common/enterprise_audit_integration.py +634 -0
- runbooks/common/mcp_cost_explorer_integration.py +900 -0
- runbooks/common/mcp_integration.py +548 -0
- runbooks/common/performance_monitor.py +387 -0
- runbooks/common/profile_utils.py +216 -0
- runbooks/common/rich_utils.py +172 -1
- runbooks/feedback/user_feedback_collector.py +440 -0
- runbooks/finops/README.md +377 -458
- runbooks/finops/__init__.py +4 -21
- runbooks/finops/account_resolver.py +279 -0
- runbooks/finops/accuracy_cross_validator.py +638 -0
- runbooks/finops/aws_client.py +721 -36
- runbooks/finops/budget_integration.py +313 -0
- runbooks/finops/cli.py +59 -5
- runbooks/finops/cost_optimizer.py +1340 -0
- runbooks/finops/cost_processor.py +211 -37
- runbooks/finops/dashboard_router.py +900 -0
- runbooks/finops/dashboard_runner.py +990 -232
- runbooks/finops/embedded_mcp_validator.py +288 -0
- runbooks/finops/enhanced_dashboard_runner.py +8 -7
- runbooks/finops/enhanced_progress.py +327 -0
- runbooks/finops/enhanced_trend_visualization.py +423 -0
- runbooks/finops/finops_dashboard.py +184 -1829
- runbooks/finops/helpers.py +509 -196
- runbooks/finops/iam_guidance.py +400 -0
- runbooks/finops/markdown_exporter.py +466 -0
- runbooks/finops/multi_dashboard.py +1502 -0
- runbooks/finops/optimizer.py +15 -15
- runbooks/finops/profile_processor.py +2 -2
- runbooks/finops/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/finops/runbooks.security.report_generator.log +0 -0
- runbooks/finops/runbooks.security.run_script.log +0 -0
- runbooks/finops/runbooks.security.security_export.log +0 -0
- runbooks/finops/schemas.py +589 -0
- runbooks/finops/service_mapping.py +195 -0
- runbooks/finops/single_dashboard.py +710 -0
- runbooks/finops/tests/test_reference_images_validation.py +1 -1
- runbooks/inventory/README.md +12 -1
- runbooks/inventory/core/collector.py +157 -29
- runbooks/inventory/list_ec2_instances.py +9 -6
- runbooks/inventory/list_ssm_parameters.py +10 -10
- runbooks/inventory/organizations_discovery.py +210 -164
- runbooks/inventory/rich_inventory_display.py +74 -107
- runbooks/inventory/run_on_multi_accounts.py +13 -13
- runbooks/inventory/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/inventory/runbooks.security.security_export.log +0 -0
- runbooks/main.py +1371 -240
- runbooks/metrics/dora_metrics_engine.py +711 -17
- runbooks/monitoring/performance_monitor.py +433 -0
- runbooks/operate/README.md +394 -0
- runbooks/operate/base.py +215 -47
- runbooks/operate/ec2_operations.py +435 -5
- runbooks/operate/iam_operations.py +598 -3
- runbooks/operate/privatelink_operations.py +1 -1
- runbooks/operate/rds_operations.py +508 -0
- runbooks/operate/s3_operations.py +508 -0
- runbooks/operate/vpc_endpoints.py +1 -1
- runbooks/remediation/README.md +489 -13
- runbooks/remediation/base.py +5 -3
- runbooks/remediation/commons.py +8 -4
- runbooks/security/ENTERPRISE_SECURITY_FRAMEWORK.md +506 -0
- runbooks/security/README.md +12 -1
- runbooks/security/__init__.py +265 -33
- runbooks/security/cloudops_automation_security_validator.py +1164 -0
- runbooks/security/compliance_automation.py +12 -10
- runbooks/security/compliance_automation_engine.py +1021 -0
- runbooks/security/enterprise_security_framework.py +930 -0
- runbooks/security/enterprise_security_policies.json +293 -0
- runbooks/security/executive_security_dashboard.py +1247 -0
- runbooks/security/integration_test_enterprise_security.py +879 -0
- runbooks/security/module_security_integrator.py +641 -0
- runbooks/security/multi_account_security_controls.py +2254 -0
- runbooks/security/real_time_security_monitor.py +1196 -0
- runbooks/security/report_generator.py +1 -1
- runbooks/security/run_script.py +4 -8
- runbooks/security/security_baseline_tester.py +39 -52
- runbooks/security/security_export.py +99 -120
- runbooks/sre/README.md +472 -0
- runbooks/sre/__init__.py +33 -0
- runbooks/sre/mcp_reliability_engine.py +1049 -0
- runbooks/sre/performance_optimization_engine.py +1032 -0
- runbooks/sre/production_monitoring_framework.py +584 -0
- runbooks/sre/reliability_monitoring_framework.py +1011 -0
- runbooks/validation/__init__.py +2 -2
- runbooks/validation/benchmark.py +154 -149
- runbooks/validation/cli.py +159 -147
- runbooks/validation/mcp_validator.py +291 -248
- runbooks/vpc/README.md +478 -0
- runbooks/vpc/__init__.py +2 -2
- runbooks/vpc/manager_interface.py +366 -351
- runbooks/vpc/networking_wrapper.py +68 -36
- runbooks/vpc/rich_formatters.py +22 -8
- runbooks-0.9.1.dist-info/METADATA +308 -0
- {runbooks-0.7.9.dist-info → runbooks-0.9.1.dist-info}/RECORD +120 -59
- {runbooks-0.7.9.dist-info → runbooks-0.9.1.dist-info}/entry_points.txt +1 -1
- runbooks/finops/cross_validation.py +0 -375
- runbooks-0.7.9.dist-info/METADATA +0 -636
- {runbooks-0.7.9.dist-info → runbooks-0.9.1.dist-info}/WHEEL +0 -0
- {runbooks-0.7.9.dist-info → runbooks-0.9.1.dist-info}/licenses/LICENSE +0 -0
- {runbooks-0.7.9.dist-info → runbooks-0.9.1.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ with multiple format support (JSON, CSV, PDF) and multi-language reporting.
|
|
7
7
|
|
8
8
|
Features:
|
9
9
|
- JSON export for dashboard integration
|
10
|
-
- CSV export for spreadsheet analysis
|
10
|
+
- CSV export for spreadsheet analysis
|
11
11
|
- PDF export for executive reports
|
12
12
|
- Multi-language export support (EN, JP, KR, VN)
|
13
13
|
- Rich CLI progress tracking
|
@@ -43,68 +43,60 @@ logger = configure_logger(__name__)
|
|
43
43
|
class SecurityExporter:
|
44
44
|
"""
|
45
45
|
Enterprise security assessment export functionality with Rich CLI.
|
46
|
-
|
46
|
+
|
47
47
|
Supports JSON, CSV, and PDF exports with multi-language capabilities
|
48
48
|
and professional formatting for enterprise compliance requirements.
|
49
49
|
"""
|
50
|
-
|
50
|
+
|
51
51
|
def __init__(self, output_dir: Optional[str] = None):
|
52
52
|
self.output_dir = Path(output_dir) if output_dir else Path.cwd() / "security-exports"
|
53
53
|
self.supported_formats = ["json", "csv", "pdf"]
|
54
54
|
self.supported_languages = ["EN", "JP", "KR", "VN"]
|
55
|
-
|
55
|
+
|
56
56
|
# Ensure output directory exists
|
57
57
|
self.output_dir.mkdir(parents=True, exist_ok=True)
|
58
|
-
|
58
|
+
|
59
59
|
def export_security_results(
|
60
|
-
self,
|
61
|
-
account_id: str,
|
62
|
-
results: Dict[str, List],
|
63
|
-
language: str = "EN",
|
64
|
-
formats: List[str] = None
|
60
|
+
self, account_id: str, results: Dict[str, List], language: str = "EN", formats: List[str] = None
|
65
61
|
) -> Dict[str, str]:
|
66
62
|
"""
|
67
63
|
Export security assessment results in multiple formats.
|
68
|
-
|
64
|
+
|
69
65
|
Args:
|
70
66
|
account_id: AWS account ID
|
71
67
|
results: Security assessment results
|
72
68
|
language: Report language (EN, JP, KR, VN)
|
73
69
|
formats: Export formats (json, csv, pdf)
|
74
|
-
|
70
|
+
|
75
71
|
Returns:
|
76
72
|
Dictionary mapping format to file path
|
77
73
|
"""
|
78
74
|
if formats is None:
|
79
75
|
formats = ["json", "csv"]
|
80
|
-
|
76
|
+
|
81
77
|
export_results = {}
|
82
78
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
83
|
-
|
79
|
+
|
84
80
|
# Display export startup
|
85
81
|
export_info = f"""[bold cyan]Security Export Configuration[/bold cyan]
|
86
82
|
|
87
83
|
[green]Account ID:[/green] {account_id}
|
88
84
|
[green]Language:[/green] {language}
|
89
|
-
[green]Formats:[/green] {
|
85
|
+
[green]Formats:[/green] {", ".join(formats)}
|
90
86
|
[green]Output Directory:[/green] {self.output_dir}
|
91
87
|
|
92
88
|
[dim]Exporting assessment results...[/dim]"""
|
93
|
-
|
94
|
-
console.print(create_panel(
|
95
|
-
|
96
|
-
title="📤 Security Data Export",
|
97
|
-
border_style="cyan"
|
98
|
-
))
|
99
|
-
|
89
|
+
|
90
|
+
console.print(create_panel(export_info, title="📤 Security Data Export", border_style="cyan"))
|
91
|
+
|
100
92
|
with create_progress_bar(description="Exporting Data") as progress:
|
101
93
|
export_task = progress.add_task("Processing exports...", total=len(formats))
|
102
|
-
|
94
|
+
|
103
95
|
for format_type in formats:
|
104
96
|
if format_type not in self.supported_formats:
|
105
97
|
print_warning(f"Unsupported format: {format_type}")
|
106
98
|
continue
|
107
|
-
|
99
|
+
|
108
100
|
try:
|
109
101
|
if format_type == "json":
|
110
102
|
file_path = self._export_json(account_id, results, language, timestamp)
|
@@ -112,25 +104,25 @@ class SecurityExporter:
|
|
112
104
|
file_path = self._export_csv(account_id, results, language, timestamp)
|
113
105
|
elif format_type == "pdf":
|
114
106
|
file_path = self._export_pdf(account_id, results, language, timestamp)
|
115
|
-
|
107
|
+
|
116
108
|
export_results[format_type] = str(file_path)
|
117
109
|
print_success(f"Exported {format_type.upper()}: {file_path}")
|
118
|
-
|
110
|
+
|
119
111
|
except Exception as e:
|
120
112
|
print_error(f"Failed to export {format_type}: {e}")
|
121
113
|
logger.error(f"Export failed for {format_type}: {e}", exc_info=True)
|
122
|
-
|
114
|
+
|
123
115
|
progress.update(export_task, advance=1)
|
124
|
-
|
116
|
+
|
125
117
|
# Display export summary
|
126
118
|
self._display_export_summary(export_results, account_id)
|
127
119
|
return export_results
|
128
|
-
|
120
|
+
|
129
121
|
def _export_json(self, account_id: str, results: Dict[str, List], language: str, timestamp: str) -> Path:
|
130
122
|
"""Export results to JSON format for dashboard integration."""
|
131
123
|
filename = f"security-assessment-{account_id}-{timestamp}.json"
|
132
124
|
file_path = self.output_dir / filename
|
133
|
-
|
125
|
+
|
134
126
|
# Transform results for JSON export
|
135
127
|
json_data = {
|
136
128
|
"metadata": {
|
@@ -138,56 +130,56 @@ class SecurityExporter:
|
|
138
130
|
"assessment_date": datetime.now().isoformat(),
|
139
131
|
"language": language,
|
140
132
|
"export_format": "json",
|
141
|
-
"version": "0.7.8"
|
133
|
+
"version": "0.7.8",
|
142
134
|
},
|
143
135
|
"summary": self._calculate_summary_stats(results),
|
144
136
|
"findings": self._transform_findings_for_json(results),
|
145
137
|
"compliance_frameworks": {
|
146
138
|
"aws_well_architected": self._map_to_wa_framework(results),
|
147
139
|
"soc2": self._map_to_soc2_framework(results),
|
148
|
-
"enterprise_baseline": self._map_to_enterprise_framework(results)
|
149
|
-
}
|
140
|
+
"enterprise_baseline": self._map_to_enterprise_framework(results),
|
141
|
+
},
|
150
142
|
}
|
151
|
-
|
143
|
+
|
152
144
|
with file_path.open("w", encoding="utf-8") as f:
|
153
145
|
json.dump(json_data, f, indent=2, ensure_ascii=False)
|
154
|
-
|
146
|
+
|
155
147
|
return file_path
|
156
|
-
|
148
|
+
|
157
149
|
def _export_csv(self, account_id: str, results: Dict[str, List], language: str, timestamp: str) -> Path:
|
158
150
|
"""Export results to CSV format for spreadsheet analysis."""
|
159
151
|
filename = f"security-findings-{account_id}-{timestamp}.csv"
|
160
152
|
file_path = self.output_dir / filename
|
161
|
-
|
153
|
+
|
162
154
|
with file_path.open("w", newline="", encoding="utf-8") as f:
|
163
155
|
writer = csv.writer(f)
|
164
|
-
|
156
|
+
|
165
157
|
# CSV Headers
|
166
158
|
headers = [
|
167
159
|
"Finding_ID",
|
168
|
-
"Status_Level",
|
160
|
+
"Status_Level",
|
169
161
|
"Title",
|
170
162
|
"Message",
|
171
163
|
"Severity",
|
172
164
|
"Compliance_Framework",
|
173
165
|
"Remediation_Available",
|
174
|
-
"Assessment_Date"
|
166
|
+
"Assessment_Date",
|
175
167
|
]
|
176
168
|
writer.writerow(headers)
|
177
|
-
|
169
|
+
|
178
170
|
# Write findings data
|
179
171
|
finding_id = 1
|
180
172
|
assessment_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
181
|
-
|
173
|
+
|
182
174
|
for level, findings in results.items():
|
183
175
|
for finding in findings:
|
184
|
-
if hasattr(finding,
|
176
|
+
if hasattr(finding, "to_dict"):
|
185
177
|
finding_dict = finding.to_dict()
|
186
178
|
elif isinstance(finding, dict):
|
187
179
|
finding_dict = finding
|
188
180
|
else:
|
189
181
|
continue
|
190
|
-
|
182
|
+
|
191
183
|
row = [
|
192
184
|
f"SEC-{finding_id:04d}",
|
193
185
|
level,
|
@@ -196,65 +188,65 @@ class SecurityExporter:
|
|
196
188
|
self._map_level_to_severity(level),
|
197
189
|
"AWS Security Baseline",
|
198
190
|
"Manual" if level in ["Danger", "Warning"] else "N/A",
|
199
|
-
assessment_date
|
191
|
+
assessment_date,
|
200
192
|
]
|
201
193
|
writer.writerow(row)
|
202
194
|
finding_id += 1
|
203
|
-
|
195
|
+
|
204
196
|
return file_path
|
205
|
-
|
197
|
+
|
206
198
|
def _export_pdf(self, account_id: str, results: Dict[str, List], language: str, timestamp: str) -> Path:
|
207
199
|
"""Export results to PDF format for executive reports."""
|
208
200
|
filename = f"security-executive-report-{account_id}-{timestamp}.pdf"
|
209
201
|
file_path = self.output_dir / filename
|
210
|
-
|
202
|
+
|
211
203
|
# For now, create a placeholder PDF export
|
212
204
|
# In production, this would use a proper PDF library like reportlab
|
213
205
|
html_content = self._generate_executive_html(account_id, results, language)
|
214
|
-
|
206
|
+
|
215
207
|
# Write HTML version as PDF placeholder
|
216
|
-
html_path = file_path.with_suffix(
|
208
|
+
html_path = file_path.with_suffix(".html")
|
217
209
|
with html_path.open("w", encoding="utf-8") as f:
|
218
210
|
f.write(html_content)
|
219
|
-
|
211
|
+
|
220
212
|
print_info(f"PDF export created as HTML: {html_path}")
|
221
213
|
return html_path
|
222
|
-
|
214
|
+
|
223
215
|
def _calculate_summary_stats(self, results: Dict[str, List]) -> Dict[str, Any]:
|
224
216
|
"""Calculate summary statistics for the assessment."""
|
225
217
|
total_checks = sum(len(findings) for findings in results.values())
|
226
218
|
critical_issues = len(results.get("Danger", []))
|
227
219
|
warnings = len(results.get("Warning", []))
|
228
220
|
successful = len(results.get("Success", []))
|
229
|
-
|
221
|
+
|
230
222
|
if total_checks > 0:
|
231
223
|
security_score = (successful / total_checks) * 100
|
232
224
|
else:
|
233
225
|
security_score = 0
|
234
|
-
|
226
|
+
|
235
227
|
return {
|
236
228
|
"total_checks": total_checks,
|
237
229
|
"critical_issues": critical_issues,
|
238
230
|
"warnings": warnings,
|
239
231
|
"successful_checks": successful,
|
240
232
|
"security_score": round(security_score, 1),
|
241
|
-
"compliance_status": "COMPLIANT" if security_score >= 80 else "NON_COMPLIANT"
|
233
|
+
"compliance_status": "COMPLIANT" if security_score >= 80 else "NON_COMPLIANT",
|
242
234
|
}
|
243
|
-
|
235
|
+
|
244
236
|
def _transform_findings_for_json(self, results: Dict[str, List]) -> List[Dict[str, Any]]:
|
245
237
|
"""Transform findings into structured JSON format."""
|
246
238
|
findings = []
|
247
239
|
finding_id = 1
|
248
|
-
|
240
|
+
|
249
241
|
for level, level_findings in results.items():
|
250
242
|
for finding in level_findings:
|
251
|
-
if hasattr(finding,
|
243
|
+
if hasattr(finding, "to_dict"):
|
252
244
|
finding_dict = finding.to_dict()
|
253
245
|
elif isinstance(finding, dict):
|
254
246
|
finding_dict = finding
|
255
247
|
else:
|
256
248
|
continue
|
257
|
-
|
249
|
+
|
258
250
|
structured_finding = {
|
259
251
|
"finding_id": f"SEC-{finding_id:04d}",
|
260
252
|
"status": level,
|
@@ -264,25 +256,19 @@ class SecurityExporter:
|
|
264
256
|
"result_columns": finding_dict.get("result_cols", []),
|
265
257
|
"result_rows": finding_dict.get("result_rows", []),
|
266
258
|
"remediation_required": level in ["Danger", "Warning"],
|
267
|
-
"compliance_impact": self._assess_compliance_impact(level)
|
259
|
+
"compliance_impact": self._assess_compliance_impact(level),
|
268
260
|
}
|
269
|
-
|
261
|
+
|
270
262
|
findings.append(structured_finding)
|
271
263
|
finding_id += 1
|
272
|
-
|
264
|
+
|
273
265
|
return findings
|
274
|
-
|
266
|
+
|
275
267
|
def _map_level_to_severity(self, level: str) -> str:
|
276
268
|
"""Map security level to severity classification."""
|
277
|
-
mapping = {
|
278
|
-
"Danger": "CRITICAL",
|
279
|
-
"Warning": "HIGH",
|
280
|
-
"Success": "PASS",
|
281
|
-
"Info": "INFO",
|
282
|
-
"Error": "ERROR"
|
283
|
-
}
|
269
|
+
mapping = {"Danger": "CRITICAL", "Warning": "HIGH", "Success": "PASS", "Info": "INFO", "Error": "ERROR"}
|
284
270
|
return mapping.get(level, "UNKNOWN")
|
285
|
-
|
271
|
+
|
286
272
|
def _assess_compliance_impact(self, level: str) -> str:
|
287
273
|
"""Assess compliance impact of finding."""
|
288
274
|
if level == "Danger":
|
@@ -291,7 +277,7 @@ class SecurityExporter:
|
|
291
277
|
return "MEDIUM"
|
292
278
|
else:
|
293
279
|
return "LOW"
|
294
|
-
|
280
|
+
|
295
281
|
def _map_to_wa_framework(self, results: Dict[str, List]) -> Dict[str, Any]:
|
296
282
|
"""Map findings to AWS Well-Architected framework."""
|
297
283
|
return {
|
@@ -301,10 +287,10 @@ class SecurityExporter:
|
|
301
287
|
"identity_access_management": self._assess_iam_findings(results),
|
302
288
|
"detective_controls": self._assess_detective_findings(results),
|
303
289
|
"infrastructure_protection": self._assess_infrastructure_findings(results),
|
304
|
-
"data_protection": self._assess_data_findings(results)
|
305
|
-
}
|
290
|
+
"data_protection": self._assess_data_findings(results),
|
291
|
+
},
|
306
292
|
}
|
307
|
-
|
293
|
+
|
308
294
|
def _map_to_soc2_framework(self, results: Dict[str, List]) -> Dict[str, Any]:
|
309
295
|
"""Map findings to SOC2 compliance framework."""
|
310
296
|
return {
|
@@ -314,10 +300,10 @@ class SecurityExporter:
|
|
314
300
|
"security": self._assess_soc2_security(results),
|
315
301
|
"availability": self._assess_soc2_availability(results),
|
316
302
|
"processing_integrity": self._assess_soc2_processing(results),
|
317
|
-
"confidentiality": self._assess_soc2_confidentiality(results)
|
318
|
-
}
|
303
|
+
"confidentiality": self._assess_soc2_confidentiality(results),
|
304
|
+
},
|
319
305
|
}
|
320
|
-
|
306
|
+
|
321
307
|
def _map_to_enterprise_framework(self, results: Dict[str, List]) -> Dict[str, Any]:
|
322
308
|
"""Map findings to enterprise baseline framework."""
|
323
309
|
return {
|
@@ -327,72 +313,72 @@ class SecurityExporter:
|
|
327
313
|
"access_controls": self._assess_access_controls(results),
|
328
314
|
"monitoring_logging": self._assess_monitoring_controls(results),
|
329
315
|
"encryption_protection": self._assess_encryption_controls(results),
|
330
|
-
"incident_response": self._assess_incident_controls(results)
|
331
|
-
}
|
316
|
+
"incident_response": self._assess_incident_controls(results),
|
317
|
+
},
|
332
318
|
}
|
333
|
-
|
319
|
+
|
334
320
|
def _calculate_framework_score(self, results: Dict[str, List], framework: str) -> float:
|
335
321
|
"""Calculate compliance score for specific framework."""
|
336
322
|
# Simplified scoring - in production would map specific checks to framework requirements
|
337
323
|
total_checks = sum(len(findings) for findings in results.values())
|
338
324
|
successful = len(results.get("Success", []))
|
339
|
-
|
325
|
+
|
340
326
|
if total_checks > 0:
|
341
327
|
return round((successful / total_checks) * 100, 1)
|
342
328
|
return 0.0
|
343
|
-
|
329
|
+
|
344
330
|
def _assess_iam_findings(self, results: Dict[str, List]) -> Dict[str, Any]:
|
345
331
|
"""Assess IAM-related findings."""
|
346
332
|
return {"status": "ASSESSED", "findings_count": len(results.get("Success", [])), "risk_level": "LOW"}
|
347
|
-
|
333
|
+
|
348
334
|
def _assess_detective_findings(self, results: Dict[str, List]) -> Dict[str, Any]:
|
349
335
|
"""Assess detective control findings."""
|
350
336
|
return {"status": "ASSESSED", "findings_count": len(results.get("Warning", [])), "risk_level": "MEDIUM"}
|
351
|
-
|
337
|
+
|
352
338
|
def _assess_infrastructure_findings(self, results: Dict[str, List]) -> Dict[str, Any]:
|
353
339
|
"""Assess infrastructure protection findings."""
|
354
340
|
return {"status": "ASSESSED", "findings_count": len(results.get("Danger", [])), "risk_level": "HIGH"}
|
355
|
-
|
341
|
+
|
356
342
|
def _assess_data_findings(self, results: Dict[str, List]) -> Dict[str, Any]:
|
357
|
-
"""Assess data protection findings."""
|
343
|
+
"""Assess data protection findings."""
|
358
344
|
return {"status": "ASSESSED", "findings_count": len(results.get("Info", [])), "risk_level": "LOW"}
|
359
|
-
|
345
|
+
|
360
346
|
def _assess_soc2_security(self, results: Dict[str, List]) -> Dict[str, Any]:
|
361
347
|
"""Assess SOC2 security criteria."""
|
362
348
|
return {"status": "COMPLIANT", "findings_count": 0, "risk_level": "LOW"}
|
363
|
-
|
349
|
+
|
364
350
|
def _assess_soc2_availability(self, results: Dict[str, List]) -> Dict[str, Any]:
|
365
351
|
"""Assess SOC2 availability criteria."""
|
366
352
|
return {"status": "COMPLIANT", "findings_count": 0, "risk_level": "LOW"}
|
367
|
-
|
353
|
+
|
368
354
|
def _assess_soc2_processing(self, results: Dict[str, List]) -> Dict[str, Any]:
|
369
355
|
"""Assess SOC2 processing integrity."""
|
370
356
|
return {"status": "COMPLIANT", "findings_count": 0, "risk_level": "LOW"}
|
371
|
-
|
357
|
+
|
372
358
|
def _assess_soc2_confidentiality(self, results: Dict[str, List]) -> Dict[str, Any]:
|
373
359
|
"""Assess SOC2 confidentiality criteria."""
|
374
360
|
return {"status": "COMPLIANT", "findings_count": 0, "risk_level": "LOW"}
|
375
|
-
|
361
|
+
|
376
362
|
def _assess_access_controls(self, results: Dict[str, List]) -> Dict[str, Any]:
|
377
363
|
"""Assess access control compliance."""
|
378
364
|
return {"status": "COMPLIANT", "findings_count": 0, "risk_level": "LOW"}
|
379
|
-
|
365
|
+
|
380
366
|
def _assess_monitoring_controls(self, results: Dict[str, List]) -> Dict[str, Any]:
|
381
367
|
"""Assess monitoring and logging controls."""
|
382
368
|
return {"status": "COMPLIANT", "findings_count": 0, "risk_level": "LOW"}
|
383
|
-
|
369
|
+
|
384
370
|
def _assess_encryption_controls(self, results: Dict[str, List]) -> Dict[str, Any]:
|
385
371
|
"""Assess encryption and protection controls."""
|
386
372
|
return {"status": "COMPLIANT", "findings_count": 0, "risk_level": "LOW"}
|
387
|
-
|
373
|
+
|
388
374
|
def _assess_incident_controls(self, results: Dict[str, List]) -> Dict[str, Any]:
|
389
375
|
"""Assess incident response controls."""
|
390
376
|
return {"status": "COMPLIANT", "findings_count": 0, "risk_level": "LOW"}
|
391
|
-
|
377
|
+
|
392
378
|
def _generate_executive_html(self, account_id: str, results: Dict[str, List], language: str) -> str:
|
393
379
|
"""Generate executive HTML report."""
|
394
380
|
summary = self._calculate_summary_stats(results)
|
395
|
-
|
381
|
+
|
396
382
|
html_content = f"""
|
397
383
|
<!DOCTYPE html>
|
398
384
|
<html lang="{language.lower()}">
|
@@ -413,30 +399,30 @@ class SecurityExporter:
|
|
413
399
|
<div class="header">
|
414
400
|
<h1>🛡️ Security Assessment Executive Report</h1>
|
415
401
|
<p><strong>Account ID:</strong> {account_id}</p>
|
416
|
-
<p><strong>Assessment Date:</strong> {datetime.now().strftime(
|
402
|
+
<p><strong>Assessment Date:</strong> {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</p>
|
417
403
|
<p><strong>Language:</strong> {language}</p>
|
418
404
|
</div>
|
419
405
|
|
420
406
|
<div class="summary">
|
421
407
|
<h2>Executive Summary</h2>
|
422
|
-
<p><strong>Security Score:</strong> {summary[
|
423
|
-
<p><strong>Total Checks:</strong> {summary[
|
424
|
-
<p class="critical"><strong>Critical Issues:</strong> {summary[
|
425
|
-
<p class="warning"><strong>Warnings:</strong> {summary[
|
426
|
-
<p class="success"><strong>Successful Checks:</strong> {summary[
|
427
|
-
<p><strong>Compliance Status:</strong> {summary[
|
408
|
+
<p><strong>Security Score:</strong> {summary["security_score"]}%</p>
|
409
|
+
<p><strong>Total Checks:</strong> {summary["total_checks"]}</p>
|
410
|
+
<p class="critical"><strong>Critical Issues:</strong> {summary["critical_issues"]}</p>
|
411
|
+
<p class="warning"><strong>Warnings:</strong> {summary["warnings"]}</p>
|
412
|
+
<p class="success"><strong>Successful Checks:</strong> {summary["successful_checks"]}</p>
|
413
|
+
<p><strong>Compliance Status:</strong> {summary["compliance_status"]}</p>
|
428
414
|
</div>
|
429
415
|
</body>
|
430
416
|
</html>
|
431
417
|
"""
|
432
418
|
return html_content
|
433
|
-
|
419
|
+
|
434
420
|
def _display_export_summary(self, export_results: Dict[str, str], account_id: str):
|
435
421
|
"""Display export summary with Rich formatting."""
|
436
422
|
if not export_results:
|
437
423
|
print_warning("No files were exported successfully")
|
438
424
|
return
|
439
|
-
|
425
|
+
|
440
426
|
# Create export summary table
|
441
427
|
summary_table = create_table(
|
442
428
|
title="📁 Export Summary",
|
@@ -444,19 +430,16 @@ class SecurityExporter:
|
|
444
430
|
{"name": "Format", "style": "bold cyan", "justify": "left"},
|
445
431
|
{"name": "File Path", "style": "dim", "justify": "left"},
|
446
432
|
{"name": "Status", "style": "bold", "justify": "center"},
|
447
|
-
]
|
433
|
+
],
|
448
434
|
)
|
449
|
-
|
435
|
+
|
450
436
|
for format_type, file_path in export_results.items():
|
451
437
|
summary_table.add_row(
|
452
|
-
format_type.upper(),
|
453
|
-
str(file_path),
|
454
|
-
f"{STATUS_INDICATORS['success']} Exported",
|
455
|
-
style="success"
|
438
|
+
format_type.upper(), str(file_path), f"{STATUS_INDICATORS['success']} Exported", style="success"
|
456
439
|
)
|
457
|
-
|
440
|
+
|
458
441
|
console.print(summary_table)
|
459
|
-
|
442
|
+
|
460
443
|
# Display final export summary
|
461
444
|
export_summary = f"""[bold green]Security Data Export Complete[/bold green]
|
462
445
|
|
@@ -466,12 +449,8 @@ class SecurityExporter:
|
|
466
449
|
|
467
450
|
[dim]All exports completed successfully. Files are ready for analysis.[/dim]"""
|
468
451
|
|
469
|
-
console.print(create_panel(
|
470
|
-
export_summary,
|
471
|
-
title="✅ Export Complete",
|
472
|
-
border_style="green"
|
473
|
-
))
|
452
|
+
console.print(create_panel(export_summary, title="✅ Export Complete", border_style="green"))
|
474
453
|
|
475
454
|
|
476
455
|
# Export functionality for external use
|
477
|
-
__all__ = ["SecurityExporter"]
|
456
|
+
__all__ = ["SecurityExporter"]
|