runbooks 0.2.3__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.
Files changed (221) hide show
  1. conftest.py +26 -0
  2. jupyter-agent/.env.template +2 -0
  3. jupyter-agent/.gitattributes +35 -0
  4. jupyter-agent/README.md +16 -0
  5. jupyter-agent/app.py +256 -0
  6. jupyter-agent/cloudops-agent.png +0 -0
  7. jupyter-agent/ds-system-prompt.txt +154 -0
  8. jupyter-agent/jupyter-agent.png +0 -0
  9. jupyter-agent/llama3_template.jinja +123 -0
  10. jupyter-agent/requirements.txt +9 -0
  11. jupyter-agent/utils.py +409 -0
  12. runbooks/__init__.py +71 -3
  13. runbooks/__main__.py +13 -0
  14. runbooks/aws/ec2_describe_instances.py +1 -1
  15. runbooks/aws/ec2_run_instances.py +8 -2
  16. runbooks/aws/ec2_start_stop_instances.py +17 -4
  17. runbooks/aws/ec2_unused_volumes.py +5 -1
  18. runbooks/aws/s3_create_bucket.py +4 -2
  19. runbooks/aws/s3_list_objects.py +6 -1
  20. runbooks/aws/tagging_lambda_handler.py +13 -2
  21. runbooks/aws/tags.json +12 -0
  22. runbooks/base.py +353 -0
  23. runbooks/cfat/README.md +49 -0
  24. runbooks/cfat/__init__.py +74 -0
  25. runbooks/cfat/app.ts +644 -0
  26. runbooks/cfat/assessment/__init__.py +40 -0
  27. runbooks/cfat/assessment/asana-import.csv +39 -0
  28. runbooks/cfat/assessment/cfat-checks.csv +31 -0
  29. runbooks/cfat/assessment/cfat.txt +520 -0
  30. runbooks/cfat/assessment/collectors.py +200 -0
  31. runbooks/cfat/assessment/jira-import.csv +39 -0
  32. runbooks/cfat/assessment/runner.py +387 -0
  33. runbooks/cfat/assessment/validators.py +290 -0
  34. runbooks/cfat/cli.py +103 -0
  35. runbooks/cfat/docs/asana-import.csv +24 -0
  36. runbooks/cfat/docs/cfat-checks.csv +31 -0
  37. runbooks/cfat/docs/cfat.txt +335 -0
  38. runbooks/cfat/docs/checks-output.png +0 -0
  39. runbooks/cfat/docs/cloudshell-console-run.png +0 -0
  40. runbooks/cfat/docs/cloudshell-download.png +0 -0
  41. runbooks/cfat/docs/cloudshell-output.png +0 -0
  42. runbooks/cfat/docs/downloadfile.png +0 -0
  43. runbooks/cfat/docs/jira-import.csv +24 -0
  44. runbooks/cfat/docs/open-cloudshell.png +0 -0
  45. runbooks/cfat/docs/report-header.png +0 -0
  46. runbooks/cfat/models.py +1026 -0
  47. runbooks/cfat/package-lock.json +5116 -0
  48. runbooks/cfat/package.json +38 -0
  49. runbooks/cfat/report.py +496 -0
  50. runbooks/cfat/reporting/__init__.py +46 -0
  51. runbooks/cfat/reporting/exporters.py +337 -0
  52. runbooks/cfat/reporting/formatters.py +496 -0
  53. runbooks/cfat/reporting/templates.py +135 -0
  54. runbooks/cfat/run-assessment.sh +23 -0
  55. runbooks/cfat/runner.py +69 -0
  56. runbooks/cfat/src/actions/check-cloudtrail-existence.ts +43 -0
  57. runbooks/cfat/src/actions/check-config-existence.ts +37 -0
  58. runbooks/cfat/src/actions/check-control-tower.ts +37 -0
  59. runbooks/cfat/src/actions/check-ec2-existence.ts +46 -0
  60. runbooks/cfat/src/actions/check-iam-users.ts +50 -0
  61. runbooks/cfat/src/actions/check-legacy-cur.ts +30 -0
  62. runbooks/cfat/src/actions/check-org-cloudformation.ts +30 -0
  63. runbooks/cfat/src/actions/check-vpc-existence.ts +43 -0
  64. runbooks/cfat/src/actions/create-asanaimport.ts +14 -0
  65. runbooks/cfat/src/actions/create-backlog.ts +372 -0
  66. runbooks/cfat/src/actions/create-jiraimport.ts +15 -0
  67. runbooks/cfat/src/actions/create-report.ts +616 -0
  68. runbooks/cfat/src/actions/define-account-type.ts +51 -0
  69. runbooks/cfat/src/actions/get-enabled-org-policy-types.ts +40 -0
  70. runbooks/cfat/src/actions/get-enabled-org-services.ts +26 -0
  71. runbooks/cfat/src/actions/get-idc-info.ts +34 -0
  72. runbooks/cfat/src/actions/get-org-da-accounts.ts +34 -0
  73. runbooks/cfat/src/actions/get-org-details.ts +35 -0
  74. runbooks/cfat/src/actions/get-org-member-accounts.ts +44 -0
  75. runbooks/cfat/src/actions/get-org-ous.ts +35 -0
  76. runbooks/cfat/src/actions/get-regions.ts +22 -0
  77. runbooks/cfat/src/actions/zip-assessment.ts +27 -0
  78. runbooks/cfat/src/types/index.d.ts +147 -0
  79. runbooks/cfat/tests/__init__.py +141 -0
  80. runbooks/cfat/tests/test_cli.py +340 -0
  81. runbooks/cfat/tests/test_integration.py +290 -0
  82. runbooks/cfat/tests/test_models.py +505 -0
  83. runbooks/cfat/tests/test_reporting.py +354 -0
  84. runbooks/cfat/tsconfig.json +16 -0
  85. runbooks/cfat/webpack.config.cjs +27 -0
  86. runbooks/config.py +260 -0
  87. runbooks/finops/__init__.py +88 -0
  88. runbooks/finops/aws_client.py +245 -0
  89. runbooks/finops/cli.py +151 -0
  90. runbooks/finops/cost_processor.py +410 -0
  91. runbooks/finops/dashboard_runner.py +448 -0
  92. runbooks/finops/helpers.py +355 -0
  93. runbooks/finops/main.py +14 -0
  94. runbooks/finops/profile_processor.py +174 -0
  95. runbooks/finops/types.py +66 -0
  96. runbooks/finops/visualisations.py +80 -0
  97. runbooks/inventory/.gitignore +354 -0
  98. runbooks/inventory/ArgumentsClass.py +261 -0
  99. runbooks/inventory/Inventory_Modules.py +6130 -0
  100. runbooks/inventory/LandingZone/delete_lz.py +1075 -0
  101. runbooks/inventory/README.md +1320 -0
  102. runbooks/inventory/__init__.py +62 -0
  103. runbooks/inventory/account_class.py +532 -0
  104. runbooks/inventory/all_my_instances_wrapper.py +123 -0
  105. runbooks/inventory/aws_decorators.py +201 -0
  106. runbooks/inventory/cfn_move_stack_instances.py +1526 -0
  107. runbooks/inventory/check_cloudtrail_compliance.py +614 -0
  108. runbooks/inventory/check_controltower_readiness.py +1107 -0
  109. runbooks/inventory/check_landingzone_readiness.py +711 -0
  110. runbooks/inventory/cloudtrail.md +727 -0
  111. runbooks/inventory/collectors/__init__.py +20 -0
  112. runbooks/inventory/collectors/aws_compute.py +518 -0
  113. runbooks/inventory/collectors/aws_networking.py +275 -0
  114. runbooks/inventory/collectors/base.py +222 -0
  115. runbooks/inventory/core/__init__.py +19 -0
  116. runbooks/inventory/core/collector.py +303 -0
  117. runbooks/inventory/core/formatter.py +296 -0
  118. runbooks/inventory/delete_s3_buckets_objects.py +169 -0
  119. runbooks/inventory/discovery.md +81 -0
  120. runbooks/inventory/draw_org_structure.py +748 -0
  121. runbooks/inventory/ec2_vpc_utils.py +341 -0
  122. runbooks/inventory/find_cfn_drift_detection.py +272 -0
  123. runbooks/inventory/find_cfn_orphaned_stacks.py +719 -0
  124. runbooks/inventory/find_cfn_stackset_drift.py +733 -0
  125. runbooks/inventory/find_ec2_security_groups.py +669 -0
  126. runbooks/inventory/find_landingzone_versions.py +201 -0
  127. runbooks/inventory/find_vpc_flow_logs.py +1221 -0
  128. runbooks/inventory/inventory.sh +659 -0
  129. runbooks/inventory/list_cfn_stacks.py +558 -0
  130. runbooks/inventory/list_cfn_stackset_operation_results.py +252 -0
  131. runbooks/inventory/list_cfn_stackset_operations.py +734 -0
  132. runbooks/inventory/list_cfn_stacksets.py +453 -0
  133. runbooks/inventory/list_config_recorders_delivery_channels.py +681 -0
  134. runbooks/inventory/list_ds_directories.py +354 -0
  135. runbooks/inventory/list_ec2_availability_zones.py +286 -0
  136. runbooks/inventory/list_ec2_ebs_volumes.py +244 -0
  137. runbooks/inventory/list_ec2_instances.py +425 -0
  138. runbooks/inventory/list_ecs_clusters_and_tasks.py +562 -0
  139. runbooks/inventory/list_elbs_load_balancers.py +411 -0
  140. runbooks/inventory/list_enis_network_interfaces.py +526 -0
  141. runbooks/inventory/list_guardduty_detectors.py +568 -0
  142. runbooks/inventory/list_iam_policies.py +404 -0
  143. runbooks/inventory/list_iam_roles.py +518 -0
  144. runbooks/inventory/list_iam_saml_providers.py +359 -0
  145. runbooks/inventory/list_lambda_functions.py +882 -0
  146. runbooks/inventory/list_org_accounts.py +446 -0
  147. runbooks/inventory/list_org_accounts_users.py +354 -0
  148. runbooks/inventory/list_rds_db_instances.py +406 -0
  149. runbooks/inventory/list_route53_hosted_zones.py +318 -0
  150. runbooks/inventory/list_servicecatalog_provisioned_products.py +575 -0
  151. runbooks/inventory/list_sns_topics.py +360 -0
  152. runbooks/inventory/list_ssm_parameters.py +402 -0
  153. runbooks/inventory/list_vpc_subnets.py +433 -0
  154. runbooks/inventory/list_vpcs.py +422 -0
  155. runbooks/inventory/lockdown_cfn_stackset_role.py +224 -0
  156. runbooks/inventory/models/__init__.py +24 -0
  157. runbooks/inventory/models/account.py +192 -0
  158. runbooks/inventory/models/inventory.py +309 -0
  159. runbooks/inventory/models/resource.py +247 -0
  160. runbooks/inventory/recover_cfn_stack_ids.py +205 -0
  161. runbooks/inventory/requirements.txt +12 -0
  162. runbooks/inventory/run_on_multi_accounts.py +211 -0
  163. runbooks/inventory/tests/common_test_data.py +3661 -0
  164. runbooks/inventory/tests/common_test_functions.py +204 -0
  165. runbooks/inventory/tests/script_test_data.py +0 -0
  166. runbooks/inventory/tests/setup.py +24 -0
  167. runbooks/inventory/tests/src.py +18 -0
  168. runbooks/inventory/tests/test_cfn_describe_stacks.py +208 -0
  169. runbooks/inventory/tests/test_ec2_describe_instances.py +162 -0
  170. runbooks/inventory/tests/test_inventory_modules.py +55 -0
  171. runbooks/inventory/tests/test_lambda_list_functions.py +86 -0
  172. runbooks/inventory/tests/test_moto_integration_example.py +273 -0
  173. runbooks/inventory/tests/test_org_list_accounts.py +49 -0
  174. runbooks/inventory/update_aws_actions.py +173 -0
  175. runbooks/inventory/update_cfn_stacksets.py +1215 -0
  176. runbooks/inventory/update_cloudwatch_logs_retention_policy.py +294 -0
  177. runbooks/inventory/update_iam_roles_cross_accounts.py +478 -0
  178. runbooks/inventory/update_s3_public_access_block.py +539 -0
  179. runbooks/inventory/utils/__init__.py +23 -0
  180. runbooks/inventory/utils/aws_helpers.py +510 -0
  181. runbooks/inventory/utils/threading_utils.py +493 -0
  182. runbooks/inventory/utils/validation.py +682 -0
  183. runbooks/inventory/verify_ec2_security_groups.py +1430 -0
  184. runbooks/main.py +785 -0
  185. runbooks/organizations/__init__.py +12 -0
  186. runbooks/organizations/manager.py +374 -0
  187. runbooks/security_baseline/README.md +324 -0
  188. runbooks/security_baseline/checklist/alternate_contacts.py +8 -1
  189. runbooks/security_baseline/checklist/bucket_public_access.py +4 -1
  190. runbooks/security_baseline/checklist/cloudwatch_alarm_configuration.py +9 -2
  191. runbooks/security_baseline/checklist/guardduty_enabled.py +9 -2
  192. runbooks/security_baseline/checklist/multi_region_instance_usage.py +5 -1
  193. runbooks/security_baseline/checklist/root_access_key.py +6 -1
  194. runbooks/security_baseline/config-origin.json +1 -1
  195. runbooks/security_baseline/config.json +1 -1
  196. runbooks/security_baseline/permission.json +1 -1
  197. runbooks/security_baseline/report_generator.py +10 -2
  198. runbooks/security_baseline/report_template_en.html +8 -8
  199. runbooks/security_baseline/report_template_jp.html +8 -8
  200. runbooks/security_baseline/report_template_kr.html +13 -13
  201. runbooks/security_baseline/report_template_vn.html +8 -8
  202. runbooks/security_baseline/requirements.txt +7 -0
  203. runbooks/security_baseline/run_script.py +8 -2
  204. runbooks/security_baseline/security_baseline_tester.py +10 -2
  205. runbooks/security_baseline/utils/common.py +5 -1
  206. runbooks/utils/__init__.py +204 -0
  207. runbooks-0.6.1.dist-info/METADATA +373 -0
  208. runbooks-0.6.1.dist-info/RECORD +237 -0
  209. {runbooks-0.2.3.dist-info → runbooks-0.6.1.dist-info}/WHEEL +1 -1
  210. runbooks-0.6.1.dist-info/entry_points.txt +7 -0
  211. runbooks-0.6.1.dist-info/licenses/LICENSE +201 -0
  212. runbooks-0.6.1.dist-info/top_level.txt +3 -0
  213. runbooks/python101/calculator.py +0 -34
  214. runbooks/python101/config.py +0 -1
  215. runbooks/python101/exceptions.py +0 -16
  216. runbooks/python101/file_manager.py +0 -218
  217. runbooks/python101/toolkit.py +0 -153
  218. runbooks-0.2.3.dist-info/METADATA +0 -435
  219. runbooks-0.2.3.dist-info/RECORD +0 -61
  220. runbooks-0.2.3.dist-info/entry_points.txt +0 -3
  221. runbooks-0.2.3.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