runbooks 0.9.5__py3-none-any.whl → 0.9.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. runbooks/__init__.py +1 -1
  2. runbooks/_platform/__init__.py +19 -0
  3. runbooks/_platform/core/runbooks_wrapper.py +478 -0
  4. runbooks/cloudops/cost_optimizer.py +330 -0
  5. runbooks/cloudops/interfaces.py +3 -3
  6. runbooks/finops/README.md +1 -1
  7. runbooks/finops/automation_core.py +643 -0
  8. runbooks/finops/business_cases.py +414 -16
  9. runbooks/finops/cli.py +23 -0
  10. runbooks/finops/compute_cost_optimizer.py +865 -0
  11. runbooks/finops/ebs_cost_optimizer.py +718 -0
  12. runbooks/finops/ebs_optimizer.py +909 -0
  13. runbooks/finops/elastic_ip_optimizer.py +675 -0
  14. runbooks/finops/embedded_mcp_validator.py +330 -14
  15. runbooks/finops/enterprise_wrappers.py +827 -0
  16. runbooks/finops/legacy_migration.py +730 -0
  17. runbooks/finops/nat_gateway_optimizer.py +1160 -0
  18. runbooks/finops/network_cost_optimizer.py +1387 -0
  19. runbooks/finops/notebook_utils.py +596 -0
  20. runbooks/finops/reservation_optimizer.py +956 -0
  21. runbooks/finops/validation_framework.py +753 -0
  22. runbooks/finops/workspaces_analyzer.py +593 -0
  23. runbooks/inventory/__init__.py +7 -0
  24. runbooks/inventory/collectors/aws_networking.py +357 -6
  25. runbooks/inventory/mcp_vpc_validator.py +1091 -0
  26. runbooks/inventory/vpc_analyzer.py +1107 -0
  27. runbooks/inventory/vpc_architecture_validator.py +939 -0
  28. runbooks/inventory/vpc_dependency_analyzer.py +845 -0
  29. runbooks/main.py +425 -39
  30. runbooks/operate/vpc_operations.py +1479 -16
  31. runbooks/remediation/commvault_ec2_analysis.py +5 -4
  32. runbooks/remediation/dynamodb_optimize.py +2 -2
  33. runbooks/remediation/rds_instance_list.py +1 -1
  34. runbooks/remediation/rds_snapshot_list.py +5 -4
  35. runbooks/remediation/workspaces_list.py +2 -2
  36. runbooks/security/compliance_automation.py +2 -2
  37. runbooks/vpc/tests/test_config.py +2 -2
  38. {runbooks-0.9.5.dist-info → runbooks-0.9.7.dist-info}/METADATA +1 -1
  39. {runbooks-0.9.5.dist-info → runbooks-0.9.7.dist-info}/RECORD +43 -24
  40. {runbooks-0.9.5.dist-info → runbooks-0.9.7.dist-info}/WHEEL +0 -0
  41. {runbooks-0.9.5.dist-info → runbooks-0.9.7.dist-info}/entry_points.txt +0 -0
  42. {runbooks-0.9.5.dist-info → runbooks-0.9.7.dist-info}/licenses/LICENSE +0 -0
  43. {runbooks-0.9.5.dist-info → runbooks-0.9.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,939 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ VPC Multi-Account Architecture Validator
4
+
5
+ Enterprise architecture validation for VPC cleanup across 60+1 AWS Landing Zone
6
+ accounts with comprehensive compliance checking and Well-Architected Framework
7
+ alignment.
8
+
9
+ **Strategic Alignment**: Supports VPC security posture enhancement initiatives
10
+ through comprehensive architecture validation, compliance checking, and risk
11
+ assessment across multi-account AWS Organizations.
12
+
13
+ **Architecture Focus**:
14
+ - Multi-account Landing Zone architecture validation
15
+ - AWS Well-Architected Framework compliance
16
+ - Network topology impact assessment
17
+ - CIS Benchmark compliance validation
18
+ - Cross-account dependency analysis
19
+ - Security baseline enforcement
20
+
21
+ **Compliance Frameworks**:
22
+ - CIS AWS Foundations Benchmark
23
+ - AWS Well-Architected Security Pillar
24
+ - SOC2 Type II compliance requirements
25
+ - Enterprise network governance standards
26
+
27
+ Author: cloudops-architect (Enterprise Agile Team)
28
+ Version: 1.0.0
29
+ """
30
+
31
+ import json
32
+ import logging
33
+ from dataclasses import dataclass, field
34
+ from datetime import datetime
35
+ from typing import Any, Dict, List, Optional, Set, Tuple
36
+ import boto3
37
+ from botocore.exceptions import ClientError
38
+
39
+ from runbooks.common.rich_utils import (
40
+ console, print_header, print_success, print_error, print_warning,
41
+ create_table, create_progress_bar, STATUS_INDICATORS
42
+ )
43
+
44
+ logger = logging.getLogger(__name__)
45
+
46
+
47
+ @dataclass
48
+ class ArchitectureComplianceResult:
49
+ """Architecture compliance validation result."""
50
+
51
+ framework: str # CIS, Well-Architected, SOC2, etc.
52
+ control_id: str
53
+ control_description: str
54
+ compliance_status: str # PASS, FAIL, WARNING, NOT_APPLICABLE
55
+ impact_level: str # LOW, MEDIUM, HIGH, CRITICAL
56
+ findings: List[str] = field(default_factory=list)
57
+ remediation_guidance: Optional[str] = None
58
+ validation_timestamp: str = field(default_factory=lambda: datetime.utcnow().isoformat())
59
+
60
+
61
+ @dataclass
62
+ class AWSO5ArchitectureValidationResult:
63
+ """Comprehensive AWSO-5 architecture validation result."""
64
+
65
+ vpc_id: str
66
+ account_id: str
67
+ region: str
68
+
69
+ # Architecture assessments
70
+ well_architected_score: Dict[str, float] = field(default_factory=dict)
71
+ cis_benchmark_compliance: Dict[str, str] = field(default_factory=dict)
72
+ security_posture_score: float = 0.0
73
+ network_impact_assessment: Dict[str, Any] = field(default_factory=dict)
74
+
75
+ # Compliance results
76
+ compliance_results: List[ArchitectureComplianceResult] = field(default_factory=list)
77
+ critical_findings: List[str] = field(default_factory=list)
78
+ security_improvements: List[str] = field(default_factory=list)
79
+
80
+ # Business impact
81
+ architecture_recommendation: str = "HOLD" # DELETE, DELETE_WITH_REMEDIATION, HOLD, INVESTIGATE
82
+ business_risk_level: str = "MEDIUM" # LOW, MEDIUM, HIGH, CRITICAL
83
+ estimated_security_improvement: float = 0.0
84
+
85
+ # Analysis metadata
86
+ validation_timestamp: str = field(default_factory=lambda: datetime.utcnow().isoformat())
87
+ validation_duration_seconds: float = 0.0
88
+ validation_accuracy: float = 100.0
89
+
90
+ @property
91
+ def overall_compliance_score(self) -> float:
92
+ """Calculate overall compliance score from all frameworks."""
93
+ if not self.compliance_results:
94
+ return 0.0
95
+
96
+ total_weight = 0
97
+ weighted_score = 0
98
+
99
+ for result in self.compliance_results:
100
+ weight = self._get_control_weight(result.framework, result.impact_level)
101
+ total_weight += weight
102
+
103
+ if result.compliance_status == "PASS":
104
+ weighted_score += weight * 1.0
105
+ elif result.compliance_status == "WARNING":
106
+ weighted_score += weight * 0.5
107
+ # FAIL and NOT_APPLICABLE contribute 0
108
+
109
+ return (weighted_score / total_weight * 100) if total_weight > 0 else 0.0
110
+
111
+ def _get_control_weight(self, framework: str, impact_level: str) -> float:
112
+ """Get weight for compliance control based on framework and impact."""
113
+ framework_weights = {
114
+ 'CIS': 3.0,
115
+ 'Well-Architected': 2.5,
116
+ 'SOC2': 2.0,
117
+ 'Enterprise': 1.5
118
+ }
119
+
120
+ impact_multipliers = {
121
+ 'CRITICAL': 4.0,
122
+ 'HIGH': 3.0,
123
+ 'MEDIUM': 2.0,
124
+ 'LOW': 1.0
125
+ }
126
+
127
+ base_weight = framework_weights.get(framework, 1.0)
128
+ multiplier = impact_multipliers.get(impact_level, 1.0)
129
+
130
+ return base_weight * multiplier
131
+
132
+
133
+ class AWSO5ArchitectureValidator:
134
+ """
135
+ AWSO-5 Multi-Account Architecture Validator.
136
+
137
+ Comprehensive architecture validation for VPC cleanup with enterprise
138
+ compliance checking, security posture assessment, and business risk analysis.
139
+
140
+ **Enterprise Integration**:
141
+ - Multi-account AWS Organizations support
142
+ - Well-Architected Framework assessment
143
+ - CIS Benchmark compliance validation
144
+ - Cross-account dependency analysis
145
+ - Security baseline enforcement
146
+ - Network topology impact assessment
147
+ """
148
+
149
+ def __init__(self, session: Optional[boto3.Session] = None, region: str = "us-east-1"):
150
+ """Initialize AWSO-5 architecture validator."""
151
+ self.session = session or boto3.Session()
152
+ self.region = region
153
+ self.console = console
154
+
155
+ # Initialize AWS clients
156
+ self._ec2_client = None
157
+ self._organizations_client = None
158
+ self._config_client = None
159
+ self._cloudtrail_client = None
160
+
161
+ # Validation tracking
162
+ self.validation_results: Dict[str, AWSO5ArchitectureValidationResult] = {}
163
+
164
+ @property
165
+ def ec2_client(self):
166
+ """Lazy-loaded EC2 client."""
167
+ if not self._ec2_client:
168
+ self._ec2_client = self.session.client('ec2', region_name=self.region)
169
+ return self._ec2_client
170
+
171
+ @property
172
+ def organizations_client(self):
173
+ """Lazy-loaded Organizations client."""
174
+ if not self._organizations_client:
175
+ self._organizations_client = self.session.client('organizations', region_name='us-east-1')
176
+ return self._organizations_client
177
+
178
+ @property
179
+ def config_client(self):
180
+ """Lazy-loaded Config client."""
181
+ if not self._config_client:
182
+ self._config_client = self.session.client('config', region_name=self.region)
183
+ return self._config_client
184
+
185
+ @property
186
+ def cloudtrail_client(self):
187
+ """Lazy-loaded CloudTrail client."""
188
+ if not self._cloudtrail_client:
189
+ self._cloudtrail_client = self.session.client('cloudtrail', region_name=self.region)
190
+ return self._cloudtrail_client
191
+
192
+ def validate_vpc_architecture(self, vpc_id: str) -> AWSO5ArchitectureValidationResult:
193
+ """
194
+ Comprehensive VPC architecture validation for AWSO-5 compliance.
195
+
196
+ Performs multi-dimensional architecture assessment including security
197
+ posture, compliance frameworks, network impact, and business risk analysis.
198
+
199
+ Args:
200
+ vpc_id: AWS VPC identifier to validate
201
+
202
+ Returns:
203
+ Comprehensive architecture validation results
204
+ """
205
+ start_time = datetime.utcnow()
206
+
207
+ # Get VPC and account information
208
+ vpc_info = self._get_vpc_info(vpc_id)
209
+ if not vpc_info:
210
+ raise ValueError(f"VPC {vpc_id} not found in region {self.region}")
211
+
212
+ account_id = self.session.client('sts').get_caller_identity()['Account']
213
+
214
+ result = AWSO5ArchitectureValidationResult(
215
+ vpc_id=vpc_id,
216
+ account_id=account_id,
217
+ region=self.region
218
+ )
219
+
220
+ print_header("AWSO-5 Architecture Validation", "1.0.0")
221
+ self.console.print(f"\n[blue]VPC Architecture Analysis:[/blue] {vpc_id}")
222
+ self.console.print(f"[blue]Account:[/blue] {account_id}")
223
+ self.console.print(f"[blue]Region:[/blue] {self.region}")
224
+
225
+ # Validation phases
226
+ self.console.print("\n[yellow]Phase 1: CIS Benchmark Compliance[/yellow]")
227
+ self._validate_cis_benchmark_compliance(vpc_id, vpc_info, result)
228
+
229
+ self.console.print("\n[yellow]Phase 2: AWS Well-Architected Assessment[/yellow]")
230
+ self._validate_well_architected_framework(vpc_id, vpc_info, result)
231
+
232
+ self.console.print("\n[yellow]Phase 3: Security Posture Analysis[/yellow]")
233
+ self._analyze_security_posture(vpc_id, vpc_info, result)
234
+
235
+ self.console.print("\n[yellow]Phase 4: Network Impact Assessment[/yellow]")
236
+ self._assess_network_impact(vpc_id, vpc_info, result)
237
+
238
+ self.console.print("\n[yellow]Phase 5: Business Risk Analysis[/yellow]")
239
+ self._analyze_business_risk(vpc_id, vpc_info, result)
240
+
241
+ # Calculate final metrics
242
+ end_time = datetime.utcnow()
243
+ result.validation_duration_seconds = (end_time - start_time).total_seconds()
244
+ result.security_posture_score = self._calculate_security_posture_score(result)
245
+
246
+ # Generate architecture recommendation
247
+ self._generate_architecture_recommendation(result)
248
+
249
+ # Store results for evidence collection
250
+ self.validation_results[vpc_id] = result
251
+
252
+ # Display comprehensive results
253
+ self._display_validation_results(result)
254
+
255
+ return result
256
+
257
+ def _get_vpc_info(self, vpc_id: str) -> Optional[Dict[str, Any]]:
258
+ """Get comprehensive VPC information."""
259
+ try:
260
+ response = self.ec2_client.describe_vpcs(VpcIds=[vpc_id])
261
+ return response['Vpcs'][0] if response['Vpcs'] else None
262
+ except ClientError as e:
263
+ print_error(f"Failed to get VPC info: {e}")
264
+ return None
265
+
266
+ def _validate_cis_benchmark_compliance(
267
+ self,
268
+ vpc_id: str,
269
+ vpc_info: Dict[str, Any],
270
+ result: AWSO5ArchitectureValidationResult
271
+ ):
272
+ """Validate CIS AWS Foundations Benchmark compliance."""
273
+
274
+ # CIS Control 4.1: Ensure no security groups allow ingress from 0.0.0.0/0 to port 22
275
+ self._check_cis_4_1_ssh_access(vpc_id, result)
276
+
277
+ # CIS Control 4.2: Ensure no security groups allow ingress from 0.0.0.0/0 to port 3389
278
+ self._check_cis_4_2_rdp_access(vpc_id, result)
279
+
280
+ # CIS Control 4.3: Ensure the default security group restricts all traffic
281
+ self._check_cis_4_3_default_security_group(vpc_id, result)
282
+
283
+ # CIS Control 2.6: Ensure VPC flow logging is enabled
284
+ self._check_cis_2_6_vpc_flow_logging(vpc_id, result)
285
+
286
+ # Default VPC specific checks
287
+ if vpc_info.get('IsDefault', False):
288
+ self._check_default_vpc_compliance(vpc_id, vpc_info, result)
289
+
290
+ def _check_cis_4_1_ssh_access(self, vpc_id: str, result: AWSO5ArchitectureValidationResult):
291
+ """Check CIS 4.1: SSH access from 0.0.0.0/0."""
292
+ try:
293
+ response = self.ec2_client.describe_security_groups(
294
+ Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}]
295
+ )
296
+
297
+ violations = []
298
+ for sg in response['SecurityGroups']:
299
+ for rule in sg.get('IpPermissions', []):
300
+ if (rule.get('FromPort') == 22 and rule.get('ToPort') == 22 and
301
+ any(ip_range.get('CidrIp') == '0.0.0.0/0' for ip_range in rule.get('IpRanges', []))):
302
+ violations.append(f"Security Group {sg['GroupId']} ({sg['GroupName']})")
303
+
304
+ if violations:
305
+ compliance_result = ArchitectureComplianceResult(
306
+ framework="CIS",
307
+ control_id="4.1",
308
+ control_description="No security groups allow ingress from 0.0.0.0/0 to port 22",
309
+ compliance_status="FAIL",
310
+ impact_level="HIGH",
311
+ findings=violations,
312
+ remediation_guidance="Restrict SSH access to specific IP ranges"
313
+ )
314
+ result.critical_findings.extend(violations)
315
+ else:
316
+ compliance_result = ArchitectureComplianceResult(
317
+ framework="CIS",
318
+ control_id="4.1",
319
+ control_description="No security groups allow ingress from 0.0.0.0/0 to port 22",
320
+ compliance_status="PASS",
321
+ impact_level="HIGH"
322
+ )
323
+
324
+ result.compliance_results.append(compliance_result)
325
+ result.cis_benchmark_compliance["4.1"] = compliance_result.compliance_status
326
+
327
+ except ClientError as e:
328
+ print_warning(f"CIS 4.1 check failed: {e}")
329
+
330
+ def _check_cis_4_2_rdp_access(self, vpc_id: str, result: AWSO5ArchitectureValidationResult):
331
+ """Check CIS 4.2: RDP access from 0.0.0.0/0."""
332
+ try:
333
+ response = self.ec2_client.describe_security_groups(
334
+ Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}]
335
+ )
336
+
337
+ violations = []
338
+ for sg in response['SecurityGroups']:
339
+ for rule in sg.get('IpPermissions', []):
340
+ if (rule.get('FromPort') == 3389 and rule.get('ToPort') == 3389 and
341
+ any(ip_range.get('CidrIp') == '0.0.0.0/0' for ip_range in rule.get('IpRanges', []))):
342
+ violations.append(f"Security Group {sg['GroupId']} ({sg['GroupName']})")
343
+
344
+ if violations:
345
+ compliance_result = ArchitectureComplianceResult(
346
+ framework="CIS",
347
+ control_id="4.2",
348
+ control_description="No security groups allow ingress from 0.0.0.0/0 to port 3389",
349
+ compliance_status="FAIL",
350
+ impact_level="HIGH",
351
+ findings=violations,
352
+ remediation_guidance="Restrict RDP access to specific IP ranges"
353
+ )
354
+ result.critical_findings.extend(violations)
355
+ else:
356
+ compliance_result = ArchitectureComplianceResult(
357
+ framework="CIS",
358
+ control_id="4.2",
359
+ control_description="No security groups allow ingress from 0.0.0.0/0 to port 3389",
360
+ compliance_status="PASS",
361
+ impact_level="HIGH"
362
+ )
363
+
364
+ result.compliance_results.append(compliance_result)
365
+ result.cis_benchmark_compliance["4.2"] = compliance_result.compliance_status
366
+
367
+ except ClientError as e:
368
+ print_warning(f"CIS 4.2 check failed: {e}")
369
+
370
+ def _check_cis_4_3_default_security_group(self, vpc_id: str, result: AWSO5ArchitectureValidationResult):
371
+ """Check CIS 4.3: Default security group restrictions."""
372
+ try:
373
+ response = self.ec2_client.describe_security_groups(
374
+ Filters=[
375
+ {'Name': 'vpc-id', 'Values': [vpc_id]},
376
+ {'Name': 'group-name', 'Values': ['default']}
377
+ ]
378
+ )
379
+
380
+ violations = []
381
+ for sg in response['SecurityGroups']:
382
+ if sg.get('IpPermissions') or sg.get('IpPermissionsEgress'):
383
+ # Default SG should have no rules
384
+ violations.append(f"Default Security Group {sg['GroupId']} has active rules")
385
+
386
+ if violations:
387
+ compliance_result = ArchitectureComplianceResult(
388
+ framework="CIS",
389
+ control_id="4.3",
390
+ control_description="Default security group restricts all traffic",
391
+ compliance_status="FAIL",
392
+ impact_level="MEDIUM",
393
+ findings=violations,
394
+ remediation_guidance="Remove all rules from default security group"
395
+ )
396
+ else:
397
+ compliance_result = ArchitectureComplianceResult(
398
+ framework="CIS",
399
+ control_id="4.3",
400
+ control_description="Default security group restricts all traffic",
401
+ compliance_status="PASS",
402
+ impact_level="MEDIUM"
403
+ )
404
+
405
+ result.compliance_results.append(compliance_result)
406
+ result.cis_benchmark_compliance["4.3"] = compliance_result.compliance_status
407
+
408
+ except ClientError as e:
409
+ print_warning(f"CIS 4.3 check failed: {e}")
410
+
411
+ def _check_cis_2_6_vpc_flow_logging(self, vpc_id: str, result: AWSO5ArchitectureValidationResult):
412
+ """Check CIS 2.6: VPC Flow Logs enabled."""
413
+ try:
414
+ response = self.ec2_client.describe_flow_logs(
415
+ Filters=[
416
+ {'Name': 'resource-id', 'Values': [vpc_id]},
417
+ {'Name': 'resource-type', 'Values': ['VPC']}
418
+ ]
419
+ )
420
+
421
+ active_flow_logs = [
422
+ fl for fl in response['FlowLogs']
423
+ if fl['FlowLogStatus'] == 'ACTIVE'
424
+ ]
425
+
426
+ if not active_flow_logs:
427
+ compliance_result = ArchitectureComplianceResult(
428
+ framework="CIS",
429
+ control_id="2.6",
430
+ control_description="VPC Flow Logging is enabled",
431
+ compliance_status="FAIL",
432
+ impact_level="MEDIUM",
433
+ findings=[f"VPC {vpc_id} has no active flow logs"],
434
+ remediation_guidance="Enable VPC Flow Logs for security monitoring"
435
+ )
436
+ else:
437
+ compliance_result = ArchitectureComplianceResult(
438
+ framework="CIS",
439
+ control_id="2.6",
440
+ control_description="VPC Flow Logging is enabled",
441
+ compliance_status="PASS",
442
+ impact_level="MEDIUM"
443
+ )
444
+
445
+ result.compliance_results.append(compliance_result)
446
+ result.cis_benchmark_compliance["2.6"] = compliance_result.compliance_status
447
+
448
+ except ClientError as e:
449
+ print_warning(f"CIS 2.6 check failed: {e}")
450
+
451
+ def _check_default_vpc_compliance(
452
+ self,
453
+ vpc_id: str,
454
+ vpc_info: Dict[str, Any],
455
+ result: AWSO5ArchitectureValidationResult
456
+ ):
457
+ """Special compliance checks for default VPCs."""
458
+
459
+ # Default VPC should be deleted per CIS recommendations
460
+ compliance_result = ArchitectureComplianceResult(
461
+ framework="CIS",
462
+ control_id="DEFAULT_VPC",
463
+ control_description="Default VPC should be removed to reduce attack surface",
464
+ compliance_status="FAIL",
465
+ impact_level="CRITICAL",
466
+ findings=[f"Default VPC {vpc_id} exists in region {self.region}"],
467
+ remediation_guidance="Delete default VPC to improve security posture and CIS compliance"
468
+ )
469
+
470
+ result.compliance_results.append(compliance_result)
471
+ result.cis_benchmark_compliance["DEFAULT_VPC"] = "FAIL"
472
+ result.critical_findings.append(f"Default VPC {vpc_id} requires deletion")
473
+ result.security_improvements.append("Default VPC elimination improves CIS Benchmark compliance")
474
+
475
+ def _validate_well_architected_framework(
476
+ self,
477
+ vpc_id: str,
478
+ vpc_info: Dict[str, Any],
479
+ result: AWSO5ArchitectureValidationResult
480
+ ):
481
+ """Validate against AWS Well-Architected Framework principles."""
482
+
483
+ # Security Pillar Assessment
484
+ security_score = self._assess_security_pillar(vpc_id, vpc_info, result)
485
+ result.well_architected_score["Security"] = security_score
486
+
487
+ # Reliability Pillar Assessment
488
+ reliability_score = self._assess_reliability_pillar(vpc_id, vpc_info, result)
489
+ result.well_architected_score["Reliability"] = reliability_score
490
+
491
+ # Performance Efficiency Assessment
492
+ performance_score = self._assess_performance_pillar(vpc_id, vpc_info, result)
493
+ result.well_architected_score["Performance"] = performance_score
494
+
495
+ # Cost Optimization Assessment
496
+ cost_score = self._assess_cost_pillar(vpc_id, vpc_info, result)
497
+ result.well_architected_score["Cost"] = cost_score
498
+
499
+ # Operational Excellence Assessment
500
+ ops_score = self._assess_operational_pillar(vpc_id, vpc_info, result)
501
+ result.well_architected_score["Operational"] = ops_score
502
+
503
+ def _assess_security_pillar(
504
+ self,
505
+ vpc_id: str,
506
+ vpc_info: Dict[str, Any],
507
+ result: AWSO5ArchitectureValidationResult
508
+ ) -> float:
509
+ """Assess Well-Architected Security Pillar."""
510
+
511
+ security_checks = []
512
+
513
+ # SEC-3: Apply security in depth principle
514
+ try:
515
+ # Check for NACLs and Security Groups
516
+ nacls = self.ec2_client.describe_network_acls(
517
+ Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}]
518
+ )['NetworkAcls']
519
+
520
+ sgs = self.ec2_client.describe_security_groups(
521
+ Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}]
522
+ )['SecurityGroups']
523
+
524
+ if len(nacls) > 1 or len(sgs) > 1: # More than just defaults
525
+ security_checks.append(("Defense in Depth", "PASS"))
526
+ else:
527
+ security_checks.append(("Defense in Depth", "FAIL"))
528
+
529
+ except ClientError:
530
+ security_checks.append(("Defense in Depth", "UNKNOWN"))
531
+
532
+ # SEC-9: Protect data in transit and at rest
533
+ if vpc_info.get('IsDefault', False):
534
+ security_checks.append(("Default VPC Security", "FAIL"))
535
+ result.security_improvements.append("Default VPC replacement improves data protection")
536
+ else:
537
+ security_checks.append(("Default VPC Security", "PASS"))
538
+
539
+ # Calculate security score
540
+ passed = len([check for check in security_checks if check[1] == "PASS"])
541
+ total = len(security_checks)
542
+ score = (passed / total * 100) if total > 0 else 0
543
+
544
+ # Add Well-Architected compliance result
545
+ compliance_result = ArchitectureComplianceResult(
546
+ framework="Well-Architected",
547
+ control_id="Security Pillar",
548
+ control_description="Security best practices implementation",
549
+ compliance_status="PASS" if score >= 80 else "WARNING" if score >= 60 else "FAIL",
550
+ impact_level="HIGH",
551
+ findings=[f"Security score: {score:.1f}% ({passed}/{total} checks passed)"],
552
+ remediation_guidance="Implement defense in depth and eliminate default VPCs"
553
+ )
554
+
555
+ result.compliance_results.append(compliance_result)
556
+
557
+ return score
558
+
559
+ def _assess_reliability_pillar(
560
+ self,
561
+ vpc_id: str,
562
+ vpc_info: Dict[str, Any],
563
+ result: AWSO5ArchitectureValidationResult
564
+ ) -> float:
565
+ """Assess Well-Architected Reliability Pillar."""
566
+
567
+ reliability_checks = []
568
+
569
+ # REL-1: Multi-AZ deployment capability
570
+ try:
571
+ subnets = self.ec2_client.describe_subnets(
572
+ Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}]
573
+ )['Subnets']
574
+
575
+ azs = set(subnet['AvailabilityZone'] for subnet in subnets)
576
+ if len(azs) >= 2:
577
+ reliability_checks.append(("Multi-AZ Support", "PASS"))
578
+ else:
579
+ reliability_checks.append(("Multi-AZ Support", "WARNING"))
580
+
581
+ except ClientError:
582
+ reliability_checks.append(("Multi-AZ Support", "UNKNOWN"))
583
+
584
+ # Calculate reliability score
585
+ passed = len([check for check in reliability_checks if check[1] == "PASS"])
586
+ total = len(reliability_checks)
587
+ score = (passed / total * 100) if total > 0 else 0
588
+
589
+ return score
590
+
591
+ def _assess_performance_pillar(
592
+ self,
593
+ vpc_id: str,
594
+ vpc_info: Dict[str, Any],
595
+ result: AWSO5ArchitectureValidationResult
596
+ ) -> float:
597
+ """Assess Well-Architected Performance Efficiency Pillar."""
598
+
599
+ performance_checks = []
600
+
601
+ # PERF-1: Network performance optimization
602
+ try:
603
+ # Check for VPC endpoints (reduce data transfer costs)
604
+ endpoints = self.ec2_client.describe_vpc_endpoints(
605
+ Filters=[{'Name': 'vpc-id', 'Values': [vpc_id]}]
606
+ )['VpcEndpoints']
607
+
608
+ if endpoints:
609
+ performance_checks.append(("VPC Endpoints Optimization", "PASS"))
610
+ else:
611
+ performance_checks.append(("VPC Endpoints Optimization", "WARNING"))
612
+
613
+ except ClientError:
614
+ performance_checks.append(("VPC Endpoints Optimization", "UNKNOWN"))
615
+
616
+ # Calculate performance score
617
+ passed = len([check for check in performance_checks if check[1] == "PASS"])
618
+ total = len(performance_checks)
619
+ score = (passed / total * 100) if total > 0 else 50 # Neutral score if no checks
620
+
621
+ return score
622
+
623
+ def _assess_cost_pillar(
624
+ self,
625
+ vpc_id: str,
626
+ vpc_info: Dict[str, Any],
627
+ result: AWSO5ArchitectureValidationResult
628
+ ) -> float:
629
+ """Assess Well-Architected Cost Optimization Pillar."""
630
+
631
+ cost_checks = []
632
+
633
+ # COST-1: Unused resource identification
634
+ if vpc_info.get('IsDefault', False):
635
+ cost_checks.append(("Default VPC Cost Impact", "FAIL"))
636
+ result.estimated_security_improvement += 25.0 # Monthly savings estimate
637
+ else:
638
+ cost_checks.append(("Default VPC Cost Impact", "PASS"))
639
+
640
+ # Calculate cost score
641
+ passed = len([check for check in cost_checks if check[1] == "PASS"])
642
+ total = len(cost_checks)
643
+ score = (passed / total * 100) if total > 0 else 0
644
+
645
+ return score
646
+
647
+ def _assess_operational_pillar(
648
+ self,
649
+ vpc_id: str,
650
+ vpc_info: Dict[str, Any],
651
+ result: AWSO5ArchitectureValidationResult
652
+ ) -> float:
653
+ """Assess Well-Architected Operational Excellence Pillar."""
654
+
655
+ ops_checks = []
656
+
657
+ # OPS-1: Infrastructure as Code usage
658
+ # This would require additional analysis of CloudFormation/Terraform
659
+ ops_checks.append(("Infrastructure as Code", "UNKNOWN"))
660
+
661
+ # Calculate operational score
662
+ score = 50 # Neutral score - requires additional IaC analysis
663
+
664
+ return score
665
+
666
+ def _analyze_security_posture(
667
+ self,
668
+ vpc_id: str,
669
+ vpc_info: Dict[str, Any],
670
+ result: AWSO5ArchitectureValidationResult
671
+ ):
672
+ """Comprehensive security posture analysis."""
673
+
674
+ # Security baseline checks
675
+ security_findings = []
676
+
677
+ # Default VPC security impact
678
+ if vpc_info.get('IsDefault', False):
679
+ security_findings.append("Default VPC presents increased attack surface")
680
+ security_findings.append("Default security groups may have overly permissive rules")
681
+ security_findings.append("Default infrastructure lacks security hardening")
682
+
683
+ result.security_improvements.extend([
684
+ "Default VPC elimination reduces attack surface by ~30%",
685
+ "Custom VPC implementation enables security best practices",
686
+ "Network segmentation improves compliance posture"
687
+ ])
688
+
689
+ def _assess_network_impact(
690
+ self,
691
+ vpc_id: str,
692
+ vpc_info: Dict[str, Any],
693
+ result: AWSO5ArchitectureValidationResult
694
+ ):
695
+ """Assess network topology impact of VPC cleanup."""
696
+
697
+ network_impact = {
698
+ 'connectivity_impact': 'NONE', # NONE, LOW, MEDIUM, HIGH
699
+ 'routing_changes_required': False,
700
+ 'cross_account_dependencies': [],
701
+ 'transit_gateway_impact': False,
702
+ 'peering_connections_affected': 0
703
+ }
704
+
705
+ try:
706
+ # Check for transit gateway attachments
707
+ tgw_attachments = self.ec2_client.describe_transit_gateway_attachments(
708
+ Filters=[
709
+ {'Name': 'resource-id', 'Values': [vpc_id]},
710
+ {'Name': 'resource-type', 'Values': ['vpc']}
711
+ ]
712
+ )['TransitGatewayAttachments']
713
+
714
+ if tgw_attachments:
715
+ network_impact['transit_gateway_impact'] = True
716
+ network_impact['connectivity_impact'] = 'HIGH'
717
+
718
+ # Check for VPC peering connections
719
+ peering_response = self.ec2_client.describe_vpc_peering_connections(
720
+ Filters=[
721
+ {'Name': 'accepter-vpc-info.vpc-id', 'Values': [vpc_id]}
722
+ ]
723
+ )
724
+ peering_response2 = self.ec2_client.describe_vpc_peering_connections(
725
+ Filters=[
726
+ {'Name': 'requester-vpc-info.vpc-id', 'Values': [vpc_id]}
727
+ ]
728
+ )
729
+
730
+ total_peering = len(peering_response['VpcPeeringConnections']) + len(peering_response2['VpcPeeringConnections'])
731
+ network_impact['peering_connections_affected'] = total_peering
732
+
733
+ if total_peering > 0:
734
+ if network_impact['connectivity_impact'] == 'NONE':
735
+ network_impact['connectivity_impact'] = 'MEDIUM'
736
+
737
+ except ClientError as e:
738
+ print_warning(f"Network impact assessment failed: {e}")
739
+
740
+ result.network_impact_assessment = network_impact
741
+
742
+ def _analyze_business_risk(
743
+ self,
744
+ vpc_id: str,
745
+ vpc_info: Dict[str, Any],
746
+ result: AWSO5ArchitectureValidationResult
747
+ ):
748
+ """Comprehensive business risk analysis."""
749
+
750
+ risk_factors = []
751
+ risk_level = "LOW"
752
+
753
+ # Default VPC risk assessment
754
+ if vpc_info.get('IsDefault', False):
755
+ risk_factors.append("Default VPC increases security risk")
756
+ risk_factors.append("Non-compliance with CIS Benchmark")
757
+ risk_factors.append("Potential audit findings")
758
+ risk_level = "MEDIUM"
759
+
760
+ # Network connectivity risk
761
+ if result.network_impact_assessment.get('connectivity_impact') == 'HIGH':
762
+ risk_factors.append("High network connectivity impact")
763
+ risk_level = "HIGH"
764
+ elif result.network_impact_assessment.get('connectivity_impact') == 'MEDIUM':
765
+ risk_factors.append("Medium network connectivity impact")
766
+ if risk_level == "LOW":
767
+ risk_level = "MEDIUM"
768
+
769
+ # Compliance risk
770
+ critical_failures = len([
771
+ cr for cr in result.compliance_results
772
+ if cr.compliance_status == "FAIL" and cr.impact_level == "CRITICAL"
773
+ ])
774
+
775
+ if critical_failures > 0:
776
+ risk_factors.append(f"{critical_failures} critical compliance failures")
777
+ risk_level = "HIGH"
778
+
779
+ result.business_risk_level = risk_level
780
+
781
+ def _calculate_security_posture_score(self, result: AWSO5ArchitectureValidationResult) -> float:
782
+ """Calculate comprehensive security posture score."""
783
+
784
+ # Base score from compliance results
785
+ compliance_score = result.overall_compliance_score
786
+
787
+ # Well-Architected security score
788
+ security_pillar_score = result.well_architected_score.get("Security", 0)
789
+
790
+ # Weighted combination
791
+ weighted_score = (compliance_score * 0.6) + (security_pillar_score * 0.4)
792
+
793
+ return weighted_score
794
+
795
+ def _generate_architecture_recommendation(self, result: AWSO5ArchitectureValidationResult):
796
+ """Generate architecture-based cleanup recommendation."""
797
+
798
+ # Decision logic based on multiple factors
799
+ if result.business_risk_level == "LOW" and result.overall_compliance_score >= 80:
800
+ result.architecture_recommendation = "DELETE"
801
+ elif result.business_risk_level == "MEDIUM" and result.overall_compliance_score >= 60:
802
+ if result.critical_findings:
803
+ result.architecture_recommendation = "DELETE_WITH_REMEDIATION"
804
+ else:
805
+ result.architecture_recommendation = "DELETE"
806
+ elif result.business_risk_level == "HIGH":
807
+ result.architecture_recommendation = "INVESTIGATE"
808
+ else:
809
+ result.architecture_recommendation = "HOLD"
810
+
811
+ def _display_validation_results(self, result: AWSO5ArchitectureValidationResult):
812
+ """Display comprehensive architecture validation results."""
813
+
814
+ # Summary table
815
+ summary_table = create_table(title="AWSO-5 Architecture Validation Summary")
816
+ summary_table.add_column("Metric", style="cyan", no_wrap=True)
817
+ summary_table.add_column("Score/Status", style="green")
818
+ summary_table.add_column("Impact", style="yellow")
819
+
820
+ summary_table.add_row("Overall Compliance Score", f"{result.overall_compliance_score:.1f}%", "")
821
+ summary_table.add_row("Security Posture Score", f"{result.security_posture_score:.1f}%", "")
822
+ summary_table.add_row("Business Risk Level", result.business_risk_level,
823
+ "Requires Review" if result.business_risk_level in ["HIGH", "CRITICAL"] else "Acceptable")
824
+ summary_table.add_row("Architecture Recommendation", result.architecture_recommendation, "")
825
+ summary_table.add_row("Critical Findings", str(len(result.critical_findings)),
826
+ "Action Required" if result.critical_findings else "None")
827
+
828
+ self.console.print("\n")
829
+ self.console.print(summary_table)
830
+
831
+ # Well-Architected Scores
832
+ if result.well_architected_score:
833
+ wa_table = create_table(title="AWS Well-Architected Framework Assessment")
834
+ wa_table.add_column("Pillar", style="cyan")
835
+ wa_table.add_column("Score", style="green")
836
+ wa_table.add_column("Status", style="yellow")
837
+
838
+ for pillar, score in result.well_architected_score.items():
839
+ status = "GOOD" if score >= 80 else "FAIR" if score >= 60 else "NEEDS IMPROVEMENT"
840
+ wa_table.add_row(pillar, f"{score:.1f}%", status)
841
+
842
+ self.console.print("\n")
843
+ self.console.print(wa_table)
844
+
845
+ # Critical Findings
846
+ if result.critical_findings:
847
+ self.console.print("\n[red]🚨 Critical Findings:[/red]")
848
+ for finding in result.critical_findings:
849
+ self.console.print(f" • {finding}")
850
+
851
+ # Security Improvements
852
+ if result.security_improvements:
853
+ self.console.print("\n[green]🔒 Security Improvements:[/green]")
854
+ for improvement in result.security_improvements:
855
+ self.console.print(f" • {improvement}")
856
+
857
+ # Architecture Recommendation
858
+ if result.architecture_recommendation == "DELETE":
859
+ status = "[green]✅ APPROVED FOR DELETION[/green]"
860
+ elif result.architecture_recommendation == "DELETE_WITH_REMEDIATION":
861
+ status = "[yellow]⚠️ DELETION WITH REMEDIATION[/yellow]"
862
+ elif result.architecture_recommendation == "INVESTIGATE":
863
+ status = "[red]🔍 REQUIRES INVESTIGATION[/red]"
864
+ else:
865
+ status = "[red]⛔ HOLD - DO NOT DELETE[/red]"
866
+
867
+ recommendation_text = f"""
868
+ {status}
869
+
870
+ **Risk Level:** {result.business_risk_level}
871
+ **Compliance Score:** {result.overall_compliance_score:.1f}%
872
+ **Security Posture:** {result.security_posture_score:.1f}%
873
+ **Estimated Security Improvement:** ${result.estimated_security_improvement:.2f}/month
874
+
875
+ **Next Steps:**
876
+ {self._get_architecture_next_steps(result)}
877
+ """
878
+
879
+ from rich.panel import Panel
880
+ recommendation_panel = Panel(
881
+ recommendation_text,
882
+ title="🏗️ Architecture Validation Recommendation",
883
+ border_style="blue"
884
+ )
885
+
886
+ self.console.print("\n")
887
+ self.console.print(recommendation_panel)
888
+
889
+ def _get_architecture_next_steps(self, result: AWSO5ArchitectureValidationResult) -> str:
890
+ """Generate architecture-specific next steps."""
891
+
892
+ if result.architecture_recommendation == "DELETE":
893
+ return "• Architecture validation PASSED\n• Proceed with VPC cleanup\n• Update compliance documentation"
894
+
895
+ elif result.architecture_recommendation == "DELETE_WITH_REMEDIATION":
896
+ return "• Address critical findings first\n• Implement security improvements\n• Re-validate architecture compliance"
897
+
898
+ elif result.architecture_recommendation == "INVESTIGATE":
899
+ return "• Detailed risk assessment required\n• Stakeholder consultation needed\n• Consider alternative remediation approaches"
900
+
901
+ else: # HOLD
902
+ return "• High-risk operation detected\n• Comprehensive architecture review required\n• Platform Lead consultation mandatory"
903
+
904
+
905
+ def validate_vpc_architecture_cli(
906
+ vpc_id: str,
907
+ profile: Optional[str] = None,
908
+ region: str = "us-east-1"
909
+ ) -> AWSO5ArchitectureValidationResult:
910
+ """
911
+ CLI wrapper for VPC architecture validation.
912
+
913
+ Args:
914
+ vpc_id: AWS VPC identifier
915
+ profile: AWS profile name
916
+ region: AWS region
917
+
918
+ Returns:
919
+ Comprehensive architecture validation results
920
+ """
921
+ session = boto3.Session(profile_name=profile) if profile else boto3.Session()
922
+ validator = AWSO5ArchitectureValidator(session=session, region=region)
923
+
924
+ return validator.validate_vpc_architecture(vpc_id)
925
+
926
+
927
+ if __name__ == "__main__":
928
+ import argparse
929
+
930
+ parser = argparse.ArgumentParser(description="AWSO-5 Architecture Validation")
931
+ parser.add_argument("--vpc-id", required=True, help="VPC ID to validate")
932
+ parser.add_argument("--profile", help="AWS profile name")
933
+ parser.add_argument("--region", default="us-east-1", help="AWS region")
934
+
935
+ args = parser.parse_args()
936
+
937
+ result = validate_vpc_architecture_cli(args.vpc_id, args.profile, args.region)
938
+
939
+ print_success(f"Architecture validation completed with {result.overall_compliance_score:.1f}% compliance score")