runbooks 0.2.3__py3-none-any.whl → 0.6.1__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.
- conftest.py +26 -0
- jupyter-agent/.env.template +2 -0
- jupyter-agent/.gitattributes +35 -0
- jupyter-agent/README.md +16 -0
- jupyter-agent/app.py +256 -0
- jupyter-agent/cloudops-agent.png +0 -0
- jupyter-agent/ds-system-prompt.txt +154 -0
- jupyter-agent/jupyter-agent.png +0 -0
- jupyter-agent/llama3_template.jinja +123 -0
- jupyter-agent/requirements.txt +9 -0
- jupyter-agent/utils.py +409 -0
- runbooks/__init__.py +71 -3
- runbooks/__main__.py +13 -0
- runbooks/aws/ec2_describe_instances.py +1 -1
- runbooks/aws/ec2_run_instances.py +8 -2
- runbooks/aws/ec2_start_stop_instances.py +17 -4
- runbooks/aws/ec2_unused_volumes.py +5 -1
- runbooks/aws/s3_create_bucket.py +4 -2
- runbooks/aws/s3_list_objects.py +6 -1
- runbooks/aws/tagging_lambda_handler.py +13 -2
- runbooks/aws/tags.json +12 -0
- runbooks/base.py +353 -0
- runbooks/cfat/README.md +49 -0
- runbooks/cfat/__init__.py +74 -0
- runbooks/cfat/app.ts +644 -0
- runbooks/cfat/assessment/__init__.py +40 -0
- runbooks/cfat/assessment/asana-import.csv +39 -0
- runbooks/cfat/assessment/cfat-checks.csv +31 -0
- runbooks/cfat/assessment/cfat.txt +520 -0
- runbooks/cfat/assessment/collectors.py +200 -0
- runbooks/cfat/assessment/jira-import.csv +39 -0
- runbooks/cfat/assessment/runner.py +387 -0
- runbooks/cfat/assessment/validators.py +290 -0
- runbooks/cfat/cli.py +103 -0
- runbooks/cfat/docs/asana-import.csv +24 -0
- runbooks/cfat/docs/cfat-checks.csv +31 -0
- runbooks/cfat/docs/cfat.txt +335 -0
- runbooks/cfat/docs/checks-output.png +0 -0
- runbooks/cfat/docs/cloudshell-console-run.png +0 -0
- runbooks/cfat/docs/cloudshell-download.png +0 -0
- runbooks/cfat/docs/cloudshell-output.png +0 -0
- runbooks/cfat/docs/downloadfile.png +0 -0
- runbooks/cfat/docs/jira-import.csv +24 -0
- runbooks/cfat/docs/open-cloudshell.png +0 -0
- runbooks/cfat/docs/report-header.png +0 -0
- runbooks/cfat/models.py +1026 -0
- runbooks/cfat/package-lock.json +5116 -0
- runbooks/cfat/package.json +38 -0
- runbooks/cfat/report.py +496 -0
- runbooks/cfat/reporting/__init__.py +46 -0
- runbooks/cfat/reporting/exporters.py +337 -0
- runbooks/cfat/reporting/formatters.py +496 -0
- runbooks/cfat/reporting/templates.py +135 -0
- runbooks/cfat/run-assessment.sh +23 -0
- runbooks/cfat/runner.py +69 -0
- runbooks/cfat/src/actions/check-cloudtrail-existence.ts +43 -0
- runbooks/cfat/src/actions/check-config-existence.ts +37 -0
- runbooks/cfat/src/actions/check-control-tower.ts +37 -0
- runbooks/cfat/src/actions/check-ec2-existence.ts +46 -0
- runbooks/cfat/src/actions/check-iam-users.ts +50 -0
- runbooks/cfat/src/actions/check-legacy-cur.ts +30 -0
- runbooks/cfat/src/actions/check-org-cloudformation.ts +30 -0
- runbooks/cfat/src/actions/check-vpc-existence.ts +43 -0
- runbooks/cfat/src/actions/create-asanaimport.ts +14 -0
- runbooks/cfat/src/actions/create-backlog.ts +372 -0
- runbooks/cfat/src/actions/create-jiraimport.ts +15 -0
- runbooks/cfat/src/actions/create-report.ts +616 -0
- runbooks/cfat/src/actions/define-account-type.ts +51 -0
- runbooks/cfat/src/actions/get-enabled-org-policy-types.ts +40 -0
- runbooks/cfat/src/actions/get-enabled-org-services.ts +26 -0
- runbooks/cfat/src/actions/get-idc-info.ts +34 -0
- runbooks/cfat/src/actions/get-org-da-accounts.ts +34 -0
- runbooks/cfat/src/actions/get-org-details.ts +35 -0
- runbooks/cfat/src/actions/get-org-member-accounts.ts +44 -0
- runbooks/cfat/src/actions/get-org-ous.ts +35 -0
- runbooks/cfat/src/actions/get-regions.ts +22 -0
- runbooks/cfat/src/actions/zip-assessment.ts +27 -0
- runbooks/cfat/src/types/index.d.ts +147 -0
- runbooks/cfat/tests/__init__.py +141 -0
- runbooks/cfat/tests/test_cli.py +340 -0
- runbooks/cfat/tests/test_integration.py +290 -0
- runbooks/cfat/tests/test_models.py +505 -0
- runbooks/cfat/tests/test_reporting.py +354 -0
- runbooks/cfat/tsconfig.json +16 -0
- runbooks/cfat/webpack.config.cjs +27 -0
- runbooks/config.py +260 -0
- runbooks/finops/__init__.py +88 -0
- runbooks/finops/aws_client.py +245 -0
- runbooks/finops/cli.py +151 -0
- runbooks/finops/cost_processor.py +410 -0
- runbooks/finops/dashboard_runner.py +448 -0
- runbooks/finops/helpers.py +355 -0
- runbooks/finops/main.py +14 -0
- runbooks/finops/profile_processor.py +174 -0
- runbooks/finops/types.py +66 -0
- runbooks/finops/visualisations.py +80 -0
- runbooks/inventory/.gitignore +354 -0
- runbooks/inventory/ArgumentsClass.py +261 -0
- runbooks/inventory/Inventory_Modules.py +6130 -0
- runbooks/inventory/LandingZone/delete_lz.py +1075 -0
- runbooks/inventory/README.md +1320 -0
- runbooks/inventory/__init__.py +62 -0
- runbooks/inventory/account_class.py +532 -0
- runbooks/inventory/all_my_instances_wrapper.py +123 -0
- runbooks/inventory/aws_decorators.py +201 -0
- runbooks/inventory/cfn_move_stack_instances.py +1526 -0
- runbooks/inventory/check_cloudtrail_compliance.py +614 -0
- runbooks/inventory/check_controltower_readiness.py +1107 -0
- runbooks/inventory/check_landingzone_readiness.py +711 -0
- runbooks/inventory/cloudtrail.md +727 -0
- runbooks/inventory/collectors/__init__.py +20 -0
- runbooks/inventory/collectors/aws_compute.py +518 -0
- runbooks/inventory/collectors/aws_networking.py +275 -0
- runbooks/inventory/collectors/base.py +222 -0
- runbooks/inventory/core/__init__.py +19 -0
- runbooks/inventory/core/collector.py +303 -0
- runbooks/inventory/core/formatter.py +296 -0
- runbooks/inventory/delete_s3_buckets_objects.py +169 -0
- runbooks/inventory/discovery.md +81 -0
- runbooks/inventory/draw_org_structure.py +748 -0
- runbooks/inventory/ec2_vpc_utils.py +341 -0
- runbooks/inventory/find_cfn_drift_detection.py +272 -0
- runbooks/inventory/find_cfn_orphaned_stacks.py +719 -0
- runbooks/inventory/find_cfn_stackset_drift.py +733 -0
- runbooks/inventory/find_ec2_security_groups.py +669 -0
- runbooks/inventory/find_landingzone_versions.py +201 -0
- runbooks/inventory/find_vpc_flow_logs.py +1221 -0
- runbooks/inventory/inventory.sh +659 -0
- runbooks/inventory/list_cfn_stacks.py +558 -0
- runbooks/inventory/list_cfn_stackset_operation_results.py +252 -0
- runbooks/inventory/list_cfn_stackset_operations.py +734 -0
- runbooks/inventory/list_cfn_stacksets.py +453 -0
- runbooks/inventory/list_config_recorders_delivery_channels.py +681 -0
- runbooks/inventory/list_ds_directories.py +354 -0
- runbooks/inventory/list_ec2_availability_zones.py +286 -0
- runbooks/inventory/list_ec2_ebs_volumes.py +244 -0
- runbooks/inventory/list_ec2_instances.py +425 -0
- runbooks/inventory/list_ecs_clusters_and_tasks.py +562 -0
- runbooks/inventory/list_elbs_load_balancers.py +411 -0
- runbooks/inventory/list_enis_network_interfaces.py +526 -0
- runbooks/inventory/list_guardduty_detectors.py +568 -0
- runbooks/inventory/list_iam_policies.py +404 -0
- runbooks/inventory/list_iam_roles.py +518 -0
- runbooks/inventory/list_iam_saml_providers.py +359 -0
- runbooks/inventory/list_lambda_functions.py +882 -0
- runbooks/inventory/list_org_accounts.py +446 -0
- runbooks/inventory/list_org_accounts_users.py +354 -0
- runbooks/inventory/list_rds_db_instances.py +406 -0
- runbooks/inventory/list_route53_hosted_zones.py +318 -0
- runbooks/inventory/list_servicecatalog_provisioned_products.py +575 -0
- runbooks/inventory/list_sns_topics.py +360 -0
- runbooks/inventory/list_ssm_parameters.py +402 -0
- runbooks/inventory/list_vpc_subnets.py +433 -0
- runbooks/inventory/list_vpcs.py +422 -0
- runbooks/inventory/lockdown_cfn_stackset_role.py +224 -0
- runbooks/inventory/models/__init__.py +24 -0
- runbooks/inventory/models/account.py +192 -0
- runbooks/inventory/models/inventory.py +309 -0
- runbooks/inventory/models/resource.py +247 -0
- runbooks/inventory/recover_cfn_stack_ids.py +205 -0
- runbooks/inventory/requirements.txt +12 -0
- runbooks/inventory/run_on_multi_accounts.py +211 -0
- runbooks/inventory/tests/common_test_data.py +3661 -0
- runbooks/inventory/tests/common_test_functions.py +204 -0
- runbooks/inventory/tests/script_test_data.py +0 -0
- runbooks/inventory/tests/setup.py +24 -0
- runbooks/inventory/tests/src.py +18 -0
- runbooks/inventory/tests/test_cfn_describe_stacks.py +208 -0
- runbooks/inventory/tests/test_ec2_describe_instances.py +162 -0
- runbooks/inventory/tests/test_inventory_modules.py +55 -0
- runbooks/inventory/tests/test_lambda_list_functions.py +86 -0
- runbooks/inventory/tests/test_moto_integration_example.py +273 -0
- runbooks/inventory/tests/test_org_list_accounts.py +49 -0
- runbooks/inventory/update_aws_actions.py +173 -0
- runbooks/inventory/update_cfn_stacksets.py +1215 -0
- runbooks/inventory/update_cloudwatch_logs_retention_policy.py +294 -0
- runbooks/inventory/update_iam_roles_cross_accounts.py +478 -0
- runbooks/inventory/update_s3_public_access_block.py +539 -0
- runbooks/inventory/utils/__init__.py +23 -0
- runbooks/inventory/utils/aws_helpers.py +510 -0
- runbooks/inventory/utils/threading_utils.py +493 -0
- runbooks/inventory/utils/validation.py +682 -0
- runbooks/inventory/verify_ec2_security_groups.py +1430 -0
- runbooks/main.py +785 -0
- runbooks/organizations/__init__.py +12 -0
- runbooks/organizations/manager.py +374 -0
- runbooks/security_baseline/README.md +324 -0
- runbooks/security_baseline/checklist/alternate_contacts.py +8 -1
- runbooks/security_baseline/checklist/bucket_public_access.py +4 -1
- runbooks/security_baseline/checklist/cloudwatch_alarm_configuration.py +9 -2
- runbooks/security_baseline/checklist/guardduty_enabled.py +9 -2
- runbooks/security_baseline/checklist/multi_region_instance_usage.py +5 -1
- runbooks/security_baseline/checklist/root_access_key.py +6 -1
- runbooks/security_baseline/config-origin.json +1 -1
- runbooks/security_baseline/config.json +1 -1
- runbooks/security_baseline/permission.json +1 -1
- runbooks/security_baseline/report_generator.py +10 -2
- runbooks/security_baseline/report_template_en.html +8 -8
- runbooks/security_baseline/report_template_jp.html +8 -8
- runbooks/security_baseline/report_template_kr.html +13 -13
- runbooks/security_baseline/report_template_vn.html +8 -8
- runbooks/security_baseline/requirements.txt +7 -0
- runbooks/security_baseline/run_script.py +8 -2
- runbooks/security_baseline/security_baseline_tester.py +10 -2
- runbooks/security_baseline/utils/common.py +5 -1
- runbooks/utils/__init__.py +204 -0
- runbooks-0.6.1.dist-info/METADATA +373 -0
- runbooks-0.6.1.dist-info/RECORD +237 -0
- {runbooks-0.2.3.dist-info → runbooks-0.6.1.dist-info}/WHEEL +1 -1
- runbooks-0.6.1.dist-info/entry_points.txt +7 -0
- runbooks-0.6.1.dist-info/licenses/LICENSE +201 -0
- runbooks-0.6.1.dist-info/top_level.txt +3 -0
- runbooks/python101/calculator.py +0 -34
- runbooks/python101/config.py +0 -1
- runbooks/python101/exceptions.py +0 -16
- runbooks/python101/file_manager.py +0 -218
- runbooks/python101/toolkit.py +0 -153
- runbooks-0.2.3.dist-info/METADATA +0 -435
- runbooks-0.2.3.dist-info/RECORD +0 -61
- runbooks-0.2.3.dist-info/entry_points.txt +0 -3
- runbooks-0.2.3.dist-info/top_level.txt +0 -1
@@ -0,0 +1,354 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
"""
|
4
|
+
AWS Directory Service (DS) Directory Discovery and Inventory Script
|
5
|
+
|
6
|
+
This enterprise-grade script provides comprehensive discovery and enumeration of AWS Directory
|
7
|
+
Service (DS) directories across multi-account AWS Organizations environments. Designed for
|
8
|
+
infrastructure teams managing Microsoft Active Directory and Simple AD deployments at scale,
|
9
|
+
offering detailed directory metadata extraction, status analysis, and regional distribution
|
10
|
+
visibility for enterprise identity and access management governance.
|
11
|
+
|
12
|
+
Key Features:
|
13
|
+
- Multi-account, multi-region Directory Service directory discovery
|
14
|
+
- Comprehensive directory metadata extraction including status, type, and ownership
|
15
|
+
- Fragment-based filtering for targeted directory identification and management
|
16
|
+
- Enterprise governance support with organizational context and compliance tracking
|
17
|
+
- Regional directory distribution analysis for operational planning and optimization
|
18
|
+
- Progress tracking and performance metrics for large-scale directory discovery operations
|
19
|
+
|
20
|
+
Authentication & Access:
|
21
|
+
- AWS Organizations support for centralized directory service management
|
22
|
+
- Cross-account role assumption for organizational directory visibility
|
23
|
+
- Regional validation and opt-in status verification for directory service availability
|
24
|
+
- Profile-based authentication with comprehensive credential management
|
25
|
+
|
26
|
+
Performance & Scalability:
|
27
|
+
- Progress bars and operational feedback for large-scale directory discovery
|
28
|
+
- Efficient credential management for multi-account directory enumeration
|
29
|
+
- Regional optimization with targeted directory service API calls
|
30
|
+
- Memory-efficient processing for extensive directory service inventories
|
31
|
+
|
32
|
+
Enterprise Use Cases:
|
33
|
+
- Directory service governance and compliance reporting across organizational accounts
|
34
|
+
- Identity infrastructure audit and directory service configuration validation
|
35
|
+
- Directory service consolidation and migration planning with organizational visibility
|
36
|
+
- Operational monitoring and directory service health assessment
|
37
|
+
|
38
|
+
Security & Compliance:
|
39
|
+
- Read-only directory discovery operations for operational safety
|
40
|
+
- Comprehensive audit logging for directory service access and discovery activities
|
41
|
+
- Regional access validation preventing unauthorized directory service enumeration
|
42
|
+
- Safe credential handling with automatic session management
|
43
|
+
|
44
|
+
Dependencies:
|
45
|
+
- boto3: AWS SDK for Directory Service API access
|
46
|
+
- colorama: Terminal output formatting and colored display
|
47
|
+
- tqdm: Progress bars for operational visibility during discovery
|
48
|
+
- Custom modules: Inventory_Modules, ArgumentsClass for enterprise argument parsing
|
49
|
+
|
50
|
+
Output Format:
|
51
|
+
- Tabular directory service inventory with sortable columns
|
52
|
+
- Management account context for organizational directory visibility
|
53
|
+
- Regional distribution summary for operational planning
|
54
|
+
- Directory status and configuration details for enterprise governance
|
55
|
+
"""
|
56
|
+
|
57
|
+
import logging
|
58
|
+
import sys
|
59
|
+
from time import time
|
60
|
+
|
61
|
+
from ArgumentsClass import CommonArguments
|
62
|
+
from botocore.exceptions import ClientError
|
63
|
+
from colorama import Fore, init
|
64
|
+
from Inventory_Modules import display_results, find_directories2, get_all_credentials
|
65
|
+
from tqdm.auto import tqdm
|
66
|
+
|
67
|
+
init()
|
68
|
+
__version__ = "2024.05.31"
|
69
|
+
|
70
|
+
|
71
|
+
def parse_args(f_arguments):
|
72
|
+
"""
|
73
|
+
Parse and validate command-line arguments for Directory Service directory discovery operations.
|
74
|
+
|
75
|
+
Configures comprehensive argument parsing for AWS Directory Service discovery across multi-account
|
76
|
+
AWS Organizations environments. Supports enterprise-grade directory management with profile
|
77
|
+
management, regional targeting, fragment-based filtering, and operational controls for large-scale
|
78
|
+
directory service governance and compliance operations.
|
79
|
+
|
80
|
+
Args:
|
81
|
+
f_arguments (list): Command-line argument list for directory discovery configuration
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
argparse.Namespace: Parsed argument namespace containing:
|
85
|
+
- Profiles: List of AWS profiles for multi-account directory discovery
|
86
|
+
- Regions: Target AWS regions for directory service enumeration
|
87
|
+
- Fragments: Directory name fragments for targeted discovery and filtering
|
88
|
+
- Exact: Boolean flag for exact fragment matching vs substring matching
|
89
|
+
- Accounts: Specific account list for targeted directory discovery
|
90
|
+
- SkipAccounts: Account exclusion list for selective directory enumeration
|
91
|
+
- SkipProfiles: Profile exclusion list for selective discovery operations
|
92
|
+
- Time: Performance timing flag for operational metrics and optimization
|
93
|
+
- RootOnly: Flag restricting discovery to management account only
|
94
|
+
- loglevel: Logging verbosity for operational visibility and troubleshooting
|
95
|
+
|
96
|
+
CLI Argument Categories:
|
97
|
+
- Multi-profile support for organizational directory service management
|
98
|
+
- Multi-region targeting for comprehensive directory service coverage
|
99
|
+
- Fragment-based filtering for targeted directory identification and management
|
100
|
+
- Extended arguments including account filtering and performance timing
|
101
|
+
- Root-only mode for management account directory service discovery
|
102
|
+
- Verbosity controls for operational logging and troubleshooting
|
103
|
+
|
104
|
+
Enterprise Features:
|
105
|
+
- Organizational profile management for centralized directory service governance
|
106
|
+
- Regional filtering for geo-distributed directory service architectures
|
107
|
+
- Account inclusion/exclusion for selective directory service discovery
|
108
|
+
- Performance monitoring with timing metrics for operational optimization
|
109
|
+
- Comprehensive logging controls for audit and compliance requirements
|
110
|
+
|
111
|
+
Usage Examples:
|
112
|
+
- Multi-account discovery: --profiles profile1 profile2 --regions us-east-1 us-west-2
|
113
|
+
- Fragment filtering: --fragment "corp" --exact for targeted directory discovery
|
114
|
+
- Root account only: --rootonly for management account directory enumeration
|
115
|
+
- Performance timing: --timing for operational metrics and optimization analysis
|
116
|
+
"""
|
117
|
+
parser = CommonArguments()
|
118
|
+
parser.multiprofile() # Enable multi-profile support for organizational directory discovery
|
119
|
+
parser.multiregion() # Enable multi-region targeting for comprehensive directory coverage
|
120
|
+
parser.fragment() # Enable fragment-based filtering for targeted directory identification
|
121
|
+
parser.extendedargs() # Enable account filtering and performance timing capabilities
|
122
|
+
parser.timing() # Enable performance timing metrics for operational optimization
|
123
|
+
parser.rootOnly() # Enable management account only mode for centralized directory discovery
|
124
|
+
parser.version(__version__)
|
125
|
+
parser.verbosity() # Enable logging verbosity controls for operational visibility
|
126
|
+
return parser.my_parser.parse_args(f_arguments)
|
127
|
+
|
128
|
+
|
129
|
+
def find_all_directories(f_credentials, f_fragments, f_exact):
|
130
|
+
"""
|
131
|
+
Discover and enumerate AWS Directory Service directories across multiple accounts and regions.
|
132
|
+
|
133
|
+
Performs comprehensive Directory Service discovery using credential-based enumeration to inventory
|
134
|
+
Microsoft Active Directory, Simple AD, and AD Connector directories across large-scale AWS
|
135
|
+
Organizations environments. Supports fragment-based filtering for targeted directory identification
|
136
|
+
and provides detailed directory metadata extraction for enterprise identity and access management
|
137
|
+
governance.
|
138
|
+
|
139
|
+
Args:
|
140
|
+
f_credentials (list): List of credential dictionaries for cross-account directory discovery containing:
|
141
|
+
- AccountId: AWS account number for Directory Service access
|
142
|
+
- Region: Target AWS region for directory enumeration
|
143
|
+
- Success: Boolean indicating credential validity and access status
|
144
|
+
- MgmtAccount: Management account identifier for organizational context
|
145
|
+
- AccessError: Error details for failed credential attempts
|
146
|
+
f_fragments (list): Directory name fragments for targeted search and filtering
|
147
|
+
Supports partial name matching for flexible directory identification
|
148
|
+
f_exact (bool): Exact matching flag for precise directory name filtering
|
149
|
+
True for exact match, False for substring matching
|
150
|
+
|
151
|
+
Returns:
|
152
|
+
list: Comprehensive list of directory dictionaries containing:
|
153
|
+
- DirectoryName: Human-readable directory name identifier
|
154
|
+
- DirectoryId: Unique AWS Directory Service identifier
|
155
|
+
- HomeRegion: Primary region where directory service is hosted
|
156
|
+
- Status: Current operational status (Active, Creating, Deleting, etc.)
|
157
|
+
- Type: Directory type (SimpleAD, MicrosoftAD, ADConnector, etc.)
|
158
|
+
- Owner: Directory ownership context (Self, Shared, etc.)
|
159
|
+
- MgmtAccount: Management account for organizational directory oversight
|
160
|
+
- Region: AWS region where directory is deployed
|
161
|
+
- AccountId: AWS account containing the directory
|
162
|
+
|
163
|
+
Directory Discovery Features:
|
164
|
+
- Multi-account, multi-region Directory Service enumeration
|
165
|
+
- Fragment-based filtering for targeted directory identification
|
166
|
+
- Comprehensive directory metadata extraction for governance and compliance
|
167
|
+
- Cross-account directory visibility for organizational identity management
|
168
|
+
- Regional directory distribution analysis for operational planning
|
169
|
+
|
170
|
+
Processing Architecture:
|
171
|
+
- Sequential processing with progress tracking for operational visibility
|
172
|
+
- Credential validation and error handling for authorization issues
|
173
|
+
- Regional validation ensuring directory service availability
|
174
|
+
- Memory-efficient processing for extensive directory service inventories
|
175
|
+
|
176
|
+
Performance Considerations:
|
177
|
+
- Progress bars for operational feedback during large-scale discovery
|
178
|
+
- Efficient Directory Service API usage for optimal performance
|
179
|
+
- Error handling and graceful degradation for authorization failures
|
180
|
+
- TODO: Future enhancement for multi-threading support to improve performance
|
181
|
+
|
182
|
+
Enterprise Identity Management:
|
183
|
+
- Organizational directory service visibility across accounts and regions
|
184
|
+
- Directory metadata aggregation for compliance and audit tracking
|
185
|
+
- Fragment-based search capabilities for targeted directory management
|
186
|
+
- Comprehensive error handling for operational resilience and troubleshooting
|
187
|
+
|
188
|
+
Error Handling:
|
189
|
+
- Authorization failure detection with graceful degradation
|
190
|
+
- AWS API error management with comprehensive logging
|
191
|
+
- Type error handling for malformed directory service responses
|
192
|
+
- Credential validation and failure tracking for multi-account operations
|
193
|
+
"""
|
194
|
+
AllDirectories = [] # Aggregated list for all discovered directories
|
195
|
+
|
196
|
+
# TODO: Need to use multi-threading here for improved performance
|
197
|
+
# Sequential processing with progress tracking for operational visibility
|
198
|
+
for credential in tqdm(
|
199
|
+
f_credentials, desc=f"Looking through {len(f_credentials)} accounts and regions", unit="credentials"
|
200
|
+
):
|
201
|
+
logging.info(f"{ERASE_LINE}Looking in account: {credential['AccountId']} in region {credential['Region']}")
|
202
|
+
|
203
|
+
# Skip failed credentials to avoid API errors
|
204
|
+
if not credential["Success"]:
|
205
|
+
continue
|
206
|
+
|
207
|
+
try:
|
208
|
+
# Discover directories using Directory Service API with fragment filtering
|
209
|
+
directories = find_directories2(credential, credential["Region"], f_fragments, f_exact)
|
210
|
+
logging.info(f"directories: {directories}")
|
211
|
+
logging.info(
|
212
|
+
f"{ERASE_LINE}Account: {credential['AccountId']} Region: {credential['Region']} Found {len(directories)} directories"
|
213
|
+
)
|
214
|
+
|
215
|
+
# Process and aggregate discovered directories with organizational context
|
216
|
+
if directories:
|
217
|
+
for directory in directories:
|
218
|
+
# Enhance directory metadata with organizational and regional context
|
219
|
+
# Available directory metadata includes:
|
220
|
+
# - DirectoryName: Human-readable directory identifier
|
221
|
+
# - DirectoryId: Unique AWS Directory Service identifier
|
222
|
+
# - HomeRegion: Primary directory service region
|
223
|
+
# - Status: Operational status (Active, Creating, etc.)
|
224
|
+
# - Type: Directory type (SimpleAD, MicrosoftAD, etc.)
|
225
|
+
# - Owner: Directory ownership context
|
226
|
+
|
227
|
+
directory.update(
|
228
|
+
{
|
229
|
+
"MgmtAccount": credential["MgmtAccount"], # Management account context
|
230
|
+
"Region": credential["Region"], # Regional deployment information
|
231
|
+
"AccountId": credential["AccountId"], # Account ownership details
|
232
|
+
}
|
233
|
+
)
|
234
|
+
AllDirectories.append(directory)
|
235
|
+
|
236
|
+
except TypeError as my_Error:
|
237
|
+
# Handle type errors from malformed Directory Service API responses
|
238
|
+
logging.info(f"Error: {my_Error}")
|
239
|
+
continue
|
240
|
+
except ClientError as my_Error:
|
241
|
+
# Handle AWS API authorization failures with informative logging
|
242
|
+
if "AuthFailure" in str(my_Error):
|
243
|
+
logging.error(f"{ERASE_LINE} Account {credential['AccountId']} : Authorization Failure")
|
244
|
+
|
245
|
+
return AllDirectories
|
246
|
+
|
247
|
+
|
248
|
+
##########################
|
249
|
+
|
250
|
+
if __name__ == "__main__":
|
251
|
+
# Parse command-line arguments for Directory Service discovery configuration
|
252
|
+
args = parse_args(sys.argv[1:])
|
253
|
+
pProfiles = args.Profiles # AWS profiles for multi-account directory discovery
|
254
|
+
pRegionList = args.Regions # Target regions for directory service enumeration
|
255
|
+
pFragments = args.Fragments # Directory name fragments for targeted filtering
|
256
|
+
pExact = args.Exact # Exact matching flag for precise directory identification
|
257
|
+
pAccounts = args.Accounts # Specific account list for targeted discovery
|
258
|
+
pSkipAccounts = args.SkipAccounts # Account exclusion list for selective enumeration
|
259
|
+
pSkipProfiles = args.SkipProfiles # Profile exclusion list for selective operations
|
260
|
+
pTiming = args.Time # Performance timing flag for operational metrics
|
261
|
+
pRootOnly = args.RootOnly # Management account only mode for centralized discovery
|
262
|
+
verbose = args.loglevel # Logging verbosity for operational visibility
|
263
|
+
|
264
|
+
# Configure comprehensive logging for Directory Service discovery operations
|
265
|
+
logging.basicConfig(level=verbose, format="[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s")
|
266
|
+
logging.getLogger("boto3").setLevel(logging.CRITICAL) # Suppress AWS SDK logging
|
267
|
+
logging.getLogger("botocore").setLevel(logging.CRITICAL) # Suppress AWS core logging
|
268
|
+
logging.getLogger("s3transfer").setLevel(logging.CRITICAL) # Suppress S3 transfer logging
|
269
|
+
logging.getLogger("urllib3").setLevel(logging.CRITICAL) # Suppress HTTP logging
|
270
|
+
logging.getLogger("botocore").setLevel(logging.CRITICAL) # Suppress boto core logging
|
271
|
+
|
272
|
+
ERASE_LINE = "\x1b[2K" # Terminal control for dynamic output updates
|
273
|
+
logging.info(f"Profiles: {pProfiles}")
|
274
|
+
begin_time = time() # Performance timing baseline for operational metrics
|
275
|
+
|
276
|
+
print()
|
277
|
+
print(f"Checking for Directories... ")
|
278
|
+
print()
|
279
|
+
|
280
|
+
# Initialize credential management for multi-account Directory Service access
|
281
|
+
AllCredentials = []
|
282
|
+
if pSkipAccounts is None:
|
283
|
+
pSkipAccounts = [] # Initialize empty skip list if not provided
|
284
|
+
if pSkipProfiles is None:
|
285
|
+
SkipProfiles = [] # Initialize empty profile skip list if not provided
|
286
|
+
account_num = 0
|
287
|
+
|
288
|
+
# Retrieve and validate credentials for multi-account Directory Service discovery
|
289
|
+
AllCredentials = get_all_credentials(
|
290
|
+
pProfiles, pTiming, pSkipProfiles, pSkipAccounts, pRootOnly, pAccounts, pRegionList
|
291
|
+
)
|
292
|
+
|
293
|
+
# Display credential retrieval timing for performance optimization
|
294
|
+
if pTiming:
|
295
|
+
print(
|
296
|
+
f"{Fore.GREEN}\tAfter getting credentials, this script took {time() - begin_time:.3f} seconds{Fore.RESET}"
|
297
|
+
)
|
298
|
+
print()
|
299
|
+
|
300
|
+
# Extract unique regional and account context for discovery scope analysis
|
301
|
+
RegionList = list(set([x["Region"] for x in AllCredentials]))
|
302
|
+
AccountList = list(set([x["AccountId"] for x in AllCredentials]))
|
303
|
+
|
304
|
+
# Display credential parsing timing for operational metrics
|
305
|
+
if pTiming:
|
306
|
+
print(
|
307
|
+
f"{Fore.GREEN}\tAfter parsing out all Regions, Account and Profiles, this script took {time() - begin_time:.3f} seconds{Fore.RESET}"
|
308
|
+
)
|
309
|
+
print()
|
310
|
+
|
311
|
+
print()
|
312
|
+
|
313
|
+
credential_number = 0
|
314
|
+
logging.info(f"Looking through {len(AccountList)} accounts and {len(RegionList)} regions")
|
315
|
+
|
316
|
+
# Execute comprehensive Directory Service discovery across organizational accounts
|
317
|
+
all_directories = find_all_directories(AllCredentials, pFragments, pExact)
|
318
|
+
|
319
|
+
print()
|
320
|
+
|
321
|
+
# Configure display formatting for comprehensive directory service inventory
|
322
|
+
display_dict = {
|
323
|
+
"MgmtAccount": {"DisplayOrder": 1, "Heading": "Parent Acct"}, # Management account context
|
324
|
+
"AccountId": {"DisplayOrder": 2, "Heading": "Account Number"}, # Account ownership
|
325
|
+
"Region": {"DisplayOrder": 3, "Heading": "Region"}, # Regional deployment
|
326
|
+
"DirectoryName": {"DisplayOrder": 4, "Heading": "Directory Name"}, # Human-readable identifier
|
327
|
+
"DirectoryId": {"DisplayOrder": 5, "Heading": "Directory ID"}, # Unique service identifier
|
328
|
+
"HomeRegion": {"DisplayOrder": 6, "Heading": "Home Region"}, # Primary service region
|
329
|
+
"Status": {"DisplayOrder": 7, "Heading": "Status"}, # Operational status
|
330
|
+
"Type": {"DisplayOrder": 8, "Heading": "Type"}, # Directory type classification
|
331
|
+
"Owner": {"DisplayOrder": 9, "Heading": "Owner"}, # Ownership context
|
332
|
+
}
|
333
|
+
|
334
|
+
# Sort directory results for consistent organizational reporting
|
335
|
+
sorted_Results = sorted(
|
336
|
+
all_directories, key=lambda d: (d["MgmtAccount"], d["AccountId"], d["Region"], d["DirectoryName"])
|
337
|
+
)
|
338
|
+
|
339
|
+
# Display comprehensive directory service inventory with formatted output
|
340
|
+
display_results(sorted_Results, display_dict, "None")
|
341
|
+
|
342
|
+
# Provide operational summary with discovery metrics and performance timing
|
343
|
+
print(ERASE_LINE)
|
344
|
+
print(
|
345
|
+
f"Found {len(all_directories)} directories across {len(AccountList)} accounts across {len(RegionList)} regions"
|
346
|
+
)
|
347
|
+
print()
|
348
|
+
|
349
|
+
# Display total execution timing for performance analysis and optimization
|
350
|
+
if pTiming:
|
351
|
+
print(f"{Fore.GREEN}\tThis script took {time() - begin_time:.3f} seconds{Fore.RESET}")
|
352
|
+
print()
|
353
|
+
print("Thank you for using this script")
|
354
|
+
print()
|
@@ -0,0 +1,286 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
"""
|
4
|
+
AWS EC2 Availability Zones Discovery and Mapping Script
|
5
|
+
|
6
|
+
This script provides comprehensive discovery and analysis capabilities for AWS EC2
|
7
|
+
availability zones across multiple accounts and regions. It's designed for enterprise
|
8
|
+
infrastructure teams who need visibility into availability zone distribution, capacity
|
9
|
+
planning, and regional architecture across large-scale AWS deployments.
|
10
|
+
|
11
|
+
Key Features:
|
12
|
+
- Multi-account availability zone discovery using assume role capabilities
|
13
|
+
- Multi-region scanning with configurable region targeting
|
14
|
+
- Availability zone metadata extraction including zone IDs and types
|
15
|
+
- Regional capacity planning and architecture documentation
|
16
|
+
- Cross-account zone consistency analysis and validation
|
17
|
+
- Enterprise reporting with CSV export and structured output
|
18
|
+
- Profile-based authentication with support for federated access
|
19
|
+
|
20
|
+
Enterprise Use Cases:
|
21
|
+
- Infrastructure capacity planning and availability zone selection
|
22
|
+
- Multi-account regional architecture documentation and standardization
|
23
|
+
- Disaster recovery planning with availability zone distribution analysis
|
24
|
+
- Compliance reporting for regional data residency requirements
|
25
|
+
- Cost optimization through availability zone placement strategies
|
26
|
+
- Network architecture planning with zone-aware resource placement
|
27
|
+
|
28
|
+
Infrastructure Planning Features:
|
29
|
+
- Zone ID mapping for consistent cross-account resource placement
|
30
|
+
- Availability zone enumeration for capacity planning
|
31
|
+
- Regional coverage analysis across organizational boundaries
|
32
|
+
- Zone type classification for infrastructure decision making
|
33
|
+
- Cross-account zone consistency validation for disaster recovery
|
34
|
+
|
35
|
+
Security Considerations:
|
36
|
+
- Uses IAM assume role capabilities for cross-account access
|
37
|
+
- Implements proper error handling for authorization failures
|
38
|
+
- Supports read-only operations with no infrastructure modification capabilities
|
39
|
+
- Respects regional access permissions and zone visibility constraints
|
40
|
+
- Provides comprehensive audit trail through detailed logging
|
41
|
+
|
42
|
+
Availability Zone Analysis:
|
43
|
+
- Zone name and ID correlation for consistent placement
|
44
|
+
- Zone type classification (availability-zone, local-zone, wavelength-zone)
|
45
|
+
- Regional availability zone count validation
|
46
|
+
- Cross-account zone naming consistency analysis
|
47
|
+
- Capacity planning data aggregation
|
48
|
+
|
49
|
+
Performance Considerations:
|
50
|
+
- Sequential processing for reliability across large account sets
|
51
|
+
- Progress tracking for operational visibility during long operations
|
52
|
+
- Efficient credential management for cross-account operations
|
53
|
+
- Memory-optimized data structures for large organizational inventories
|
54
|
+
|
55
|
+
Dependencies:
|
56
|
+
- boto3/botocore for AWS EC2 API interactions
|
57
|
+
- Inventory_Modules for common utility functions and credential management
|
58
|
+
- ArgumentsClass for standardized CLI argument parsing
|
59
|
+
- colorama for enhanced output formatting
|
60
|
+
|
61
|
+
Author: AWS CloudOps Team
|
62
|
+
Version: 2024.03.06
|
63
|
+
"""
|
64
|
+
|
65
|
+
import logging
|
66
|
+
import sys
|
67
|
+
from time import time
|
68
|
+
|
69
|
+
from ArgumentsClass import CommonArguments
|
70
|
+
from colorama import Fore, init
|
71
|
+
from Inventory_Modules import display_results, get_all_credentials, get_region_azs2
|
72
|
+
|
73
|
+
init()
|
74
|
+
__version__ = "2024.03.06"
|
75
|
+
ERASE_LINE = "\x1b[2K"
|
76
|
+
begin_time = time()
|
77
|
+
|
78
|
+
|
79
|
+
###########################
|
80
|
+
# Functions
|
81
|
+
###########################
|
82
|
+
def parse_args(args):
|
83
|
+
"""
|
84
|
+
Parse command line arguments for EC2 availability zone discovery operations.
|
85
|
+
|
86
|
+
Configures comprehensive argument parsing for multi-account, multi-region availability
|
87
|
+
zone inventory operations. Supports enterprise deployment patterns with profile
|
88
|
+
management, region targeting, and organizational access controls for infrastructure
|
89
|
+
planning and capacity management.
|
90
|
+
|
91
|
+
Args:
|
92
|
+
args (list): Command line arguments from sys.argv[1:]
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
argparse.Namespace: Parsed arguments containing:
|
96
|
+
- Profiles: List of AWS profiles to process
|
97
|
+
- Regions: Target regions for availability zone discovery
|
98
|
+
- SkipProfiles/SkipAccounts: Exclusion filters
|
99
|
+
- RootOnly: Limit to organization root accounts
|
100
|
+
- AccessRoles: IAM roles for cross-account access
|
101
|
+
- Filename: Output file for CSV export
|
102
|
+
- Time: Enable performance timing metrics
|
103
|
+
- loglevel: Logging verbosity configuration
|
104
|
+
|
105
|
+
Configuration Options:
|
106
|
+
- Multi-region scanning with region filters for targeted analysis
|
107
|
+
- Multi-profile support for federated access across organizations
|
108
|
+
- Extended arguments for advanced filtering and account selection
|
109
|
+
- Root-only mode for organization-level infrastructure inventory
|
110
|
+
- Role-based access for cross-account availability zone discovery
|
111
|
+
- File output for integration with capacity planning tools
|
112
|
+
- Timing metrics for performance optimization and monitoring
|
113
|
+
- Verbose logging for debugging and infrastructure audit
|
114
|
+
"""
|
115
|
+
parser = CommonArguments()
|
116
|
+
parser.multiprofile()
|
117
|
+
parser.multiregion()
|
118
|
+
parser.extendedargs()
|
119
|
+
parser.rootOnly()
|
120
|
+
parser.timing()
|
121
|
+
parser.save_to_file()
|
122
|
+
parser.rolestouse()
|
123
|
+
parser.verbosity()
|
124
|
+
parser.version(__version__)
|
125
|
+
return parser.my_parser.parse_args(args)
|
126
|
+
|
127
|
+
|
128
|
+
def azs_across_accounts(
|
129
|
+
fProfiles, fRegionList, fSkipProfiles, fSkipAccounts, fAccountList, fTiming, fRootOnly, fverbose, fRoleList
|
130
|
+
) -> dict:
|
131
|
+
"""
|
132
|
+
Discover and map availability zones across multiple AWS accounts and regions.
|
133
|
+
|
134
|
+
Performs comprehensive availability zone discovery across organizational boundaries
|
135
|
+
to provide infrastructure teams with complete visibility into zone distribution,
|
136
|
+
capacity planning data, and regional architecture patterns. Supports large-scale
|
137
|
+
enterprise environments with multiple AWS organizations and standalone accounts.
|
138
|
+
|
139
|
+
Args:
|
140
|
+
fProfiles (list): AWS profiles for authentication and access
|
141
|
+
fRegionList (list): Target regions for availability zone discovery
|
142
|
+
fSkipProfiles (list): Profiles to exclude from processing
|
143
|
+
fSkipAccounts (list): Account IDs to exclude from discovery
|
144
|
+
fAccountList (list): Specific accounts to target (if provided)
|
145
|
+
fTiming (bool): Enable performance timing metrics
|
146
|
+
fRootOnly (bool): Limit discovery to organization root accounts
|
147
|
+
fverbose (int): Logging verbosity level for operational visibility
|
148
|
+
fRoleList (list): IAM roles for cross-account access
|
149
|
+
|
150
|
+
Returns:
|
151
|
+
dict: Nested dictionary structure with availability zone data:
|
152
|
+
- First level: Account numbers as keys
|
153
|
+
- Second level: Region names as keys
|
154
|
+
- Third level: List of availability zone objects containing:
|
155
|
+
- ZoneName: Human-readable zone name (e.g., us-east-1a)
|
156
|
+
- ZoneId: Unique zone identifier for consistent placement
|
157
|
+
- ZoneType: Zone classification (availability-zone, local-zone, etc.)
|
158
|
+
- Region: AWS region containing the zone
|
159
|
+
- State: Zone operational state
|
160
|
+
|
161
|
+
Processing Flow:
|
162
|
+
1. Credential Discovery: Obtain cross-account credentials for all target accounts
|
163
|
+
2. Organization Analysis: Identify unique organizations and standalone accounts
|
164
|
+
3. Sequential Processing: Iterate through successful credentials for zone discovery
|
165
|
+
4. Zone Enumeration: Call EC2 API to discover availability zones per account/region
|
166
|
+
5. Data Aggregation: Structure results for enterprise reporting and analysis
|
167
|
+
|
168
|
+
Enterprise Features:
|
169
|
+
- Progress tracking with real-time feedback for long operations
|
170
|
+
- Organizational boundary detection for multi-org environments
|
171
|
+
- Error handling with graceful degradation for access failures
|
172
|
+
- Performance timing for optimization and capacity planning
|
173
|
+
|
174
|
+
Infrastructure Planning Use Cases:
|
175
|
+
- Capacity planning with zone-aware resource allocation
|
176
|
+
- Disaster recovery planning with cross-zone distribution analysis
|
177
|
+
- Regional architecture standardization across accounts
|
178
|
+
- Zone ID mapping for consistent multi-account deployments
|
179
|
+
"""
|
180
|
+
if fTiming:
|
181
|
+
begin_time = time()
|
182
|
+
logging.warning(f"These profiles are being checked {fProfiles}.")
|
183
|
+
|
184
|
+
# Obtain credentials for all accounts across specified regions and profiles
|
185
|
+
AllCredentials = get_all_credentials(
|
186
|
+
fProfiles, fTiming, fSkipProfiles, fSkipAccounts, fRootOnly, fAccountList, fRegionList, fRoleList
|
187
|
+
)
|
188
|
+
|
189
|
+
# Identify unique organizations for progress tracking
|
190
|
+
OrgList = list(set([x["MgmtAccount"] for x in AllCredentials]))
|
191
|
+
print(f"Please bear with us as we run through {len(OrgList)} organizations / standalone accounts")
|
192
|
+
|
193
|
+
print(ERASE_LINE)
|
194
|
+
|
195
|
+
# Initialize nested dictionary for organizing availability zone data by account and region
|
196
|
+
AllOrgAZs = dict()
|
197
|
+
SuccessfulCredentials = [x for x in AllCredentials if x["Success"]]
|
198
|
+
passnumber = 0
|
199
|
+
|
200
|
+
# Process each successful credential set to discover availability zones
|
201
|
+
for item in SuccessfulCredentials:
|
202
|
+
# Initialize account structure if not present
|
203
|
+
if item["AccountNumber"] not in AllOrgAZs.keys():
|
204
|
+
AllOrgAZs[item["AccountNumber"]] = dict()
|
205
|
+
passnumber += 1
|
206
|
+
|
207
|
+
# Discover availability zones for this account/region combination
|
208
|
+
if item["Success"]:
|
209
|
+
region_azs = get_region_azs2(item)
|
210
|
+
print(
|
211
|
+
f"{ERASE_LINE}Looking at account {item['AccountNumber']} in region {item['Region']} -- {passnumber}/{len(SuccessfulCredentials)}",
|
212
|
+
end="\r",
|
213
|
+
)
|
214
|
+
|
215
|
+
# Store availability zone data in structured format
|
216
|
+
AllOrgAZs[item["AccountNumber"]][item["Region"]] = region_azs
|
217
|
+
return AllOrgAZs
|
218
|
+
|
219
|
+
|
220
|
+
###########################
|
221
|
+
# Main
|
222
|
+
###########################
|
223
|
+
|
224
|
+
if __name__ == "__main__":
|
225
|
+
args = parse_args(sys.argv[1:])
|
226
|
+
|
227
|
+
pProfiles = args.Profiles
|
228
|
+
pRegions = args.Regions
|
229
|
+
pRootOnly = args.RootOnly
|
230
|
+
pTiming = args.Time
|
231
|
+
pSkipProfiles = args.SkipProfiles
|
232
|
+
pSkipAccounts = args.SkipAccounts
|
233
|
+
pverbose = args.loglevel
|
234
|
+
pSaveFilename = args.Filename
|
235
|
+
pAccountList = args.Accounts
|
236
|
+
pRoleList = args.AccessRoles
|
237
|
+
# Setup logging levels
|
238
|
+
logging.basicConfig(level=pverbose, format="[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s")
|
239
|
+
logging.getLogger("boto3").setLevel(logging.CRITICAL)
|
240
|
+
logging.getLogger("botocore").setLevel(logging.CRITICAL)
|
241
|
+
logging.getLogger("s3transfer").setLevel(logging.CRITICAL)
|
242
|
+
logging.getLogger("urllib3").setLevel(logging.CRITICAL)
|
243
|
+
|
244
|
+
print(f"Collecting credentials for all accounts in your org, across multiple regions")
|
245
|
+
AllOrgAZs = azs_across_accounts(
|
246
|
+
pProfiles, pRegions, pSkipProfiles, pSkipAccounts, pAccountList, pTiming, pRootOnly, pverbose, pRoleList
|
247
|
+
)
|
248
|
+
histogram = list()
|
249
|
+
for account, account_info in AllOrgAZs.items():
|
250
|
+
for region, az_info in account_info.items():
|
251
|
+
for az in az_info:
|
252
|
+
if az["ZoneType"] == "availability-zone":
|
253
|
+
# print(az)
|
254
|
+
histogram.append(
|
255
|
+
{"AccountNumber": account, "Region": az["Region"], "Name": az["ZoneName"], "Id": az["ZoneId"]}
|
256
|
+
)
|
257
|
+
|
258
|
+
summary = dict()
|
259
|
+
for item in histogram:
|
260
|
+
if item["AccountNumber"] not in summary.keys(): # item['AccountNumber'] not in t:
|
261
|
+
summary[item["AccountNumber"]] = dict()
|
262
|
+
summary[item["AccountNumber"]][item["Region"]] = list()
|
263
|
+
summary[item["AccountNumber"]][item["Region"]].append((item["Name"], item["Id"]))
|
264
|
+
elif item["AccountNumber"] in summary.keys() and item["Region"] not in summary[item["AccountNumber"]].keys():
|
265
|
+
summary[item["AccountNumber"]][item["Region"]] = list()
|
266
|
+
summary[item["AccountNumber"]][item["Region"]].append((item["Name"], item["Id"]))
|
267
|
+
elif item["AccountNumber"] in summary.keys():
|
268
|
+
summary[item["AccountNumber"]][item["Region"]].append((item["Name"], item["Id"]))
|
269
|
+
|
270
|
+
display_dict = {
|
271
|
+
"AccountNumber": {"DisplayOrder": 1, "Heading": "Account Number"},
|
272
|
+
"Region": {"DisplayOrder": 2, "Heading": "Region Name"},
|
273
|
+
"ZoneName": {"DisplayOrder": 3, "Heading": "Zone Name"},
|
274
|
+
"ZoneId": {"DisplayOrder": 4, "Heading": "Zone Id"},
|
275
|
+
"ZoneType": {"DisplayOrder": 5, "Heading": "Zone Type"},
|
276
|
+
}
|
277
|
+
# How to sort a dictionary by the key:
|
278
|
+
sorted_summary = dict(sorted(summary.items()))
|
279
|
+
# sorted_Results = sorted(summary, key=lambda d: (d['MgmtAccount'], d['AccountId'], d['Region']))
|
280
|
+
display_results(summary, display_dict, "None", pSaveFilename)
|
281
|
+
|
282
|
+
print()
|
283
|
+
if pTiming:
|
284
|
+
print(f"{Fore.GREEN}This script took {time() - begin_time:.2f} seconds{Fore.RESET}")
|
285
|
+
print("Thanks for using this script")
|
286
|
+
print()
|