runbooks 1.1.3__py3-none-any.whl → 1.1.5__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 +31 -2
- runbooks/__init___optimized.py +18 -4
- runbooks/_platform/__init__.py +1 -5
- runbooks/_platform/core/runbooks_wrapper.py +141 -138
- runbooks/aws2/accuracy_validator.py +812 -0
- runbooks/base.py +7 -0
- runbooks/cfat/WEIGHT_CONFIG_README.md +1 -1
- runbooks/cfat/assessment/compliance.py +8 -8
- runbooks/cfat/assessment/runner.py +1 -0
- runbooks/cfat/cloud_foundations_assessment.py +227 -239
- runbooks/cfat/models.py +6 -2
- runbooks/cfat/tests/__init__.py +6 -1
- runbooks/cli/__init__.py +13 -0
- runbooks/cli/commands/cfat.py +274 -0
- runbooks/cli/commands/finops.py +1164 -0
- runbooks/cli/commands/inventory.py +379 -0
- runbooks/cli/commands/operate.py +239 -0
- runbooks/cli/commands/security.py +248 -0
- runbooks/cli/commands/validation.py +825 -0
- runbooks/cli/commands/vpc.py +310 -0
- runbooks/cli/registry.py +107 -0
- runbooks/cloudops/__init__.py +23 -30
- runbooks/cloudops/base.py +96 -107
- runbooks/cloudops/cost_optimizer.py +549 -547
- runbooks/cloudops/infrastructure_optimizer.py +5 -4
- runbooks/cloudops/interfaces.py +226 -227
- runbooks/cloudops/lifecycle_manager.py +5 -4
- runbooks/cloudops/mcp_cost_validation.py +252 -235
- runbooks/cloudops/models.py +78 -53
- runbooks/cloudops/monitoring_automation.py +5 -4
- runbooks/cloudops/notebook_framework.py +179 -215
- runbooks/cloudops/security_enforcer.py +125 -159
- runbooks/common/accuracy_validator.py +11 -0
- runbooks/common/aws_pricing.py +349 -326
- runbooks/common/aws_pricing_api.py +211 -212
- runbooks/common/aws_profile_manager.py +341 -0
- runbooks/common/aws_utils.py +75 -80
- runbooks/common/business_logic.py +127 -105
- runbooks/common/cli_decorators.py +36 -60
- runbooks/common/comprehensive_cost_explorer_integration.py +456 -464
- runbooks/common/cross_account_manager.py +198 -205
- runbooks/common/date_utils.py +27 -39
- runbooks/common/decorators.py +235 -0
- runbooks/common/dry_run_examples.py +173 -208
- runbooks/common/dry_run_framework.py +157 -155
- runbooks/common/enhanced_exception_handler.py +15 -4
- runbooks/common/enhanced_logging_example.py +50 -64
- runbooks/common/enhanced_logging_integration_example.py +65 -37
- runbooks/common/env_utils.py +16 -16
- runbooks/common/error_handling.py +40 -38
- runbooks/common/lazy_loader.py +41 -23
- runbooks/common/logging_integration_helper.py +79 -86
- runbooks/common/mcp_cost_explorer_integration.py +478 -495
- runbooks/common/mcp_integration.py +63 -74
- runbooks/common/memory_optimization.py +140 -118
- runbooks/common/module_cli_base.py +37 -58
- runbooks/common/organizations_client.py +176 -194
- runbooks/common/patterns.py +204 -0
- runbooks/common/performance_monitoring.py +67 -71
- runbooks/common/performance_optimization_engine.py +283 -274
- runbooks/common/profile_utils.py +248 -39
- runbooks/common/rich_utils.py +643 -92
- runbooks/common/sre_performance_suite.py +177 -186
- runbooks/enterprise/__init__.py +1 -1
- runbooks/enterprise/logging.py +144 -106
- runbooks/enterprise/security.py +187 -204
- runbooks/enterprise/validation.py +43 -56
- runbooks/finops/__init__.py +29 -33
- runbooks/finops/account_resolver.py +1 -1
- runbooks/finops/advanced_optimization_engine.py +980 -0
- runbooks/finops/automation_core.py +268 -231
- runbooks/finops/business_case_config.py +184 -179
- runbooks/finops/cli.py +660 -139
- runbooks/finops/commvault_ec2_analysis.py +157 -164
- runbooks/finops/compute_cost_optimizer.py +336 -320
- runbooks/finops/config.py +20 -20
- runbooks/finops/cost_optimizer.py +488 -622
- runbooks/finops/cost_processor.py +332 -214
- runbooks/finops/dashboard_runner.py +1006 -172
- runbooks/finops/ebs_cost_optimizer.py +991 -657
- runbooks/finops/elastic_ip_optimizer.py +317 -257
- runbooks/finops/enhanced_mcp_integration.py +340 -0
- runbooks/finops/enhanced_progress.py +40 -37
- runbooks/finops/enhanced_trend_visualization.py +3 -2
- runbooks/finops/enterprise_wrappers.py +230 -292
- runbooks/finops/executive_export.py +203 -160
- runbooks/finops/helpers.py +130 -288
- runbooks/finops/iam_guidance.py +1 -1
- runbooks/finops/infrastructure/__init__.py +80 -0
- runbooks/finops/infrastructure/commands.py +506 -0
- runbooks/finops/infrastructure/load_balancer_optimizer.py +866 -0
- runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +832 -0
- runbooks/finops/markdown_exporter.py +338 -175
- runbooks/finops/mcp_validator.py +1952 -0
- runbooks/finops/nat_gateway_optimizer.py +1513 -482
- runbooks/finops/network_cost_optimizer.py +657 -587
- runbooks/finops/notebook_utils.py +226 -188
- runbooks/finops/optimization_engine.py +1136 -0
- runbooks/finops/optimizer.py +25 -29
- runbooks/finops/rds_snapshot_optimizer.py +367 -411
- runbooks/finops/reservation_optimizer.py +427 -363
- runbooks/finops/scenario_cli_integration.py +77 -78
- runbooks/finops/scenarios.py +1278 -439
- runbooks/finops/schemas.py +218 -182
- runbooks/finops/snapshot_manager.py +2289 -0
- runbooks/finops/tests/test_finops_dashboard.py +3 -3
- runbooks/finops/tests/test_reference_images_validation.py +2 -2
- runbooks/finops/tests/test_single_account_features.py +17 -17
- runbooks/finops/tests/validate_test_suite.py +1 -1
- runbooks/finops/types.py +3 -3
- runbooks/finops/validation_framework.py +263 -269
- runbooks/finops/vpc_cleanup_exporter.py +191 -146
- runbooks/finops/vpc_cleanup_optimizer.py +593 -575
- runbooks/finops/workspaces_analyzer.py +171 -182
- runbooks/hitl/enhanced_workflow_engine.py +1 -1
- runbooks/integration/__init__.py +89 -0
- runbooks/integration/mcp_integration.py +1920 -0
- runbooks/inventory/CLAUDE.md +816 -0
- runbooks/inventory/README.md +3 -3
- runbooks/inventory/Tests/common_test_data.py +30 -30
- runbooks/inventory/__init__.py +2 -2
- runbooks/inventory/cloud_foundations_integration.py +144 -149
- runbooks/inventory/collectors/aws_comprehensive.py +28 -11
- runbooks/inventory/collectors/aws_networking.py +111 -101
- runbooks/inventory/collectors/base.py +4 -0
- runbooks/inventory/core/collector.py +495 -313
- runbooks/inventory/discovery.md +2 -2
- runbooks/inventory/drift_detection_cli.py +69 -96
- runbooks/inventory/find_ec2_security_groups.py +1 -1
- runbooks/inventory/inventory_mcp_cli.py +48 -46
- runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
- runbooks/inventory/mcp_inventory_validator.py +549 -465
- runbooks/inventory/mcp_vpc_validator.py +359 -442
- runbooks/inventory/organizations_discovery.py +56 -52
- runbooks/inventory/rich_inventory_display.py +33 -32
- runbooks/inventory/unified_validation_engine.py +278 -251
- runbooks/inventory/vpc_analyzer.py +733 -696
- runbooks/inventory/vpc_architecture_validator.py +293 -348
- runbooks/inventory/vpc_dependency_analyzer.py +382 -378
- runbooks/inventory/vpc_flow_analyzer.py +3 -3
- runbooks/main.py +152 -9147
- runbooks/main_final.py +91 -60
- runbooks/main_minimal.py +22 -10
- runbooks/main_optimized.py +131 -100
- runbooks/main_ultra_minimal.py +7 -2
- runbooks/mcp/__init__.py +36 -0
- runbooks/mcp/integration.py +679 -0
- runbooks/metrics/dora_metrics_engine.py +2 -2
- runbooks/monitoring/performance_monitor.py +9 -4
- runbooks/operate/dynamodb_operations.py +3 -1
- runbooks/operate/ec2_operations.py +145 -137
- runbooks/operate/iam_operations.py +146 -152
- runbooks/operate/mcp_integration.py +1 -1
- runbooks/operate/networking_cost_heatmap.py +33 -10
- runbooks/operate/privatelink_operations.py +1 -1
- runbooks/operate/rds_operations.py +223 -254
- runbooks/operate/s3_operations.py +107 -118
- runbooks/operate/vpc_endpoints.py +1 -1
- runbooks/operate/vpc_operations.py +648 -618
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/commons.py +10 -7
- runbooks/remediation/commvault_ec2_analysis.py +71 -67
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
- runbooks/remediation/multi_account.py +24 -21
- runbooks/remediation/rds_snapshot_list.py +91 -65
- runbooks/remediation/remediation_cli.py +92 -146
- runbooks/remediation/universal_account_discovery.py +83 -79
- runbooks/remediation/workspaces_list.py +49 -44
- runbooks/security/__init__.py +19 -0
- runbooks/security/assessment_runner.py +1150 -0
- runbooks/security/baseline_checker.py +812 -0
- runbooks/security/cloudops_automation_security_validator.py +509 -535
- runbooks/security/compliance_automation_engine.py +17 -17
- runbooks/security/config/__init__.py +2 -2
- runbooks/security/config/compliance_config.py +50 -50
- runbooks/security/config_template_generator.py +63 -76
- runbooks/security/enterprise_security_framework.py +1 -1
- runbooks/security/executive_security_dashboard.py +519 -508
- runbooks/security/integration_test_enterprise_security.py +5 -3
- runbooks/security/multi_account_security_controls.py +959 -1210
- runbooks/security/real_time_security_monitor.py +422 -444
- runbooks/security/run_script.py +1 -1
- runbooks/security/security_baseline_tester.py +1 -1
- runbooks/security/security_cli.py +143 -112
- runbooks/security/test_2way_validation.py +439 -0
- runbooks/security/two_way_validation_framework.py +852 -0
- runbooks/sre/mcp_reliability_engine.py +6 -6
- runbooks/sre/production_monitoring_framework.py +167 -177
- runbooks/tdd/__init__.py +15 -0
- runbooks/tdd/cli.py +1071 -0
- runbooks/utils/__init__.py +14 -17
- runbooks/utils/logger.py +7 -2
- runbooks/utils/version_validator.py +51 -48
- runbooks/validation/__init__.py +6 -6
- runbooks/validation/cli.py +9 -3
- runbooks/validation/comprehensive_2way_validator.py +754 -708
- runbooks/validation/mcp_validator.py +906 -228
- runbooks/validation/terraform_citations_validator.py +104 -115
- runbooks/validation/terraform_drift_detector.py +447 -451
- runbooks/vpc/README.md +617 -0
- runbooks/vpc/__init__.py +8 -1
- runbooks/vpc/analyzer.py +577 -0
- runbooks/vpc/cleanup_wrapper.py +476 -413
- runbooks/vpc/cli_cloudtrail_commands.py +339 -0
- runbooks/vpc/cli_mcp_validation_commands.py +480 -0
- runbooks/vpc/cloudtrail_audit_integration.py +717 -0
- runbooks/vpc/config.py +92 -97
- runbooks/vpc/cost_engine.py +411 -148
- runbooks/vpc/cost_explorer_integration.py +553 -0
- runbooks/vpc/cross_account_session.py +101 -106
- runbooks/vpc/enhanced_mcp_validation.py +917 -0
- runbooks/vpc/eni_gate_validator.py +961 -0
- runbooks/vpc/heatmap_engine.py +190 -162
- runbooks/vpc/mcp_no_eni_validator.py +681 -640
- runbooks/vpc/nat_gateway_optimizer.py +358 -0
- runbooks/vpc/networking_wrapper.py +15 -8
- runbooks/vpc/pdca_remediation_planner.py +528 -0
- runbooks/vpc/performance_optimized_analyzer.py +219 -231
- runbooks/vpc/runbooks_adapter.py +1167 -241
- runbooks/vpc/tdd_red_phase_stubs.py +601 -0
- runbooks/vpc/test_data_loader.py +358 -0
- runbooks/vpc/tests/conftest.py +314 -4
- runbooks/vpc/tests/test_cleanup_framework.py +1022 -0
- runbooks/vpc/tests/test_cost_engine.py +0 -2
- runbooks/vpc/topology_generator.py +326 -0
- runbooks/vpc/unified_scenarios.py +1302 -1129
- runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
- runbooks-1.1.5.dist-info/METADATA +328 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/RECORD +233 -200
- runbooks/finops/README.md +0 -414
- runbooks/finops/accuracy_cross_validator.py +0 -647
- runbooks/finops/business_cases.py +0 -950
- runbooks/finops/dashboard_router.py +0 -922
- runbooks/finops/ebs_optimizer.py +0 -956
- runbooks/finops/embedded_mcp_validator.py +0 -1629
- runbooks/finops/enhanced_dashboard_runner.py +0 -527
- runbooks/finops/finops_dashboard.py +0 -584
- runbooks/finops/finops_scenarios.py +0 -1218
- runbooks/finops/legacy_migration.py +0 -730
- runbooks/finops/multi_dashboard.py +0 -1519
- runbooks/finops/single_dashboard.py +0 -1113
- runbooks/finops/unlimited_scenarios.py +0 -393
- runbooks-1.1.3.dist-info/METADATA +0 -799
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/WHEEL +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/top_level.txt +0 -0
@@ -24,8 +24,9 @@ logger = logging.getLogger(__name__)
|
|
24
24
|
@dataclass
|
25
25
|
class AccountSession:
|
26
26
|
"""Represents a cross-account session with metadata"""
|
27
|
+
|
27
28
|
account_id: str
|
28
|
-
account_name: Optional[str]
|
29
|
+
account_name: Optional[str]
|
29
30
|
session: boto3.Session
|
30
31
|
status: str
|
31
32
|
error_message: Optional[str] = None
|
@@ -34,68 +35,67 @@ class AccountSession:
|
|
34
35
|
def create_multi_profile_sessions(profiles: List[str]) -> List[AccountSession]:
|
35
36
|
"""
|
36
37
|
Create sessions using direct profile access for organizations without cross-account roles.
|
37
|
-
|
38
|
+
|
38
39
|
This is an alternative approach when OrganizationAccountAccessRole is not available.
|
39
40
|
Uses environment variables like CENTRALISED_OPS_PROFILE, BILLING_PROFILE, etc.
|
40
|
-
|
41
|
+
|
41
42
|
Args:
|
42
43
|
profiles: List of AWS profile names to use
|
43
|
-
|
44
|
+
|
44
45
|
Returns:
|
45
46
|
List of AccountSession objects with successful and failed sessions
|
46
47
|
"""
|
47
48
|
import os
|
48
|
-
|
49
|
+
|
49
50
|
print_info(f"🌐 Creating sessions for {len(profiles)} profiles")
|
50
51
|
account_sessions = []
|
51
|
-
|
52
|
+
|
52
53
|
for profile_name in profiles:
|
53
54
|
try:
|
54
55
|
# Validate profile exists and is accessible
|
55
56
|
session = boto3.Session(profile_name=profile_name)
|
56
|
-
sts_client = session.client(
|
57
|
+
sts_client = session.client("sts")
|
57
58
|
identity = sts_client.get_caller_identity()
|
58
|
-
|
59
|
-
account_id = identity[
|
60
|
-
|
59
|
+
|
60
|
+
account_id = identity["Account"]
|
61
|
+
|
61
62
|
# Try to get account name from Organizations if possible
|
62
63
|
account_name = profile_name # Default to profile name
|
63
64
|
try:
|
64
|
-
orgs_client = session.client(
|
65
|
+
orgs_client = session.client("organizations")
|
65
66
|
account_info = orgs_client.describe_account(AccountId=account_id)
|
66
|
-
account_name = account_info[
|
67
|
+
account_name = account_info["Account"]["Name"]
|
67
68
|
except:
|
68
69
|
pass # Use profile name as fallback
|
69
|
-
|
70
|
-
account_sessions.append(
|
71
|
-
account_id=account_id,
|
72
|
-
|
73
|
-
|
74
|
-
status="success"
|
75
|
-
))
|
76
|
-
|
70
|
+
|
71
|
+
account_sessions.append(
|
72
|
+
AccountSession(account_id=account_id, account_name=account_name, session=session, status="success")
|
73
|
+
)
|
74
|
+
|
77
75
|
print_success(f"✅ Session created for {account_id} using profile {profile_name}")
|
78
|
-
|
76
|
+
|
79
77
|
except Exception as e:
|
80
78
|
print_warning(f"⚠️ Failed to create session for profile {profile_name}: {e}")
|
81
|
-
account_sessions.append(
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
79
|
+
account_sessions.append(
|
80
|
+
AccountSession(
|
81
|
+
account_id=profile_name, # Use profile name as ID when we can't get real ID
|
82
|
+
account_name=profile_name,
|
83
|
+
session=None,
|
84
|
+
status="failed",
|
85
|
+
error_message=str(e),
|
86
|
+
)
|
87
|
+
)
|
88
|
+
|
89
89
|
return account_sessions
|
90
90
|
|
91
91
|
|
92
92
|
class CrossAccountSessionManager:
|
93
93
|
"""
|
94
94
|
Enterprise cross-account session manager using STS AssumeRole pattern.
|
95
|
-
|
95
|
+
|
96
96
|
This replaces the broken profile@accountId format with proper STS AssumeRole
|
97
97
|
for multi-account VPC discovery across Landing Zone accounts.
|
98
|
-
|
98
|
+
|
99
99
|
Key Features:
|
100
100
|
- Uses CENTRALISED_OPS_PROFILE as base session for assuming roles
|
101
101
|
- Standard OrganizationAccountAccessRole assumption
|
@@ -103,91 +103,94 @@ class CrossAccountSessionManager:
|
|
103
103
|
- Comprehensive error handling and graceful degradation
|
104
104
|
- Compatible with existing VPC module architecture
|
105
105
|
"""
|
106
|
-
|
106
|
+
|
107
107
|
def __init__(self, base_profile: str, role_name: str = "OrganizationAccountAccessRole"):
|
108
108
|
"""
|
109
109
|
Initialize cross-account session manager.
|
110
|
-
|
110
|
+
|
111
111
|
Args:
|
112
112
|
base_profile: Base profile (e.g., CENTRALISED_OPS_PROFILE) for assuming roles
|
113
113
|
role_name: IAM role name to assume in target accounts
|
114
114
|
"""
|
115
115
|
self.base_profile = base_profile
|
116
116
|
self.role_name = role_name
|
117
|
-
|
117
|
+
|
118
118
|
# Use management session for cross-account role assumptions
|
119
119
|
# Management account has the trust relationships for OrganizationAccountAccessRole
|
120
|
-
self.session = create_management_session(
|
121
|
-
|
120
|
+
self.session = create_management_session(profile_name=base_profile)
|
121
|
+
|
122
122
|
print_info(f"🔐 Cross-account session manager initialized with {base_profile}")
|
123
|
-
|
123
|
+
|
124
124
|
def create_cross_account_sessions(
|
125
|
-
self,
|
126
|
-
accounts: List[Dict[str, str]],
|
127
|
-
max_workers: int = 10
|
125
|
+
self, accounts: List[Dict[str, str]], max_workers: int = 10
|
128
126
|
) -> List[AccountSession]:
|
129
127
|
"""
|
130
128
|
Create cross-account sessions using STS AssumeRole pattern.
|
131
|
-
|
129
|
+
|
132
130
|
Args:
|
133
131
|
accounts: List of account dictionaries from Organizations API
|
134
132
|
max_workers: Maximum parallel workers for session creation
|
135
|
-
|
133
|
+
|
136
134
|
Returns:
|
137
135
|
List of AccountSession objects with successful and failed sessions
|
138
136
|
"""
|
139
137
|
print_info(f"🌐 Creating cross-account sessions for {len(accounts)} accounts")
|
140
|
-
|
138
|
+
|
141
139
|
account_sessions = []
|
142
|
-
|
140
|
+
|
143
141
|
# Filter active accounts only
|
144
142
|
active_accounts = [acc for acc in accounts if acc.get("status") == "ACTIVE"]
|
145
143
|
print_info(f"📋 Processing {len(active_accounts)} active accounts")
|
146
|
-
|
144
|
+
|
147
145
|
# Create sessions in parallel for performance
|
148
146
|
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
149
147
|
future_to_account = {
|
150
|
-
executor.submit(self._create_account_session, account): account
|
151
|
-
for account in active_accounts
|
148
|
+
executor.submit(self._create_account_session, account): account for account in active_accounts
|
152
149
|
}
|
153
|
-
|
150
|
+
|
154
151
|
for future in as_completed(future_to_account):
|
155
152
|
account = future_to_account[future]
|
156
153
|
try:
|
157
154
|
account_session = future.result()
|
158
155
|
account_sessions.append(account_session)
|
159
|
-
|
156
|
+
|
160
157
|
if account_session.status == "success":
|
161
158
|
print_success(f"✅ Session created for {account_session.account_id}")
|
162
159
|
else:
|
163
|
-
print_warning(
|
164
|
-
|
160
|
+
print_warning(
|
161
|
+
f"⚠️ Session failed for {account_session.account_id}: {account_session.error_message}"
|
162
|
+
)
|
163
|
+
|
165
164
|
except Exception as e:
|
166
165
|
print_error(f"❌ Unexpected error creating session for {account['id']}: {e}")
|
167
|
-
account_sessions.append(
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
166
|
+
account_sessions.append(
|
167
|
+
AccountSession(
|
168
|
+
account_id=account["id"],
|
169
|
+
account_name=account.get("name"),
|
170
|
+
session=None,
|
171
|
+
status="error",
|
172
|
+
error_message=str(e),
|
173
|
+
)
|
174
|
+
)
|
175
|
+
|
175
176
|
successful_sessions = [s for s in account_sessions if s.status == "success"]
|
176
177
|
failed_sessions = [s for s in account_sessions if s.status != "success"]
|
177
|
-
|
178
|
-
print_info(
|
179
|
-
|
178
|
+
|
179
|
+
print_info(
|
180
|
+
f"🎯 Session creation complete: {len(successful_sessions)} successful, {len(failed_sessions)} failed"
|
181
|
+
)
|
182
|
+
|
180
183
|
return account_sessions
|
181
|
-
|
184
|
+
|
182
185
|
def _create_account_session(self, account: Dict[str, str]) -> AccountSession:
|
183
186
|
"""
|
184
187
|
Create a session for a single account using STS AssumeRole.
|
185
|
-
|
188
|
+
|
186
189
|
This is the core implementation of the enterprise pattern.
|
187
190
|
"""
|
188
191
|
account_id = account["id"]
|
189
192
|
account_name = account.get("name", f"Account-{account_id}")
|
190
|
-
|
193
|
+
|
191
194
|
# Try multiple role patterns for different organization setups - universal compatibility
|
192
195
|
role_patterns = [
|
193
196
|
self.role_name, # Default: OrganizationAccountAccessRole
|
@@ -199,87 +202,80 @@ class CrossAccountSessionManager:
|
|
199
202
|
"CrossAccountRole", # Generic cross-account role
|
200
203
|
"AssumeRole", # Generic assume role
|
201
204
|
]
|
202
|
-
|
205
|
+
|
203
206
|
for role_name in role_patterns:
|
204
207
|
try:
|
205
208
|
# Step 1: Assume role in target account using STS
|
206
|
-
sts_client = self.session.client(
|
209
|
+
sts_client = self.session.client("sts")
|
207
210
|
assumed_role = sts_client.assume_role(
|
208
211
|
RoleArn=f"arn:aws:iam::{account_id}:role/{role_name}",
|
209
|
-
RoleSessionName=f"VPCDiscovery-{account_id[:12]}"
|
212
|
+
RoleSessionName=f"VPCDiscovery-{account_id[:12]}",
|
210
213
|
)
|
211
|
-
|
214
|
+
|
212
215
|
# If successful, continue with this role
|
213
|
-
|
216
|
+
|
214
217
|
# Step 2: Create session with assumed role credentials
|
215
218
|
assumed_session = boto3.Session(
|
216
|
-
aws_access_key_id=assumed_role[
|
217
|
-
aws_secret_access_key=assumed_role[
|
218
|
-
aws_session_token=assumed_role[
|
219
|
+
aws_access_key_id=assumed_role["Credentials"]["AccessKeyId"],
|
220
|
+
aws_secret_access_key=assumed_role["Credentials"]["SecretAccessKey"],
|
221
|
+
aws_session_token=assumed_role["Credentials"]["SessionToken"],
|
219
222
|
)
|
220
|
-
|
223
|
+
|
221
224
|
# Step 3: Validate session with basic STS call
|
222
|
-
assumed_sts = assumed_session.client(
|
225
|
+
assumed_sts = assumed_session.client("sts")
|
223
226
|
identity = assumed_sts.get_caller_identity()
|
224
|
-
|
225
|
-
logger.debug(
|
226
|
-
|
227
|
+
|
228
|
+
logger.debug(
|
229
|
+
f"Successfully assumed role {role_name} in account {account_id}, identity: {identity['Arn']}"
|
230
|
+
)
|
231
|
+
|
227
232
|
return AccountSession(
|
228
|
-
account_id=account_id,
|
229
|
-
account_name=account_name,
|
230
|
-
session=assumed_session,
|
231
|
-
status="success"
|
233
|
+
account_id=account_id, account_name=account_name, session=assumed_session, status="success"
|
232
234
|
)
|
233
|
-
|
235
|
+
|
234
236
|
except ClientError as e:
|
235
237
|
# Continue to next role pattern
|
236
238
|
continue
|
237
|
-
|
239
|
+
|
238
240
|
# If no role patterns worked, return failure
|
239
241
|
error_msg = f"Unable to assume any role pattern in {account_id} - tried: {', '.join(role_patterns)}"
|
240
242
|
logger.warning(f"Failed to create session for {account_id}: {error_msg}")
|
241
|
-
|
243
|
+
|
242
244
|
return AccountSession(
|
243
|
-
account_id=account_id,
|
244
|
-
account_name=account_name,
|
245
|
-
session=None,
|
246
|
-
status="failed",
|
247
|
-
error_message=error_msg
|
245
|
+
account_id=account_id, account_name=account_name, session=None, status="failed", error_message=error_msg
|
248
246
|
)
|
249
|
-
|
247
|
+
|
250
248
|
def get_successful_sessions(self, account_sessions: List[AccountSession]) -> List[AccountSession]:
|
251
249
|
"""Get only successful account sessions for VPC discovery."""
|
252
250
|
successful = [s for s in account_sessions if s.status == "success"]
|
253
251
|
print_info(f"🎯 {len(successful)} accounts ready for VPC discovery")
|
254
252
|
return successful
|
255
|
-
|
253
|
+
|
256
254
|
def get_session_summary(self, account_sessions: List[AccountSession]) -> Dict[str, int]:
|
257
255
|
"""Get summary statistics for session creation."""
|
258
256
|
summary = {
|
259
257
|
"total": len(account_sessions),
|
260
258
|
"successful": len([s for s in account_sessions if s.status == "success"]),
|
261
259
|
"failed": len([s for s in account_sessions if s.status == "failed"]),
|
262
|
-
"errors": len([s for s in account_sessions if s.status == "error"])
|
260
|
+
"errors": len([s for s in account_sessions if s.status == "error"]),
|
263
261
|
}
|
264
262
|
return summary
|
265
263
|
|
266
264
|
|
267
265
|
def create_cross_account_vpc_sessions(
|
268
|
-
accounts: List[Dict[str, str]],
|
269
|
-
base_profile: str,
|
270
|
-
role_name: str = "OrganizationAccountAccessRole"
|
266
|
+
accounts: List[Dict[str, str]], base_profile: str, role_name: str = "OrganizationAccountAccessRole"
|
271
267
|
) -> List[AccountSession]:
|
272
268
|
"""
|
273
269
|
Convenience function to create cross-account VPC sessions.
|
274
|
-
|
270
|
+
|
275
271
|
This is the main entry point for VPC modules to replace the broken
|
276
272
|
profile@accountId pattern with proper STS AssumeRole.
|
277
|
-
|
273
|
+
|
278
274
|
Args:
|
279
275
|
accounts: List of organization accounts from get_organization_accounts
|
280
276
|
base_profile: Base profile for assuming roles (CENTRALISED_OPS_PROFILE)
|
281
277
|
role_name: IAM role name to assume
|
282
|
-
|
278
|
+
|
283
279
|
Returns:
|
284
280
|
List of AccountSession objects ready for VPC discovery
|
285
281
|
"""
|
@@ -289,24 +285,23 @@ def create_cross_account_vpc_sessions(
|
|
289
285
|
|
290
286
|
# Compatibility functions for existing VPC module integration
|
291
287
|
def convert_accounts_to_sessions(
|
292
|
-
accounts: List[Dict[str, str]],
|
293
|
-
base_profile: str
|
288
|
+
accounts: List[Dict[str, str]], base_profile: str
|
294
289
|
) -> Tuple[List[AccountSession], Dict[str, Dict[str, str]]]:
|
295
290
|
"""
|
296
291
|
Convert organization accounts to cross-account sessions.
|
297
|
-
|
292
|
+
|
298
293
|
This replaces the broken convert_accounts_to_profiles function
|
299
294
|
with proper STS AssumeRole session creation.
|
300
|
-
|
295
|
+
|
301
296
|
Returns:
|
302
297
|
Tuple of (successful_sessions, account_metadata)
|
303
298
|
"""
|
304
299
|
account_sessions = create_cross_account_vpc_sessions(accounts, base_profile)
|
305
300
|
successful_sessions = [s for s in account_sessions if s.status == "success"]
|
306
|
-
|
301
|
+
|
307
302
|
# Create account metadata dict for compatibility
|
308
303
|
account_metadata = {}
|
309
304
|
for account in accounts:
|
310
305
|
account_metadata[account["id"]] = account
|
311
|
-
|
312
|
-
return successful_sessions, account_metadata
|
306
|
+
|
307
|
+
return successful_sessions, account_metadata
|