runbooks 1.1.5__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/cli/commands/inventory.py +21 -80
- runbooks/common/accuracy_validator.py +6 -12
- runbooks/common/mcp_integration.py +38 -7
- runbooks/common/rich_utils.py +116 -2
- runbooks/inventory/CLAUDE.md +1 -1
- 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/core/formatter.py +11 -0
- runbooks/inventory/draw_org_structure.py +8 -9
- 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_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_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 +5 -3
- runbooks/inventory/organizations_discovery.py +8 -4
- runbooks/inventory/recover_cfn_stack_ids.py +7 -8
- runbooks/inventory/requirements.txt +0 -1
- runbooks/inventory/rich_inventory_display.py +2 -2
- runbooks/inventory/run_on_multi_accounts.py +3 -5
- runbooks/inventory/unified_validation_engine.py +3 -2
- runbooks/inventory/verify_ec2_security_groups.py +1 -1
- runbooks/inventory/vpc_analyzer.py +3 -2
- runbooks/inventory/vpc_dependency_analyzer.py +2 -2
- runbooks/validation/terraform_drift_detector.py +16 -5
- {runbooks-1.1.5.dist-info → runbooks-1.1.6.dist-info}/METADATA +3 -4
- {runbooks-1.1.5.dist-info → runbooks-1.1.6.dist-info}/RECORD +62 -62
- {runbooks-1.1.5.dist-info → runbooks-1.1.6.dist-info}/WHEEL +0 -0
- {runbooks-1.1.5.dist-info → runbooks-1.1.6.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.5.dist-info → runbooks-1.1.6.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.5.dist-info → runbooks-1.1.6.dist-info}/top_level.txt +0 -0
@@ -7,15 +7,13 @@ from time import time
|
|
7
7
|
|
8
8
|
from ArgumentsClass import CommonArguments
|
9
9
|
from botocore.exceptions import ClientError
|
10
|
-
from
|
10
|
+
from runbooks.common.rich_utils import console
|
11
11
|
from Inventory_Modules import display_results, find_account_volumes2, get_all_credentials
|
12
|
-
from
|
12
|
+
from runbooks.common.rich_utils import create_progress_bar
|
13
13
|
|
14
|
-
init()
|
15
14
|
__version__ = "2024.05.31"
|
16
15
|
|
17
16
|
# ANSI escape code for clearing current line (progress bar cleanup)
|
18
|
-
ERASE_LINE = "\x1b[2K"
|
19
17
|
|
20
18
|
|
21
19
|
##################
|
@@ -92,7 +90,7 @@ def present_results(fVolumesFound: list):
|
|
92
90
|
# Calculate and display orphaned volumes
|
93
91
|
orphaned_volumes = [vol for vol in de_dupe_VolumesFound if vol.get("State") == "available"]
|
94
92
|
if orphaned_volumes:
|
95
|
-
print(f"
|
93
|
+
print(f"[yellow]Warning: {len(orphaned_volumes)} orphaned (unattached) volumes found")
|
96
94
|
total_orphaned_size = sum(vol.get("Size", 0) for vol in orphaned_volumes)
|
97
95
|
print(f"Total orphaned storage: {total_orphaned_size} GB")
|
98
96
|
|
@@ -136,9 +134,9 @@ def check_accounts_for_ebs_volumes(f_CredentialList, f_fragment_list=None):
|
|
136
134
|
continue
|
137
135
|
finally:
|
138
136
|
logging.info(
|
139
|
-
f"
|
137
|
+
f"Finished finding EBS volumes in account {c_account_credentials['AccountId']} in region {c_account_credentials['Region']}"
|
140
138
|
)
|
141
|
-
|
139
|
+
progress.update(task, advance=1)
|
142
140
|
self.queue.task_done()
|
143
141
|
|
144
142
|
if f_fragment_list is None:
|
@@ -148,32 +146,31 @@ def check_accounts_for_ebs_volumes(f_CredentialList, f_fragment_list=None):
|
|
148
146
|
|
149
147
|
checkqueue = Queue()
|
150
148
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
pbar.close()
|
149
|
+
with create_progress_bar() as progress:
|
150
|
+
task = progress.add_task(
|
151
|
+
f"Finding ebs volumes from {len(f_CredentialList)} accounts and regions",
|
152
|
+
total=len(f_CredentialList)
|
153
|
+
)
|
154
|
+
|
155
|
+
for x in range(WorkerThreads):
|
156
|
+
worker = FindVolumes(checkqueue)
|
157
|
+
# Setting daemon to True will let the main thread exit even though the workers are blocking
|
158
|
+
worker.daemon = True
|
159
|
+
worker.start()
|
160
|
+
|
161
|
+
for credential in f_CredentialList:
|
162
|
+
logging.info(f"Connecting to account {credential['AccountId']}")
|
163
|
+
try:
|
164
|
+
# print(f"Queuing account {credential['AccountId']} in region {region}", end='\r')
|
165
|
+
checkqueue.put((credential, credential["Region"], f_fragment_list))
|
166
|
+
except ClientError as my_Error:
|
167
|
+
if "AuthFailure" in str(my_Error):
|
168
|
+
logging.error(
|
169
|
+
f"Authorization Failure accessing account {credential['AccountId']} in '{credential['Region']}' region"
|
170
|
+
)
|
171
|
+
logging.warning(f"It's possible that the region '{credential['Region']}' hasn't been opted-into")
|
172
|
+
pass
|
173
|
+
checkqueue.join()
|
177
174
|
return AllVolumes
|
178
175
|
|
179
176
|
|
@@ -231,8 +228,8 @@ def main():
|
|
231
228
|
|
232
229
|
# Display execution timing if requested
|
233
230
|
if pTiming:
|
234
|
-
print(
|
235
|
-
print(f"
|
231
|
+
console.print()
|
232
|
+
print(f"[green]This script completed in {time() - begin_time:.2f} seconds")
|
236
233
|
|
237
234
|
|
238
235
|
if __name__ == "__main__":
|
@@ -62,13 +62,10 @@ from time import time
|
|
62
62
|
from . import inventory_modules as Inventory_Modules
|
63
63
|
from .ArgumentsClass import CommonArguments
|
64
64
|
from botocore.exceptions import ClientError
|
65
|
-
from colorama import Fore, init
|
66
65
|
from .inventory_modules import display_results, get_all_credentials
|
67
|
-
from
|
66
|
+
from runbooks.common.rich_utils import create_progress_bar
|
68
67
|
|
69
|
-
init()
|
70
68
|
__version__ = "2025.04.09"
|
71
|
-
ERASE_LINE = "\x1b[2K"
|
72
69
|
begin_time = time()
|
73
70
|
|
74
71
|
|
@@ -322,30 +319,28 @@ def find_all_instances(fAllCredentials: list, fStatus: str = None) -> list:
|
|
322
319
|
AllInstances = []
|
323
320
|
WorkerThreads = min(len(fAllCredentials), 25)
|
324
321
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
checkqueue.join()
|
348
|
-
pbar.close()
|
322
|
+
with create_progress_bar() as progress:
|
323
|
+
task = progress.add_task(f"Finding instances from {len(fAllCredentials)} locations", total=len(fAllCredentials))
|
324
|
+
|
325
|
+
for x in range(WorkerThreads):
|
326
|
+
worker = FindInstances(checkqueue)
|
327
|
+
# Setting daemon to True will let the main thread exit even though the workers are blocking
|
328
|
+
worker.daemon = True
|
329
|
+
worker.start()
|
330
|
+
|
331
|
+
for credential in fAllCredentials:
|
332
|
+
logging.info(f"Beginning to queue data - starting with {credential['AccountId']}")
|
333
|
+
try:
|
334
|
+
# I don't know why - but double parens are necessary below. If you remove them, only the first parameter is queued.
|
335
|
+
checkqueue.put((credential))
|
336
|
+
except ClientError as my_Error:
|
337
|
+
if "AuthFailure" in str(my_Error):
|
338
|
+
logging.error(
|
339
|
+
f"Authorization Failure accessing account {credential['AccountId']} in {credential['Region']} region"
|
340
|
+
)
|
341
|
+
logging.warning(f"It's possible that the region {credential['Region']} hasn't been opted-into")
|
342
|
+
pass
|
343
|
+
checkqueue.join()
|
349
344
|
return AllInstances
|
350
345
|
|
351
346
|
|
@@ -90,13 +90,11 @@ from time import time
|
|
90
90
|
import Inventory_Modules
|
91
91
|
from ArgumentsClass import CommonArguments
|
92
92
|
from botocore.exceptions import ClientError
|
93
|
-
from
|
93
|
+
from runbooks.common.rich_utils import console
|
94
94
|
from Inventory_Modules import display_results, find_account_ecs_clusters_services_and_tasks2, get_all_credentials
|
95
|
-
from
|
95
|
+
from runbooks.common.rich_utils import create_progress_bar
|
96
96
|
|
97
|
-
init()
|
98
97
|
__version__ = "2024.09.06"
|
99
|
-
ERASE_LINE = "\x1b[2K"
|
100
98
|
begin_time = time()
|
101
99
|
|
102
100
|
# TODO: Need a table at the bottom that summarizes the results, by instance-type, by running/ stopped, maybe by account and region
|
@@ -246,7 +244,7 @@ def find_all_clusters_and_tasks(fAllCredentials: list, fStatus: str = None) -> l
|
|
246
244
|
"""
|
247
245
|
while True:
|
248
246
|
# Retrieve ECS discovery work item from thread-safe queue
|
249
|
-
c_account_credentials = self.queue.get()
|
247
|
+
c_account_credentials, c_progress, c_task = self.queue.get()
|
250
248
|
logging.info(f"De-queued info for account number {c_account_credentials['AccountId']}")
|
251
249
|
|
252
250
|
try:
|
@@ -406,7 +404,7 @@ def find_all_clusters_and_tasks(fAllCredentials: list, fStatus: str = None) -> l
|
|
406
404
|
continue
|
407
405
|
finally:
|
408
406
|
# Ensure progress tracking and queue management regardless of success/failure
|
409
|
-
|
407
|
+
c_progress.update(c_task, advance=1)
|
410
408
|
self.queue.task_done()
|
411
409
|
|
412
410
|
###########
|
@@ -423,13 +421,6 @@ def find_all_clusters_and_tasks(fAllCredentials: list, fStatus: str = None) -> l
|
|
423
421
|
# Maximum 25 threads to prevent overwhelming AWS APIs while maintaining efficiency
|
424
422
|
WorkerThreads = min(len(fAllCredentials), 25)
|
425
423
|
|
426
|
-
# Initialize progress tracking for operational visibility during large-scale operations
|
427
|
-
pbar = tqdm(
|
428
|
-
desc=f"Finding ECS clusters, services and tasks from {len(fAllCredentials)} accounts / regions",
|
429
|
-
total=len(fAllCredentials),
|
430
|
-
unit=" locations",
|
431
|
-
)
|
432
|
-
|
433
424
|
# Start worker threads for concurrent ECS resource discovery
|
434
425
|
for x in range(WorkerThreads):
|
435
426
|
worker = FindInstances(checkqueue)
|
@@ -437,25 +428,26 @@ def find_all_clusters_and_tasks(fAllCredentials: list, fStatus: str = None) -> l
|
|
437
428
|
worker.daemon = True
|
438
429
|
worker.start()
|
439
430
|
|
440
|
-
# Queue credential sets for processing by worker threads
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
431
|
+
# Queue credential sets for processing by worker threads with progress tracking
|
432
|
+
with create_progress_bar() as progress:
|
433
|
+
task = progress.add_task("Discovering ECS clusters, services and tasks", total=len(fAllCredentials))
|
434
|
+
for credential in fAllCredentials:
|
435
|
+
logging.info(f"Beginning to queue data - starting with {credential['AccountId']}")
|
436
|
+
try:
|
437
|
+
# Queue individual credential set for ECS resource discovery with progress tracking
|
438
|
+
# Tuple format: (credential, progress, task)
|
439
|
+
checkqueue.put((credential, progress, task))
|
440
|
+
except ClientError as my_Error:
|
441
|
+
# Handle authorization failures during credential queuing
|
442
|
+
if "AuthFailure" in str(my_Error):
|
443
|
+
logging.error(
|
444
|
+
f"Authorization Failure accessing account {credential['AccountId']} in {credential['Region']} region"
|
445
|
+
)
|
446
|
+
logging.warning(f"It's possible that the region {credential['Region']} hasn't been opted-into")
|
447
|
+
pass
|
448
|
+
|
449
|
+
# Wait for all queued work to complete before proceeding
|
450
|
+
checkqueue.join()
|
459
451
|
return AllInstances
|
460
452
|
|
461
453
|
|
@@ -514,7 +506,7 @@ if __name__ == "__main__":
|
|
514
506
|
print()
|
515
507
|
milestone_time1 = time()
|
516
508
|
print(
|
517
|
-
f"
|
509
|
+
f"[green]\t\tCredential discovery and region enumeration took: {(milestone_time1 - begin_time):.3f} seconds"
|
518
510
|
)
|
519
511
|
print()
|
520
512
|
|
@@ -549,7 +541,7 @@ if __name__ == "__main__":
|
|
549
541
|
# Display performance timing metrics for operational optimization and SLA compliance
|
550
542
|
if pTiming:
|
551
543
|
print(ERASE_LINE)
|
552
|
-
print(f"
|
544
|
+
print(f"[green]This script took {time() - begin_time:.2f} seconds")
|
553
545
|
|
554
546
|
print(ERASE_LINE)
|
555
547
|
|
@@ -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()
|