runbooks 0.2.5__py3-none-any.whl → 0.7.0__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 +2 -0
- jupyter-agent/.env.template +2 -0
- jupyter-agent/.gitattributes +35 -0
- jupyter-agent/.gradio/certificate.pem +31 -0
- jupyter-agent/README.md +16 -0
- jupyter-agent/__main__.log +8 -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/tmp/4ojbs8a02ir/jupyter-agent.ipynb +68 -0
- jupyter-agent/tmp/cm5iasgpm3p/jupyter-agent.ipynb +91 -0
- jupyter-agent/tmp/crqbsseag5/jupyter-agent.ipynb +91 -0
- jupyter-agent/tmp/hohanq1u097/jupyter-agent.ipynb +57 -0
- jupyter-agent/tmp/jns1sam29wm/jupyter-agent.ipynb +53 -0
- jupyter-agent/tmp/jupyter-agent.ipynb +27 -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/README.md +337 -0
- runbooks/finops/__init__.py +86 -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/FAILED_SCRIPTS_TROUBLESHOOTING.md +619 -0
- runbooks/inventory/Inventory_Modules.py +6130 -0
- runbooks/inventory/LandingZone/delete_lz.py +1075 -0
- runbooks/inventory/PASSED_SCRIPTS_GUIDE.md +738 -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/aws_organization.png +0 -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/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 +1004 -0
- runbooks/organizations/__init__.py +12 -0
- runbooks/organizations/manager.py +374 -0
- runbooks/security/README.md +447 -0
- runbooks/security/__init__.py +71 -0
- runbooks/{security_baseline → security}/checklist/alternate_contacts.py +8 -1
- runbooks/{security_baseline → security}/checklist/bucket_public_access.py +4 -1
- runbooks/{security_baseline → security}/checklist/cloudwatch_alarm_configuration.py +9 -2
- runbooks/{security_baseline → security}/checklist/guardduty_enabled.py +9 -2
- runbooks/{security_baseline → security}/checklist/multi_region_instance_usage.py +5 -1
- runbooks/{security_baseline → security}/checklist/root_access_key.py +6 -1
- runbooks/{security_baseline → security}/config-origin.json +1 -1
- runbooks/{security_baseline → security}/config.json +1 -1
- runbooks/{security_baseline → security}/permission.json +1 -1
- runbooks/{security_baseline → security}/report_generator.py +10 -2
- runbooks/{security_baseline → security}/report_template_en.html +7 -7
- runbooks/{security_baseline → security}/report_template_jp.html +7 -7
- runbooks/{security_baseline → security}/report_template_kr.html +12 -12
- runbooks/{security_baseline → security}/report_template_vn.html +7 -7
- runbooks/{security_baseline → security}/run_script.py +8 -2
- runbooks/{security_baseline → security}/security_baseline_tester.py +12 -4
- runbooks/{security_baseline → security}/utils/common.py +5 -1
- runbooks/utils/__init__.py +204 -0
- runbooks-0.7.0.dist-info/METADATA +375 -0
- runbooks-0.7.0.dist-info/RECORD +249 -0
- {runbooks-0.2.5.dist-info → runbooks-0.7.0.dist-info}/WHEEL +1 -1
- runbooks-0.7.0.dist-info/entry_points.txt +7 -0
- runbooks-0.7.0.dist-info/licenses/LICENSE +201 -0
- runbooks-0.7.0.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.5.dist-info/METADATA +0 -439
- runbooks-0.2.5.dist-info/RECORD +0 -61
- runbooks-0.2.5.dist-info/entry_points.txt +0 -3
- runbooks-0.2.5.dist-info/top_level.txt +0 -1
- /runbooks/{security_baseline/__init__.py → inventory/tests/script_test_data.py} +0 -0
- /runbooks/{security_baseline → security}/checklist/__init__.py +0 -0
- /runbooks/{security_baseline → security}/checklist/account_level_bucket_public_access.py +0 -0
- /runbooks/{security_baseline → security}/checklist/direct_attached_policy.py +0 -0
- /runbooks/{security_baseline → security}/checklist/iam_password_policy.py +0 -0
- /runbooks/{security_baseline → security}/checklist/iam_user_mfa.py +0 -0
- /runbooks/{security_baseline → security}/checklist/multi_region_trail.py +0 -0
- /runbooks/{security_baseline → security}/checklist/root_mfa.py +0 -0
- /runbooks/{security_baseline → security}/checklist/root_usage.py +0 -0
- /runbooks/{security_baseline → security}/checklist/trail_enabled.py +0 -0
- /runbooks/{security_baseline → security}/checklist/trusted_advisor.py +0 -0
- /runbooks/{security_baseline → security}/utils/__init__.py +0 -0
- /runbooks/{security_baseline → security}/utils/enums.py +0 -0
- /runbooks/{security_baseline → security}/utils/language.py +0 -0
- /runbooks/{security_baseline → security}/utils/level_const.py +0 -0
- /runbooks/{security_baseline → security}/utils/permission_list.py +0 -0
@@ -0,0 +1,406 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
AWS RDS Database Instance Inventory Collection
|
4
|
+
|
5
|
+
A comprehensive RDS database discovery tool for multi-account AWS Organizations that
|
6
|
+
provides detailed database infrastructure visibility across all accounts and regions.
|
7
|
+
Essential for database governance, compliance, and cost optimization initiatives.
|
8
|
+
|
9
|
+
**AWS API Mapping**: `boto3.client('rds').describe_db_instances()`
|
10
|
+
|
11
|
+
Features:
|
12
|
+
- Multi-account RDS instance discovery via AWS Organizations
|
13
|
+
- Database engine and version inventory
|
14
|
+
- Storage allocation and backup status analysis
|
15
|
+
- Instance class and performance tier mapping
|
16
|
+
- Database state and availability monitoring
|
17
|
+
- Cross-region database topology visibility
|
18
|
+
|
19
|
+
Database Governance Use Cases:
|
20
|
+
- Database inventory and asset management
|
21
|
+
- Engine version compliance auditing
|
22
|
+
- Backup policy validation and compliance
|
23
|
+
- Cost optimization through instance right-sizing
|
24
|
+
- Security assessment of database configurations
|
25
|
+
- Disaster recovery planning and validation
|
26
|
+
|
27
|
+
Compatibility:
|
28
|
+
- AWS Organizations with cross-account roles
|
29
|
+
- AWS Control Tower managed accounts
|
30
|
+
- Standalone AWS accounts
|
31
|
+
- All AWS regions including opt-in regions
|
32
|
+
- All RDS engine types (MySQL, PostgreSQL, Oracle, SQL Server, MariaDB, Aurora)
|
33
|
+
|
34
|
+
Example:
|
35
|
+
Discover all RDS instances across organization:
|
36
|
+
```bash
|
37
|
+
python list_rds_db_instances.py --profile my-org-profile
|
38
|
+
```
|
39
|
+
|
40
|
+
Export database inventory to file:
|
41
|
+
```bash
|
42
|
+
python list_rds_db_instances.py --profile my-profile \
|
43
|
+
--save rds_inventory.json --output json
|
44
|
+
```
|
45
|
+
|
46
|
+
Requirements:
|
47
|
+
- IAM permissions: `rds:DescribeDBInstances`, `sts:AssumeRole`
|
48
|
+
- AWS Organizations access (for multi-account scanning)
|
49
|
+
- Python 3.8+ with required dependencies
|
50
|
+
|
51
|
+
Author:
|
52
|
+
AWS Cloud Foundations Team
|
53
|
+
|
54
|
+
Version:
|
55
|
+
2025.04.09
|
56
|
+
"""
|
57
|
+
|
58
|
+
# import boto3
|
59
|
+
import logging
|
60
|
+
import sys
|
61
|
+
from queue import Queue
|
62
|
+
from threading import Thread
|
63
|
+
from time import time
|
64
|
+
|
65
|
+
import Inventory_Modules
|
66
|
+
from ArgumentsClass import CommonArguments
|
67
|
+
from botocore.exceptions import ClientError
|
68
|
+
from colorama import Fore, init
|
69
|
+
from Inventory_Modules import display_results, find_account_rds_instances2, get_all_credentials
|
70
|
+
from tqdm.auto import tqdm
|
71
|
+
|
72
|
+
init()
|
73
|
+
|
74
|
+
__version__ = "2025.04.09"
|
75
|
+
|
76
|
+
|
77
|
+
##################
|
78
|
+
# Functions
|
79
|
+
##################
|
80
|
+
|
81
|
+
|
82
|
+
def parse_args(args):
|
83
|
+
"""
|
84
|
+
Parse and validate command-line arguments for RDS database inventory discovery.
|
85
|
+
|
86
|
+
Configures the argument parser with RDS-specific options for comprehensive
|
87
|
+
database infrastructure discovery across multi-account AWS environments.
|
88
|
+
Uses the standardized CommonArguments framework for consistency.
|
89
|
+
|
90
|
+
Args:
|
91
|
+
args (list): Command-line arguments to parse (typically sys.argv[1:])
|
92
|
+
|
93
|
+
Returns:
|
94
|
+
argparse.Namespace: Parsed arguments containing:
|
95
|
+
- Profiles: AWS profiles for multi-account database discovery
|
96
|
+
- Regions: Target AWS regions for RDS enumeration
|
97
|
+
- AccessRoles: Cross-account roles for Organizations access
|
98
|
+
- RootOnly: Limit to Organization Management Accounts
|
99
|
+
- Filename: Output file prefix for database inventory export
|
100
|
+
- Other standard framework arguments
|
101
|
+
|
102
|
+
Database Discovery Use Cases:
|
103
|
+
- Database asset inventory: Complete RDS instance enumeration
|
104
|
+
- Compliance auditing: Engine version and configuration validation
|
105
|
+
- Cost optimization: Instance class and storage utilization analysis
|
106
|
+
- Backup validation: Backup policy and recovery point assessment
|
107
|
+
- Security assessment: Database configuration and access review
|
108
|
+
- Migration planning: Cross-account database architecture analysis
|
109
|
+
"""
|
110
|
+
parser = CommonArguments()
|
111
|
+
parser.my_parser.description = "We're going to find all rds instances within any of the accounts we have access to, given the profile(s) provided."
|
112
|
+
parser.multiprofile()
|
113
|
+
parser.multiregion()
|
114
|
+
parser.extendedargs()
|
115
|
+
parser.rolestouse()
|
116
|
+
parser.rootOnly()
|
117
|
+
parser.save_to_file()
|
118
|
+
parser.timing()
|
119
|
+
parser.verbosity()
|
120
|
+
parser.version(__version__)
|
121
|
+
return parser.my_parser.parse_args(args)
|
122
|
+
|
123
|
+
|
124
|
+
def check_accounts_for_instances(fAllCredentials: list) -> list:
|
125
|
+
"""
|
126
|
+
Execute multi-threaded RDS database instance discovery across AWS accounts and regions.
|
127
|
+
|
128
|
+
This is the core database infrastructure discovery engine that performs concurrent
|
129
|
+
RDS instance enumeration across all provided AWS accounts and regions. Essential for
|
130
|
+
understanding database architecture, capacity planning, and compliance assessment.
|
131
|
+
|
132
|
+
Args:
|
133
|
+
fAllCredentials (list): List of credential dictionaries containing:
|
134
|
+
- AccountId: AWS account identifier
|
135
|
+
- Region: AWS region name
|
136
|
+
- AccessKeyId, SecretAccessKey, SessionToken: AWS credentials
|
137
|
+
- MgmtAccount: Management account identifier
|
138
|
+
- Success: Boolean flag indicating credential validation status
|
139
|
+
|
140
|
+
Returns:
|
141
|
+
list: Comprehensive RDS database inventory with metadata:
|
142
|
+
- DBId: RDS database instance identifier
|
143
|
+
- Name: Database name (or "No Name" if unspecified)
|
144
|
+
- Engine: Database engine type (MySQL, PostgreSQL, etc.)
|
145
|
+
- InstanceType: RDS instance class (db.t3.micro, etc.)
|
146
|
+
- State: Database instance status
|
147
|
+
- Size: Allocated storage in GB
|
148
|
+
- LastBackup: Latest restorable time for backup validation
|
149
|
+
- AccountNumber: Source AWS account
|
150
|
+
- Region: Source AWS region
|
151
|
+
- MgmtAccount: Management account identifier
|
152
|
+
|
153
|
+
Threading Architecture:
|
154
|
+
- Uses Queue for thread-safe work distribution
|
155
|
+
- Worker thread pool for concurrent database discovery
|
156
|
+
- Progress tracking for large-scale database inventory
|
157
|
+
- Comprehensive error handling for account access failures
|
158
|
+
|
159
|
+
Database Analysis Features:
|
160
|
+
- Engine type and version enumeration
|
161
|
+
- Storage capacity and utilization tracking
|
162
|
+
- Backup status and recovery point validation
|
163
|
+
- Instance class and performance tier analysis
|
164
|
+
- Multi-AZ configuration detection
|
165
|
+
- Cross-account database topology mapping
|
166
|
+
|
167
|
+
Enterprise Use Cases:
|
168
|
+
- Database governance and asset management
|
169
|
+
- Compliance auditing (SOX, PCI DSS, HIPAA)
|
170
|
+
- Cost optimization through right-sizing analysis
|
171
|
+
- Backup policy validation and disaster recovery planning
|
172
|
+
- Security assessment of database configurations
|
173
|
+
- Migration planning and capacity assessment
|
174
|
+
"""
|
175
|
+
|
176
|
+
class FindRDSInstances(Thread):
|
177
|
+
"""
|
178
|
+
Worker thread for concurrent RDS database instance discovery across AWS accounts.
|
179
|
+
|
180
|
+
Each worker thread processes credential sets from the shared queue,
|
181
|
+
calls AWS RDS APIs to discover database instances, and performs detailed
|
182
|
+
metadata extraction including engine types, storage, and backup analysis.
|
183
|
+
|
184
|
+
Database Discovery Capabilities:
|
185
|
+
- RDS instance enumeration with comprehensive metadata
|
186
|
+
- Database engine and version analysis
|
187
|
+
- Storage allocation and backup status assessment
|
188
|
+
- Instance class and performance tier evaluation
|
189
|
+
- Multi-account database inventory aggregation
|
190
|
+
"""
|
191
|
+
|
192
|
+
def __init__(self, queue):
|
193
|
+
"""
|
194
|
+
Initialize worker thread with reference to shared work queue.
|
195
|
+
|
196
|
+
Args:
|
197
|
+
queue (Queue): Thread-safe queue containing RDS discovery work items
|
198
|
+
"""
|
199
|
+
Thread.__init__(self)
|
200
|
+
self.queue = queue
|
201
|
+
|
202
|
+
def run(self):
|
203
|
+
"""
|
204
|
+
Main worker thread execution loop for RDS database instance discovery.
|
205
|
+
|
206
|
+
Continuously processes credential sets from queue, performs database
|
207
|
+
discovery via AWS RDS APIs, and aggregates database infrastructure data
|
208
|
+
with comprehensive metadata extraction and analysis.
|
209
|
+
"""
|
210
|
+
while True:
|
211
|
+
# Get RDS discovery work item from thread-safe queue
|
212
|
+
c_account_credentials = self.queue.get()
|
213
|
+
logging.info(f"De-queued info for account number {c_account_credentials['AccountId']}")
|
214
|
+
|
215
|
+
try:
|
216
|
+
# Call AWS RDS API to discover database instances in this account/region
|
217
|
+
# find_account_rds_instances2() handles DescribeDBInstances API with pagination
|
218
|
+
# This is the most time-intensive operation in the discovery process
|
219
|
+
DBInstances = find_account_rds_instances2(c_account_credentials)
|
220
|
+
logging.info(
|
221
|
+
f"Account: {c_account_credentials['AccountId']} Region: {c_account_credentials['Region']} | Found {len(DBInstances['DBInstances'])} RDS instances"
|
222
|
+
)
|
223
|
+
|
224
|
+
# Process discovered RDS instances with comprehensive metadata extraction
|
225
|
+
if "DBInstances" in DBInstances.keys():
|
226
|
+
for RDSinstance in DBInstances["DBInstances"]:
|
227
|
+
# Extract database name with fallback for unnamed databases
|
228
|
+
# Proper database naming is essential for operational visibility
|
229
|
+
Name = RDSinstance["DBName"] if "DBName" in RDSinstance.keys() else "No Name"
|
230
|
+
|
231
|
+
# Extract backup information for compliance and recovery planning
|
232
|
+
# Critical for disaster recovery and regulatory compliance
|
233
|
+
LastBackup = (
|
234
|
+
RDSinstance["LatestRestorableTime"]
|
235
|
+
if "LatestRestorableTime" in RDSinstance.keys()
|
236
|
+
else "No Backups"
|
237
|
+
)
|
238
|
+
|
239
|
+
# Create comprehensive database record for inventory
|
240
|
+
database_record = {
|
241
|
+
# Organizational context
|
242
|
+
"MgmtAccount": c_account_credentials["MgmtAccount"],
|
243
|
+
"AccountNumber": c_account_credentials["AccountId"],
|
244
|
+
"Region": c_account_credentials["Region"],
|
245
|
+
# Database identification and naming
|
246
|
+
"DBId": RDSinstance["DBInstanceIdentifier"],
|
247
|
+
"Name": Name,
|
248
|
+
# Database engine and performance attributes
|
249
|
+
"Engine": RDSinstance["Engine"],
|
250
|
+
"InstanceType": RDSinstance["DBInstanceClass"],
|
251
|
+
"State": RDSinstance["DBInstanceStatus"],
|
252
|
+
# Storage and backup configuration
|
253
|
+
"Size": RDSinstance["AllocatedStorage"],
|
254
|
+
"LastBackup": LastBackup,
|
255
|
+
}
|
256
|
+
|
257
|
+
# Add to global database inventory collection
|
258
|
+
AllRDSInstances.append(database_record)
|
259
|
+
else:
|
260
|
+
# No RDS instances found in this account/region combination
|
261
|
+
continue
|
262
|
+
except KeyError as my_Error:
|
263
|
+
logging.error(f"Account Access failed - trying to access {c_account_credentials['AccountId']}")
|
264
|
+
logging.info(f"Actual Error: {my_Error}")
|
265
|
+
pass
|
266
|
+
except AttributeError as my_Error:
|
267
|
+
logging.error(f"Error: Likely that one of the supplied profiles was wrong")
|
268
|
+
logging.warning(my_Error)
|
269
|
+
continue
|
270
|
+
except ClientError as my_Error:
|
271
|
+
if "AuthFailure" in str(my_Error):
|
272
|
+
logging.error(
|
273
|
+
f"Authorization Failure accessing account {c_account_credentials['AccountId']} in {c_account_credentials['Region']} region"
|
274
|
+
)
|
275
|
+
logging.warning(
|
276
|
+
f"It's possible that the region {c_account_credentials['Region']} hasn't been opted-into"
|
277
|
+
)
|
278
|
+
continue
|
279
|
+
if my_Error.response["Error"]["Code"] == "AccessDenied":
|
280
|
+
logging.warning(
|
281
|
+
f"Authorization Failure accessing account {c_account_credentials['AccountId']} in {c_account_credentials['Region']} region"
|
282
|
+
)
|
283
|
+
logging.warning(
|
284
|
+
f"It's likely there's an SCP blocking access to this {c_account_credentials['AccountId']} account"
|
285
|
+
)
|
286
|
+
continue
|
287
|
+
else:
|
288
|
+
logging.error(f"Error: Likely throttling errors from too much activity")
|
289
|
+
logging.warning(my_Error)
|
290
|
+
continue
|
291
|
+
finally:
|
292
|
+
pbar.update()
|
293
|
+
self.queue.task_done()
|
294
|
+
|
295
|
+
checkqueue = Queue()
|
296
|
+
|
297
|
+
AllRDSInstances = []
|
298
|
+
WorkerThreads = min(len(fAllCredentials), 25)
|
299
|
+
|
300
|
+
pbar = tqdm(
|
301
|
+
desc=f"Finding RDS instances from {len(fAllCredentials)} locations",
|
302
|
+
total=len(fAllCredentials),
|
303
|
+
unit=" location",
|
304
|
+
)
|
305
|
+
|
306
|
+
for x in range(WorkerThreads):
|
307
|
+
worker = FindRDSInstances(checkqueue)
|
308
|
+
# Setting daemon to True will let the main thread exit even though the workers are blocking
|
309
|
+
worker.daemon = True
|
310
|
+
worker.start()
|
311
|
+
|
312
|
+
for credential in fAllCredentials:
|
313
|
+
logging.info(f"Beginning to queue data - starting with {credential['AccountId']}")
|
314
|
+
try:
|
315
|
+
# I don't know why - but double parens are necessary below. If you remove them, only the first parameter is queued.
|
316
|
+
checkqueue.put((credential))
|
317
|
+
except ClientError as my_Error:
|
318
|
+
if "AuthFailure" in str(my_Error):
|
319
|
+
logging.error(
|
320
|
+
f"Authorization Failure accessing account {credential['AccountId']} in {credential['Region']} region"
|
321
|
+
)
|
322
|
+
logging.warning(f"It's possible that the region {credential['Region']} hasn't been opted-into")
|
323
|
+
pass
|
324
|
+
checkqueue.join()
|
325
|
+
pbar.close()
|
326
|
+
return AllRDSInstances
|
327
|
+
|
328
|
+
|
329
|
+
##################
|
330
|
+
# Main
|
331
|
+
##################
|
332
|
+
|
333
|
+
|
334
|
+
if __name__ == "__main__":
|
335
|
+
args = parse_args(sys.argv[1:])
|
336
|
+
pProfiles = args.Profiles
|
337
|
+
pRegionList = args.Regions
|
338
|
+
pAccounts = args.Accounts
|
339
|
+
pSkipAccounts = args.SkipAccounts
|
340
|
+
pSkipProfiles = args.SkipProfiles
|
341
|
+
pAccessRoles = args.AccessRoles
|
342
|
+
pRootOnly = args.RootOnly
|
343
|
+
pFilename = args.Filename
|
344
|
+
pTiming = args.Time
|
345
|
+
verbose = args.loglevel
|
346
|
+
|
347
|
+
# Setup logging levels
|
348
|
+
logging.basicConfig(level=verbose, format="[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s")
|
349
|
+
logging.getLogger("boto3").setLevel(logging.CRITICAL)
|
350
|
+
logging.getLogger("botocore").setLevel(logging.CRITICAL)
|
351
|
+
logging.getLogger("s3transfer").setLevel(logging.CRITICAL)
|
352
|
+
logging.getLogger("urllib3").setLevel(logging.CRITICAL)
|
353
|
+
|
354
|
+
ERASE_LINE = "\x1b[2K"
|
355
|
+
begin_time = time()
|
356
|
+
logging.info(f"Profiles: {pProfiles}")
|
357
|
+
|
358
|
+
print()
|
359
|
+
print(f"Checking for rds instances... ")
|
360
|
+
print()
|
361
|
+
|
362
|
+
InstancesFound = []
|
363
|
+
AllChildAccounts = []
|
364
|
+
|
365
|
+
# Display RDS Instances found
|
366
|
+
display_dict = {
|
367
|
+
"MgmtAccount": {"DisplayOrder": 1, "Heading": "Mgmt Acct"},
|
368
|
+
"AccountNumber": {"DisplayOrder": 2, "Heading": "Acct Number"},
|
369
|
+
"Region": {"DisplayOrder": 3, "Heading": "Region"},
|
370
|
+
"InstanceType": {"DisplayOrder": 4, "Heading": "Instance Type"},
|
371
|
+
"Name": {"DisplayOrder": 5, "Heading": "DB Name"},
|
372
|
+
"DBId": {"DisplayOrder": 6, "Heading": "Database ID"},
|
373
|
+
"Engine": {"DisplayOrder": 7, "Heading": "DB Engine"},
|
374
|
+
"Size": {"DisplayOrder": 8, "Heading": "Size (GB)"},
|
375
|
+
"LastBackup": {"DisplayOrder": 9, "Heading": "Latest Backup"},
|
376
|
+
"State": {
|
377
|
+
"DisplayOrder": 10,
|
378
|
+
"Heading": "State",
|
379
|
+
"Condition": ["Failed", "Deleting", "Maintenance", "Rebooting", "Upgrading"],
|
380
|
+
},
|
381
|
+
}
|
382
|
+
|
383
|
+
# Get credentials
|
384
|
+
CredentialList = get_all_credentials(
|
385
|
+
pProfiles, pTiming, pSkipProfiles, pSkipAccounts, pRootOnly, pAccounts, pRegionList, pAccessRoles
|
386
|
+
)
|
387
|
+
AccountNum = len(set([acct["AccountId"] for acct in CredentialList]))
|
388
|
+
RegionNum = len(set([acct["Region"] for acct in CredentialList]))
|
389
|
+
|
390
|
+
# Get RDS Instances
|
391
|
+
InstancesFound = check_accounts_for_instances(CredentialList)
|
392
|
+
sorted_results = sorted(
|
393
|
+
InstancesFound, key=lambda d: (d["MgmtAccount"], d["AccountNumber"], d["Region"], d["DBId"])
|
394
|
+
)
|
395
|
+
# unique_results = uniqify_dict(sorted_results)
|
396
|
+
# Display results
|
397
|
+
display_results(sorted_results, display_dict, None, pFilename)
|
398
|
+
|
399
|
+
print(ERASE_LINE)
|
400
|
+
print(f"Found {len(InstancesFound)} instances across {AccountNum} accounts across {RegionNum} regions")
|
401
|
+
if pTiming:
|
402
|
+
print(ERASE_LINE)
|
403
|
+
print(f"{Fore.GREEN}This script took {time() - begin_time:.2f} seconds{Fore.RESET}")
|
404
|
+
print()
|
405
|
+
print("Thank you for using this script")
|
406
|
+
print()
|