runbooks 0.7.9__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/cfat/README.md +12 -1
- runbooks/cfat/__init__.py +1 -1
- runbooks/cfat/assessment/runner.py +42 -34
- runbooks/cfat/models.py +1 -1
- 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_integration.py +539 -0
- runbooks/common/performance_monitor.py +387 -0
- runbooks/common/profile_utils.py +216 -0
- runbooks/common/rich_utils.py +171 -0
- runbooks/feedback/user_feedback_collector.py +440 -0
- runbooks/finops/README.md +339 -451
- 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_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 +29 -1880
- 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/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/main.py +740 -134
- 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 +7 -5
- runbooks/operate/privatelink_operations.py +1 -1
- runbooks/operate/vpc_endpoints.py +1 -1
- runbooks/remediation/README.md +489 -13
- runbooks/remediation/commons.py +8 -4
- runbooks/security/ENTERPRISE_SECURITY_FRAMEWORK.md +506 -0
- runbooks/security/README.md +12 -1
- runbooks/security/__init__.py +164 -33
- runbooks/security/compliance_automation.py +12 -10
- 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 +1 -1
- runbooks/security/run_script.py +4 -8
- runbooks/security/security_baseline_tester.py +36 -49
- 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/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 +265 -236
- runbooks/vpc/README.md +478 -0
- runbooks/vpc/__init__.py +2 -2
- runbooks/vpc/manager_interface.py +366 -351
- runbooks/vpc/networking_wrapper.py +62 -33
- runbooks/vpc/rich_formatters.py +22 -8
- {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/METADATA +136 -54
- {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/RECORD +94 -55
- {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/entry_points.txt +1 -1
- runbooks/finops/cross_validation.py +0 -375
- {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/WHEEL +0 -0
- {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/licenses/LICENSE +0 -0
- {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,400 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
Enhanced Exception Handling with IAM/SSO Role Requirements
|
4
|
+
Enterprise-grade error messaging with actionable guidance for AWS permissions.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import re
|
8
|
+
from typing import Dict, List, Optional
|
9
|
+
|
10
|
+
from rich.console import Console
|
11
|
+
from rich.panel import Panel
|
12
|
+
from rich.table import Table
|
13
|
+
|
14
|
+
console = Console()
|
15
|
+
|
16
|
+
|
17
|
+
class EnterpriseIAMGuidance:
|
18
|
+
"""Provides clear IAM/SSO role requirements and troubleshooting guidance."""
|
19
|
+
|
20
|
+
# AWS API Permission Requirements for Runbooks Operations
|
21
|
+
# ANY AWS profile needs these specific API permissions to run runbooks commands
|
22
|
+
RUNBOOKS_API_REQUIREMENTS = {
|
23
|
+
# FinOps Operations
|
24
|
+
"ce:GetCostAndUsage": {
|
25
|
+
"purpose": "Retrieve cost and usage data from Cost Explorer",
|
26
|
+
"functionality_impact": "Cost analysis, spending trends, budget reports",
|
27
|
+
"command_impact": "runbooks finops (dashboard, trend analysis)",
|
28
|
+
"aws_managed_policies": ["AWBillingReadOnlyAccess", "AWCostExplorerServiceRolePolicy"],
|
29
|
+
},
|
30
|
+
"budgets:ViewBudget": {
|
31
|
+
"purpose": "Access budget information and alerts",
|
32
|
+
"functionality_impact": "Budget status, alerts, spending limits",
|
33
|
+
"command_impact": "runbooks finops (budget dashboard)",
|
34
|
+
"aws_managed_policies": ["AWBillingReadOnlyAccess"],
|
35
|
+
},
|
36
|
+
# Resource Discovery Operations
|
37
|
+
"ec2:DescribeInstances": {
|
38
|
+
"purpose": "List and describe EC2 instances",
|
39
|
+
"functionality_impact": "Instance inventory, cost allocation, resource optimization",
|
40
|
+
"command_impact": "runbooks inventory, runbooks operate ec2",
|
41
|
+
"aws_managed_policies": ["ReadOnlyAccess", "EC2ReadOnlyAccess"],
|
42
|
+
},
|
43
|
+
"ec2:DescribeRegions": {
|
44
|
+
"purpose": "List available AWS regions",
|
45
|
+
"functionality_impact": "Multi-region resource discovery",
|
46
|
+
"command_impact": "runbooks inventory (region scanning)",
|
47
|
+
"aws_managed_policies": ["ReadOnlyAccess"],
|
48
|
+
},
|
49
|
+
"sts:GetCallerIdentity": {
|
50
|
+
"purpose": "Retrieve AWS account ID and user information",
|
51
|
+
"functionality_impact": "Account verification, audit trails",
|
52
|
+
"command_impact": "All runbooks commands (account identification)",
|
53
|
+
"aws_managed_policies": ["ReadOnlyAccess"],
|
54
|
+
},
|
55
|
+
"ec2:DescribeVolumes": {
|
56
|
+
"purpose": "List and describe EBS volumes",
|
57
|
+
"functionality_impact": "Storage cost analysis, orphaned volume detection",
|
58
|
+
"command_impact": "runbooks inventory, runbooks operate ebs",
|
59
|
+
"aws_managed_policies": ["ReadOnlyAccess", "EC2ReadOnlyAccess"],
|
60
|
+
},
|
61
|
+
"ec2:DescribeAddresses": {
|
62
|
+
"purpose": "List elastic IP addresses",
|
63
|
+
"functionality_impact": "IP cost optimization, unused resource detection",
|
64
|
+
"command_impact": "runbooks inventory, runbooks operate eip",
|
65
|
+
"aws_managed_policies": ["ReadOnlyAccess", "EC2ReadOnlyAccess"],
|
66
|
+
},
|
67
|
+
"rds:DescribeDBInstances": {
|
68
|
+
"purpose": "List and describe RDS database instances",
|
69
|
+
"functionality_impact": "Database cost analysis, resource optimization",
|
70
|
+
"command_impact": "runbooks inventory, runbooks operate rds",
|
71
|
+
"aws_managed_policies": ["ReadOnlyAccess", "RDSReadOnlyAccess"],
|
72
|
+
},
|
73
|
+
"rds:ListTagsForResource": {
|
74
|
+
"purpose": "Retrieve tags for RDS resources",
|
75
|
+
"functionality_impact": "Cost allocation, compliance tracking",
|
76
|
+
"command_impact": "runbooks inventory (tag-based filtering)",
|
77
|
+
"aws_managed_policies": ["ReadOnlyAccess", "RDSReadOnlyAccess"],
|
78
|
+
},
|
79
|
+
"lambda:ListFunctions": {
|
80
|
+
"purpose": "List Lambda functions",
|
81
|
+
"functionality_impact": "Serverless cost analysis, function inventory",
|
82
|
+
"command_impact": "runbooks inventory, runbooks operate lambda",
|
83
|
+
"aws_managed_policies": ["ReadOnlyAccess", "AWSLambda_ReadOnlyAccess"],
|
84
|
+
},
|
85
|
+
"lambda:ListTags": {
|
86
|
+
"purpose": "Retrieve tags for Lambda functions",
|
87
|
+
"functionality_impact": "Cost allocation, resource organization",
|
88
|
+
"command_impact": "runbooks inventory (Lambda tag analysis)",
|
89
|
+
"aws_managed_policies": ["ReadOnlyAccess", "AWSLambda_ReadOnlyAccess"],
|
90
|
+
},
|
91
|
+
"elbv2:DescribeLoadBalancers": {
|
92
|
+
"purpose": "List and describe Application Load Balancers",
|
93
|
+
"functionality_impact": "Load balancer cost analysis, traffic optimization",
|
94
|
+
"command_impact": "runbooks inventory, runbooks operate alb",
|
95
|
+
"aws_managed_policies": ["ReadOnlyAccess", "ElasticLoadBalancingReadOnly"],
|
96
|
+
},
|
97
|
+
"elbv2:DescribeTags": {
|
98
|
+
"purpose": "Retrieve tags for load balancers",
|
99
|
+
"functionality_impact": "Cost allocation, compliance tracking",
|
100
|
+
"command_impact": "runbooks inventory (ALB tag analysis)",
|
101
|
+
"aws_managed_policies": ["ReadOnlyAccess", "ElasticLoadBalancingReadOnly"],
|
102
|
+
},
|
103
|
+
}
|
104
|
+
|
105
|
+
@staticmethod
|
106
|
+
def parse_aws_error(error_message: str) -> Dict[str, str]:
|
107
|
+
"""Parse AWS error message to extract key components."""
|
108
|
+
|
109
|
+
# Extract permission that was denied
|
110
|
+
permission_match = re.search(r"perform: ([a-zA-Z0-9:*]+)", str(error_message))
|
111
|
+
permission_denied = permission_match.group(1) if permission_match else "Unknown"
|
112
|
+
|
113
|
+
# Extract resource ARN
|
114
|
+
resource_match = re.search(r"resource: (arn:aws:[^)]+)", str(error_message))
|
115
|
+
resource_arn = resource_match.group(1) if resource_match else "Unknown"
|
116
|
+
|
117
|
+
# Extract user ARN
|
118
|
+
user_match = re.search(r"User: (arn:aws:sts::[^)]+)", str(error_message))
|
119
|
+
user_arn = user_match.group(1) if user_match else "Unknown"
|
120
|
+
|
121
|
+
# Determine error type
|
122
|
+
if "AccessDeniedException" in str(error_message):
|
123
|
+
error_type = "Access Denied"
|
124
|
+
elif "UnauthorizedOperation" in str(error_message):
|
125
|
+
error_type = "Unauthorized Operation"
|
126
|
+
elif "Token has expired" in str(error_message):
|
127
|
+
error_type = "SSO Token Expired"
|
128
|
+
else:
|
129
|
+
error_type = "Permission Error"
|
130
|
+
|
131
|
+
return {
|
132
|
+
"error_type": error_type,
|
133
|
+
"permission_denied": permission_denied,
|
134
|
+
"resource_arn": resource_arn,
|
135
|
+
"user_arn": user_arn,
|
136
|
+
}
|
137
|
+
|
138
|
+
@classmethod
|
139
|
+
def get_permission_guidance(cls, permission_denied: str) -> Optional[Dict]:
|
140
|
+
"""Get specific guidance for the denied AWS API permission."""
|
141
|
+
|
142
|
+
# Direct permission match
|
143
|
+
if permission_denied in cls.RUNBOOKS_API_REQUIREMENTS:
|
144
|
+
return cls.RUNBOOKS_API_REQUIREMENTS[permission_denied]
|
145
|
+
|
146
|
+
# Pattern matching for wildcard permissions (e.g., ec2:Describe* matches ec2:DescribeInstances)
|
147
|
+
for api_permission, config in cls.RUNBOOKS_API_REQUIREMENTS.items():
|
148
|
+
permission_prefix = api_permission.split(":")[0]
|
149
|
+
denied_prefix = permission_denied.split(":")[0]
|
150
|
+
|
151
|
+
if permission_prefix == denied_prefix:
|
152
|
+
# Same service, likely related permission
|
153
|
+
return config
|
154
|
+
|
155
|
+
return None
|
156
|
+
|
157
|
+
@classmethod
|
158
|
+
def display_enhanced_error(cls, error: Exception, operation_context: str = "runbooks operation"):
|
159
|
+
"""Display enterprise-grade error message with actionable guidance."""
|
160
|
+
|
161
|
+
error_details = cls.parse_aws_error(str(error))
|
162
|
+
permission_guidance = cls.get_permission_guidance(error_details["permission_denied"])
|
163
|
+
|
164
|
+
# Create main error panel
|
165
|
+
error_panel = Panel(
|
166
|
+
f"[red]❌ {error_details['error_type']}: {error_details['permission_denied']}[/red]\n\n"
|
167
|
+
f"[yellow]Operation:[/yellow] {operation_context}\n"
|
168
|
+
f"[yellow]Resource:[/yellow] {error_details['resource_arn']}\n"
|
169
|
+
f"[yellow]User:[/yellow] {error_details['user_arn']}",
|
170
|
+
title="🚨 AWS Permission Error",
|
171
|
+
border_style="red",
|
172
|
+
)
|
173
|
+
console.print(error_panel)
|
174
|
+
|
175
|
+
# Display specific guidance if available
|
176
|
+
if permission_guidance:
|
177
|
+
cls._display_permission_requirements(error_details["permission_denied"], permission_guidance)
|
178
|
+
else:
|
179
|
+
cls._display_general_guidance(error_details["permission_denied"])
|
180
|
+
|
181
|
+
# Display troubleshooting steps
|
182
|
+
cls._display_troubleshooting_steps(error_details["error_type"])
|
183
|
+
|
184
|
+
@classmethod
|
185
|
+
def _display_permission_requirements(cls, permission_denied: str, permission_config: Dict):
|
186
|
+
"""Display specific AWS API permission requirements and impact."""
|
187
|
+
|
188
|
+
# Permission impact table
|
189
|
+
impact_table = Table(title=f"📋 AWS API Permission Analysis: {permission_denied}")
|
190
|
+
impact_table.add_column("Aspect", style="bold cyan")
|
191
|
+
impact_table.add_column("Details", style="white")
|
192
|
+
|
193
|
+
impact_table.add_row("Permission", permission_denied)
|
194
|
+
impact_table.add_row("Purpose", permission_config["purpose"])
|
195
|
+
impact_table.add_row("Functionality Impact", permission_config["functionality_impact"])
|
196
|
+
impact_table.add_row("Affected Commands", permission_config["command_impact"])
|
197
|
+
|
198
|
+
console.print(impact_table)
|
199
|
+
|
200
|
+
# Solution panel
|
201
|
+
solution_panel = Panel(
|
202
|
+
f"[green]✅ IAM/SSO Configuration Required:[/green]\n\n"
|
203
|
+
f"1. **Required Permission**: `{permission_denied}`\n"
|
204
|
+
f"2. **Add to IAM Policy**: Include this permission in your IAM role/policy\n"
|
205
|
+
f"3. **SSO Configuration**: Ensure your SSO role includes this permission\n"
|
206
|
+
f"4. **SCP Compliance**: Verify Service Control Policies don't deny this permission\n\n"
|
207
|
+
f"[bold]AWS Managed Policies (containing this permission):[/bold]\n"
|
208
|
+
+ "\n".join([f"• {policy}" for policy in permission_config["aws_managed_policies"]]),
|
209
|
+
title="🔧 Permission Resolution Guidance",
|
210
|
+
border_style="green",
|
211
|
+
)
|
212
|
+
console.print(solution_panel)
|
213
|
+
|
214
|
+
@classmethod
|
215
|
+
def _display_general_guidance(cls, permission_denied: str):
|
216
|
+
"""Display general IAM guidance for unknown permissions."""
|
217
|
+
|
218
|
+
guidance_panel = Panel(
|
219
|
+
f"[yellow]⚠️ Permission Required: {permission_denied}[/yellow]\n\n"
|
220
|
+
f"[bold]General Resolution Steps:[/bold]\n"
|
221
|
+
f"• **IAM Policy**: Add `{permission_denied}` to your IAM role/policy\n"
|
222
|
+
f"• **SSO Role**: Ensure your AWS SSO role includes this permission\n"
|
223
|
+
f"• **SCP Review**: Check Service Control Policies don't deny this permission\n"
|
224
|
+
f"• **Resource Policy**: Verify resource-based policies allow access\n"
|
225
|
+
f"• **Console Test**: Test this permission via AWS Console first\n\n"
|
226
|
+
f"[bold]Common Solutions:[/bold]\n"
|
227
|
+
f"• Attach AWS managed policy: `ReadOnlyAccess`\n"
|
228
|
+
f"• Create custom policy with this specific permission\n"
|
229
|
+
f"• Contact your AWS administrator for permission escalation",
|
230
|
+
title="📋 Permission Resolution Guidance",
|
231
|
+
border_style="yellow",
|
232
|
+
)
|
233
|
+
console.print(guidance_panel)
|
234
|
+
|
235
|
+
@classmethod
|
236
|
+
def _display_troubleshooting_steps(cls, error_type: str):
|
237
|
+
"""Display troubleshooting steps based on error type."""
|
238
|
+
|
239
|
+
if error_type == "SSO Token Expired":
|
240
|
+
troubleshooting = (
|
241
|
+
"[bold]🔄 SSO Token Refresh Steps:[/bold]\n"
|
242
|
+
"1. Run: `aws sso login --profile your-profile-name`\n"
|
243
|
+
"2. Follow browser authentication flow\n"
|
244
|
+
"3. Retry the runbooks operation\n"
|
245
|
+
"4. Consider extending SSO session duration in AWS SSO settings"
|
246
|
+
)
|
247
|
+
else:
|
248
|
+
troubleshooting = (
|
249
|
+
"[bold]🛠️ Permission Resolution Steps:[/bold]\n"
|
250
|
+
"1. **Verify Profile**: Check `aws sts get-caller-identity --profile your-profile`\n"
|
251
|
+
"2. **Review IAM Policy**: Ensure your role has the required permission\n"
|
252
|
+
"3. **Check SCP**: Verify Service Control Policies allow this action\n"
|
253
|
+
"4. **Test Console Access**: Try the same operation in AWS Console\n"
|
254
|
+
"5. **Contact Administrator**: Request IAM policy update with required permission"
|
255
|
+
)
|
256
|
+
|
257
|
+
troubleshoot_panel = Panel(troubleshooting, title="🔧 Next Steps", border_style="blue")
|
258
|
+
console.print(troubleshoot_panel)
|
259
|
+
|
260
|
+
@classmethod
|
261
|
+
def display_runbooks_permission_requirements(cls):
|
262
|
+
"""Display complete runbooks AWS API permission requirements."""
|
263
|
+
|
264
|
+
matrix_table = Table(title="🔧 Runbooks AWS API Permission Requirements")
|
265
|
+
matrix_table.add_column("AWS API Permission", style="bold cyan")
|
266
|
+
matrix_table.add_column("Purpose", style="white")
|
267
|
+
matrix_table.add_column("Affected Commands", style="green")
|
268
|
+
matrix_table.add_column("AWS Managed Policy", style="yellow")
|
269
|
+
|
270
|
+
for permission, config in cls.RUNBOOKS_API_REQUIREMENTS.items():
|
271
|
+
policies = ", ".join(config["aws_managed_policies"][:2]) + (
|
272
|
+
"..." if len(config["aws_managed_policies"]) > 2 else ""
|
273
|
+
)
|
274
|
+
matrix_table.add_row(permission, config["purpose"], config["command_impact"], policies)
|
275
|
+
|
276
|
+
console.print(matrix_table)
|
277
|
+
|
278
|
+
# Enterprise guidance
|
279
|
+
enterprise_panel = Panel(
|
280
|
+
"[bold]🎯 IAM Configuration Best Practices:[/bold]\n\n"
|
281
|
+
"• **Any AWS Profile**: Requires these specific API permissions to run runbooks\n"
|
282
|
+
"• **SSO Integration**: Configure SSO roles with required permissions\n"
|
283
|
+
"• **SCP Compliance**: Ensure Service Control Policies don't deny these permissions\n\n"
|
284
|
+
"[bold]🔒 Security Notes:[/bold]\n"
|
285
|
+
"• All permissions are ReadOnly - no destructive operations possible\n"
|
286
|
+
"• Permissions follow least-privilege principle\n"
|
287
|
+
"• IAM policies can be customized based on specific runbooks usage",
|
288
|
+
title="🔧 Runbooks Permission Configuration",
|
289
|
+
border_style="cyan",
|
290
|
+
)
|
291
|
+
console.print(enterprise_panel)
|
292
|
+
|
293
|
+
|
294
|
+
# Enhanced Cost Explorer Error Handling for Single Account Scenarios
|
295
|
+
def handle_cost_explorer_error(error: Exception, profile_name: Optional[str] = None):
|
296
|
+
"""
|
297
|
+
Handle Cost Explorer specific errors with context-aware guidance for single accounts.
|
298
|
+
|
299
|
+
Provides enhanced error messaging that explains why single accounts typically
|
300
|
+
don't have Cost Explorer access and suggests practical solutions.
|
301
|
+
"""
|
302
|
+
error_str = str(error)
|
303
|
+
|
304
|
+
# Check if this is a single account Cost Explorer access issue
|
305
|
+
if ("AccessDeniedException" in error_str or "explicitly denied" in error_str) and "ce:GetCostAndUsage" in error_str:
|
306
|
+
_display_single_account_cost_explorer_guidance(error, profile_name)
|
307
|
+
else:
|
308
|
+
# Fall back to general IAM guidance
|
309
|
+
EnterpriseIAMGuidance.display_enhanced_error(error, "runbooks finops operation (Cost Explorer API)")
|
310
|
+
|
311
|
+
|
312
|
+
def _display_single_account_cost_explorer_guidance(error: Exception, profile_name: Optional[str] = None):
|
313
|
+
"""Display context-aware guidance for single account Cost Explorer limitations."""
|
314
|
+
|
315
|
+
# Main explanation panel
|
316
|
+
explanation_panel = Panel(
|
317
|
+
"[yellow]ℹ️ Cost Explorer Access Limitation[/yellow]\n\n"
|
318
|
+
"[bold]What's happening:[/bold]\n"
|
319
|
+
"• Individual AWS accounts often don't have Cost Explorer API permissions\n"
|
320
|
+
"• Cost Explorer is typically accessible through the billing/payer account\n"
|
321
|
+
"• This is expected behavior for member accounts in AWS Organizations\n\n"
|
322
|
+
"[bold]Why this occurs:[/bold]\n"
|
323
|
+
"• Cost Explorer requires specific billing permissions\n"
|
324
|
+
"• Member accounts may not have consolidated billing access\n"
|
325
|
+
"• Service Control Policies (SCPs) may restrict Cost Explorer access",
|
326
|
+
title="🔍 Single Account Cost Explorer Context",
|
327
|
+
border_style="yellow",
|
328
|
+
)
|
329
|
+
console.print(explanation_panel)
|
330
|
+
|
331
|
+
# Solution panel with actionable guidance
|
332
|
+
if profile_name:
|
333
|
+
profile_text = f"your current profile `{profile_name}`"
|
334
|
+
solution_commands = f"""[bold]Option 1: Use Billing Profile (Recommended)[/bold]
|
335
|
+
• Set environment variable: `export BILLING_PROFILE="your-billing-profile-name"`
|
336
|
+
• Run: `runbooks finops --profile your-billing-profile-name`
|
337
|
+
|
338
|
+
[bold]Option 2: Use Your Current Profile for Resource Analysis[/bold]
|
339
|
+
• Current profile: `{profile_name}`
|
340
|
+
• Resource discovery will work, but cost data will be limited
|
341
|
+
• Consider using: `runbooks inventory collect --profile {profile_name}`"""
|
342
|
+
else:
|
343
|
+
profile_text = "your current profile"
|
344
|
+
solution_commands = """[bold]Option 1: Use Billing Profile (Recommended)[/bold]
|
345
|
+
• Set environment variable: `export BILLING_PROFILE="your-billing-profile-name"`
|
346
|
+
• Run: `runbooks finops --profile your-billing-profile-name`
|
347
|
+
|
348
|
+
[bold]Option 2: Request Billing Account Access[/bold]
|
349
|
+
• Contact your AWS administrator
|
350
|
+
• Request access to the organization's billing account
|
351
|
+
• Use that profile for Cost Explorer operations"""
|
352
|
+
|
353
|
+
solution_panel = Panel(
|
354
|
+
f"[green]✅ Recommended Solutions:[/green]\n\n"
|
355
|
+
f"{solution_commands}\n\n"
|
356
|
+
f"[bold]🎯 Quick Test Commands:[/bold]\n"
|
357
|
+
f"• Test billing access: `aws ce get-cost-and-usage --time-period Start=2024-01-01,End=2024-01-02 --granularity MONTHLY --metrics UnblendedCost --profile your-billing-profile`\n"
|
358
|
+
f"• List available profiles: `aws configure list-profiles`\n"
|
359
|
+
f"• Check current identity: `aws sts get-caller-identity --profile {profile_name or 'your-profile'}`\n\n"
|
360
|
+
f"[bold]💡 Alternative Approach:[/bold]\n"
|
361
|
+
f"• Use resource-based analysis: `runbooks inventory collect`\n"
|
362
|
+
f"• Focus on resource optimization rather than cost analysis\n"
|
363
|
+
f"• Generate resource reports for cost discussions with billing team",
|
364
|
+
title="🔧 Cost Explorer Access Solutions",
|
365
|
+
border_style="green",
|
366
|
+
)
|
367
|
+
console.print(solution_panel)
|
368
|
+
|
369
|
+
# Enterprise context panel
|
370
|
+
enterprise_context = Panel(
|
371
|
+
"[bold]🏢 Enterprise Context:[/bold]\n\n"
|
372
|
+
"• **Single Account Limitations**: Member accounts typically lack billing permissions\n"
|
373
|
+
"• **Billing Account Access**: Contact your cloud team for billing profile access\n"
|
374
|
+
"• **Alternative Analysis**: Resource inventory can provide optimization insights\n"
|
375
|
+
"• **Cost Management**: Consider AWS Cost and Usage Reports (CUR) for detailed analysis\n\n"
|
376
|
+
"[bold]📊 What You Can Still Do:[/bold]\n"
|
377
|
+
"• Resource discovery and optimization recommendations\n"
|
378
|
+
"• Security compliance scanning and remediation\n"
|
379
|
+
"• Infrastructure inventory and tagging analysis\n"
|
380
|
+
"• Performance monitoring and optimization guidance",
|
381
|
+
title="🎯 Enterprise Guidance",
|
382
|
+
border_style="cyan",
|
383
|
+
)
|
384
|
+
console.print(enterprise_context)
|
385
|
+
|
386
|
+
|
387
|
+
# Original convenience functions maintained for compatibility
|
388
|
+
def handle_cost_explorer_error_simple(error: Exception):
|
389
|
+
"""Handle Cost Explorer specific errors with guidance (legacy function)."""
|
390
|
+
EnterpriseIAMGuidance.display_enhanced_error(error, "runbooks finops operation (Cost Explorer API)")
|
391
|
+
|
392
|
+
|
393
|
+
def handle_organizations_error(error: Exception):
|
394
|
+
"""Handle AWS Organizations specific errors with guidance."""
|
395
|
+
EnterpriseIAMGuidance.display_enhanced_error(error, "runbooks inventory operation (Organizations API)")
|
396
|
+
|
397
|
+
|
398
|
+
def handle_resource_discovery_error(error: Exception):
|
399
|
+
"""Handle resource discovery specific errors with guidance."""
|
400
|
+
EnterpriseIAMGuidance.display_enhanced_error(error, "runbooks inventory operation (Resource Discovery APIs)")
|