runbooks 0.7.7__py3-none-any.whl → 0.9.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.
- runbooks/__init__.py +1 -1
- runbooks/base.py +2 -2
- runbooks/cfat/README.md +12 -1
- runbooks/cfat/__init__.py +8 -4
- runbooks/cfat/assessment/collectors.py +171 -14
- runbooks/cfat/assessment/compliance.py +546 -522
- runbooks/cfat/assessment/runner.py +129 -10
- runbooks/cfat/models.py +6 -2
- 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/logger.py +14 -0
- runbooks/common/mcp_integration.py +539 -0
- runbooks/common/performance_monitor.py +387 -0
- runbooks/common/profile_utils.py +216 -0
- runbooks/common/rich_utils.py +622 -0
- runbooks/enterprise/__init__.py +68 -0
- runbooks/enterprise/error_handling.py +411 -0
- runbooks/enterprise/logging.py +439 -0
- runbooks/enterprise/multi_tenant.py +583 -0
- runbooks/feedback/user_feedback_collector.py +440 -0
- runbooks/finops/README.md +129 -14
- runbooks/finops/__init__.py +22 -3
- 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 +90 -33
- runbooks/finops/cost_processor.py +211 -37
- runbooks/finops/dashboard_router.py +900 -0
- runbooks/finops/dashboard_runner.py +1334 -399
- runbooks/finops/embedded_mcp_validator.py +288 -0
- runbooks/finops/enhanced_dashboard_runner.py +526 -0
- runbooks/finops/enhanced_progress.py +327 -0
- runbooks/finops/enhanced_trend_visualization.py +423 -0
- runbooks/finops/finops_dashboard.py +41 -0
- runbooks/finops/helpers.py +639 -323
- 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 +396 -395
- 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/service_mapping.py +195 -0
- runbooks/finops/single_dashboard.py +710 -0
- runbooks/finops/tests/__init__.py +19 -0
- runbooks/finops/tests/results_test_finops_dashboard.xml +1 -0
- runbooks/finops/tests/run_comprehensive_tests.py +421 -0
- runbooks/finops/tests/run_tests.py +305 -0
- runbooks/finops/tests/test_finops_dashboard.py +705 -0
- runbooks/finops/tests/test_integration.py +477 -0
- runbooks/finops/tests/test_performance.py +380 -0
- runbooks/finops/tests/test_performance_benchmarks.py +500 -0
- runbooks/finops/tests/test_reference_images_validation.py +867 -0
- runbooks/finops/tests/test_single_account_features.py +715 -0
- runbooks/finops/tests/validate_test_suite.py +220 -0
- runbooks/finops/types.py +1 -1
- runbooks/hitl/enhanced_workflow_engine.py +725 -0
- runbooks/inventory/README.md +12 -1
- runbooks/inventory/artifacts/scale-optimize-status.txt +12 -0
- runbooks/inventory/collectors/aws_comprehensive.py +192 -185
- runbooks/inventory/collectors/enterprise_scale.py +281 -0
- runbooks/inventory/core/collector.py +299 -12
- runbooks/inventory/list_ec2_instances.py +21 -20
- runbooks/inventory/list_ssm_parameters.py +31 -3
- runbooks/inventory/organizations_discovery.py +1315 -0
- runbooks/inventory/rich_inventory_display.py +360 -0
- runbooks/inventory/run_on_multi_accounts.py +32 -16
- runbooks/inventory/runbooks.security.report_generator.log +0 -0
- runbooks/inventory/runbooks.security.run_script.log +0 -0
- runbooks/inventory/vpc_flow_analyzer.py +1030 -0
- runbooks/main.py +4171 -1615
- runbooks/metrics/dora_metrics_engine.py +1293 -0
- runbooks/monitoring/performance_monitor.py +433 -0
- runbooks/operate/README.md +394 -0
- runbooks/operate/__init__.py +2 -2
- runbooks/operate/base.py +291 -11
- runbooks/operate/deployment_framework.py +1032 -0
- runbooks/operate/deployment_validator.py +853 -0
- runbooks/operate/dynamodb_operations.py +10 -6
- runbooks/operate/ec2_operations.py +321 -11
- runbooks/operate/executive_dashboard.py +779 -0
- runbooks/operate/mcp_integration.py +750 -0
- runbooks/operate/nat_gateway_operations.py +1120 -0
- runbooks/operate/networking_cost_heatmap.py +685 -0
- runbooks/operate/privatelink_operations.py +940 -0
- runbooks/operate/s3_operations.py +10 -6
- runbooks/operate/vpc_endpoints.py +644 -0
- runbooks/operate/vpc_operations.py +1038 -0
- runbooks/remediation/README.md +489 -13
- runbooks/remediation/__init__.py +2 -2
- runbooks/remediation/acm_remediation.py +1 -1
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/cloudtrail_remediation.py +1 -1
- runbooks/remediation/cognito_remediation.py +1 -1
- runbooks/remediation/commons.py +8 -4
- runbooks/remediation/dynamodb_remediation.py +1 -1
- runbooks/remediation/ec2_remediation.py +1 -1
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -1
- runbooks/remediation/kms_enable_key_rotation.py +1 -1
- runbooks/remediation/kms_remediation.py +1 -1
- runbooks/remediation/lambda_remediation.py +1 -1
- runbooks/remediation/multi_account.py +1 -1
- runbooks/remediation/rds_remediation.py +1 -1
- runbooks/remediation/s3_block_public_access.py +1 -1
- runbooks/remediation/s3_enable_access_logging.py +1 -1
- runbooks/remediation/s3_encryption.py +1 -1
- runbooks/remediation/s3_remediation.py +1 -1
- runbooks/remediation/vpc_remediation.py +475 -0
- runbooks/security/ENTERPRISE_SECURITY_FRAMEWORK.md +506 -0
- runbooks/security/README.md +12 -1
- runbooks/security/__init__.py +166 -33
- runbooks/security/compliance_automation.py +634 -0
- runbooks/security/compliance_automation_engine.py +1021 -0
- runbooks/security/enterprise_security_framework.py +931 -0
- runbooks/security/enterprise_security_policies.json +293 -0
- runbooks/security/integration_test_enterprise_security.py +879 -0
- runbooks/security/module_security_integrator.py +641 -0
- runbooks/security/report_generator.py +10 -0
- runbooks/security/run_script.py +27 -5
- runbooks/security/security_baseline_tester.py +153 -27
- runbooks/security/security_export.py +456 -0
- 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/reliability_monitoring_framework.py +1011 -0
- runbooks/validation/__init__.py +10 -0
- runbooks/validation/benchmark.py +489 -0
- runbooks/validation/cli.py +368 -0
- runbooks/validation/mcp_validator.py +797 -0
- runbooks/vpc/README.md +478 -0
- runbooks/vpc/__init__.py +38 -0
- runbooks/vpc/config.py +212 -0
- runbooks/vpc/cost_engine.py +347 -0
- runbooks/vpc/heatmap_engine.py +605 -0
- runbooks/vpc/manager_interface.py +649 -0
- runbooks/vpc/networking_wrapper.py +1289 -0
- runbooks/vpc/rich_formatters.py +693 -0
- runbooks/vpc/tests/__init__.py +5 -0
- runbooks/vpc/tests/conftest.py +356 -0
- runbooks/vpc/tests/test_cli_integration.py +530 -0
- runbooks/vpc/tests/test_config.py +458 -0
- runbooks/vpc/tests/test_cost_engine.py +479 -0
- runbooks/vpc/tests/test_networking_wrapper.py +512 -0
- {runbooks-0.7.7.dist-info → runbooks-0.9.0.dist-info}/METADATA +175 -65
- {runbooks-0.7.7.dist-info → runbooks-0.9.0.dist-info}/RECORD +157 -60
- {runbooks-0.7.7.dist-info → runbooks-0.9.0.dist-info}/entry_points.txt +1 -1
- {runbooks-0.7.7.dist-info → runbooks-0.9.0.dist-info}/WHEEL +0 -0
- {runbooks-0.7.7.dist-info → runbooks-0.9.0.dist-info}/licenses/LICENSE +0 -0
- {runbooks-0.7.7.dist-info → runbooks-0.9.0.dist-info}/top_level.txt +0 -0
runbooks/security/run_script.py
CHANGED
@@ -15,6 +15,14 @@ Compatible with both local (via pip or Docker) and AWS Lambda environments.
|
|
15
15
|
import argparse
|
16
16
|
import sys
|
17
17
|
|
18
|
+
from runbooks.common.rich_utils import (
|
19
|
+
console,
|
20
|
+
create_panel,
|
21
|
+
print_error,
|
22
|
+
print_info,
|
23
|
+
print_success,
|
24
|
+
print_warning,
|
25
|
+
)
|
18
26
|
from runbooks.utils.logger import configure_logger
|
19
27
|
|
20
28
|
from .security_baseline_tester import SecurityBaselineTester
|
@@ -65,17 +73,31 @@ def main():
|
|
65
73
|
try:
|
66
74
|
args = parse_arguments()
|
67
75
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
76
|
+
# Display startup information with Rich formatting
|
77
|
+
startup_info = f"""[bold cyan]AWS Security Baseline Tester[/bold cyan]
|
78
|
+
|
79
|
+
[green]Configuration:[/green]
|
80
|
+
[cyan]AWS Profile:[/cyan] {args.profile}
|
81
|
+
[cyan]Language:[/cyan] {args.language}
|
82
|
+
[cyan]Output Directory:[/cyan] {args.output or "./results"}
|
83
|
+
|
84
|
+
[dim]Starting comprehensive security assessment...[/dim]"""
|
85
|
+
|
86
|
+
console.print(create_panel(startup_info, title="🔒 Security Baseline Tester", border_style="cyan"))
|
87
|
+
|
88
|
+
print_info("Initializing AWS Security Baseline Tester...")
|
89
|
+
print_info(f"Using AWS profile: {args.profile}")
|
90
|
+
print_info(f"Report language: {args.language}")
|
91
|
+
print_info(f"Output directory: {args.output or './results'}")
|
72
92
|
|
73
93
|
## Instantiate and run the Security Baseline Tester
|
74
94
|
tester = SecurityBaselineTester(args.profile, args.language, args.output)
|
75
95
|
tester.run()
|
76
96
|
|
77
|
-
|
97
|
+
print_success("AWS Security Baseline testing completed successfully!")
|
98
|
+
|
78
99
|
except Exception as e:
|
100
|
+
print_error(f"An unexpected error occurred: {e}", exception=e)
|
79
101
|
logger.error(f"An unexpected error occurred: {e}", exc_info=True)
|
80
102
|
sys.exit(1)
|
81
103
|
|
@@ -5,26 +5,43 @@ import logging
|
|
5
5
|
import os
|
6
6
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
7
7
|
from pathlib import Path
|
8
|
+
from typing import Any, Dict, List, Optional
|
8
9
|
|
9
10
|
import boto3
|
10
11
|
import botocore
|
11
12
|
|
13
|
+
from runbooks.common.rich_utils import (
|
14
|
+
STATUS_INDICATORS,
|
15
|
+
console,
|
16
|
+
create_panel,
|
17
|
+
create_progress_bar,
|
18
|
+
create_table,
|
19
|
+
print_error,
|
20
|
+
print_info,
|
21
|
+
print_status,
|
22
|
+
print_success,
|
23
|
+
print_warning,
|
24
|
+
)
|
25
|
+
|
12
26
|
from . import (
|
13
27
|
checklist, # noqa: F403
|
14
28
|
report_generator,
|
15
29
|
)
|
30
|
+
from .security_export import SecurityExporter
|
16
31
|
from .utils import common, language, level_const
|
17
32
|
|
18
33
|
# from .utils.language import get_translator
|
19
34
|
|
20
35
|
|
21
36
|
class SecurityBaselineTester:
|
22
|
-
def __init__(self, profile, lang_code, output_dir):
|
37
|
+
def __init__(self, profile, lang_code, output_dir, export_formats: List[str] = None):
|
23
38
|
self.profile = profile
|
24
39
|
self.language = lang_code
|
25
40
|
self.output = output_dir
|
41
|
+
self.export_formats = export_formats or ["json", "csv"]
|
26
42
|
self.session = self._create_session()
|
27
43
|
self.config = self._load_config()
|
44
|
+
self.exporter = SecurityExporter(output_dir)
|
28
45
|
## Call module 'language' and pass the string 'lang_code'
|
29
46
|
self.translator = language.get_translator("main", lang_code)
|
30
47
|
|
@@ -50,22 +67,40 @@ class SecurityBaselineTester:
|
|
50
67
|
raise
|
51
68
|
|
52
69
|
def run(self):
|
70
|
+
"""Execute the security baseline assessment with Rich CLI output."""
|
53
71
|
try:
|
72
|
+
# Print security assessment header
|
73
|
+
console.print(
|
74
|
+
create_panel(
|
75
|
+
"[bold cyan]AWS Security Baseline Assessment[/bold cyan]\n\n"
|
76
|
+
f"[dim]Profile: {self.profile} | Language: {self.language}[/dim]",
|
77
|
+
title="🛡️ Starting Security Assessment",
|
78
|
+
border_style="cyan",
|
79
|
+
)
|
80
|
+
)
|
81
|
+
|
54
82
|
self._validate_session()
|
55
83
|
caller_identity = self._get_caller_identity()
|
56
84
|
self._print_auditor_info(caller_identity)
|
57
85
|
|
58
|
-
|
86
|
+
print_info("Initiating comprehensive security baseline tests...")
|
59
87
|
|
60
88
|
account_id, results = self._execute_tests()
|
61
89
|
self._generate_report(account_id, results)
|
62
90
|
|
63
|
-
|
91
|
+
# Export results in multiple formats
|
92
|
+
if self.export_formats:
|
93
|
+
print_info("Exporting security assessment results...")
|
94
|
+
self.exporter.export_security_results(
|
95
|
+
account_id=account_id, results=results, language=self.language, formats=self.export_formats
|
96
|
+
)
|
97
|
+
|
98
|
+
print_success("Security baseline assessment completed successfully!")
|
99
|
+
|
64
100
|
except Exception as e:
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
)
|
101
|
+
print_error(f"Security baseline test failed: {str(e)}", exception=e)
|
102
|
+
logging.error(f"An error occurred during the security baseline test: {str(e)}", exc_info=True)
|
103
|
+
raise
|
69
104
|
|
70
105
|
def _validate_session(self):
|
71
106
|
if self.session.region_name is None:
|
@@ -79,35 +114,114 @@ class SecurityBaselineTester:
|
|
79
114
|
raise
|
80
115
|
|
81
116
|
def _print_auditor_info(self, caller_identity):
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
117
|
+
"""Display auditor information with Rich formatting."""
|
118
|
+
auditor_info = f"""[bold cyan]User ID:[/bold cyan] {caller_identity["UserId"]}
|
119
|
+
[bold cyan]Account:[/bold cyan] {caller_identity["Account"]}
|
120
|
+
[bold cyan]ARN:[/bold cyan] {caller_identity["Arn"]}"""
|
121
|
+
|
122
|
+
console.print(
|
123
|
+
create_panel(auditor_info, title="🔐 Security Assessment Context", border_style="cyan", padding=1)
|
124
|
+
)
|
87
125
|
|
88
126
|
def _execute_tests(self):
|
89
127
|
iam_client = self.session.client("iam")
|
90
128
|
sts_client = self.session.client("sts")
|
91
129
|
|
92
130
|
account_id = common.get_account_id(sts_client)
|
93
|
-
|
131
|
+
print_info(f"Generating credential report for account {account_id}")
|
94
132
|
credential_report = common.generate_credential_report(iam_client)
|
95
133
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
for check_name in self.config.get("checks", [])
|
100
|
-
}
|
134
|
+
# Create progress bar for security checks
|
135
|
+
checks = self.config.get("checks", [])
|
136
|
+
total_checks = len(checks)
|
101
137
|
|
102
|
-
|
103
|
-
|
104
|
-
}
|
105
|
-
for future in as_completed(futures):
|
106
|
-
result = future.result()
|
107
|
-
results[result.level].append(result)
|
138
|
+
with create_progress_bar(description="Security Assessment") as progress:
|
139
|
+
task = progress.add_task("Running security checks...", total=total_checks)
|
108
140
|
|
141
|
+
with ThreadPoolExecutor(max_workers=self.config.get("max_workers", 5)) as executor:
|
142
|
+
futures = {
|
143
|
+
executor.submit(self._run_check, check_name, credential_report): check_name for check_name in checks
|
144
|
+
}
|
145
|
+
|
146
|
+
results = {
|
147
|
+
level: [] for level in ["Success", "Warning", "Danger", "Error", "Info"] if isinstance(level, str)
|
148
|
+
}
|
149
|
+
completed_checks = 0
|
150
|
+
|
151
|
+
for future in as_completed(futures):
|
152
|
+
result = future.result()
|
153
|
+
results[result.level].append(result)
|
154
|
+
completed_checks += 1
|
155
|
+
progress.update(task, completed=completed_checks)
|
156
|
+
|
157
|
+
# Display security assessment summary
|
158
|
+
self._display_security_summary(results, total_checks)
|
109
159
|
return account_id, results
|
110
160
|
|
161
|
+
def _display_security_summary(self, results: Dict[str, List], total_checks: int):
|
162
|
+
"""Display security assessment summary with Rich formatting."""
|
163
|
+
# Create summary table
|
164
|
+
summary_table = create_table(
|
165
|
+
title="🛡️ Security Assessment Summary",
|
166
|
+
columns=[
|
167
|
+
{"name": "Status", "style": "bold", "justify": "left"},
|
168
|
+
{"name": "Count", "style": "bold", "justify": "center"},
|
169
|
+
{"name": "Percentage", "style": "dim", "justify": "right"},
|
170
|
+
],
|
171
|
+
)
|
172
|
+
|
173
|
+
# Calculate statistics
|
174
|
+
for level in ["Danger", "Warning", "Success", "Info", "Error"]:
|
175
|
+
count = len(results.get(level, []))
|
176
|
+
if total_checks > 0:
|
177
|
+
percentage = (count / total_checks) * 100
|
178
|
+
percentage_str = f"{percentage:.1f}%"
|
179
|
+
else:
|
180
|
+
percentage_str = "0%"
|
181
|
+
|
182
|
+
# Style based on level
|
183
|
+
if level == "Danger":
|
184
|
+
status_text = f"🔴 {level}"
|
185
|
+
style = "error"
|
186
|
+
elif level == "Warning":
|
187
|
+
status_text = f"🟡 {level}"
|
188
|
+
style = "warning"
|
189
|
+
elif level == "Success":
|
190
|
+
status_text = f"🟢 {level}"
|
191
|
+
style = "success"
|
192
|
+
elif level == "Info":
|
193
|
+
status_text = f"🔵 {level}"
|
194
|
+
style = "info"
|
195
|
+
else: # Error
|
196
|
+
status_text = f"❌ {level}"
|
197
|
+
style = "critical"
|
198
|
+
|
199
|
+
summary_table.add_row(status_text, str(count), percentage_str, style=style)
|
200
|
+
|
201
|
+
console.print(summary_table)
|
202
|
+
|
203
|
+
# Calculate overall security score
|
204
|
+
total_issues = len(results.get("Danger", [])) + len(results.get("Warning", []))
|
205
|
+
total_success = len(results.get("Success", []))
|
206
|
+
|
207
|
+
if total_checks > 0:
|
208
|
+
security_score = (total_success / total_checks) * 100
|
209
|
+
if security_score >= 90:
|
210
|
+
score_style = "success"
|
211
|
+
score_icon = "🛡️"
|
212
|
+
elif security_score >= 75:
|
213
|
+
score_style = "warning"
|
214
|
+
score_icon = "⚠️"
|
215
|
+
else:
|
216
|
+
score_style = "error"
|
217
|
+
score_icon = "🚨"
|
218
|
+
|
219
|
+
score_summary = f"""[bold {score_style}]{score_icon} Overall Security Score: {security_score:.1f}%[/bold {score_style}]
|
220
|
+
|
221
|
+
[dim]Total Checks: {total_checks} | Issues Found: {total_issues} | Successful: {total_success}[/dim]"""
|
222
|
+
|
223
|
+
console.print(create_panel(score_summary, title="Security Posture Assessment", border_style=score_style))
|
224
|
+
|
111
225
|
def _run_check(self, check_name, credential_report):
|
112
226
|
# check_module = __import__(f"checklist.{check_name}", fromlist=[check_name])
|
113
227
|
check_module = importlib.import_module(f"runbooks.security.checklist.{check_name}")
|
@@ -164,9 +278,9 @@ class SecurityBaselineTester:
|
|
164
278
|
|
165
279
|
if not results_dir.exists():
|
166
280
|
results_dir.mkdir(parents=True, exist_ok=True)
|
167
|
-
|
281
|
+
print_info(f"Created results directory: {results_dir}")
|
168
282
|
else:
|
169
|
-
|
283
|
+
print_info(f"Using existing results directory: {results_dir}")
|
170
284
|
|
171
285
|
return results_dir
|
172
286
|
|
@@ -198,4 +312,16 @@ class SecurityBaselineTester:
|
|
198
312
|
with report_path.open("w", encoding="utf-8") as file:
|
199
313
|
file.write(html_report)
|
200
314
|
|
201
|
-
|
315
|
+
# Display report generation success with Rich formatting
|
316
|
+
report_success = f"""[bold green]Security Report Generated Successfully[/bold green]
|
317
|
+
|
318
|
+
[cyan]Report Location:[/cyan] {report_path}
|
319
|
+
[cyan]Account ID:[/cyan] {account_id}
|
320
|
+
[cyan]Language:[/cyan] {self.language}
|
321
|
+
[cyan]Report Time:[/cyan] {current_time}
|
322
|
+
|
323
|
+
[dim]Open the HTML report in your browser to view detailed findings.[/dim]"""
|
324
|
+
|
325
|
+
console.print(create_panel(report_success, title="📊 Report Generation Complete", border_style="green"))
|
326
|
+
|
327
|
+
print_success(f"HTML report saved to: {report_path}")
|