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
@@ -88,13 +88,11 @@ from time import time
|
|
88
88
|
|
89
89
|
from ArgumentsClass import CommonArguments
|
90
90
|
from botocore.exceptions import ClientError
|
91
|
-
from
|
91
|
+
from runbooks.common.rich_utils import console
|
92
92
|
from Inventory_Modules import display_results, find_load_balancers2, get_all_credentials
|
93
|
-
from
|
93
|
+
from runbooks.common.rich_utils import create_progress_bar
|
94
94
|
|
95
|
-
init()
|
96
95
|
__version__ = "2024.05.06"
|
97
|
-
ERASE_LINE = "\x1b[2K"
|
98
96
|
begin_time = time()
|
99
97
|
|
100
98
|
|
@@ -306,20 +304,24 @@ def find_all_elbs(fAllCredentials: list, ffragment: list, fstatus: str):
|
|
306
304
|
worker.start()
|
307
305
|
|
308
306
|
# Queue credential sets with progress tracking for operational visibility
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
307
|
+
with create_progress_bar() as progress:
|
308
|
+
task = progress.add_task("Queueing ELB discovery tasks", total=len(fAllCredentials))
|
309
|
+
for credential in fAllCredentials:
|
310
|
+
logging.info(f"Beginning to queue data - starting with {credential['AccountId']}")
|
311
|
+
try:
|
312
|
+
# Queue credential set with fragment and status filters for targeted discovery
|
313
|
+
# Tuple format: (credentials, fragment_filter, status_filter)
|
314
|
+
checkqueue.put((credential, ffragment, fstatus))
|
315
|
+
except ClientError as my_Error:
|
316
|
+
# Handle authorization failures during credential queuing
|
317
|
+
if "AuthFailure" in str(my_Error):
|
318
|
+
logging.error(
|
319
|
+
f"Authorization Failure accessing account {credential['AccountId']} in {credential['Region']} region"
|
320
|
+
)
|
321
|
+
logging.warning(f"It's possible that the region {credential['Region']} hasn't been opted-into")
|
322
|
+
pass
|
323
|
+
finally:
|
324
|
+
progress.update(task, advance=1)
|
323
325
|
|
324
326
|
# Wait for all queued work to complete before proceeding
|
325
327
|
checkqueue.join()
|
@@ -396,13 +398,13 @@ if __name__ == "__main__":
|
|
396
398
|
# Display performance timing metrics for operational optimization and SLA compliance
|
397
399
|
if pTiming:
|
398
400
|
print(ERASE_LINE)
|
399
|
-
print(f"
|
401
|
+
print(f"[green]This script took {time() - begin_time:.2f} seconds")
|
400
402
|
|
401
403
|
print(ERASE_LINE)
|
402
404
|
|
403
405
|
# Display comprehensive operational summary for executive traffic management reporting
|
404
406
|
print(
|
405
|
-
f"
|
407
|
+
f"[red]Found {len(All_Load_Balancers)} Load Balancers across {AccountNum} profiles across {RegionNum} regions"
|
406
408
|
)
|
407
409
|
print()
|
408
410
|
|
@@ -96,11 +96,10 @@ from ArgumentsClass import CommonArguments
|
|
96
96
|
from botocore.exceptions import ClientError
|
97
97
|
|
98
98
|
# from datetime import datetime
|
99
|
-
from
|
99
|
+
from runbooks.common.rich_utils import console
|
100
100
|
from Inventory_Modules import display_results, find_account_enis2, get_all_credentials
|
101
|
-
from
|
101
|
+
from runbooks.common.rich_utils import create_progress_bar
|
102
102
|
|
103
|
-
init()
|
104
103
|
|
105
104
|
__version__ = "2024.10.24"
|
106
105
|
|
@@ -269,8 +268,8 @@ def check_accounts_for_enis(fCredentialList, fip=None, fPublicOnly: bool = False
|
|
269
268
|
"""
|
270
269
|
while True:
|
271
270
|
# Retrieve ENI discovery work item from thread-safe queue
|
272
|
-
c_account_credentials, c_region, c_fip, c_PlacesToLook, c_PlaceCount = self.queue.get()
|
273
|
-
|
271
|
+
c_account_credentials, c_region, c_fip, c_PlacesToLook, c_PlaceCount, c_progress, c_task = self.queue.get()
|
272
|
+
c_progress.update(c_task, advance=1) # Update progress tracking for operational visibility
|
274
273
|
logging.info(f"De-queued info for account {c_account_credentials['AccountId']}")
|
275
274
|
|
276
275
|
try:
|
@@ -323,13 +322,6 @@ def check_accounts_for_enis(fCredentialList, fip=None, fPublicOnly: bool = False
|
|
323
322
|
# Initialize queue-based threading architecture for scalable ENI discovery
|
324
323
|
checkqueue = Queue()
|
325
324
|
|
326
|
-
# Initialize progress tracking for operational visibility during large-scale operations
|
327
|
-
pbar = tqdm(
|
328
|
-
desc=f"Finding enis from {len(CredentialList)} accounts / regions",
|
329
|
-
total=len(fCredentialList),
|
330
|
-
unit=" locations",
|
331
|
-
)
|
332
|
-
|
333
325
|
# Initialize results list for aggregating discovered ENIs
|
334
326
|
Results = []
|
335
327
|
PlaceCount = 0
|
@@ -347,24 +339,26 @@ def check_accounts_for_enis(fCredentialList, fip=None, fPublicOnly: bool = False
|
|
347
339
|
worker.start()
|
348
340
|
|
349
341
|
# Queue credential sets for processing by worker threads
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
342
|
+
with create_progress_bar() as progress:
|
343
|
+
task = progress.add_task("Discovering ENIs", total=len(fCredentialList))
|
344
|
+
for credential in fCredentialList:
|
345
|
+
logging.info(f"Connecting to account {credential['AccountId']} in region {credential['Region']}")
|
346
|
+
try:
|
347
|
+
# Queue credential set with IP filter and progress tracking parameters
|
348
|
+
# Tuple format: (credentials, region, ip_filter, total_places, current_count, progress, task)
|
349
|
+
checkqueue.put((credential, credential["Region"], fip, PlacesToLook, PlaceCount, progress, task))
|
350
|
+
PlaceCount += 1
|
351
|
+
except ClientError as my_Error:
|
352
|
+
# Handle authorization failures during credential queuing
|
353
|
+
if "AuthFailure" in str(my_Error):
|
354
|
+
logging.error(
|
355
|
+
f"Authorization Failure accessing account {credential['AccountId']} in {credential['Region']} region"
|
356
|
+
)
|
357
|
+
logging.warning(f"It's possible that the region {credential['Region']} hasn't been opted-into")
|
358
|
+
pass
|
359
|
+
|
360
|
+
# Wait for all queued work to complete before proceeding
|
361
|
+
checkqueue.join()
|
368
362
|
return Results
|
369
363
|
|
370
364
|
|
@@ -450,7 +444,7 @@ def present_results(f_ENIsFound: list):
|
|
450
444
|
|
451
445
|
# Highlight cost optimization opportunities with unused ENI identification
|
452
446
|
print(
|
453
|
-
f"
|
447
|
+
f"[red]Found {len(DetachedENIs)} ENIs that are not listed as 'in-use' and may therefore be costing you additional money while they're unused."
|
454
448
|
) if DetachedENIs else ""
|
455
449
|
print()
|
456
450
|
|
@@ -464,7 +458,6 @@ def present_results(f_ENIsFound: list):
|
|
464
458
|
# Main execution entry point for enterprise ENI discovery and network security analysis
|
465
459
|
##################
|
466
460
|
|
467
|
-
ERASE_LINE = "\x1b[2K"
|
468
461
|
|
469
462
|
if __name__ == "__main__":
|
470
463
|
"""
|
@@ -518,7 +511,7 @@ if __name__ == "__main__":
|
|
518
511
|
|
519
512
|
# Display performance timing metrics for operational optimization and SLA compliance
|
520
513
|
if pTiming:
|
521
|
-
print(f"
|
514
|
+
print(f"[green]This script took {time() - begin_time:.2f} seconds")
|
522
515
|
|
523
516
|
# Display completion message for user confirmation and operational closure
|
524
517
|
print()
|
@@ -95,10 +95,9 @@ import Inventory_Modules
|
|
95
95
|
from account_class import aws_acct_access
|
96
96
|
from ArgumentsClass import CommonArguments
|
97
97
|
from botocore.exceptions import ClientError
|
98
|
-
from
|
98
|
+
from runbooks.common.rich_utils import console
|
99
99
|
from Inventory_Modules import get_all_credentials
|
100
100
|
|
101
|
-
init()
|
102
101
|
__version__ = "2023.07.18"
|
103
102
|
|
104
103
|
# Parse enterprise command-line arguments with GuardDuty-specific security management options
|
@@ -150,7 +149,6 @@ logging.getLogger("urllib3").setLevel(logging.CRITICAL)
|
|
150
149
|
# Initialize enterprise GuardDuty discovery and security management operations
|
151
150
|
##########################
|
152
151
|
|
153
|
-
ERASE_LINE = "\x1b[2K"
|
154
152
|
|
155
153
|
# Initialize AWS account access for GuardDuty administrative operations
|
156
154
|
aws_acct = aws_acct_access(pProfile)
|
@@ -337,7 +335,7 @@ for credential in AllCredentials:
|
|
337
335
|
# Display progress for accounts without GuardDuty detectors for operational visibility
|
338
336
|
print(
|
339
337
|
ERASE_LINE,
|
340
|
-
f"
|
338
|
+
f"[red]No luck in account: {credential['AccountId']} in region {credential['Region']} -- {places_to_try} of {len(AllCredentials)}",
|
341
339
|
end="\r",
|
342
340
|
)
|
343
341
|
except ClientError as my_Error:
|
@@ -94,12 +94,10 @@ from time import time
|
|
94
94
|
|
95
95
|
from ArgumentsClass import CommonArguments
|
96
96
|
from botocore.exceptions import ClientError
|
97
|
-
from
|
97
|
+
from runbooks.common.rich_utils import console
|
98
98
|
from Inventory_Modules import display_results, find_account_policies2, find_policy_action2, get_all_credentials
|
99
99
|
|
100
|
-
init()
|
101
100
|
__version__ = "2023.12.12"
|
102
|
-
ERASE_LINE = "\x1b[2K"
|
103
101
|
begin_time = time()
|
104
102
|
|
105
103
|
|
@@ -392,7 +390,7 @@ if __name__ == "__main__":
|
|
392
390
|
|
393
391
|
if pTiming:
|
394
392
|
print(ERASE_LINE)
|
395
|
-
print(f"
|
393
|
+
print(f"[green]This script took {time() - begin_time:.2f} seconds")
|
396
394
|
print(f"These accounts were skipped - as requested: {pSkipAccounts}") if pSkipAccounts is not None else print()
|
397
395
|
print()
|
398
396
|
print(
|
@@ -43,10 +43,9 @@ from time import sleep, time
|
|
43
43
|
import boto3
|
44
44
|
from ArgumentsClass import CommonArguments
|
45
45
|
from botocore.exceptions import ClientError
|
46
|
-
from colorama import Fore, init
|
47
46
|
from Inventory_Modules import display_results, find_in, get_all_credentials
|
47
|
+
from runbooks.common.rich_utils import console
|
48
48
|
|
49
|
-
init()
|
50
49
|
__version__ = "2023.11.06"
|
51
50
|
|
52
51
|
|
@@ -249,8 +248,8 @@ def find_and_collect_roles_across_accounts(fAllCredentials: list, frole_fragment
|
|
249
248
|
print(f"Listing out all roles across {len(fAllCredentials)} accounts")
|
250
249
|
print()
|
251
250
|
elif pExact:
|
252
|
-
print(
|
253
|
-
f"Looking for a role
|
251
|
+
console.print(
|
252
|
+
f"Looking for a role [red]exactly[/red] named one of these strings {frole_fragments} across {len(fAllCredentials)} accounts"
|
254
253
|
)
|
255
254
|
print()
|
256
255
|
else:
|
@@ -475,7 +474,6 @@ if __name__ == "__main__":
|
|
475
474
|
logging.getLogger("s3transfer").setLevel(logging.CRITICAL)
|
476
475
|
logging.getLogger("urllib3").setLevel(logging.CRITICAL)
|
477
476
|
|
478
|
-
ERASE_LINE = "\x1b[2K"
|
479
477
|
time_to_sleep = 5
|
480
478
|
begin_time = time()
|
481
479
|
|
@@ -511,8 +509,8 @@ if __name__ == "__main__":
|
|
511
509
|
)
|
512
510
|
|
513
511
|
if pTiming:
|
514
|
-
print(
|
515
|
-
print(f"
|
512
|
+
console.print()
|
513
|
+
console.print(f"[green]This script took {time() - begin_time:.2f} seconds[/green]")
|
516
514
|
print()
|
517
515
|
print("Thanks for using this script...")
|
518
516
|
print()
|
@@ -101,14 +101,12 @@ import boto3
|
|
101
101
|
from account_class import aws_acct_access
|
102
102
|
from ArgumentsClass import CommonArguments
|
103
103
|
from botocore.exceptions import ClientError
|
104
|
-
from
|
104
|
+
from runbooks.common.rich_utils import console
|
105
105
|
from Inventory_Modules import display_results, find_saml_components_in_acct2, get_child_access3
|
106
106
|
|
107
|
-
init()
|
108
107
|
__version__ = "2024.03.27"
|
109
108
|
|
110
109
|
begin_time = time()
|
111
|
-
ERASE_LINE = "\x1b[2K"
|
112
110
|
|
113
111
|
|
114
112
|
##################
|
@@ -254,7 +252,7 @@ def all_my_saml_providers(faws_acct: aws_acct_access, fChildAccounts: list, f_ac
|
|
254
252
|
idpNum = len(Idps)
|
255
253
|
logging.info(f"Account: {account['AccountId']} | Region: {pRegion} | Found {idpNum} Idps")
|
256
254
|
logging.info(
|
257
|
-
f"{ERASE_LINE}
|
255
|
+
f"{ERASE_LINE}[red]Account: {account['AccountId']} pRegion: {pRegion} Found {idpNum} Idps."
|
258
256
|
)
|
259
257
|
|
260
258
|
# Process discovered identity providers and extract metadata
|
@@ -342,7 +340,7 @@ if __name__ == "__main__":
|
|
342
340
|
RegionsFound = list(set([x["Region"] for x in IdpsFound]))
|
343
341
|
print()
|
344
342
|
print(
|
345
|
-
f"
|
343
|
+
f"[red]Found {len(IdpsFound)} Idps across {len(AccountsFound)} accounts in {len(RegionsFound)} regions"
|
346
344
|
)
|
347
345
|
print()
|
348
346
|
|
@@ -353,7 +351,7 @@ if __name__ == "__main__":
|
|
353
351
|
|
354
352
|
print()
|
355
353
|
if pTiming:
|
356
|
-
print(f"
|
354
|
+
print(f"[green]This script took {time() - begin_time:.2f} seconds")
|
357
355
|
print()
|
358
356
|
print("Thanks for using this script...")
|
359
357
|
print()
|
@@ -82,14 +82,12 @@ import boto3
|
|
82
82
|
import Inventory_Modules
|
83
83
|
from ArgumentsClass import CommonArguments
|
84
84
|
from botocore.exceptions import ClientError
|
85
|
-
from
|
85
|
+
from runbooks.common.rich_utils import console
|
86
86
|
from Inventory_Modules import display_results, get_all_credentials
|
87
|
-
from
|
87
|
+
from runbooks.common.rich_utils import create_progress_bar
|
88
88
|
|
89
|
-
init()
|
90
89
|
__version__ = "2024.06.05"
|
91
90
|
|
92
|
-
ERASE_LINE = "\x1b[2K"
|
93
91
|
begin_time = time()
|
94
92
|
|
95
93
|
|
@@ -497,7 +495,6 @@ def check_accounts_for_functions(CredentialList, fFragments=None):
|
|
497
495
|
while True:
|
498
496
|
# Retrieve account credentials and fragment filters from thread-safe work queue
|
499
497
|
c_account_credentials, c_fragment_list = self.queue.get()
|
500
|
-
pbar.update() # Update progress bar for operational visibility
|
501
498
|
Functions = []
|
502
499
|
logging.info(f"De-queued info for account {c_account_credentials['AccountId']}")
|
503
500
|
try:
|
@@ -543,6 +540,9 @@ def check_accounts_for_functions(CredentialList, fFragments=None):
|
|
543
540
|
# Thread-safe aggregation of discovered Lambda functions
|
544
541
|
AllFuncs.extend(Functions)
|
545
542
|
|
543
|
+
# Update progress bar for operational visibility
|
544
|
+
progress.update(task, advance=1)
|
545
|
+
|
546
546
|
# Signal task completion for thread-safe work queue management
|
547
547
|
self.queue.task_done()
|
548
548
|
|
@@ -556,40 +556,40 @@ def check_accounts_for_functions(CredentialList, fFragments=None):
|
|
556
556
|
checkqueue = Queue()
|
557
557
|
|
558
558
|
# Initialize progress tracking for operational visibility during discovery
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
# Initialize multi-threaded Lambda function discovery worker pool
|
566
|
-
for x in range(WorkerThreads):
|
567
|
-
worker = FindFunctions(checkqueue)
|
568
|
-
# Enable graceful shutdown with main thread termination for enterprise operational safety
|
569
|
-
worker.daemon = True
|
570
|
-
worker.start() # Begin concurrent Lambda function discovery processing
|
559
|
+
with create_progress_bar() as progress:
|
560
|
+
task = progress.add_task(
|
561
|
+
f"Finding instances from {len(CredentialList)} accounts / regions",
|
562
|
+
total=len(CredentialList)
|
563
|
+
)
|
571
564
|
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
f"Authorization Failure accessing account {credential['AccountId']} in {credential['Region']} region"
|
565
|
+
# Initialize multi-threaded Lambda function discovery worker pool
|
566
|
+
for x in range(WorkerThreads):
|
567
|
+
worker = FindFunctions(checkqueue)
|
568
|
+
# Enable graceful shutdown with main thread termination for enterprise operational safety
|
569
|
+
worker.daemon = True
|
570
|
+
worker.start() # Begin concurrent Lambda function discovery processing
|
571
|
+
|
572
|
+
# Populate work queue with account credentials for distributed serverless discovery
|
573
|
+
for credential in CredentialList:
|
574
|
+
logging.info(f"Connecting to account {credential['AccountId']}")
|
575
|
+
try:
|
576
|
+
# Log work queue population for operational audit trail
|
577
|
+
logging.info(
|
578
|
+
f"{ERASE_LINE}Queuing account {credential['AccountId']} in region {credential['Region']}", end="\r"
|
587
579
|
)
|
588
|
-
|
589
|
-
|
580
|
+
# Add credential and fragment filter to processing queue
|
581
|
+
checkqueue.put((credential, fFragments))
|
582
|
+
except ClientError as my_Error:
|
583
|
+
# Handle AWS API authorization failures during queue population
|
584
|
+
if "AuthFailure" in str(my_Error):
|
585
|
+
logging.error(
|
586
|
+
f"Authorization Failure accessing account {credential['AccountId']} in {credential['Region']} region"
|
587
|
+
)
|
588
|
+
logging.error(f"It's possible that the region {credential['Region']} hasn't been opted-into")
|
589
|
+
pass # Continue processing remaining accounts despite individual failures
|
590
590
|
|
591
|
-
|
592
|
-
|
591
|
+
# Wait for all Lambda function discovery tasks to complete before result aggregation
|
592
|
+
checkqueue.join()
|
593
593
|
|
594
594
|
# Return comprehensive Lambda function inventory with enterprise serverless metadata
|
595
595
|
return AllFuncs
|
@@ -744,7 +744,7 @@ def fix_my_functions(fAllFunctions, fRuntime, fNewRuntime, fForceDelete, fTiming
|
|
744
744
|
if fTiming:
|
745
745
|
print(ERASE_LINE)
|
746
746
|
print(
|
747
|
-
f"
|
747
|
+
f"[green]Fixing {len(return_response)} functions took {time() - begin_fix_time:.3f} seconds"
|
748
748
|
)
|
749
749
|
|
750
750
|
# Return operation results for enterprise reporting and audit trail
|
@@ -869,7 +869,7 @@ if __name__ == "__main__":
|
|
869
869
|
# Display performance timing metrics for operational optimization and SLA compliance
|
870
870
|
if pTiming:
|
871
871
|
print(ERASE_LINE)
|
872
|
-
print(f"
|
872
|
+
print(f"[green]This script took {time() - begin_time:.3f} seconds")
|
873
873
|
|
874
874
|
print(ERASE_LINE)
|
875
875
|
|
@@ -71,12 +71,10 @@ from time import time
|
|
71
71
|
from ArgumentsClass import CommonArguments
|
72
72
|
|
73
73
|
# from botocore.exceptions import ClientError, NoCredentialsError, InvalidConfigError
|
74
|
-
from
|
74
|
+
from runbooks.common.rich_utils import console
|
75
75
|
from Inventory_Modules import display_results, get_org_accounts_from_profiles, get_profiles
|
76
76
|
|
77
|
-
init()
|
78
77
|
__version__ = "2024.05.08"
|
79
|
-
ERASE_LINE = "\x1b[2K"
|
80
78
|
begin_time = time()
|
81
79
|
|
82
80
|
|
@@ -251,7 +249,7 @@ def all_my_orgs(
|
|
251
249
|
# Print out the results
|
252
250
|
if f_Timing:
|
253
251
|
print()
|
254
|
-
print(f"It's taken {
|
252
|
+
print(f"It's taken [green]{time() - begin_time:.2f} seconds to find profile accounts...")
|
255
253
|
print()
|
256
254
|
fmt = "%-23s %-15s %-15s %-12s %-10s"
|
257
255
|
print("<------------------------------------>")
|
@@ -278,7 +276,7 @@ def all_my_orgs(
|
|
278
276
|
else:
|
279
277
|
logging.info(f"{item['profile']} was successful.")
|
280
278
|
print(
|
281
|
-
f"{Fore.RED if item['RootAcct'] else ''}{item['profile']:23s} {item['aws_acct'].acct_number:15s} {item['MgmtAccount']:15s} {str(item['OrgId']):12s} {item['RootAcct']}
|
279
|
+
f"{Fore.RED if item['RootAcct'] else ''}{item['profile']:23s} {item['aws_acct'].acct_number:15s} {item['MgmtAccount']:15s} {str(item['OrgId']):12s} {item['RootAcct']}"
|
282
280
|
)
|
283
281
|
except TypeError as my_Error:
|
284
282
|
logging.error(f"Error - {my_Error} on {item}")
|
@@ -339,14 +337,14 @@ def all_my_orgs(
|
|
339
337
|
for item in AllProfileAccounts:
|
340
338
|
if item["Success"] and item["RootAcct"]:
|
341
339
|
print(
|
342
|
-
f"{item['profile']:{ProfileNameLength}s} {
|
340
|
+
f"{item['profile']:{ProfileNameLength}s} [bold]{item['MgmtAccount']:15s}"
|
343
341
|
)
|
344
342
|
print(
|
345
343
|
f"\t{'Child Account Number':{len('Child Account Number')}s} {'Child Account Status':{len('Child Account Status')}s} {'Child Email Address'}"
|
346
344
|
)
|
347
345
|
for child_acct in item["aws_acct"].ChildAccounts:
|
348
346
|
print(
|
349
|
-
f"\t{Fore.RED if not child_acct['AccountStatus'] == 'ACTIVE' else ''}{child_acct['AccountId']:{len('Child Account Number')}s} {child_acct['AccountStatus']:{len('Child Account Status')}s} {child_acct['AccountEmail']}
|
347
|
+
f"\t{Fore.RED if not child_acct['AccountStatus'] == 'ACTIVE' else ''}{child_acct['AccountId']:{len('Child Account Number')}s} {child_acct['AccountStatus']:{len('Child Account Status')}s} {child_acct['AccountEmail']}"
|
350
348
|
)
|
351
349
|
|
352
350
|
elif f_SaveFilename is not None:
|
@@ -440,7 +438,7 @@ if __name__ == "__main__":
|
|
440
438
|
|
441
439
|
print()
|
442
440
|
if pTiming:
|
443
|
-
print(f"
|
441
|
+
print(f"[green]This script took {time() - begin_time:.2f} seconds")
|
444
442
|
print()
|
445
443
|
print("Thanks for using this script")
|
446
444
|
print()
|
@@ -97,7 +97,7 @@ from time import time
|
|
97
97
|
|
98
98
|
from ArgumentsClass import CommonArguments
|
99
99
|
from botocore.exceptions import ClientError
|
100
|
-
from
|
100
|
+
from runbooks.common.rich_utils import console
|
101
101
|
from Inventory_Modules import (
|
102
102
|
display_results,
|
103
103
|
find_iam_users2,
|
@@ -105,11 +105,10 @@ from Inventory_Modules import (
|
|
105
105
|
find_idc_users2,
|
106
106
|
get_all_credentials,
|
107
107
|
)
|
108
|
-
|
108
|
+
# Migrated to Rich.Progress - see rich_utils.py for enterprise UX standards
|
109
|
+
# from tqdm.auto import tqdm
|
109
110
|
|
110
|
-
init()
|
111
111
|
__version__ = "2024.05.09"
|
112
|
-
ERASE_LINE = "\x1b[2K"
|
113
112
|
begin_time = time()
|
114
113
|
|
115
114
|
|
@@ -253,46 +252,58 @@ def find_all_org_users(f_credentials, f_IDC: bool, f_IAM: bool) -> list:
|
|
253
252
|
User_List = []
|
254
253
|
directories_seen = set()
|
255
254
|
|
255
|
+
# Import Rich display utilities for professional progress tracking
|
256
|
+
from runbooks.common.rich_utils import create_progress_bar
|
257
|
+
|
256
258
|
# TODO: Enhance with multi-threading for improved performance across large organizations
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
logging
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
logging
|
259
|
+
with create_progress_bar() as progress:
|
260
|
+
task = progress.add_task(
|
261
|
+
f"[cyan]Looking for users across {len(f_credentials)} Accounts...",
|
262
|
+
total=len(f_credentials)
|
263
|
+
)
|
264
|
+
|
265
|
+
for credential in f_credentials:
|
266
|
+
# Skip credentials that failed validation
|
267
|
+
if not credential["Success"]:
|
268
|
+
logging.info(f"{credential['ErrorMessage']} with roles: {credential['RolesTried']}")
|
269
|
+
progress.update(task, advance=1)
|
270
|
+
continue
|
271
|
+
|
272
|
+
# Discover traditional IAM users if requested
|
273
|
+
if f_IAM:
|
274
|
+
try:
|
275
|
+
# Call inventory module to discover IAM users in this account
|
276
|
+
User_List.extend(find_iam_users2(credential))
|
277
|
+
# Optional verbose logging for user discovery progress (currently commented)
|
278
|
+
# logging.info(f"{ERASE_LINE}Account: {credential['AccountId']} Found {len(User_List)} users")
|
279
|
+
except ClientError as my_Error:
|
280
|
+
# Handle IAM API authorization failures gracefully
|
281
|
+
if "AuthFailure" in str(my_Error):
|
282
|
+
logging.error(f"{ERASE_LINE}{credential}: Authorization Failure")
|
283
|
+
|
284
|
+
# Discover AWS Identity Center users if requested
|
285
|
+
if f_IDC:
|
286
|
+
try:
|
287
|
+
# Find out if this account hosts an Identity Center with a user directory
|
288
|
+
directory_ids = find_idc_directory_id2(credential)
|
289
|
+
for directory_instance_id in directory_ids:
|
290
|
+
# Directory deduplication: if we've already interrogated this directory, skip it
|
291
|
+
if directory_instance_id in directories_seen:
|
292
|
+
continue
|
293
|
+
else:
|
294
|
+
# Mark this directory as processed and discover users
|
295
|
+
directories_seen.update(directory_ids)
|
296
|
+
User_List.extend(find_idc_users2(credential, directory_instance_id))
|
297
|
+
# Optional verbose logging for user discovery progress (currently commented)
|
298
|
+
# logging.info(f"{ERASE_LINE}Account: {credential['AccountId']} Found {len(User_List)} users")
|
299
|
+
except ClientError as my_Error:
|
300
|
+
# Handle Identity Center API authorization failures gracefully
|
301
|
+
if "AuthFailure" in str(my_Error):
|
302
|
+
logging.error(f"{ERASE_LINE}{credential}: Authorization Failure")
|
303
|
+
|
304
|
+
# Update progress after processing each credential
|
305
|
+
progress.update(task, advance=1)
|
306
|
+
|
296
307
|
return User_List
|
297
308
|
|
298
309
|
|
@@ -344,7 +355,7 @@ if __name__ == "__main__":
|
|
344
355
|
display_results(sorted_UserListing, display_dict, "N/A", pFilename)
|
345
356
|
if pTiming:
|
346
357
|
print(ERASE_LINE)
|
347
|
-
print(f"
|
358
|
+
print(f"[green]This script took {time() - begin_time:.2f} seconds")
|
348
359
|
print(ERASE_LINE)
|
349
360
|
print(
|
350
361
|
f"Found {len(UserListing)} users across {len(SuccessfulAccountAccesses)} account{'' if len(SuccessfulAccountAccesses) == 1 else 's'}"
|