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.
Files changed (249) hide show
  1. conftest.py +26 -0
  2. jupyter-agent/.env +2 -0
  3. jupyter-agent/.env.template +2 -0
  4. jupyter-agent/.gitattributes +35 -0
  5. jupyter-agent/.gradio/certificate.pem +31 -0
  6. jupyter-agent/README.md +16 -0
  7. jupyter-agent/__main__.log +8 -0
  8. jupyter-agent/app.py +256 -0
  9. jupyter-agent/cloudops-agent.png +0 -0
  10. jupyter-agent/ds-system-prompt.txt +154 -0
  11. jupyter-agent/jupyter-agent.png +0 -0
  12. jupyter-agent/llama3_template.jinja +123 -0
  13. jupyter-agent/requirements.txt +9 -0
  14. jupyter-agent/tmp/4ojbs8a02ir/jupyter-agent.ipynb +68 -0
  15. jupyter-agent/tmp/cm5iasgpm3p/jupyter-agent.ipynb +91 -0
  16. jupyter-agent/tmp/crqbsseag5/jupyter-agent.ipynb +91 -0
  17. jupyter-agent/tmp/hohanq1u097/jupyter-agent.ipynb +57 -0
  18. jupyter-agent/tmp/jns1sam29wm/jupyter-agent.ipynb +53 -0
  19. jupyter-agent/tmp/jupyter-agent.ipynb +27 -0
  20. jupyter-agent/utils.py +409 -0
  21. runbooks/__init__.py +71 -3
  22. runbooks/__main__.py +13 -0
  23. runbooks/aws/ec2_describe_instances.py +1 -1
  24. runbooks/aws/ec2_run_instances.py +8 -2
  25. runbooks/aws/ec2_start_stop_instances.py +17 -4
  26. runbooks/aws/ec2_unused_volumes.py +5 -1
  27. runbooks/aws/s3_create_bucket.py +4 -2
  28. runbooks/aws/s3_list_objects.py +6 -1
  29. runbooks/aws/tagging_lambda_handler.py +13 -2
  30. runbooks/aws/tags.json +12 -0
  31. runbooks/base.py +353 -0
  32. runbooks/cfat/README.md +49 -0
  33. runbooks/cfat/__init__.py +74 -0
  34. runbooks/cfat/app.ts +644 -0
  35. runbooks/cfat/assessment/__init__.py +40 -0
  36. runbooks/cfat/assessment/asana-import.csv +39 -0
  37. runbooks/cfat/assessment/cfat-checks.csv +31 -0
  38. runbooks/cfat/assessment/cfat.txt +520 -0
  39. runbooks/cfat/assessment/collectors.py +200 -0
  40. runbooks/cfat/assessment/jira-import.csv +39 -0
  41. runbooks/cfat/assessment/runner.py +387 -0
  42. runbooks/cfat/assessment/validators.py +290 -0
  43. runbooks/cfat/cli.py +103 -0
  44. runbooks/cfat/docs/asana-import.csv +24 -0
  45. runbooks/cfat/docs/cfat-checks.csv +31 -0
  46. runbooks/cfat/docs/cfat.txt +335 -0
  47. runbooks/cfat/docs/checks-output.png +0 -0
  48. runbooks/cfat/docs/cloudshell-console-run.png +0 -0
  49. runbooks/cfat/docs/cloudshell-download.png +0 -0
  50. runbooks/cfat/docs/cloudshell-output.png +0 -0
  51. runbooks/cfat/docs/downloadfile.png +0 -0
  52. runbooks/cfat/docs/jira-import.csv +24 -0
  53. runbooks/cfat/docs/open-cloudshell.png +0 -0
  54. runbooks/cfat/docs/report-header.png +0 -0
  55. runbooks/cfat/models.py +1026 -0
  56. runbooks/cfat/package-lock.json +5116 -0
  57. runbooks/cfat/package.json +38 -0
  58. runbooks/cfat/report.py +496 -0
  59. runbooks/cfat/reporting/__init__.py +46 -0
  60. runbooks/cfat/reporting/exporters.py +337 -0
  61. runbooks/cfat/reporting/formatters.py +496 -0
  62. runbooks/cfat/reporting/templates.py +135 -0
  63. runbooks/cfat/run-assessment.sh +23 -0
  64. runbooks/cfat/runner.py +69 -0
  65. runbooks/cfat/src/actions/check-cloudtrail-existence.ts +43 -0
  66. runbooks/cfat/src/actions/check-config-existence.ts +37 -0
  67. runbooks/cfat/src/actions/check-control-tower.ts +37 -0
  68. runbooks/cfat/src/actions/check-ec2-existence.ts +46 -0
  69. runbooks/cfat/src/actions/check-iam-users.ts +50 -0
  70. runbooks/cfat/src/actions/check-legacy-cur.ts +30 -0
  71. runbooks/cfat/src/actions/check-org-cloudformation.ts +30 -0
  72. runbooks/cfat/src/actions/check-vpc-existence.ts +43 -0
  73. runbooks/cfat/src/actions/create-asanaimport.ts +14 -0
  74. runbooks/cfat/src/actions/create-backlog.ts +372 -0
  75. runbooks/cfat/src/actions/create-jiraimport.ts +15 -0
  76. runbooks/cfat/src/actions/create-report.ts +616 -0
  77. runbooks/cfat/src/actions/define-account-type.ts +51 -0
  78. runbooks/cfat/src/actions/get-enabled-org-policy-types.ts +40 -0
  79. runbooks/cfat/src/actions/get-enabled-org-services.ts +26 -0
  80. runbooks/cfat/src/actions/get-idc-info.ts +34 -0
  81. runbooks/cfat/src/actions/get-org-da-accounts.ts +34 -0
  82. runbooks/cfat/src/actions/get-org-details.ts +35 -0
  83. runbooks/cfat/src/actions/get-org-member-accounts.ts +44 -0
  84. runbooks/cfat/src/actions/get-org-ous.ts +35 -0
  85. runbooks/cfat/src/actions/get-regions.ts +22 -0
  86. runbooks/cfat/src/actions/zip-assessment.ts +27 -0
  87. runbooks/cfat/src/types/index.d.ts +147 -0
  88. runbooks/cfat/tests/__init__.py +141 -0
  89. runbooks/cfat/tests/test_cli.py +340 -0
  90. runbooks/cfat/tests/test_integration.py +290 -0
  91. runbooks/cfat/tests/test_models.py +505 -0
  92. runbooks/cfat/tests/test_reporting.py +354 -0
  93. runbooks/cfat/tsconfig.json +16 -0
  94. runbooks/cfat/webpack.config.cjs +27 -0
  95. runbooks/config.py +260 -0
  96. runbooks/finops/README.md +337 -0
  97. runbooks/finops/__init__.py +86 -0
  98. runbooks/finops/aws_client.py +245 -0
  99. runbooks/finops/cli.py +151 -0
  100. runbooks/finops/cost_processor.py +410 -0
  101. runbooks/finops/dashboard_runner.py +448 -0
  102. runbooks/finops/helpers.py +355 -0
  103. runbooks/finops/main.py +14 -0
  104. runbooks/finops/profile_processor.py +174 -0
  105. runbooks/finops/types.py +66 -0
  106. runbooks/finops/visualisations.py +80 -0
  107. runbooks/inventory/.gitignore +354 -0
  108. runbooks/inventory/ArgumentsClass.py +261 -0
  109. runbooks/inventory/FAILED_SCRIPTS_TROUBLESHOOTING.md +619 -0
  110. runbooks/inventory/Inventory_Modules.py +6130 -0
  111. runbooks/inventory/LandingZone/delete_lz.py +1075 -0
  112. runbooks/inventory/PASSED_SCRIPTS_GUIDE.md +738 -0
  113. runbooks/inventory/README.md +1320 -0
  114. runbooks/inventory/__init__.py +62 -0
  115. runbooks/inventory/account_class.py +532 -0
  116. runbooks/inventory/all_my_instances_wrapper.py +123 -0
  117. runbooks/inventory/aws_decorators.py +201 -0
  118. runbooks/inventory/aws_organization.png +0 -0
  119. runbooks/inventory/cfn_move_stack_instances.py +1526 -0
  120. runbooks/inventory/check_cloudtrail_compliance.py +614 -0
  121. runbooks/inventory/check_controltower_readiness.py +1107 -0
  122. runbooks/inventory/check_landingzone_readiness.py +711 -0
  123. runbooks/inventory/cloudtrail.md +727 -0
  124. runbooks/inventory/collectors/__init__.py +20 -0
  125. runbooks/inventory/collectors/aws_compute.py +518 -0
  126. runbooks/inventory/collectors/aws_networking.py +275 -0
  127. runbooks/inventory/collectors/base.py +222 -0
  128. runbooks/inventory/core/__init__.py +19 -0
  129. runbooks/inventory/core/collector.py +303 -0
  130. runbooks/inventory/core/formatter.py +296 -0
  131. runbooks/inventory/delete_s3_buckets_objects.py +169 -0
  132. runbooks/inventory/discovery.md +81 -0
  133. runbooks/inventory/draw_org_structure.py +748 -0
  134. runbooks/inventory/ec2_vpc_utils.py +341 -0
  135. runbooks/inventory/find_cfn_drift_detection.py +272 -0
  136. runbooks/inventory/find_cfn_orphaned_stacks.py +719 -0
  137. runbooks/inventory/find_cfn_stackset_drift.py +733 -0
  138. runbooks/inventory/find_ec2_security_groups.py +669 -0
  139. runbooks/inventory/find_landingzone_versions.py +201 -0
  140. runbooks/inventory/find_vpc_flow_logs.py +1221 -0
  141. runbooks/inventory/inventory.sh +659 -0
  142. runbooks/inventory/list_cfn_stacks.py +558 -0
  143. runbooks/inventory/list_cfn_stackset_operation_results.py +252 -0
  144. runbooks/inventory/list_cfn_stackset_operations.py +734 -0
  145. runbooks/inventory/list_cfn_stacksets.py +453 -0
  146. runbooks/inventory/list_config_recorders_delivery_channels.py +681 -0
  147. runbooks/inventory/list_ds_directories.py +354 -0
  148. runbooks/inventory/list_ec2_availability_zones.py +286 -0
  149. runbooks/inventory/list_ec2_ebs_volumes.py +244 -0
  150. runbooks/inventory/list_ec2_instances.py +425 -0
  151. runbooks/inventory/list_ecs_clusters_and_tasks.py +562 -0
  152. runbooks/inventory/list_elbs_load_balancers.py +411 -0
  153. runbooks/inventory/list_enis_network_interfaces.py +526 -0
  154. runbooks/inventory/list_guardduty_detectors.py +568 -0
  155. runbooks/inventory/list_iam_policies.py +404 -0
  156. runbooks/inventory/list_iam_roles.py +518 -0
  157. runbooks/inventory/list_iam_saml_providers.py +359 -0
  158. runbooks/inventory/list_lambda_functions.py +882 -0
  159. runbooks/inventory/list_org_accounts.py +446 -0
  160. runbooks/inventory/list_org_accounts_users.py +354 -0
  161. runbooks/inventory/list_rds_db_instances.py +406 -0
  162. runbooks/inventory/list_route53_hosted_zones.py +318 -0
  163. runbooks/inventory/list_servicecatalog_provisioned_products.py +575 -0
  164. runbooks/inventory/list_sns_topics.py +360 -0
  165. runbooks/inventory/list_ssm_parameters.py +402 -0
  166. runbooks/inventory/list_vpc_subnets.py +433 -0
  167. runbooks/inventory/list_vpcs.py +422 -0
  168. runbooks/inventory/lockdown_cfn_stackset_role.py +224 -0
  169. runbooks/inventory/models/__init__.py +24 -0
  170. runbooks/inventory/models/account.py +192 -0
  171. runbooks/inventory/models/inventory.py +309 -0
  172. runbooks/inventory/models/resource.py +247 -0
  173. runbooks/inventory/recover_cfn_stack_ids.py +205 -0
  174. runbooks/inventory/requirements.txt +12 -0
  175. runbooks/inventory/run_on_multi_accounts.py +211 -0
  176. runbooks/inventory/tests/common_test_data.py +3661 -0
  177. runbooks/inventory/tests/common_test_functions.py +204 -0
  178. runbooks/inventory/tests/setup.py +24 -0
  179. runbooks/inventory/tests/src.py +18 -0
  180. runbooks/inventory/tests/test_cfn_describe_stacks.py +208 -0
  181. runbooks/inventory/tests/test_ec2_describe_instances.py +162 -0
  182. runbooks/inventory/tests/test_inventory_modules.py +55 -0
  183. runbooks/inventory/tests/test_lambda_list_functions.py +86 -0
  184. runbooks/inventory/tests/test_moto_integration_example.py +273 -0
  185. runbooks/inventory/tests/test_org_list_accounts.py +49 -0
  186. runbooks/inventory/update_aws_actions.py +173 -0
  187. runbooks/inventory/update_cfn_stacksets.py +1215 -0
  188. runbooks/inventory/update_cloudwatch_logs_retention_policy.py +294 -0
  189. runbooks/inventory/update_iam_roles_cross_accounts.py +478 -0
  190. runbooks/inventory/update_s3_public_access_block.py +539 -0
  191. runbooks/inventory/utils/__init__.py +23 -0
  192. runbooks/inventory/utils/aws_helpers.py +510 -0
  193. runbooks/inventory/utils/threading_utils.py +493 -0
  194. runbooks/inventory/utils/validation.py +682 -0
  195. runbooks/inventory/verify_ec2_security_groups.py +1430 -0
  196. runbooks/main.py +1004 -0
  197. runbooks/organizations/__init__.py +12 -0
  198. runbooks/organizations/manager.py +374 -0
  199. runbooks/security/README.md +447 -0
  200. runbooks/security/__init__.py +71 -0
  201. runbooks/{security_baseline → security}/checklist/alternate_contacts.py +8 -1
  202. runbooks/{security_baseline → security}/checklist/bucket_public_access.py +4 -1
  203. runbooks/{security_baseline → security}/checklist/cloudwatch_alarm_configuration.py +9 -2
  204. runbooks/{security_baseline → security}/checklist/guardduty_enabled.py +9 -2
  205. runbooks/{security_baseline → security}/checklist/multi_region_instance_usage.py +5 -1
  206. runbooks/{security_baseline → security}/checklist/root_access_key.py +6 -1
  207. runbooks/{security_baseline → security}/config-origin.json +1 -1
  208. runbooks/{security_baseline → security}/config.json +1 -1
  209. runbooks/{security_baseline → security}/permission.json +1 -1
  210. runbooks/{security_baseline → security}/report_generator.py +10 -2
  211. runbooks/{security_baseline → security}/report_template_en.html +7 -7
  212. runbooks/{security_baseline → security}/report_template_jp.html +7 -7
  213. runbooks/{security_baseline → security}/report_template_kr.html +12 -12
  214. runbooks/{security_baseline → security}/report_template_vn.html +7 -7
  215. runbooks/{security_baseline → security}/run_script.py +8 -2
  216. runbooks/{security_baseline → security}/security_baseline_tester.py +12 -4
  217. runbooks/{security_baseline → security}/utils/common.py +5 -1
  218. runbooks/utils/__init__.py +204 -0
  219. runbooks-0.7.0.dist-info/METADATA +375 -0
  220. runbooks-0.7.0.dist-info/RECORD +249 -0
  221. {runbooks-0.2.5.dist-info → runbooks-0.7.0.dist-info}/WHEEL +1 -1
  222. runbooks-0.7.0.dist-info/entry_points.txt +7 -0
  223. runbooks-0.7.0.dist-info/licenses/LICENSE +201 -0
  224. runbooks-0.7.0.dist-info/top_level.txt +3 -0
  225. runbooks/python101/calculator.py +0 -34
  226. runbooks/python101/config.py +0 -1
  227. runbooks/python101/exceptions.py +0 -16
  228. runbooks/python101/file_manager.py +0 -218
  229. runbooks/python101/toolkit.py +0 -153
  230. runbooks-0.2.5.dist-info/METADATA +0 -439
  231. runbooks-0.2.5.dist-info/RECORD +0 -61
  232. runbooks-0.2.5.dist-info/entry_points.txt +0 -3
  233. runbooks-0.2.5.dist-info/top_level.txt +0 -1
  234. /runbooks/{security_baseline/__init__.py → inventory/tests/script_test_data.py} +0 -0
  235. /runbooks/{security_baseline → security}/checklist/__init__.py +0 -0
  236. /runbooks/{security_baseline → security}/checklist/account_level_bucket_public_access.py +0 -0
  237. /runbooks/{security_baseline → security}/checklist/direct_attached_policy.py +0 -0
  238. /runbooks/{security_baseline → security}/checklist/iam_password_policy.py +0 -0
  239. /runbooks/{security_baseline → security}/checklist/iam_user_mfa.py +0 -0
  240. /runbooks/{security_baseline → security}/checklist/multi_region_trail.py +0 -0
  241. /runbooks/{security_baseline → security}/checklist/root_mfa.py +0 -0
  242. /runbooks/{security_baseline → security}/checklist/root_usage.py +0 -0
  243. /runbooks/{security_baseline → security}/checklist/trail_enabled.py +0 -0
  244. /runbooks/{security_baseline → security}/checklist/trusted_advisor.py +0 -0
  245. /runbooks/{security_baseline → security}/utils/__init__.py +0 -0
  246. /runbooks/{security_baseline → security}/utils/enums.py +0 -0
  247. /runbooks/{security_baseline → security}/utils/language.py +0 -0
  248. /runbooks/{security_baseline → security}/utils/level_const.py +0 -0
  249. /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()