runbooks 0.2.5__py3-none-any.whl → 0.6.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.
- conftest.py +26 -0
- jupyter-agent/.env.template +2 -0
- jupyter-agent/.gitattributes +35 -0
- jupyter-agent/README.md +16 -0
- jupyter-agent/app.py +256 -0
- jupyter-agent/cloudops-agent.png +0 -0
- jupyter-agent/ds-system-prompt.txt +154 -0
- jupyter-agent/jupyter-agent.png +0 -0
- jupyter-agent/llama3_template.jinja +123 -0
- jupyter-agent/requirements.txt +9 -0
- jupyter-agent/utils.py +409 -0
- runbooks/__init__.py +71 -3
- runbooks/__main__.py +13 -0
- runbooks/aws/ec2_describe_instances.py +1 -1
- runbooks/aws/ec2_run_instances.py +8 -2
- runbooks/aws/ec2_start_stop_instances.py +17 -4
- runbooks/aws/ec2_unused_volumes.py +5 -1
- runbooks/aws/s3_create_bucket.py +4 -2
- runbooks/aws/s3_list_objects.py +6 -1
- runbooks/aws/tagging_lambda_handler.py +13 -2
- runbooks/aws/tags.json +12 -0
- runbooks/base.py +353 -0
- runbooks/cfat/README.md +49 -0
- runbooks/cfat/__init__.py +74 -0
- runbooks/cfat/app.ts +644 -0
- runbooks/cfat/assessment/__init__.py +40 -0
- runbooks/cfat/assessment/asana-import.csv +39 -0
- runbooks/cfat/assessment/cfat-checks.csv +31 -0
- runbooks/cfat/assessment/cfat.txt +520 -0
- runbooks/cfat/assessment/collectors.py +200 -0
- runbooks/cfat/assessment/jira-import.csv +39 -0
- runbooks/cfat/assessment/runner.py +387 -0
- runbooks/cfat/assessment/validators.py +290 -0
- runbooks/cfat/cli.py +103 -0
- runbooks/cfat/docs/asana-import.csv +24 -0
- runbooks/cfat/docs/cfat-checks.csv +31 -0
- runbooks/cfat/docs/cfat.txt +335 -0
- runbooks/cfat/docs/checks-output.png +0 -0
- runbooks/cfat/docs/cloudshell-console-run.png +0 -0
- runbooks/cfat/docs/cloudshell-download.png +0 -0
- runbooks/cfat/docs/cloudshell-output.png +0 -0
- runbooks/cfat/docs/downloadfile.png +0 -0
- runbooks/cfat/docs/jira-import.csv +24 -0
- runbooks/cfat/docs/open-cloudshell.png +0 -0
- runbooks/cfat/docs/report-header.png +0 -0
- runbooks/cfat/models.py +1026 -0
- runbooks/cfat/package-lock.json +5116 -0
- runbooks/cfat/package.json +38 -0
- runbooks/cfat/report.py +496 -0
- runbooks/cfat/reporting/__init__.py +46 -0
- runbooks/cfat/reporting/exporters.py +337 -0
- runbooks/cfat/reporting/formatters.py +496 -0
- runbooks/cfat/reporting/templates.py +135 -0
- runbooks/cfat/run-assessment.sh +23 -0
- runbooks/cfat/runner.py +69 -0
- runbooks/cfat/src/actions/check-cloudtrail-existence.ts +43 -0
- runbooks/cfat/src/actions/check-config-existence.ts +37 -0
- runbooks/cfat/src/actions/check-control-tower.ts +37 -0
- runbooks/cfat/src/actions/check-ec2-existence.ts +46 -0
- runbooks/cfat/src/actions/check-iam-users.ts +50 -0
- runbooks/cfat/src/actions/check-legacy-cur.ts +30 -0
- runbooks/cfat/src/actions/check-org-cloudformation.ts +30 -0
- runbooks/cfat/src/actions/check-vpc-existence.ts +43 -0
- runbooks/cfat/src/actions/create-asanaimport.ts +14 -0
- runbooks/cfat/src/actions/create-backlog.ts +372 -0
- runbooks/cfat/src/actions/create-jiraimport.ts +15 -0
- runbooks/cfat/src/actions/create-report.ts +616 -0
- runbooks/cfat/src/actions/define-account-type.ts +51 -0
- runbooks/cfat/src/actions/get-enabled-org-policy-types.ts +40 -0
- runbooks/cfat/src/actions/get-enabled-org-services.ts +26 -0
- runbooks/cfat/src/actions/get-idc-info.ts +34 -0
- runbooks/cfat/src/actions/get-org-da-accounts.ts +34 -0
- runbooks/cfat/src/actions/get-org-details.ts +35 -0
- runbooks/cfat/src/actions/get-org-member-accounts.ts +44 -0
- runbooks/cfat/src/actions/get-org-ous.ts +35 -0
- runbooks/cfat/src/actions/get-regions.ts +22 -0
- runbooks/cfat/src/actions/zip-assessment.ts +27 -0
- runbooks/cfat/src/types/index.d.ts +147 -0
- runbooks/cfat/tests/__init__.py +141 -0
- runbooks/cfat/tests/test_cli.py +340 -0
- runbooks/cfat/tests/test_integration.py +290 -0
- runbooks/cfat/tests/test_models.py +505 -0
- runbooks/cfat/tests/test_reporting.py +354 -0
- runbooks/cfat/tsconfig.json +16 -0
- runbooks/cfat/webpack.config.cjs +27 -0
- runbooks/config.py +260 -0
- runbooks/finops/__init__.py +88 -0
- runbooks/finops/aws_client.py +245 -0
- runbooks/finops/cli.py +151 -0
- runbooks/finops/cost_processor.py +410 -0
- runbooks/finops/dashboard_runner.py +448 -0
- runbooks/finops/helpers.py +355 -0
- runbooks/finops/main.py +14 -0
- runbooks/finops/profile_processor.py +174 -0
- runbooks/finops/types.py +66 -0
- runbooks/finops/visualisations.py +80 -0
- runbooks/inventory/.gitignore +354 -0
- runbooks/inventory/ArgumentsClass.py +261 -0
- runbooks/inventory/Inventory_Modules.py +6130 -0
- runbooks/inventory/LandingZone/delete_lz.py +1075 -0
- runbooks/inventory/README.md +1320 -0
- runbooks/inventory/__init__.py +62 -0
- runbooks/inventory/account_class.py +532 -0
- runbooks/inventory/all_my_instances_wrapper.py +123 -0
- runbooks/inventory/aws_decorators.py +201 -0
- runbooks/inventory/cfn_move_stack_instances.py +1526 -0
- runbooks/inventory/check_cloudtrail_compliance.py +614 -0
- runbooks/inventory/check_controltower_readiness.py +1107 -0
- runbooks/inventory/check_landingzone_readiness.py +711 -0
- runbooks/inventory/cloudtrail.md +727 -0
- runbooks/inventory/collectors/__init__.py +20 -0
- runbooks/inventory/collectors/aws_compute.py +518 -0
- runbooks/inventory/collectors/aws_networking.py +275 -0
- runbooks/inventory/collectors/base.py +222 -0
- runbooks/inventory/core/__init__.py +19 -0
- runbooks/inventory/core/collector.py +303 -0
- runbooks/inventory/core/formatter.py +296 -0
- runbooks/inventory/delete_s3_buckets_objects.py +169 -0
- runbooks/inventory/discovery.md +81 -0
- runbooks/inventory/draw_org_structure.py +748 -0
- runbooks/inventory/ec2_vpc_utils.py +341 -0
- runbooks/inventory/find_cfn_drift_detection.py +272 -0
- runbooks/inventory/find_cfn_orphaned_stacks.py +719 -0
- runbooks/inventory/find_cfn_stackset_drift.py +733 -0
- runbooks/inventory/find_ec2_security_groups.py +669 -0
- runbooks/inventory/find_landingzone_versions.py +201 -0
- runbooks/inventory/find_vpc_flow_logs.py +1221 -0
- runbooks/inventory/inventory.sh +659 -0
- runbooks/inventory/list_cfn_stacks.py +558 -0
- runbooks/inventory/list_cfn_stackset_operation_results.py +252 -0
- runbooks/inventory/list_cfn_stackset_operations.py +734 -0
- runbooks/inventory/list_cfn_stacksets.py +453 -0
- runbooks/inventory/list_config_recorders_delivery_channels.py +681 -0
- runbooks/inventory/list_ds_directories.py +354 -0
- runbooks/inventory/list_ec2_availability_zones.py +286 -0
- runbooks/inventory/list_ec2_ebs_volumes.py +244 -0
- runbooks/inventory/list_ec2_instances.py +425 -0
- runbooks/inventory/list_ecs_clusters_and_tasks.py +562 -0
- runbooks/inventory/list_elbs_load_balancers.py +411 -0
- runbooks/inventory/list_enis_network_interfaces.py +526 -0
- runbooks/inventory/list_guardduty_detectors.py +568 -0
- runbooks/inventory/list_iam_policies.py +404 -0
- runbooks/inventory/list_iam_roles.py +518 -0
- runbooks/inventory/list_iam_saml_providers.py +359 -0
- runbooks/inventory/list_lambda_functions.py +882 -0
- runbooks/inventory/list_org_accounts.py +446 -0
- runbooks/inventory/list_org_accounts_users.py +354 -0
- runbooks/inventory/list_rds_db_instances.py +406 -0
- runbooks/inventory/list_route53_hosted_zones.py +318 -0
- runbooks/inventory/list_servicecatalog_provisioned_products.py +575 -0
- runbooks/inventory/list_sns_topics.py +360 -0
- runbooks/inventory/list_ssm_parameters.py +402 -0
- runbooks/inventory/list_vpc_subnets.py +433 -0
- runbooks/inventory/list_vpcs.py +422 -0
- runbooks/inventory/lockdown_cfn_stackset_role.py +224 -0
- runbooks/inventory/models/__init__.py +24 -0
- runbooks/inventory/models/account.py +192 -0
- runbooks/inventory/models/inventory.py +309 -0
- runbooks/inventory/models/resource.py +247 -0
- runbooks/inventory/recover_cfn_stack_ids.py +205 -0
- runbooks/inventory/requirements.txt +12 -0
- runbooks/inventory/run_on_multi_accounts.py +211 -0
- runbooks/inventory/tests/common_test_data.py +3661 -0
- runbooks/inventory/tests/common_test_functions.py +204 -0
- runbooks/inventory/tests/script_test_data.py +0 -0
- runbooks/inventory/tests/setup.py +24 -0
- runbooks/inventory/tests/src.py +18 -0
- runbooks/inventory/tests/test_cfn_describe_stacks.py +208 -0
- runbooks/inventory/tests/test_ec2_describe_instances.py +162 -0
- runbooks/inventory/tests/test_inventory_modules.py +55 -0
- runbooks/inventory/tests/test_lambda_list_functions.py +86 -0
- runbooks/inventory/tests/test_moto_integration_example.py +273 -0
- runbooks/inventory/tests/test_org_list_accounts.py +49 -0
- runbooks/inventory/update_aws_actions.py +173 -0
- runbooks/inventory/update_cfn_stacksets.py +1215 -0
- runbooks/inventory/update_cloudwatch_logs_retention_policy.py +294 -0
- runbooks/inventory/update_iam_roles_cross_accounts.py +478 -0
- runbooks/inventory/update_s3_public_access_block.py +539 -0
- runbooks/inventory/utils/__init__.py +23 -0
- runbooks/inventory/utils/aws_helpers.py +510 -0
- runbooks/inventory/utils/threading_utils.py +493 -0
- runbooks/inventory/utils/validation.py +682 -0
- runbooks/inventory/verify_ec2_security_groups.py +1430 -0
- runbooks/main.py +785 -0
- runbooks/organizations/__init__.py +12 -0
- runbooks/organizations/manager.py +374 -0
- runbooks/security_baseline/README.md +324 -0
- runbooks/security_baseline/checklist/alternate_contacts.py +8 -1
- runbooks/security_baseline/checklist/bucket_public_access.py +4 -1
- runbooks/security_baseline/checklist/cloudwatch_alarm_configuration.py +9 -2
- runbooks/security_baseline/checklist/guardduty_enabled.py +9 -2
- runbooks/security_baseline/checklist/multi_region_instance_usage.py +5 -1
- runbooks/security_baseline/checklist/root_access_key.py +6 -1
- runbooks/security_baseline/config-origin.json +1 -1
- runbooks/security_baseline/config.json +1 -1
- runbooks/security_baseline/permission.json +1 -1
- runbooks/security_baseline/report_generator.py +10 -2
- runbooks/security_baseline/report_template_en.html +7 -7
- runbooks/security_baseline/report_template_jp.html +7 -7
- runbooks/security_baseline/report_template_kr.html +12 -12
- runbooks/security_baseline/report_template_vn.html +7 -7
- runbooks/security_baseline/requirements.txt +7 -0
- runbooks/security_baseline/run_script.py +8 -2
- runbooks/security_baseline/security_baseline_tester.py +10 -2
- runbooks/security_baseline/utils/common.py +5 -1
- runbooks/utils/__init__.py +204 -0
- runbooks-0.6.1.dist-info/METADATA +373 -0
- runbooks-0.6.1.dist-info/RECORD +237 -0
- {runbooks-0.2.5.dist-info → runbooks-0.6.1.dist-info}/WHEEL +1 -1
- runbooks-0.6.1.dist-info/entry_points.txt +7 -0
- runbooks-0.6.1.dist-info/licenses/LICENSE +201 -0
- runbooks-0.6.1.dist-info/top_level.txt +3 -0
- runbooks/python101/calculator.py +0 -34
- runbooks/python101/config.py +0 -1
- runbooks/python101/exceptions.py +0 -16
- runbooks/python101/file_manager.py +0 -218
- runbooks/python101/toolkit.py +0 -153
- runbooks-0.2.5.dist-info/METADATA +0 -439
- runbooks-0.2.5.dist-info/RECORD +0 -61
- runbooks-0.2.5.dist-info/entry_points.txt +0 -3
- runbooks-0.2.5.dist-info/top_level.txt +0 -1
@@ -0,0 +1,496 @@
|
|
1
|
+
"""
|
2
|
+
Report generation for Cloud Foundations Assessment Tool.
|
3
|
+
|
4
|
+
This module provides various report formats including HTML, CSV, and JSON
|
5
|
+
for assessment results.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from pathlib import Path
|
9
|
+
from typing import Union
|
10
|
+
|
11
|
+
from loguru import logger
|
12
|
+
|
13
|
+
from runbooks.cfat.models import AssessmentReport, CheckStatus, Severity
|
14
|
+
|
15
|
+
|
16
|
+
class HTMLReportGenerator:
|
17
|
+
"""Generate HTML reports for CFAT assessments."""
|
18
|
+
|
19
|
+
def __init__(self, report: AssessmentReport):
|
20
|
+
"""Initialize with assessment report."""
|
21
|
+
self.report = report
|
22
|
+
|
23
|
+
def generate(self, file_path: Union[str, Path]) -> None:
|
24
|
+
"""Generate HTML report file."""
|
25
|
+
output_path = Path(file_path)
|
26
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
27
|
+
|
28
|
+
html_content = self._generate_html()
|
29
|
+
|
30
|
+
with open(output_path, "w", encoding="utf-8") as f:
|
31
|
+
f.write(html_content)
|
32
|
+
|
33
|
+
logger.info(f"HTML report generated: {output_path}")
|
34
|
+
|
35
|
+
def _generate_html(self) -> str:
|
36
|
+
"""Generate the complete HTML content."""
|
37
|
+
return f"""
|
38
|
+
<!DOCTYPE html>
|
39
|
+
<html lang="en">
|
40
|
+
<head>
|
41
|
+
<meta charset="UTF-8">
|
42
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
43
|
+
<title>Cloud Foundations Assessment Report</title>
|
44
|
+
<style>
|
45
|
+
{self._get_css_styles()}
|
46
|
+
</style>
|
47
|
+
</head>
|
48
|
+
<body>
|
49
|
+
<div class="container">
|
50
|
+
{self._generate_header()}
|
51
|
+
{self._generate_summary()}
|
52
|
+
{self._generate_results_table()}
|
53
|
+
{self._generate_recommendations()}
|
54
|
+
{self._generate_footer()}
|
55
|
+
</div>
|
56
|
+
<script>
|
57
|
+
{self._get_javascript()}
|
58
|
+
</script>
|
59
|
+
</body>
|
60
|
+
</html>
|
61
|
+
"""
|
62
|
+
|
63
|
+
def _get_css_styles(self) -> str:
|
64
|
+
"""Get CSS styles for the HTML report."""
|
65
|
+
return """
|
66
|
+
body {
|
67
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
68
|
+
margin: 0;
|
69
|
+
padding: 20px;
|
70
|
+
background-color: #f5f5f5;
|
71
|
+
color: #333;
|
72
|
+
}
|
73
|
+
|
74
|
+
.container {
|
75
|
+
max-width: 1200px;
|
76
|
+
margin: 0 auto;
|
77
|
+
background-color: white;
|
78
|
+
border-radius: 8px;
|
79
|
+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
80
|
+
overflow: hidden;
|
81
|
+
}
|
82
|
+
|
83
|
+
.header {
|
84
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
85
|
+
color: white;
|
86
|
+
padding: 30px;
|
87
|
+
text-align: center;
|
88
|
+
}
|
89
|
+
|
90
|
+
.header h1 {
|
91
|
+
margin: 0;
|
92
|
+
font-size: 2.5em;
|
93
|
+
font-weight: 300;
|
94
|
+
}
|
95
|
+
|
96
|
+
.header .subtitle {
|
97
|
+
margin-top: 10px;
|
98
|
+
opacity: 0.9;
|
99
|
+
font-size: 1.1em;
|
100
|
+
}
|
101
|
+
|
102
|
+
.summary {
|
103
|
+
padding: 30px;
|
104
|
+
background-color: #fafafa;
|
105
|
+
border-bottom: 1px solid #eee;
|
106
|
+
}
|
107
|
+
|
108
|
+
.summary-grid {
|
109
|
+
display: grid;
|
110
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
111
|
+
gap: 20px;
|
112
|
+
margin-top: 20px;
|
113
|
+
}
|
114
|
+
|
115
|
+
.summary-card {
|
116
|
+
background: white;
|
117
|
+
padding: 20px;
|
118
|
+
border-radius: 8px;
|
119
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
120
|
+
text-align: center;
|
121
|
+
}
|
122
|
+
|
123
|
+
.summary-card .number {
|
124
|
+
font-size: 2em;
|
125
|
+
font-weight: bold;
|
126
|
+
margin-bottom: 5px;
|
127
|
+
}
|
128
|
+
|
129
|
+
.summary-card .label {
|
130
|
+
color: #666;
|
131
|
+
font-size: 0.9em;
|
132
|
+
}
|
133
|
+
|
134
|
+
.pass { color: #4CAF50; }
|
135
|
+
.fail { color: #f44336; }
|
136
|
+
.warning { color: #ff9800; }
|
137
|
+
.critical { color: #d32f2f; }
|
138
|
+
.info { color: #2196F3; }
|
139
|
+
|
140
|
+
.results {
|
141
|
+
padding: 30px;
|
142
|
+
}
|
143
|
+
|
144
|
+
.filters {
|
145
|
+
margin-bottom: 20px;
|
146
|
+
display: flex;
|
147
|
+
gap: 10px;
|
148
|
+
flex-wrap: wrap;
|
149
|
+
}
|
150
|
+
|
151
|
+
.filter-btn {
|
152
|
+
padding: 8px 16px;
|
153
|
+
border: 1px solid #ddd;
|
154
|
+
background: white;
|
155
|
+
border-radius: 4px;
|
156
|
+
cursor: pointer;
|
157
|
+
transition: all 0.3s;
|
158
|
+
}
|
159
|
+
|
160
|
+
.filter-btn:hover {
|
161
|
+
background: #f0f0f0;
|
162
|
+
}
|
163
|
+
|
164
|
+
.filter-btn.active {
|
165
|
+
background: #2196F3;
|
166
|
+
color: white;
|
167
|
+
border-color: #2196F3;
|
168
|
+
}
|
169
|
+
|
170
|
+
.results-table {
|
171
|
+
width: 100%;
|
172
|
+
border-collapse: collapse;
|
173
|
+
margin-top: 20px;
|
174
|
+
}
|
175
|
+
|
176
|
+
.results-table th,
|
177
|
+
.results-table td {
|
178
|
+
padding: 12px;
|
179
|
+
text-align: left;
|
180
|
+
border-bottom: 1px solid #eee;
|
181
|
+
}
|
182
|
+
|
183
|
+
.results-table th {
|
184
|
+
background-color: #f8f9fa;
|
185
|
+
font-weight: 600;
|
186
|
+
color: #555;
|
187
|
+
}
|
188
|
+
|
189
|
+
.results-table tr:hover {
|
190
|
+
background-color: #f8f9fa;
|
191
|
+
}
|
192
|
+
|
193
|
+
.status-badge {
|
194
|
+
padding: 4px 8px;
|
195
|
+
border-radius: 4px;
|
196
|
+
font-size: 0.8em;
|
197
|
+
font-weight: bold;
|
198
|
+
text-transform: uppercase;
|
199
|
+
}
|
200
|
+
|
201
|
+
.status-pass {
|
202
|
+
background-color: #e8f5e8;
|
203
|
+
color: #2e7d32;
|
204
|
+
}
|
205
|
+
|
206
|
+
.status-fail {
|
207
|
+
background-color: #ffebee;
|
208
|
+
color: #c62828;
|
209
|
+
}
|
210
|
+
|
211
|
+
.status-error {
|
212
|
+
background-color: #fff3e0;
|
213
|
+
color: #ef6c00;
|
214
|
+
}
|
215
|
+
|
216
|
+
.severity-badge {
|
217
|
+
padding: 4px 8px;
|
218
|
+
border-radius: 4px;
|
219
|
+
font-size: 0.8em;
|
220
|
+
font-weight: bold;
|
221
|
+
}
|
222
|
+
|
223
|
+
.severity-info {
|
224
|
+
background-color: #e3f2fd;
|
225
|
+
color: #1976d2;
|
226
|
+
}
|
227
|
+
|
228
|
+
.severity-warning {
|
229
|
+
background-color: #fff8e1;
|
230
|
+
color: #f57c00;
|
231
|
+
}
|
232
|
+
|
233
|
+
.severity-critical {
|
234
|
+
background-color: #ffebee;
|
235
|
+
color: #d32f2f;
|
236
|
+
}
|
237
|
+
|
238
|
+
.recommendations {
|
239
|
+
padding: 30px;
|
240
|
+
background-color: #f8f9fa;
|
241
|
+
}
|
242
|
+
|
243
|
+
.footer {
|
244
|
+
padding: 20px 30px;
|
245
|
+
background-color: #666;
|
246
|
+
color: white;
|
247
|
+
text-align: center;
|
248
|
+
font-size: 0.9em;
|
249
|
+
}
|
250
|
+
|
251
|
+
.expandable {
|
252
|
+
cursor: pointer;
|
253
|
+
}
|
254
|
+
|
255
|
+
.details {
|
256
|
+
display: none;
|
257
|
+
margin-top: 10px;
|
258
|
+
padding: 10px;
|
259
|
+
background-color: #f8f9fa;
|
260
|
+
border-radius: 4px;
|
261
|
+
font-size: 0.9em;
|
262
|
+
}
|
263
|
+
|
264
|
+
@media (max-width: 768px) {
|
265
|
+
.container {
|
266
|
+
margin: 10px;
|
267
|
+
}
|
268
|
+
|
269
|
+
.header {
|
270
|
+
padding: 20px;
|
271
|
+
}
|
272
|
+
|
273
|
+
.header h1 {
|
274
|
+
font-size: 2em;
|
275
|
+
}
|
276
|
+
|
277
|
+
.summary,
|
278
|
+
.results {
|
279
|
+
padding: 20px;
|
280
|
+
}
|
281
|
+
|
282
|
+
.results-table {
|
283
|
+
font-size: 0.9em;
|
284
|
+
}
|
285
|
+
}
|
286
|
+
"""
|
287
|
+
|
288
|
+
def _generate_header(self) -> str:
|
289
|
+
"""Generate the report header."""
|
290
|
+
return f"""
|
291
|
+
<div class="header">
|
292
|
+
<h1>Cloud Foundations Assessment Report</h1>
|
293
|
+
<div class="subtitle">
|
294
|
+
Account: {self.report.account_id} |
|
295
|
+
Region: {self.report.region} |
|
296
|
+
Generated: {self.report.timestamp.strftime("%Y-%m-%d %H:%M:%S")}
|
297
|
+
</div>
|
298
|
+
</div>
|
299
|
+
"""
|
300
|
+
|
301
|
+
def _generate_summary(self) -> str:
|
302
|
+
"""Generate the summary section."""
|
303
|
+
summary = self.report.summary
|
304
|
+
|
305
|
+
return f"""
|
306
|
+
<div class="summary">
|
307
|
+
<h2>Assessment Summary</h2>
|
308
|
+
<div class="summary-grid">
|
309
|
+
<div class="summary-card">
|
310
|
+
<div class="number">{summary.total_checks}</div>
|
311
|
+
<div class="label">Total Checks</div>
|
312
|
+
</div>
|
313
|
+
<div class="summary-card">
|
314
|
+
<div class="number pass">{summary.passed_checks}</div>
|
315
|
+
<div class="label">Passed</div>
|
316
|
+
</div>
|
317
|
+
<div class="summary-card">
|
318
|
+
<div class="number fail">{summary.failed_checks}</div>
|
319
|
+
<div class="label">Failed</div>
|
320
|
+
</div>
|
321
|
+
<div class="summary-card">
|
322
|
+
<div class="number warning">{summary.warnings}</div>
|
323
|
+
<div class="label">Warnings</div>
|
324
|
+
</div>
|
325
|
+
<div class="summary-card">
|
326
|
+
<div class="number critical">{summary.critical_issues}</div>
|
327
|
+
<div class="label">Critical Issues</div>
|
328
|
+
</div>
|
329
|
+
<div class="summary-card">
|
330
|
+
<div class="number info">{summary.pass_rate:.1f}%</div>
|
331
|
+
<div class="label">Pass Rate</div>
|
332
|
+
</div>
|
333
|
+
</div>
|
334
|
+
</div>
|
335
|
+
"""
|
336
|
+
|
337
|
+
def _generate_results_table(self) -> str:
|
338
|
+
"""Generate the results table."""
|
339
|
+
table_rows = ""
|
340
|
+
|
341
|
+
for result in self.report.results:
|
342
|
+
status_class = f"status-{result.status.value.lower()}"
|
343
|
+
severity_class = f"severity-{result.severity.value.lower()}"
|
344
|
+
|
345
|
+
table_rows += f"""
|
346
|
+
<tr class="result-row expandable" onclick="toggleDetails(this)">
|
347
|
+
<td>{result.check_name}</td>
|
348
|
+
<td>{result.check_category}</td>
|
349
|
+
<td><span class="status-badge {status_class}">{result.status.value}</span></td>
|
350
|
+
<td><span class="severity-badge {severity_class}">{result.severity.value}</span></td>
|
351
|
+
<td>{result.message}</td>
|
352
|
+
<td>{result.execution_time:.2f}s</td>
|
353
|
+
</tr>
|
354
|
+
"""
|
355
|
+
|
356
|
+
if result.recommendations:
|
357
|
+
recommendations_html = "<ul>" + "".join(f"<li>{rec}</li>" for rec in result.recommendations) + "</ul>"
|
358
|
+
table_rows += f"""
|
359
|
+
<tr class="details-row">
|
360
|
+
<td colspan="6">
|
361
|
+
<div class="details">
|
362
|
+
<strong>Recommendations:</strong>
|
363
|
+
{recommendations_html}
|
364
|
+
</div>
|
365
|
+
</td>
|
366
|
+
</tr>
|
367
|
+
"""
|
368
|
+
|
369
|
+
return f"""
|
370
|
+
<div class="results">
|
371
|
+
<h2>Assessment Results</h2>
|
372
|
+
<div class="filters">
|
373
|
+
<button class="filter-btn active" onclick="filterResults('all')">All</button>
|
374
|
+
<button class="filter-btn" onclick="filterResults('fail')">Failed</button>
|
375
|
+
<button class="filter-btn" onclick="filterResults('pass')">Passed</button>
|
376
|
+
<button class="filter-btn" onclick="filterResults('critical')">Critical</button>
|
377
|
+
<button class="filter-btn" onclick="filterResults('warning')">Warning</button>
|
378
|
+
</div>
|
379
|
+
|
380
|
+
<table class="results-table">
|
381
|
+
<thead>
|
382
|
+
<tr>
|
383
|
+
<th>Check Name</th>
|
384
|
+
<th>Category</th>
|
385
|
+
<th>Status</th>
|
386
|
+
<th>Severity</th>
|
387
|
+
<th>Message</th>
|
388
|
+
<th>Execution Time</th>
|
389
|
+
</tr>
|
390
|
+
</thead>
|
391
|
+
<tbody>
|
392
|
+
{table_rows}
|
393
|
+
</tbody>
|
394
|
+
</table>
|
395
|
+
</div>
|
396
|
+
"""
|
397
|
+
|
398
|
+
def _generate_recommendations(self) -> str:
|
399
|
+
"""Generate recommendations section."""
|
400
|
+
failed_results = self.report.get_failed_results()
|
401
|
+
|
402
|
+
if not failed_results:
|
403
|
+
return """
|
404
|
+
<div class="recommendations">
|
405
|
+
<h2>Recommendations</h2>
|
406
|
+
<p>Congratulations! All assessment checks passed successfully.</p>
|
407
|
+
</div>
|
408
|
+
"""
|
409
|
+
|
410
|
+
recommendations_html = ""
|
411
|
+
for result in failed_results:
|
412
|
+
if result.recommendations:
|
413
|
+
recommendations_html += f"""
|
414
|
+
<div class="recommendation-item">
|
415
|
+
<h4>{result.check_name}</h4>
|
416
|
+
<ul>
|
417
|
+
{"".join(f"<li>{rec}</li>" for rec in result.recommendations)}
|
418
|
+
</ul>
|
419
|
+
</div>
|
420
|
+
"""
|
421
|
+
|
422
|
+
return f"""
|
423
|
+
<div class="recommendations">
|
424
|
+
<h2>Recommendations</h2>
|
425
|
+
<p>Based on the assessment results, here are the recommended actions to improve your AWS account security and compliance:</p>
|
426
|
+
{recommendations_html}
|
427
|
+
</div>
|
428
|
+
"""
|
429
|
+
|
430
|
+
def _generate_footer(self) -> str:
|
431
|
+
"""Generate the report footer."""
|
432
|
+
return f"""
|
433
|
+
<div class="footer">
|
434
|
+
Generated by CloudOps Runbooks v{self.report.version} |
|
435
|
+
Execution time: {self.report.summary.total_execution_time:.1f}s |
|
436
|
+
Profile: {self.report.profile}
|
437
|
+
</div>
|
438
|
+
"""
|
439
|
+
|
440
|
+
def _get_javascript(self) -> str:
|
441
|
+
"""Get JavaScript for interactive features."""
|
442
|
+
return """
|
443
|
+
function toggleDetails(row) {
|
444
|
+
const detailsRow = row.nextElementSibling;
|
445
|
+
if (detailsRow && detailsRow.classList.contains('details-row')) {
|
446
|
+
const details = detailsRow.querySelector('.details');
|
447
|
+
if (details.style.display === 'none' || details.style.display === '') {
|
448
|
+
details.style.display = 'block';
|
449
|
+
} else {
|
450
|
+
details.style.display = 'none';
|
451
|
+
}
|
452
|
+
}
|
453
|
+
}
|
454
|
+
|
455
|
+
function filterResults(filter) {
|
456
|
+
const rows = document.querySelectorAll('.result-row');
|
457
|
+
const buttons = document.querySelectorAll('.filter-btn');
|
458
|
+
|
459
|
+
// Update active button
|
460
|
+
buttons.forEach(btn => btn.classList.remove('active'));
|
461
|
+
event.target.classList.add('active');
|
462
|
+
|
463
|
+
rows.forEach(row => {
|
464
|
+
const statusBadge = row.querySelector('.status-badge');
|
465
|
+
const severityBadge = row.querySelector('.severity-badge');
|
466
|
+
const detailsRow = row.nextElementSibling;
|
467
|
+
|
468
|
+
let show = false;
|
469
|
+
|
470
|
+
if (filter === 'all') {
|
471
|
+
show = true;
|
472
|
+
} else if (filter === 'fail') {
|
473
|
+
show = statusBadge && statusBadge.textContent.toLowerCase() === 'fail';
|
474
|
+
} else if (filter === 'pass') {
|
475
|
+
show = statusBadge && statusBadge.textContent.toLowerCase() === 'pass';
|
476
|
+
} else if (filter === 'critical') {
|
477
|
+
show = severityBadge && severityBadge.textContent.toLowerCase() === 'critical';
|
478
|
+
} else if (filter === 'warning') {
|
479
|
+
show = severityBadge && severityBadge.textContent.toLowerCase() === 'warning';
|
480
|
+
}
|
481
|
+
|
482
|
+
row.style.display = show ? '' : 'none';
|
483
|
+
if (detailsRow && detailsRow.classList.contains('details-row')) {
|
484
|
+
detailsRow.style.display = show ? '' : 'none';
|
485
|
+
}
|
486
|
+
});
|
487
|
+
}
|
488
|
+
|
489
|
+
// Initialize details as hidden
|
490
|
+
document.addEventListener('DOMContentLoaded', function() {
|
491
|
+
const details = document.querySelectorAll('.details');
|
492
|
+
details.forEach(detail => {
|
493
|
+
detail.style.display = 'none';
|
494
|
+
});
|
495
|
+
});
|
496
|
+
"""
|
@@ -0,0 +1,135 @@
|
|
1
|
+
"""
|
2
|
+
Report Templates for Cloud Foundations Assessment.
|
3
|
+
|
4
|
+
This module provides different report templates optimized for
|
5
|
+
different audiences and use cases:
|
6
|
+
|
7
|
+
- Executive templates for management reporting
|
8
|
+
- Technical templates for engineering teams
|
9
|
+
- Compliance templates for audit and governance
|
10
|
+
- Custom templates for specific requirements
|
11
|
+
|
12
|
+
Each template defines structure, styling, and content
|
13
|
+
organization appropriate for its target audience.
|
14
|
+
"""
|
15
|
+
|
16
|
+
from abc import ABC, abstractmethod
|
17
|
+
from typing import Any, Dict
|
18
|
+
|
19
|
+
from runbooks.cfat.models import AssessmentReport
|
20
|
+
|
21
|
+
|
22
|
+
class BaseTemplate(ABC):
|
23
|
+
"""Base class for report templates."""
|
24
|
+
|
25
|
+
@abstractmethod
|
26
|
+
def generate(self, report: AssessmentReport) -> str:
|
27
|
+
"""Generate report content using this template."""
|
28
|
+
pass
|
29
|
+
|
30
|
+
@abstractmethod
|
31
|
+
def get_template_name(self) -> str:
|
32
|
+
"""Get template name."""
|
33
|
+
pass
|
34
|
+
|
35
|
+
|
36
|
+
class ExecutiveTemplate(BaseTemplate):
|
37
|
+
"""Executive summary template for management reporting."""
|
38
|
+
|
39
|
+
def get_template_name(self) -> str:
|
40
|
+
return "executive"
|
41
|
+
|
42
|
+
def generate(self, report: AssessmentReport) -> str:
|
43
|
+
"""
|
44
|
+
Generate executive summary report.
|
45
|
+
|
46
|
+
Args:
|
47
|
+
report: Assessment report data
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
Formatted executive summary
|
51
|
+
"""
|
52
|
+
# TODO: Implement executive template
|
53
|
+
return f"""
|
54
|
+
# Executive Summary - Cloud Foundations Assessment
|
55
|
+
|
56
|
+
## Account Overview
|
57
|
+
- **Account ID**: {report.account_id}
|
58
|
+
- **Assessment Date**: {report.timestamp.strftime("%Y-%m-%d")}
|
59
|
+
- **Compliance Score**: {report.summary.compliance_score}/100
|
60
|
+
- **Risk Level**: {report.summary.risk_level}
|
61
|
+
|
62
|
+
## Key Findings
|
63
|
+
- **Total Checks**: {report.summary.total_checks}
|
64
|
+
- **Pass Rate**: {report.summary.pass_rate:.1f}%
|
65
|
+
- **Critical Issues**: {report.summary.critical_issues}
|
66
|
+
- **Recommendations**: {len(report.get_failed_results())} items require attention
|
67
|
+
|
68
|
+
## Risk Assessment
|
69
|
+
The assessment identified {report.summary.critical_issues} critical security issues
|
70
|
+
that require immediate attention.
|
71
|
+
"""
|
72
|
+
|
73
|
+
|
74
|
+
class TechnicalTemplate(BaseTemplate):
|
75
|
+
"""Technical template for engineering teams."""
|
76
|
+
|
77
|
+
def get_template_name(self) -> str:
|
78
|
+
return "technical"
|
79
|
+
|
80
|
+
def generate(self, report: AssessmentReport) -> str:
|
81
|
+
"""
|
82
|
+
Generate technical detailed report.
|
83
|
+
|
84
|
+
Args:
|
85
|
+
report: Assessment report data
|
86
|
+
|
87
|
+
Returns:
|
88
|
+
Formatted technical report
|
89
|
+
"""
|
90
|
+
# TODO: Implement technical template
|
91
|
+
return f"""
|
92
|
+
# Technical Assessment Report
|
93
|
+
|
94
|
+
## Configuration Analysis
|
95
|
+
{report.summary.total_checks} checks executed across {len(report.get_categories())} categories.
|
96
|
+
|
97
|
+
## Failed Checks
|
98
|
+
{len(report.get_failed_results())} checks failed validation.
|
99
|
+
|
100
|
+
## Remediation Required
|
101
|
+
Immediate action required for {report.summary.critical_issues} critical findings.
|
102
|
+
"""
|
103
|
+
|
104
|
+
|
105
|
+
class ComplianceTemplate(BaseTemplate):
|
106
|
+
"""Compliance template for audit and governance."""
|
107
|
+
|
108
|
+
def get_template_name(self) -> str:
|
109
|
+
return "compliance"
|
110
|
+
|
111
|
+
def generate(self, report: AssessmentReport) -> str:
|
112
|
+
"""
|
113
|
+
Generate compliance-focused report.
|
114
|
+
|
115
|
+
Args:
|
116
|
+
report: Assessment report data
|
117
|
+
|
118
|
+
Returns:
|
119
|
+
Formatted compliance report
|
120
|
+
"""
|
121
|
+
# TODO: Implement compliance template
|
122
|
+
return f"""
|
123
|
+
# Compliance Assessment Report
|
124
|
+
|
125
|
+
## Compliance Framework
|
126
|
+
Assessment conducted against Cloud Foundations best practices.
|
127
|
+
|
128
|
+
## Compliance Score: {report.summary.compliance_score}/100
|
129
|
+
|
130
|
+
## Audit Trail
|
131
|
+
- Assessment performed: {report.timestamp.isoformat()}
|
132
|
+
- Total controls evaluated: {report.summary.total_checks}
|
133
|
+
- Controls passed: {report.summary.passed_checks}
|
134
|
+
- Controls failed: {report.summary.failed_checks}
|
135
|
+
"""
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
mkdir ./cfat -p
|
4
|
+
cd ./cfat
|
5
|
+
echo "installing npm packages..."
|
6
|
+
|
7
|
+
for i in \
|
8
|
+
'@aws-sdk/client-sts' \
|
9
|
+
'@aws-sdk/client-cloudtrail' \
|
10
|
+
'@aws-sdk/client-config-service' \
|
11
|
+
'@aws-sdk/client-ec2' \
|
12
|
+
'@aws-sdk/client-controltower' \
|
13
|
+
'@aws-sdk/client-iam' \
|
14
|
+
'@aws-sdk/client-cost-and-usage-report-service' \
|
15
|
+
'@aws-sdk/client-cloudformation' \
|
16
|
+
'@aws-sdk/client-organizations' \
|
17
|
+
'@aws-sdk/client-sso-admin' \
|
18
|
+
'@types/archiver' 'archiver' \
|
19
|
+
; do npm install "$i" --silent; done
|
20
|
+
|
21
|
+
echo "installation complete, starting cloud foundation assessment..."
|
22
|
+
download_url="https://raw.githubusercontent.com/cloud-foundations-on-aws/cloud-foundations-templates/main/cfat/dist/cfat.js"
|
23
|
+
curl -sS $download_url | node
|