runbooks 1.0.0__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- runbooks/__init__.py +1 -1
- runbooks/cfat/WEIGHT_CONFIG_README.md +368 -0
- runbooks/cfat/app.ts +27 -19
- runbooks/cfat/assessment/runner.py +6 -5
- runbooks/cfat/tests/test_weight_configuration.ts +449 -0
- runbooks/cfat/weight_config.ts +574 -0
- runbooks/cloudops/models.py +20 -14
- runbooks/common/__init__.py +26 -9
- runbooks/common/aws_pricing.py +1070 -105
- runbooks/common/aws_pricing_api.py +276 -44
- runbooks/common/date_utils.py +115 -0
- runbooks/common/dry_run_examples.py +587 -0
- runbooks/common/dry_run_framework.py +520 -0
- runbooks/common/enhanced_exception_handler.py +10 -7
- runbooks/common/mcp_cost_explorer_integration.py +5 -4
- runbooks/common/memory_optimization.py +533 -0
- runbooks/common/performance_optimization_engine.py +1153 -0
- runbooks/common/profile_utils.py +86 -118
- runbooks/common/rich_utils.py +3 -3
- runbooks/common/sre_performance_suite.py +574 -0
- runbooks/finops/business_case_config.py +314 -0
- runbooks/finops/cost_processor.py +19 -4
- runbooks/finops/dashboard_runner.py +47 -28
- runbooks/finops/ebs_cost_optimizer.py +1 -1
- runbooks/finops/ebs_optimizer.py +56 -9
- runbooks/finops/embedded_mcp_validator.py +642 -36
- runbooks/finops/enhanced_trend_visualization.py +7 -2
- runbooks/finops/executive_export.py +789 -0
- runbooks/finops/finops_dashboard.py +6 -5
- runbooks/finops/finops_scenarios.py +34 -27
- runbooks/finops/iam_guidance.py +6 -1
- runbooks/finops/nat_gateway_optimizer.py +46 -27
- runbooks/finops/notebook_utils.py +1 -1
- runbooks/finops/schemas.py +73 -58
- runbooks/finops/single_dashboard.py +20 -4
- runbooks/finops/tests/test_integration.py +3 -1
- runbooks/finops/vpc_cleanup_exporter.py +2 -1
- runbooks/finops/vpc_cleanup_optimizer.py +22 -29
- runbooks/inventory/core/collector.py +51 -28
- runbooks/inventory/discovery.md +197 -247
- runbooks/inventory/inventory_modules.py +2 -2
- runbooks/inventory/list_ec2_instances.py +3 -3
- runbooks/inventory/models/account.py +5 -3
- runbooks/inventory/models/inventory.py +1 -1
- runbooks/inventory/models/resource.py +5 -3
- runbooks/inventory/organizations_discovery.py +102 -13
- runbooks/inventory/unified_validation_engine.py +2 -15
- runbooks/main.py +255 -92
- runbooks/operate/base.py +9 -6
- runbooks/operate/deployment_framework.py +5 -4
- runbooks/operate/deployment_validator.py +6 -5
- runbooks/operate/mcp_integration.py +6 -5
- runbooks/operate/networking_cost_heatmap.py +17 -13
- runbooks/operate/vpc_operations.py +82 -13
- runbooks/remediation/base.py +3 -1
- runbooks/remediation/commons.py +5 -5
- runbooks/remediation/commvault_ec2_analysis.py +66 -18
- runbooks/remediation/config/accounts_example.json +31 -0
- runbooks/remediation/multi_account.py +120 -7
- runbooks/remediation/remediation_cli.py +710 -0
- runbooks/remediation/universal_account_discovery.py +377 -0
- runbooks/remediation/workspaces_list.py +2 -2
- runbooks/security/compliance_automation_engine.py +99 -20
- runbooks/security/config/__init__.py +24 -0
- runbooks/security/config/compliance_config.py +255 -0
- runbooks/security/config/compliance_weights_example.json +22 -0
- runbooks/security/config_template_generator.py +500 -0
- runbooks/security/security_cli.py +377 -0
- runbooks/validation/cli.py +8 -7
- runbooks/validation/comprehensive_2way_validator.py +26 -15
- runbooks/validation/mcp_validator.py +62 -8
- runbooks/vpc/config.py +49 -15
- runbooks/vpc/cross_account_session.py +5 -1
- runbooks/vpc/heatmap_engine.py +438 -59
- runbooks/vpc/mcp_no_eni_validator.py +115 -36
- runbooks/vpc/performance_optimized_analyzer.py +546 -0
- runbooks/vpc/runbooks_adapter.py +33 -12
- runbooks/vpc/tests/conftest.py +4 -2
- runbooks/vpc/tests/test_cost_engine.py +3 -1
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/METADATA +1 -1
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/RECORD +85 -79
- runbooks/finops/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/finops/runbooks.security.report_generator.log +0 -0
- runbooks/finops/runbooks.security.run_script.log +0 -0
- runbooks/finops/runbooks.security.security_export.log +0 -0
- runbooks/finops/tests/results_test_finops_dashboard.xml +0 -1
- runbooks/inventory/artifacts/scale-optimize-status.txt +0 -12
- runbooks/inventory/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/inventory/runbooks.security.report_generator.log +0 -0
- runbooks/inventory/runbooks.security.run_script.log +0 -0
- runbooks/inventory/runbooks.security.security_export.log +0 -0
- runbooks/vpc/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/vpc/runbooks.security.report_generator.log +0 -0
- runbooks/vpc/runbooks.security.run_script.log +0 -0
- runbooks/vpc/runbooks.security.security_export.log +0 -0
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/WHEEL +0 -0
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/entry_points.txt +0 -0
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/top_level.txt +0 -0
@@ -338,31 +338,39 @@ class NOENIVPCMCPValidator:
|
|
338
338
|
- ≥99.5% accuracy scoring
|
339
339
|
"""
|
340
340
|
|
341
|
-
def __init__(self,
|
341
|
+
def __init__(self, user_profile: Optional[str] = None, console: Console = None):
|
342
342
|
"""
|
343
|
-
Initialize NO-ENI VPC MCP validator.
|
343
|
+
Initialize NO-ENI VPC MCP validator with universal profile support.
|
344
344
|
|
345
345
|
Args:
|
346
|
-
|
347
|
-
{'MANAGEMENT': 'profile1', 'BILLING': 'profile2', 'CENTRALISED_OPS': 'profile3'}
|
346
|
+
user_profile: User-specified profile (from --profile parameter)
|
348
347
|
console: Rich console for output
|
349
348
|
"""
|
350
|
-
|
349
|
+
# Import universal profile management
|
350
|
+
from ..common.profile_utils import (
|
351
|
+
get_profile_for_operation,
|
352
|
+
get_available_profiles_for_validation
|
353
|
+
)
|
354
|
+
|
355
|
+
self.user_profile = user_profile
|
351
356
|
self.console = console or Console()
|
352
357
|
self.validation_cache: Dict[str, Any] = {}
|
353
358
|
self.cache_ttl = 300 # 5 minutes cache TTL
|
354
359
|
self.accuracy_threshold = 99.5 # Enterprise accuracy target
|
355
360
|
|
356
|
-
#
|
361
|
+
# Universal profile detection - NO HARDCODED PROFILES
|
362
|
+
self.profiles = self._detect_universal_profiles()
|
363
|
+
|
364
|
+
# Initialize MCP interfaces for each detected profile
|
357
365
|
self.mcp_interfaces = {}
|
358
|
-
for profile_type, profile_name in profiles.items():
|
366
|
+
for profile_type, profile_name in self.profiles.items():
|
359
367
|
try:
|
360
368
|
self.mcp_interfaces[profile_type] = MCPServerInterface(profile_name, self.console)
|
361
369
|
print_success(f"MCP interface initialized for {profile_type}: {profile_name}")
|
362
370
|
except Exception as e:
|
363
371
|
print_error(f"Failed to initialize MCP interface for {profile_type}: {e}")
|
364
372
|
|
365
|
-
print_header("NO-ENI VPC MCP Validator", "
|
373
|
+
print_header("NO-ENI VPC MCP Validator", "Universal Profile Architecture")
|
366
374
|
print_info(f"Initialized with {len(self.mcp_interfaces)} profile interfaces")
|
367
375
|
|
368
376
|
# Initialize Organizations discovery engine for dynamic account discovery
|
@@ -378,7 +386,49 @@ class NOENIVPCMCPValidator:
|
|
378
386
|
print_success("Organizations discovery engine initialized for dynamic account discovery")
|
379
387
|
except Exception as e:
|
380
388
|
print_warning(f"Organizations discovery initialization failed: {e}")
|
381
|
-
print_info("Will use
|
389
|
+
print_info("Will use profile-based discovery instead")
|
390
|
+
|
391
|
+
def _detect_universal_profiles(self) -> Dict[str, str]:
|
392
|
+
"""
|
393
|
+
Detect available profiles using universal three-tier priority system.
|
394
|
+
|
395
|
+
Returns:
|
396
|
+
Dictionary mapping profile types to actual profile names
|
397
|
+
"""
|
398
|
+
from ..common.profile_utils import get_profile_for_operation
|
399
|
+
|
400
|
+
detected_profiles = {}
|
401
|
+
|
402
|
+
# Universal profile detection - supports any AWS configuration
|
403
|
+
profile_types = ['management', 'billing', 'operational']
|
404
|
+
|
405
|
+
for profile_type in profile_types:
|
406
|
+
try:
|
407
|
+
profile_name = get_profile_for_operation(profile_type, self.user_profile)
|
408
|
+
# Convert to uppercase for compatibility with existing code
|
409
|
+
profile_key = profile_type.upper()
|
410
|
+
if profile_type == 'operational':
|
411
|
+
profile_key = 'CENTRALISED_OPS'
|
412
|
+
|
413
|
+
detected_profiles[profile_key] = profile_name
|
414
|
+
print_info(f"Detected {profile_key} profile: {profile_name}")
|
415
|
+
|
416
|
+
except Exception as e:
|
417
|
+
print_warning(f"Could not detect profile for {profile_type}: {e}")
|
418
|
+
|
419
|
+
# Ensure we have at least one profile for validation
|
420
|
+
if not detected_profiles:
|
421
|
+
import boto3
|
422
|
+
available_profiles = boto3.Session().available_profiles
|
423
|
+
if available_profiles:
|
424
|
+
fallback_profile = available_profiles[0]
|
425
|
+
detected_profiles['MANAGEMENT'] = fallback_profile
|
426
|
+
print_warning(f"Using fallback profile for validation: {fallback_profile}")
|
427
|
+
else:
|
428
|
+
detected_profiles['MANAGEMENT'] = 'default'
|
429
|
+
print_warning("Using 'default' profile as last resort")
|
430
|
+
|
431
|
+
return detected_profiles
|
382
432
|
|
383
433
|
async def validate_no_eni_vpcs_comprehensive(self, region: str = 'ap-southeast-2') -> ValidationEvidence:
|
384
434
|
"""
|
@@ -551,7 +601,9 @@ class NOENIVPCMCPValidator:
|
|
551
601
|
# Check for SSO token issues specifically
|
552
602
|
if 'does not exist' in error_msg or 'KeyError' in error_msg or 'JSONDecodeError' in error_msg:
|
553
603
|
print_warning("🔐 AWS SSO token issue detected")
|
554
|
-
|
604
|
+
import os
|
605
|
+
management_profile = os.getenv("MANAGEMENT_PROFILE", "your-management-profile")
|
606
|
+
print_info(f"💡 Fix: Run 'aws sso login --profile {management_profile}'")
|
555
607
|
|
556
608
|
print_warning(f"Organizations discovery failed: {error_msg}")
|
557
609
|
print_info("🔄 Falling back to single profile mode")
|
@@ -1226,12 +1278,28 @@ were used - all results reflect actual AWS infrastructure state.
|
|
1226
1278
|
consistency_panel = self._create_consistency_panel(evidence.cross_profile_consistency)
|
1227
1279
|
self.console.print(consistency_panel)
|
1228
1280
|
|
1229
|
-
#
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1281
|
+
# Universal Account Validation - works with ANY AWS setup
|
1282
|
+
# Get actual account IDs from sessions instead of hardcoded values
|
1283
|
+
discovered_accounts = set()
|
1284
|
+
for candidate in evidence.vpc_candidates:
|
1285
|
+
discovered_accounts.add(candidate.account_id)
|
1286
|
+
|
1287
|
+
# Create dynamic expected results based on discovered accounts
|
1288
|
+
expected_results = {}
|
1289
|
+
for profile_type in self.profiles:
|
1290
|
+
# Get account ID for this profile type
|
1291
|
+
try:
|
1292
|
+
mcp_interface = self.mcp_interfaces.get(profile_type)
|
1293
|
+
if mcp_interface:
|
1294
|
+
sts_client = mcp_interface.session.client('sts')
|
1295
|
+
identity = sts_client.get_caller_identity()
|
1296
|
+
account_id = identity['Account']
|
1297
|
+
expected_results[profile_type] = {
|
1298
|
+
'account': account_id,
|
1299
|
+
'expected_no_eni': 'any' # Universal - accept any valid result
|
1300
|
+
}
|
1301
|
+
except Exception:
|
1302
|
+
pass # Skip profiles that can't be validated
|
1235
1303
|
|
1236
1304
|
validation_status = self._validate_against_expected_results(evidence, expected_results)
|
1237
1305
|
|
@@ -1276,7 +1344,7 @@ were used - all results reflect actual AWS infrastructure state.
|
|
1276
1344
|
)
|
1277
1345
|
|
1278
1346
|
def _validate_against_expected_results(self, evidence: ValidationEvidence, expected: Dict[str, Any]) -> str:
|
1279
|
-
"""Validate results against
|
1347
|
+
"""Validate results against dynamic profile outcomes (universal compatibility)."""
|
1280
1348
|
|
1281
1349
|
validation_results = []
|
1282
1350
|
overall_passed = True
|
@@ -1295,19 +1363,31 @@ were used - all results reflect actual AWS infrastructure state.
|
|
1295
1363
|
account_candidates = [c for c in actual_candidates if c.account_id == expected_account]
|
1296
1364
|
actual_count = len(account_candidates)
|
1297
1365
|
|
1298
|
-
|
1299
|
-
if
|
1300
|
-
|
1366
|
+
# Universal validation - accept any valid result for 'any' expectation
|
1367
|
+
if expected_count == 'any':
|
1368
|
+
status = "✅ VALIDATED"
|
1369
|
+
validation_summary = f"Found {actual_count} NO-ENI VPCs"
|
1370
|
+
else:
|
1371
|
+
status = "✅ PASSED" if actual_count == expected_count else "❌ FAILED"
|
1372
|
+
if actual_count != expected_count and expected_count != 'any':
|
1373
|
+
overall_passed = False
|
1374
|
+
validation_summary = f"Expected: {expected_count}, Found: {actual_count}"
|
1301
1375
|
|
1302
1376
|
validation_results.append(
|
1303
1377
|
f"[bold {self._get_profile_color(profile_type)}]{profile_type}[/bold {self._get_profile_color(profile_type)}]: "
|
1304
|
-
f"Account {expected_account} →
|
1378
|
+
f"Account {expected_account} → {validation_summary} {status}"
|
1305
1379
|
)
|
1306
1380
|
|
1307
|
-
# Overall validation status
|
1308
|
-
|
1381
|
+
# Overall validation status - more forgiving for universal compatibility
|
1382
|
+
if not expected:
|
1383
|
+
overall_status = "✅ UNIVERSAL COMPATIBILITY - NO SPECIFIC EXPECTATIONS"
|
1384
|
+
elif overall_passed:
|
1385
|
+
overall_status = "✅ ALL VALIDATIONS PASSED"
|
1386
|
+
else:
|
1387
|
+
overall_status = "⚠️ SOME VALIDATIONS REQUIRE REVIEW"
|
1388
|
+
|
1309
1389
|
validation_results.append("")
|
1310
|
-
validation_results.append(f"[bold
|
1390
|
+
validation_results.append(f"[bold green]Overall Status: {overall_status}[/bold green]")
|
1311
1391
|
|
1312
1392
|
return "\n".join(validation_results)
|
1313
1393
|
|
@@ -1484,20 +1564,13 @@ were used - all results reflect actual AWS infrastructure state.
|
|
1484
1564
|
|
1485
1565
|
|
1486
1566
|
# CLI Entry Point for Testing
|
1487
|
-
async def main():
|
1567
|
+
async def main(user_profile: Optional[str] = None):
|
1488
1568
|
"""CLI entry point for NO-ENI VPC MCP validation with dynamic discovery."""
|
1489
1569
|
|
1490
|
-
|
1491
|
-
enterprise_profiles = {
|
1492
|
-
'MANAGEMENT': 'ams-admin-ReadOnlyAccess-909135376185',
|
1493
|
-
'BILLING': 'ams-admin-Billing-ReadOnlyAccess-909135376185',
|
1494
|
-
'CENTRALISED_OPS': 'ams-centralised-ops-ReadOnlyAccess-335083429030'
|
1495
|
-
}
|
1570
|
+
print_header("🎯 NO-ENI VPC Dynamic Discovery", "Universal Profile Architecture")
|
1496
1571
|
|
1497
|
-
|
1498
|
-
|
1499
|
-
# Initialize validator
|
1500
|
-
validator = NOENIVPCMCPValidator(enterprise_profiles)
|
1572
|
+
# Initialize validator with universal profile detection
|
1573
|
+
validator = NOENIVPCMCPValidator(user_profile)
|
1501
1574
|
|
1502
1575
|
# Run dynamic discovery across all accounts
|
1503
1576
|
print_info("🌐 Starting dynamic NO-ENI VPC discovery across all AWS accounts...")
|
@@ -1548,4 +1621,10 @@ async def main():
|
|
1548
1621
|
|
1549
1622
|
|
1550
1623
|
if __name__ == "__main__":
|
1551
|
-
|
1624
|
+
import argparse
|
1625
|
+
|
1626
|
+
parser = argparse.ArgumentParser(description="NO-ENI VPC MCP Validation with Universal Profile Support")
|
1627
|
+
parser.add_argument('--profile', help='AWS profile to use (overrides environment variables)')
|
1628
|
+
args = parser.parse_args()
|
1629
|
+
|
1630
|
+
asyncio.run(main(args.profile))
|