runbooks 1.1.4__py3-none-any.whl → 1.1.6__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/assessment/compliance.py +1 -1
- runbooks/cfat/assessment/runner.py +1 -0
- runbooks/cfat/cloud_foundations_assessment.py +227 -239
- runbooks/cli/__init__.py +1 -1
- runbooks/cli/commands/cfat.py +64 -23
- runbooks/cli/commands/finops.py +1005 -54
- runbooks/cli/commands/inventory.py +135 -91
- runbooks/cli/commands/operate.py +9 -36
- runbooks/cli/commands/security.py +42 -18
- runbooks/cli/commands/validation.py +432 -18
- runbooks/cli/commands/vpc.py +81 -17
- runbooks/cli/registry.py +22 -10
- runbooks/cloudops/__init__.py +20 -27
- runbooks/cloudops/base.py +96 -107
- runbooks/cloudops/cost_optimizer.py +544 -542
- runbooks/cloudops/infrastructure_optimizer.py +5 -4
- runbooks/cloudops/interfaces.py +224 -225
- 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 +177 -213
- runbooks/cloudops/security_enforcer.py +125 -159
- runbooks/common/accuracy_validator.py +17 -12
- runbooks/common/aws_pricing.py +349 -326
- runbooks/common/aws_pricing_api.py +211 -212
- runbooks/common/aws_profile_manager.py +40 -36
- runbooks/common/aws_utils.py +74 -79
- runbooks/common/business_logic.py +126 -104
- runbooks/common/cli_decorators.py +36 -60
- runbooks/common/comprehensive_cost_explorer_integration.py +455 -463
- runbooks/common/cross_account_manager.py +197 -204
- runbooks/common/date_utils.py +27 -39
- runbooks/common/decorators.py +29 -19
- 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 +476 -493
- runbooks/common/mcp_integration.py +99 -79
- runbooks/common/memory_optimization.py +140 -118
- runbooks/common/module_cli_base.py +37 -58
- runbooks/common/organizations_client.py +175 -193
- runbooks/common/patterns.py +23 -25
- runbooks/common/performance_monitoring.py +67 -71
- runbooks/common/performance_optimization_engine.py +283 -274
- runbooks/common/profile_utils.py +111 -37
- runbooks/common/rich_utils.py +315 -141
- 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 +26 -30
- 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 +484 -618
- 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 +32 -29
- runbooks/finops/enhanced_trend_visualization.py +3 -2
- runbooks/finops/enterprise_wrappers.py +223 -285
- 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 +337 -174
- runbooks/finops/mcp_validator.py +1952 -0
- runbooks/finops/nat_gateway_optimizer.py +1512 -481
- 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 +19 -23
- runbooks/finops/rds_snapshot_optimizer.py +367 -411
- runbooks/finops/reservation_optimizer.py +427 -363
- runbooks/finops/scenario_cli_integration.py +64 -65
- runbooks/finops/scenarios.py +1277 -438
- runbooks/finops/schemas.py +218 -182
- runbooks/finops/snapshot_manager.py +2289 -0
- runbooks/finops/types.py +3 -3
- runbooks/finops/validation_framework.py +259 -265
- runbooks/finops/vpc_cleanup_exporter.py +189 -144
- runbooks/finops/vpc_cleanup_optimizer.py +591 -573
- runbooks/finops/workspaces_analyzer.py +171 -182
- runbooks/integration/__init__.py +89 -0
- runbooks/integration/mcp_integration.py +1920 -0
- runbooks/inventory/CLAUDE.md +816 -0
- runbooks/inventory/__init__.py +2 -2
- runbooks/inventory/aws_decorators.py +2 -3
- runbooks/inventory/check_cloudtrail_compliance.py +2 -4
- runbooks/inventory/check_controltower_readiness.py +152 -151
- runbooks/inventory/check_landingzone_readiness.py +85 -84
- runbooks/inventory/cloud_foundations_integration.py +144 -149
- runbooks/inventory/collectors/aws_comprehensive.py +1 -1
- runbooks/inventory/collectors/aws_networking.py +109 -99
- runbooks/inventory/collectors/base.py +4 -0
- runbooks/inventory/core/collector.py +495 -313
- runbooks/inventory/core/formatter.py +11 -0
- runbooks/inventory/draw_org_structure.py +8 -9
- runbooks/inventory/drift_detection_cli.py +69 -96
- runbooks/inventory/ec2_vpc_utils.py +2 -2
- runbooks/inventory/find_cfn_drift_detection.py +5 -7
- runbooks/inventory/find_cfn_orphaned_stacks.py +7 -9
- runbooks/inventory/find_cfn_stackset_drift.py +5 -6
- runbooks/inventory/find_ec2_security_groups.py +48 -42
- runbooks/inventory/find_landingzone_versions.py +4 -6
- runbooks/inventory/find_vpc_flow_logs.py +7 -9
- runbooks/inventory/inventory_mcp_cli.py +48 -46
- runbooks/inventory/inventory_modules.py +103 -91
- runbooks/inventory/list_cfn_stacks.py +9 -10
- runbooks/inventory/list_cfn_stackset_operation_results.py +1 -3
- runbooks/inventory/list_cfn_stackset_operations.py +79 -57
- runbooks/inventory/list_cfn_stacksets.py +8 -10
- runbooks/inventory/list_config_recorders_delivery_channels.py +49 -39
- runbooks/inventory/list_ds_directories.py +65 -53
- runbooks/inventory/list_ec2_availability_zones.py +2 -4
- runbooks/inventory/list_ec2_ebs_volumes.py +32 -35
- runbooks/inventory/list_ec2_instances.py +23 -28
- runbooks/inventory/list_ecs_clusters_and_tasks.py +26 -34
- runbooks/inventory/list_elbs_load_balancers.py +22 -20
- runbooks/inventory/list_enis_network_interfaces.py +26 -33
- runbooks/inventory/list_guardduty_detectors.py +2 -4
- runbooks/inventory/list_iam_policies.py +2 -4
- runbooks/inventory/list_iam_roles.py +5 -7
- runbooks/inventory/list_iam_saml_providers.py +4 -6
- runbooks/inventory/list_lambda_functions.py +38 -38
- runbooks/inventory/list_org_accounts.py +6 -8
- runbooks/inventory/list_org_accounts_users.py +55 -44
- runbooks/inventory/list_rds_db_instances.py +31 -33
- runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
- runbooks/inventory/list_route53_hosted_zones.py +3 -5
- runbooks/inventory/list_servicecatalog_provisioned_products.py +37 -41
- runbooks/inventory/list_sns_topics.py +2 -4
- runbooks/inventory/list_ssm_parameters.py +4 -7
- runbooks/inventory/list_vpc_subnets.py +2 -4
- runbooks/inventory/list_vpcs.py +7 -10
- runbooks/inventory/mcp_inventory_validator.py +554 -468
- runbooks/inventory/mcp_vpc_validator.py +359 -442
- runbooks/inventory/organizations_discovery.py +63 -55
- runbooks/inventory/recover_cfn_stack_ids.py +7 -8
- runbooks/inventory/requirements.txt +0 -1
- runbooks/inventory/rich_inventory_display.py +35 -34
- runbooks/inventory/run_on_multi_accounts.py +3 -5
- runbooks/inventory/unified_validation_engine.py +281 -253
- runbooks/inventory/verify_ec2_security_groups.py +1 -1
- runbooks/inventory/vpc_analyzer.py +735 -697
- runbooks/inventory/vpc_architecture_validator.py +293 -348
- runbooks/inventory/vpc_dependency_analyzer.py +384 -380
- runbooks/inventory/vpc_flow_analyzer.py +1 -1
- runbooks/main.py +49 -34
- 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/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/networking_cost_heatmap.py +29 -8
- runbooks/operate/rds_operations.py +223 -254
- runbooks/operate/s3_operations.py +107 -118
- runbooks/operate/vpc_operations.py +646 -616
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/commons.py +10 -7
- runbooks/remediation/commvault_ec2_analysis.py +70 -66
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
- runbooks/remediation/multi_account.py +24 -21
- runbooks/remediation/rds_snapshot_list.py +86 -60
- runbooks/remediation/remediation_cli.py +92 -146
- runbooks/remediation/universal_account_discovery.py +83 -79
- runbooks/remediation/workspaces_list.py +46 -41
- 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/multi_account_security_controls.py +959 -1210
- runbooks/security/real_time_security_monitor.py +422 -444
- 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/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 +50 -47
- runbooks/validation/__init__.py +6 -6
- runbooks/validation/cli.py +9 -3
- runbooks/validation/comprehensive_2way_validator.py +745 -704
- runbooks/validation/mcp_validator.py +906 -228
- runbooks/validation/terraform_citations_validator.py +104 -115
- runbooks/validation/terraform_drift_detector.py +461 -454
- 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 +185 -160
- runbooks/vpc/mcp_no_eni_validator.py +680 -639
- 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 +1297 -1124
- runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
- runbooks-1.1.6.dist-info/METADATA +327 -0
- runbooks-1.1.6.dist-info/RECORD +489 -0
- 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 -973
- 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.4.dist-info/METADATA +0 -800
- runbooks-1.1.4.dist-info/RECORD +0 -468
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/WHEEL +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,7 @@ Strategic Enhancement: Migrated VPC discovery capabilities from vpc module follo
|
|
8
8
|
Maintains 100% compatibility with AWS Cloud Foundations inventory-scripts:
|
9
9
|
- all_my_vpcs.py -> Enhanced VPCCollector with topology mapping
|
10
10
|
- all_my_subnets.py -> SubnetCollector
|
11
|
-
- all_my_elbs.py -> ELBCollector
|
11
|
+
- all_my_elbs.py -> ELBCollector
|
12
12
|
- all_my_enis.py -> ENICollector
|
13
13
|
- all_my_phzs.py -> Route53Collector
|
14
14
|
|
@@ -293,32 +293,33 @@ if __name__ == "__main__":
|
|
293
293
|
# NEW VPC MODULE MIGRATION - Network Topology Discovery
|
294
294
|
# ============================================================================
|
295
295
|
|
296
|
+
|
296
297
|
class NetworkTopologyCollector(BaseResourceCollector):
|
297
298
|
"""
|
298
299
|
Network Topology Collector - Migrated from vpc module networking_wrapper.py
|
299
|
-
|
300
|
+
|
300
301
|
Provides comprehensive VPC topology mapping and cross-region relationships
|
301
302
|
following enterprise discovery patterns with Rich CLI integration.
|
302
303
|
"""
|
303
|
-
|
304
|
+
|
304
305
|
def __init__(self, session: Optional[boto3.Session] = None):
|
305
306
|
super().__init__(resource_type=ResourceType.VPC, session=session) # Using VPC as base type
|
306
|
-
|
307
|
+
|
307
308
|
@aws_api_retry
|
308
309
|
def collect_network_topology(self, account: AWSAccount, regions: List[str] = None) -> Dict[str, Any]:
|
309
310
|
"""
|
310
311
|
Collect comprehensive network topology across regions.
|
311
|
-
|
312
|
+
|
312
313
|
Args:
|
313
314
|
account: AWS account to analyze
|
314
315
|
regions: List of regions to analyze (default: all available)
|
315
|
-
|
316
|
+
|
316
317
|
Returns:
|
317
318
|
Dictionary with complete network topology mapping
|
318
319
|
"""
|
319
320
|
if not regions:
|
320
321
|
regions = ["us-east-1", "us-west-2", "eu-west-1"] # Default enterprise regions
|
321
|
-
|
322
|
+
|
322
323
|
print_header("Network Topology Discovery", "latest version")
|
323
324
|
topology = {
|
324
325
|
"account_id": account.account_id,
|
@@ -331,9 +332,9 @@ class NetworkTopologyCollector(BaseResourceCollector):
|
|
331
332
|
"vpc_peering": [],
|
332
333
|
"total_vpcs": 0,
|
333
334
|
"total_subnets": 0,
|
334
|
-
"recommendations": []
|
335
|
+
"recommendations": [],
|
335
336
|
}
|
336
|
-
|
337
|
+
|
337
338
|
for region in regions:
|
338
339
|
try:
|
339
340
|
print_info(f"Analyzing network topology in {region}")
|
@@ -341,22 +342,24 @@ class NetworkTopologyCollector(BaseResourceCollector):
|
|
341
342
|
topology["vpc_topology"][region] = region_topology
|
342
343
|
topology["total_vpcs"] += len(region_topology["vpcs"])
|
343
344
|
topology["total_subnets"] += len(region_topology["subnets"])
|
344
|
-
|
345
|
+
|
345
346
|
except Exception as e:
|
346
347
|
self.logger.error(f"Failed to collect topology from {region}: {e}")
|
347
348
|
continue
|
348
|
-
|
349
|
+
|
349
350
|
# Analyze cross-region connections
|
350
351
|
topology["cross_region_connections"] = self._analyze_cross_region_connections(topology["vpc_topology"])
|
351
352
|
topology["recommendations"] = self._generate_topology_recommendations(topology)
|
352
|
-
|
353
|
-
print_success(
|
353
|
+
|
354
|
+
print_success(
|
355
|
+
f"Network topology discovery completed: {topology['total_vpcs']} VPCs, {topology['total_subnets']} subnets"
|
356
|
+
)
|
354
357
|
return topology
|
355
|
-
|
358
|
+
|
356
359
|
def _collect_region_topology(self, region: str, account: AWSAccount) -> Dict[str, Any]:
|
357
360
|
"""Collect detailed network topology for a specific region."""
|
358
361
|
ec2 = self.session.client("ec2", region_name=region)
|
359
|
-
|
362
|
+
|
360
363
|
region_topology = {
|
361
364
|
"region": region,
|
362
365
|
"vpcs": [],
|
@@ -365,38 +368,38 @@ class NetworkTopologyCollector(BaseResourceCollector):
|
|
365
368
|
"internet_gateways": [],
|
366
369
|
"nat_gateways": [],
|
367
370
|
"vpc_endpoints": [],
|
368
|
-
"network_interfaces": []
|
371
|
+
"network_interfaces": [],
|
369
372
|
}
|
370
|
-
|
373
|
+
|
371
374
|
try:
|
372
375
|
# Collect VPCs with enhanced metadata
|
373
376
|
vpcs_response = ec2.describe_vpcs()
|
374
377
|
for vpc in vpcs_response["Vpcs"]:
|
375
378
|
vpc_data = self._enhance_vpc_data(ec2, vpc, region, account)
|
376
379
|
region_topology["vpcs"].append(vpc_data)
|
377
|
-
|
380
|
+
|
378
381
|
# Collect NAT Gateways
|
379
382
|
nat_response = ec2.describe_nat_gateways()
|
380
383
|
for nat in nat_response["NatGateways"]:
|
381
384
|
if nat["State"] != "deleted":
|
382
385
|
nat_data = self._enhance_nat_gateway_data(ec2, nat, region)
|
383
386
|
region_topology["nat_gateways"].append(nat_data)
|
384
|
-
|
387
|
+
|
385
388
|
# Collect VPC Endpoints
|
386
389
|
endpoints_response = ec2.describe_vpc_endpoints()
|
387
390
|
for endpoint in endpoints_response["VpcEndpoints"]:
|
388
391
|
endpoint_data = self._enhance_vpc_endpoint_data(endpoint, region)
|
389
392
|
region_topology["vpc_endpoints"].append(endpoint_data)
|
390
|
-
|
393
|
+
|
391
394
|
except ClientError as e:
|
392
395
|
self.logger.error(f"AWS API error in {region}: {e}")
|
393
|
-
|
396
|
+
|
394
397
|
return region_topology
|
395
|
-
|
398
|
+
|
396
399
|
def _enhance_vpc_data(self, ec2_client, vpc: Dict[str, Any], region: str, account: AWSAccount) -> Dict[str, Any]:
|
397
400
|
"""Enhance VPC data with topology relationships."""
|
398
401
|
tags = {tag["Key"]: tag["Value"] for tag in vpc.get("Tags", [])}
|
399
|
-
|
402
|
+
|
400
403
|
enhanced_vpc = {
|
401
404
|
"vpc_id": vpc["VpcId"],
|
402
405
|
"cidr_block": vpc["CidrBlock"],
|
@@ -412,35 +415,35 @@ class NetworkTopologyCollector(BaseResourceCollector):
|
|
412
415
|
"route_tables": [],
|
413
416
|
"internet_gateways": [],
|
414
417
|
"security_groups": [],
|
415
|
-
"network_acls": []
|
418
|
+
"network_acls": [],
|
416
419
|
}
|
417
|
-
|
420
|
+
|
418
421
|
# Get associated subnets
|
419
422
|
try:
|
420
|
-
subnets_response = ec2_client.describe_subnets(
|
421
|
-
Filters=[{"Name": "vpc-id", "Values": [vpc["VpcId"]]}]
|
422
|
-
)
|
423
|
+
subnets_response = ec2_client.describe_subnets(Filters=[{"Name": "vpc-id", "Values": [vpc["VpcId"]]}])
|
423
424
|
for subnet in subnets_response["Subnets"]:
|
424
425
|
subnet_tags = {tag["Key"]: tag["Value"] for tag in subnet.get("Tags", [])}
|
425
|
-
enhanced_vpc["subnets"].append(
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
426
|
+
enhanced_vpc["subnets"].append(
|
427
|
+
{
|
428
|
+
"subnet_id": subnet["SubnetId"],
|
429
|
+
"cidr_block": subnet["CidrBlock"],
|
430
|
+
"availability_zone": subnet["AvailabilityZone"],
|
431
|
+
"available_ip_address_count": subnet["AvailableIpAddressCount"],
|
432
|
+
"map_public_ip_on_launch": subnet.get("MapPublicIpOnLaunch", False),
|
433
|
+
"state": subnet["State"],
|
434
|
+
"tags": subnet_tags,
|
435
|
+
"name": subnet_tags.get("Name", subnet["SubnetId"]),
|
436
|
+
}
|
437
|
+
)
|
435
438
|
except ClientError as e:
|
436
439
|
self.logger.warning(f"Failed to get subnets for VPC {vpc['VpcId']}: {e}")
|
437
|
-
|
440
|
+
|
438
441
|
return enhanced_vpc
|
439
|
-
|
442
|
+
|
440
443
|
def _enhance_nat_gateway_data(self, ec2_client, nat: Dict[str, Any], region: str) -> Dict[str, Any]:
|
441
444
|
"""Enhance NAT Gateway data with usage and cost implications."""
|
442
445
|
tags = {tag["Key"]: tag["Value"] for tag in nat.get("Tags", [])}
|
443
|
-
|
446
|
+
|
444
447
|
return {
|
445
448
|
"nat_gateway_id": nat["NatGatewayId"],
|
446
449
|
"state": nat["State"],
|
@@ -454,13 +457,13 @@ class NetworkTopologyCollector(BaseResourceCollector):
|
|
454
457
|
# Enhanced with network interface information
|
455
458
|
"network_interface_id": nat.get("NatGatewayAddresses", [{}])[0].get("NetworkInterfaceId"),
|
456
459
|
"public_ip": nat.get("NatGatewayAddresses", [{}])[0].get("PublicIp"),
|
457
|
-
"private_ip": nat.get("NatGatewayAddresses", [{}])[0].get("PrivateIp")
|
460
|
+
"private_ip": nat.get("NatGatewayAddresses", [{}])[0].get("PrivateIp"),
|
458
461
|
}
|
459
|
-
|
462
|
+
|
460
463
|
def _enhance_vpc_endpoint_data(self, endpoint: Dict[str, Any], region: str) -> Dict[str, Any]:
|
461
464
|
"""Enhance VPC Endpoint data with service and cost information."""
|
462
465
|
tags = {tag["Key"]: tag["Value"] for tag in endpoint.get("Tags", [])}
|
463
|
-
|
466
|
+
|
464
467
|
return {
|
465
468
|
"vpc_endpoint_id": endpoint["VpcEndpointId"],
|
466
469
|
"vpc_id": endpoint.get("VpcId"),
|
@@ -473,64 +476,65 @@ class NetworkTopologyCollector(BaseResourceCollector):
|
|
473
476
|
"name": tags.get("Name", endpoint["VpcEndpointId"]),
|
474
477
|
"route_table_ids": endpoint.get("RouteTableIds", []),
|
475
478
|
"subnet_ids": endpoint.get("SubnetIds", []),
|
476
|
-
"policy_document": endpoint.get("PolicyDocument")
|
479
|
+
"policy_document": endpoint.get("PolicyDocument"),
|
477
480
|
}
|
478
|
-
|
481
|
+
|
479
482
|
def _analyze_cross_region_connections(self, vpc_topology: Dict[str, Any]) -> List[Dict[str, Any]]:
|
480
483
|
"""Analyze potential cross-region network connections."""
|
481
484
|
connections = []
|
482
485
|
# This would be enhanced to detect VPC peering, Transit Gateway, etc.
|
483
486
|
# For now, return empty list as foundation
|
484
487
|
return connections
|
485
|
-
|
488
|
+
|
486
489
|
def _generate_topology_recommendations(self, topology: Dict[str, Any]) -> List[Dict[str, Any]]:
|
487
490
|
"""Generate network topology optimization recommendations."""
|
488
491
|
recommendations = []
|
489
|
-
|
492
|
+
|
490
493
|
# Basic recommendations based on topology analysis
|
491
494
|
total_nat_gateways = sum(
|
492
|
-
len(region_data.get("nat_gateways", []))
|
493
|
-
for region_data in topology["vpc_topology"].values()
|
495
|
+
len(region_data.get("nat_gateways", [])) for region_data in topology["vpc_topology"].values()
|
494
496
|
)
|
495
|
-
|
497
|
+
|
496
498
|
if total_nat_gateways > topology["total_vpcs"]:
|
497
|
-
recommendations.append(
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
499
|
+
recommendations.append(
|
500
|
+
{
|
501
|
+
"type": "cost_optimization",
|
502
|
+
"priority": "high",
|
503
|
+
"description": f"Multiple NAT Gateways detected ({total_nat_gateways}) across {topology['total_vpcs']} VPCs",
|
504
|
+
"recommendation": "Consider consolidating NAT Gateways to reduce monthly costs",
|
505
|
+
"estimated_savings": f"${(total_nat_gateways - topology['total_vpcs']) * 45:.2f}/month",
|
506
|
+
}
|
507
|
+
)
|
508
|
+
|
505
509
|
return recommendations
|
506
510
|
|
507
511
|
|
508
512
|
class TransitGatewayCollector(BaseResourceCollector):
|
509
513
|
"""
|
510
514
|
Transit Gateway Collector - Enhanced discovery from vpc module
|
511
|
-
|
515
|
+
|
512
516
|
Provides comprehensive Transit Gateway and VPC peering discovery
|
513
517
|
with enterprise cost analysis integration.
|
514
518
|
"""
|
515
|
-
|
519
|
+
|
516
520
|
def __init__(self, session: Optional[boto3.Session] = None):
|
517
521
|
super().__init__(resource_type=ResourceType.VPC, session=session)
|
518
|
-
|
522
|
+
|
519
523
|
@aws_api_retry
|
520
524
|
def collect_transit_gateways(self, account: AWSAccount, regions: List[str] = None) -> Dict[str, Any]:
|
521
525
|
"""
|
522
526
|
Collect Transit Gateway configurations and attachments.
|
523
|
-
|
527
|
+
|
524
528
|
Args:
|
525
529
|
account: AWS account to analyze
|
526
530
|
regions: List of regions to analyze
|
527
|
-
|
531
|
+
|
528
532
|
Returns:
|
529
533
|
Dictionary with Transit Gateway analysis
|
530
534
|
"""
|
531
535
|
if not regions:
|
532
536
|
regions = ["us-east-1", "us-west-2", "eu-west-1"]
|
533
|
-
|
537
|
+
|
534
538
|
print_header("Transit Gateway Discovery", "latest version")
|
535
539
|
tgw_analysis = {
|
536
540
|
"account_id": account.account_id,
|
@@ -540,18 +544,18 @@ class TransitGatewayCollector(BaseResourceCollector):
|
|
540
544
|
"total_tgw": 0,
|
541
545
|
"total_attachments": 0,
|
542
546
|
"monthly_cost_estimate": 0,
|
543
|
-
"recommendations": []
|
547
|
+
"recommendations": [],
|
544
548
|
}
|
545
|
-
|
549
|
+
|
546
550
|
for region in regions:
|
547
551
|
try:
|
548
552
|
print_info(f"Analyzing Transit Gateways in {region}")
|
549
553
|
ec2 = self.session.client("ec2", region_name=region)
|
550
|
-
|
554
|
+
|
551
555
|
# Get Transit Gateways
|
552
556
|
tgw_response = ec2.describe_transit_gateways()
|
553
557
|
region_tgws = []
|
554
|
-
|
558
|
+
|
555
559
|
for tgw in tgw_response["TransitGateways"]:
|
556
560
|
if tgw["State"] not in ["deleted", "deleting"]:
|
557
561
|
tgw_data = self._enhance_transit_gateway_data(ec2, tgw, region)
|
@@ -559,22 +563,24 @@ class TransitGatewayCollector(BaseResourceCollector):
|
|
559
563
|
tgw_analysis["total_tgw"] += 1
|
560
564
|
tgw_analysis["total_attachments"] += len(tgw_data["attachments"])
|
561
565
|
tgw_analysis["monthly_cost_estimate"] += 36.50 # Base TGW cost per month
|
562
|
-
|
566
|
+
|
563
567
|
tgw_analysis["transit_gateways"][region] = region_tgws
|
564
|
-
|
568
|
+
|
565
569
|
except ClientError as e:
|
566
570
|
self.logger.error(f"Failed to collect Transit Gateways from {region}: {e}")
|
567
571
|
continue
|
568
|
-
|
572
|
+
|
569
573
|
tgw_analysis["recommendations"] = self._generate_tgw_recommendations(tgw_analysis)
|
570
|
-
|
571
|
-
print_success(
|
574
|
+
|
575
|
+
print_success(
|
576
|
+
f"Transit Gateway discovery completed: {tgw_analysis['total_tgw']} TGWs, {tgw_analysis['total_attachments']} attachments"
|
577
|
+
)
|
572
578
|
return tgw_analysis
|
573
|
-
|
579
|
+
|
574
580
|
def _enhance_transit_gateway_data(self, ec2_client, tgw: Dict[str, Any], region: str) -> Dict[str, Any]:
|
575
581
|
"""Enhance Transit Gateway data with attachments and routing information."""
|
576
582
|
tags = {tag["Key"]: tag["Value"] for tag in tgw.get("Tags", [])}
|
577
|
-
|
583
|
+
|
578
584
|
tgw_data = {
|
579
585
|
"transit_gateway_id": tgw["TransitGatewayId"],
|
580
586
|
"state": tgw["State"],
|
@@ -585,42 +591,46 @@ class TransitGatewayCollector(BaseResourceCollector):
|
|
585
591
|
"tags": tags,
|
586
592
|
"name": tags.get("Name", tgw["TransitGatewayId"]),
|
587
593
|
"attachments": [],
|
588
|
-
"route_tables": []
|
594
|
+
"route_tables": [],
|
589
595
|
}
|
590
|
-
|
596
|
+
|
591
597
|
# Get Transit Gateway Attachments
|
592
598
|
try:
|
593
599
|
attachments_response = ec2_client.describe_transit_gateway_attachments(
|
594
600
|
Filters=[{"Name": "transit-gateway-id", "Values": [tgw["TransitGatewayId"]]}]
|
595
601
|
)
|
596
|
-
|
602
|
+
|
597
603
|
for attachment in attachments_response["TransitGatewayAttachments"]:
|
598
604
|
attachment_tags = {tag["Key"]: tag["Value"] for tag in attachment.get("Tags", [])}
|
599
|
-
tgw_data["attachments"].append(
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
605
|
+
tgw_data["attachments"].append(
|
606
|
+
{
|
607
|
+
"attachment_id": attachment["TransitGatewayAttachmentId"],
|
608
|
+
"resource_type": attachment["ResourceType"],
|
609
|
+
"resource_id": attachment.get("ResourceId"),
|
610
|
+
"state": attachment["State"],
|
611
|
+
"tags": attachment_tags,
|
612
|
+
"name": attachment_tags.get("Name", attachment["TransitGatewayAttachmentId"]),
|
613
|
+
}
|
614
|
+
)
|
615
|
+
|
608
616
|
except ClientError as e:
|
609
617
|
self.logger.warning(f"Failed to get attachments for TGW {tgw['TransitGatewayId']}: {e}")
|
610
|
-
|
618
|
+
|
611
619
|
return tgw_data
|
612
|
-
|
620
|
+
|
613
621
|
def _generate_tgw_recommendations(self, tgw_analysis: Dict[str, Any]) -> List[Dict[str, Any]]:
|
614
622
|
"""Generate Transit Gateway optimization recommendations."""
|
615
623
|
recommendations = []
|
616
|
-
|
624
|
+
|
617
625
|
if tgw_analysis["total_tgw"] > 1:
|
618
|
-
recommendations.append(
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
+
recommendations.append(
|
627
|
+
{
|
628
|
+
"type": "cost_optimization",
|
629
|
+
"priority": "medium",
|
630
|
+
"description": f"Multiple Transit Gateways detected ({tgw_analysis['total_tgw']})",
|
631
|
+
"recommendation": "Consider consolidating Transit Gateways to reduce base costs",
|
632
|
+
"estimated_savings": f"${(tgw_analysis['total_tgw'] - 1) * 36.50:.2f}/month",
|
633
|
+
}
|
634
|
+
)
|
635
|
+
|
626
636
|
return recommendations
|