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,568 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ AWS GuardDuty Detector Discovery and Management Script
5
+
6
+ This script provides comprehensive discovery, inventory, and management capabilities for
7
+ AWS GuardDuty detectors and invitations across multiple accounts and regions. It's designed
8
+ for enterprise security teams who need visibility into GuardDuty deployment status,
9
+ detector configuration, and administrative relationships across large-scale AWS environments.
10
+
11
+ Key Features:
12
+ - Multi-account GuardDuty detector discovery using assume role capabilities
13
+ - Multi-region scanning with GuardDuty-enabled region targeting
14
+ - GuardDuty invitation tracking and management for organizational security
15
+ - Administrative account detection with member account relationship mapping
16
+ - Detector deletion capabilities with safety controls for cleanup operations
17
+ - Enterprise reporting with detailed detector and invitation analysis
18
+ - Profile-based authentication with support for federated access
19
+
20
+ Enterprise Use Cases:
21
+ - Security posture assessment and GuardDuty deployment validation
22
+ - GuardDuty administrative relationship mapping across organizations
23
+ - Security service cleanup and consolidation during account transitions
24
+ - Compliance reporting for threat detection service coverage
25
+ - Multi-account security governance and standardization
26
+ - GuardDuty cost optimization through detector lifecycle management
27
+ - Security incident response planning with detector coverage analysis
28
+
29
+ GuardDuty Management Features:
30
+ - Detector enumeration with administrative status identification
31
+ - Member account relationship tracking for security hierarchy mapping
32
+ - Invitation discovery and cleanup for organizational security management
33
+ - Multi-region detector coverage analysis for comprehensive protection
34
+ - Administrative account detection with member count reporting
35
+ - Detector deletion with safety controls and confirmation mechanisms
36
+
37
+ Security Considerations:
38
+ - Uses IAM assume role capabilities for cross-account GuardDuty access
39
+ - Implements proper error handling for authorization failures
40
+ - Supports both read-only discovery and controlled deletion operations
41
+ - Respects GuardDuty service permissions and regional availability constraints
42
+ - Provides comprehensive audit trail through detailed logging
43
+ - Implements safety controls for destructive operations with confirmation prompts
44
+
45
+ GuardDuty Administrative Analysis:
46
+ - Administrative account identification and member relationship mapping
47
+ - Invitation status tracking for organizational security coordination
48
+ - Detector configuration analysis across organizational boundaries
49
+ - Security service coverage assessment for compliance validation
50
+ - Multi-account threat detection architecture documentation
51
+
52
+ Deletion and Cleanup Features:
53
+ - Safe detector deletion with confirmation mechanisms
54
+ - Invitation cleanup for organizational security management
55
+ - Member disassociation handling for administrative relationship changes
56
+ - Comprehensive error handling for cleanup operation failures
57
+ - Audit logging for all deletion and modification operations
58
+
59
+ Performance Considerations:
60
+ - Sequential processing for reliable GuardDuty API operations
61
+ - Progress tracking for operational visibility during large-scale operations
62
+ - Efficient credential management for cross-account security access
63
+ - Region-aware processing optimized for GuardDuty service availability
64
+ - Memory-optimized data structures for large security inventories
65
+
66
+ Dependencies:
67
+ - boto3/botocore for AWS GuardDuty API interactions
68
+ - Inventory_Modules for common utility functions and credential management
69
+ - ArgumentsClass for standardized CLI argument parsing
70
+ - account_class for AWS account access and session management
71
+ - colorama for enhanced output formatting
72
+
73
+ Safety and Compliance:
74
+ - Confirmation prompts for destructive operations
75
+ - Comprehensive logging for security audit trails
76
+ - Error handling for failed deletion operations
77
+ - Member account protection during administrative cleanup
78
+ - Force deletion capability with additional safety controls
79
+
80
+ Future Enhancements:
81
+ - GuardDuty finding analysis and threat intelligence integration
82
+ - Automated detector configuration compliance checking
83
+ - Integration with AWS Config for security service drift detection
84
+ - Cost analysis and optimization recommendations for GuardDuty usage
85
+
86
+ Author: AWS CloudOps Team
87
+ Version: 2023.07.18
88
+ """
89
+
90
+ import logging
91
+ import sys
92
+
93
+ import boto3
94
+ import Inventory_Modules
95
+ from account_class import aws_acct_access
96
+ from ArgumentsClass import CommonArguments
97
+ from botocore.exceptions import ClientError
98
+ from colorama import Fore, init
99
+ from Inventory_Modules import get_all_credentials
100
+
101
+ init()
102
+ __version__ = "2023.07.18"
103
+
104
+ # Parse enterprise command-line arguments with GuardDuty-specific security management options
105
+ parser = CommonArguments()
106
+ parser.singleprofile() # Single profile mode for focused GuardDuty operations
107
+ parser.multiregion_nodefault() # Multi-region scanning without default region assumptions
108
+ parser.extendedargs() # Extended arguments for advanced filtering and account selection
109
+ parser.deletion() # Deletion capabilities with safety controls for GuardDuty cleanup
110
+ parser.rootOnly() # Organization root account limitation for security governance
111
+ parser.rolestouse() # Cross-account roles for Organizations GuardDuty access
112
+ parser.timing() # Performance timing for operational optimization
113
+ parser.verbosity() # Logging verbosity for security operations audit trail
114
+ parser.version(__version__) # Version information for operational documentation
115
+
116
+ # Add GuardDuty-specific deletion and management arguments
117
+ parser.my_parser.add_argument(
118
+ "+delete",
119
+ "+forreal",
120
+ "+fix",
121
+ dest="flagDelete",
122
+ action="store_true",
123
+ help="Enable GuardDuty detector deletion operations - DESTRUCTIVE ACTION with confirmation prompts for security cleanup",
124
+ )
125
+
126
+ # Parse all command-line arguments for GuardDuty security management operations
127
+ args = parser.my_parser.parse_args()
128
+
129
+ # Extract configuration parameters for multi-account GuardDuty security management
130
+ pProfile = args.Profile # AWS profile for GuardDuty administrative access
131
+ pRegions = args.Regions # Target regions for GuardDuty detector enumeration
132
+ pSkipAccounts = args.SkipAccounts # Account exclusion list for organizational policy compliance
133
+ pSkipProfiles = args.SkipProfiles # Profile exclusion for credential optimization
134
+ pAccounts = args.Accounts # Specific account targeting for focused security analysis
135
+ pRootOnly = args.RootOnly # Organization root account limitation flag
136
+ pRolesToUse = args.AccessRoles # Cross-account roles for Organizations security access
137
+ verbose = args.loglevel # Logging verbosity for security operations visibility
138
+ DeletionRun = args.flagDelete # Enable detector deletion operations - CRITICAL SECURITY FLAG
139
+ ForceDelete = args.Force # Override safety confirmations for automated security workflows
140
+ pTiming = args.Time # Performance timing for operational optimization
141
+
142
+ # Configure enterprise logging infrastructure for GuardDuty operations audit trail
143
+ logging.basicConfig(level=verbose, format="[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s")
144
+ logging.getLogger("boto3").setLevel(logging.CRITICAL)
145
+ logging.getLogger("botocore").setLevel(logging.CRITICAL)
146
+ logging.getLogger("s3transfer").setLevel(logging.CRITICAL)
147
+ logging.getLogger("urllib3").setLevel(logging.CRITICAL)
148
+
149
+ ##########################
150
+ # Initialize enterprise GuardDuty discovery and security management operations
151
+ ##########################
152
+
153
+ ERASE_LINE = "\x1b[2K"
154
+
155
+ # Initialize AWS account access for GuardDuty administrative operations
156
+ aws_acct = aws_acct_access(pProfile)
157
+
158
+ # Initialize enterprise GuardDuty inventory tracking and metrics
159
+ NumObjectsFound = 0 # Total detector count across all accounts and regions
160
+ session_gd = aws_acct.session # Primary session for GuardDuty administrative operations
161
+ all_gd_detectors = [] # Comprehensive detector inventory with administrative relationships
162
+ all_gd_invites = [] # GuardDuty invitation tracking for organizational security coordination
163
+ GD_Admin_Accounts = [] # Administrative account tracking for security hierarchy mapping
164
+
165
+ # Configure GuardDuty-enabled regions for comprehensive threat detection coverage
166
+ # This validation ensures we only scan regions where GuardDuty service is available and enabled
167
+ if pRegions is None:
168
+ pRegions = ["all"] # Default to all available GuardDuty regions for comprehensive security coverage
169
+
170
+ # Discover GuardDuty-enabled regions across organizational accounts
171
+ gd_regions = Inventory_Modules.get_regions3(aws_acct, pRegions)
172
+
173
+ # Execute enterprise credential discovery and validation across organizational GuardDuty infrastructure
174
+ AllCredentials = get_all_credentials(
175
+ pProfile, pTiming, pSkipProfiles, pSkipAccounts, pRootOnly, pAccounts, gd_regions, pRolesToUse
176
+ )
177
+
178
+ # Calculate organizational scope for executive security management reporting
179
+ RegionList = list(set([x["Region"] for x in AllCredentials]))
180
+ AccountList = list(set([x["AccountId"] for x in AllCredentials]))
181
+ print(f"Searching {len(AccountList)} accounts and {len(RegionList)} regions for GuardDuty detectors")
182
+
183
+ # Initialize STS session for cross-account credential validation and security token management
184
+ sts_session = aws_acct.session
185
+ sts_client = sts_session.client("sts")
186
+
187
+ # Execute comprehensive GuardDuty detector and invitation discovery across organizational accounts
188
+ places_to_try = len(AllCredentials) # Progress tracking for operational visibility
189
+
190
+ # Main GuardDuty discovery loop - Sequential processing for reliable security service enumeration
191
+ for credential in AllCredentials:
192
+ logging.info(f"Checking Account: {credential['AccountId']}")
193
+
194
+ # Legacy credential access pattern (commented out for reference)
195
+ # This was the original approach for cross-account access before credential pre-processing
196
+ # try:
197
+ # account_credentials = Inventory_Modules.get_child_access3(aws_acct, account['AccountId'])
198
+ # except ClientError as my_Error:
199
+ # if "AuthFailure" in str(my_Error):
200
+ # print(f"Authorization Failure for account {account['AccountId']}")
201
+ # sys.exit("Credentials failure")
202
+
203
+ logging.info(f"Checking Region: {credential['Region']}")
204
+ places_to_try -= 1 # Decrement progress counter for operational tracking
205
+
206
+ try:
207
+ # Establish AWS session for GuardDuty API operations using pre-validated credentials
208
+ # This session enables cross-account GuardDuty detector and invitation discovery
209
+ session_aws = boto3.Session(
210
+ aws_access_key_id=credential["AccessKeyId"],
211
+ aws_secret_access_key=credential["SecretAccessKey"],
212
+ aws_session_token=credential["SessionToken"],
213
+ region_name=credential["Region"],
214
+ )
215
+
216
+ # Initialize GuardDuty client for security service API operations
217
+ client_aws = session_aws.client("guardduty")
218
+ logging.debug(f"Token Info: {credential} in region {credential['Region']}")
219
+
220
+ # Execute GuardDuty invitation discovery for organizational security coordination
221
+ # Invitations represent pending or active administrative relationships between accounts
222
+ logging.info(f"Finding any invites for account: {credential['AccountId']} in region {credential['Region']}")
223
+ response = client_aws.list_invitations()
224
+ logging.debug(
225
+ f"Finished listing invites for account: {credential['AccountId']} in region {credential['Region']}"
226
+ )
227
+
228
+ except ClientError as my_Error:
229
+ # Handle AWS API authorization failures with comprehensive error analysis
230
+ if "AuthFailure" in str(my_Error):
231
+ print(f"{credential['AccountId']}: Authorization Failure for account {credential['AccountId']}")
232
+ continue # Skip this account/region combination but continue processing others
233
+
234
+ # Handle invalid security token errors typically caused by region opt-in issues
235
+ if str(my_Error).find("security token included in the request is invalid") > 0:
236
+ logging.error(
237
+ f"Account #:{credential['AccountId']} - The region you're trying '{credential['Region']}' isn't enabled for your account"
238
+ )
239
+ continue # Skip disabled regions but continue with other regions
240
+
241
+ except Exception as my_Error:
242
+ # Handle unexpected errors during GuardDuty API operations
243
+ print(my_Error)
244
+ continue # Continue processing despite unexpected errors for operational resilience
245
+ # Process discovered GuardDuty invitations for organizational security coordination
246
+ try:
247
+ if "Invitations" in response.keys():
248
+ # Process each invitation to build comprehensive security relationship mapping
249
+ for i in range(len(response["Invitations"])):
250
+ # Create invitation record with credentials for future management operations
251
+ invitation_record = {
252
+ "AccountId": response["Invitations"][i]["AccountId"], # Administrative account identifier
253
+ "InvitationId": response["Invitations"][i]["InvitationId"], # Unique invitation identifier
254
+ "Region": credential["Region"], # Regional context for security coordination
255
+ "AccessKeyId": credential["AccessKeyId"], # Credentials for invitation management
256
+ "SecretAccessKey": credential["SecretAccessKey"], # Security credentials for API operations
257
+ "SessionToken": credential["SessionToken"], # Session token for temporary access
258
+ }
259
+
260
+ # Add to enterprise GuardDuty invitation inventory for administrative tracking
261
+ all_gd_invites.append(invitation_record)
262
+
263
+ # Log invitation discovery for security audit trail and organizational visibility
264
+ logging.error(
265
+ f"Found invite ID {response['Invitations'][i]['InvitationId']} in account {response['Invitations'][i]['AccountId']} in region {credential['Region']}"
266
+ )
267
+ except NameError:
268
+ # Handle cases where response variable is undefined due to API errors
269
+ # This ensures graceful handling of failed invitation discovery operations
270
+ pass
271
+ # Execute comprehensive GuardDuty detector discovery with administrative relationship analysis
272
+ try:
273
+ # Display progress information for operational visibility during large-scale security operations
274
+ print(
275
+ f"{ERASE_LINE}Trying account {credential['AccountId']} in region {credential['Region']} -- {places_to_try} left of {len(AllCredentials)}",
276
+ end="\r",
277
+ )
278
+
279
+ # Execute GuardDuty detector enumeration for security service inventory
280
+ response = client_aws.list_detectors()
281
+
282
+ # Process discovered detectors with comprehensive metadata extraction and administrative analysis
283
+ if len(response["DetectorIds"]) > 0:
284
+ # Update enterprise security service metrics and tracking
285
+ NumObjectsFound = NumObjectsFound + len(response["DetectorIds"])
286
+
287
+ # Analyze administrative relationships and member account associations
288
+ # This is critical for understanding GuardDuty security hierarchy and governance structure
289
+ admin_acct_response = client_aws.list_members(
290
+ DetectorId=str(response["DetectorIds"][0]),
291
+ OnlyAssociated="False", # Include both associated and pending member accounts
292
+ )
293
+
294
+ # Log detector discovery for security audit trail and operational tracking
295
+ logging.warning(
296
+ f"Found another detector {str(response['DetectorIds'][0])} in account {credential['AccountId']} in region {credential['Region']} bringing the total found to {str(NumObjectsFound)}"
297
+ )
298
+
299
+ # Classify detector as administrative account based on member relationships
300
+ if len(admin_acct_response["Members"]) > 0:
301
+ # Create comprehensive administrative account record for security governance
302
+ admin_detector_record = {
303
+ "AccountId": credential["AccountId"], # Administrative account identifier
304
+ "Region": credential["Region"], # Regional context for security operations
305
+ "DetectorIds": response["DetectorIds"], # GuardDuty detector identifiers
306
+ "AccessKeyId": credential["AccessKeyId"], # Administrative credentials for management
307
+ "SecretAccessKey": credential["SecretAccessKey"], # Security credentials for detector operations
308
+ "SessionToken": credential["SessionToken"], # Session token for administrative access
309
+ "GD_Admin_Accounts": admin_acct_response[
310
+ "Members"
311
+ ], # Member account relationships for hierarchy mapping
312
+ }
313
+
314
+ # Add to enterprise GuardDuty administrative account inventory
315
+ all_gd_detectors.append(admin_detector_record)
316
+
317
+ # Log administrative account discovery for security governance visibility
318
+ logging.error(
319
+ f"Found account {credential['AccountId']} in region {credential['Region']} to be a GuardDuty Admin account."
320
+ f"It has {len(admin_acct_response['Members'])} member accounts connected to detector {response['DetectorIds'][0]}"
321
+ )
322
+ else:
323
+ # Create standard detector record for non-administrative accounts
324
+ standard_detector_record = {
325
+ "AccountId": credential["AccountId"], # Standard account identifier
326
+ "Region": credential["Region"], # Regional context for security coverage
327
+ "DetectorIds": response["DetectorIds"], # GuardDuty detector identifiers
328
+ "AccessKeyId": credential["AccessKeyId"], # Account credentials for detector management
329
+ "SecretAccessKey": credential["SecretAccessKey"], # Security credentials for API operations
330
+ "SessionToken": credential["SessionToken"], # Session token for detector access
331
+ "GD_Admin_Accounts": "Not an Admin Account", # Administrative status flag for classification
332
+ }
333
+
334
+ # Add to enterprise GuardDuty detector inventory for comprehensive security tracking
335
+ all_gd_detectors.append(standard_detector_record)
336
+ else:
337
+ # Display progress for accounts without GuardDuty detectors for operational visibility
338
+ print(
339
+ ERASE_LINE,
340
+ f"{Fore.RED}No luck in account: {credential['AccountId']} in region {credential['Region']}{Fore.RESET} -- {places_to_try} of {len(AllCredentials)}",
341
+ end="\r",
342
+ )
343
+ except ClientError as my_Error:
344
+ # Handle AWS API authorization failures during detector discovery operations
345
+ if "AuthFailure" in str(my_Error):
346
+ print(f"Authorization Failure for account {credential['AccountId']}")
347
+
348
+ # Configure enterprise GuardDuty report display formatting and column organization
349
+ display_dict = {
350
+ "ParentProfile": {
351
+ "DisplayOrder": 1,
352
+ "Heading": "Parent Profile",
353
+ }, # AWS profile context for organizational hierarchy
354
+ "MgmtAccount": {"DisplayOrder": 2, "Heading": "Mgmt Acct"}, # Management account identifier for security governance
355
+ "AccountId": {"DisplayOrder": 3, "Heading": "Acct Number"}, # Target account containing GuardDuty detectors
356
+ "Region": {
357
+ "DisplayOrder": 4,
358
+ "Heading": "Region",
359
+ "Condition": ["us-east-2"],
360
+ }, # AWS region for geographic security coverage
361
+ "DetectorIds": {
362
+ "DisplayOrder": 5,
363
+ "Heading": "DetectorId",
364
+ "Condition": ["Never"],
365
+ }, # GuardDuty detector identifiers for management
366
+ "DG_Admin_Accounts": {
367
+ "DisplayOrder": 6,
368
+ "Heading": "Admin Accounts",
369
+ }, # Administrative account relationships for security hierarchy
370
+ "Size": {"DisplayOrder": 7, "Heading": "Size (Bytes)"},
371
+ }
372
+
373
+ # Generate detailed GuardDuty detector report with administrative relationship analysis
374
+ if args.loglevel < 50:
375
+ print()
376
+ # Configure table formatting for enterprise GuardDuty security reporting
377
+ fmt = "%-20s %-15s %-35s %-25s"
378
+ print(fmt % ("Account", "Region", "DetectorId", "Admin Status"))
379
+ print(fmt % ("----------", "------", "-----------", "--------------------"))
380
+
381
+ # Display comprehensive GuardDuty detector inventory with administrative relationships
382
+ for i in range(len(all_gd_detectors)):
383
+ try:
384
+ # Process administrative GuardDuty accounts with member account relationships
385
+ if "AccountId" in all_gd_detectors[i]["GD_Admin_Accounts"][0].keys():
386
+ print(
387
+ fmt
388
+ % (
389
+ all_gd_detectors[i]["AccountId"], # Administrative account identifier
390
+ all_gd_detectors[i]["Region"], # Regional security coverage context
391
+ all_gd_detectors[i]["DetectorIds"], # GuardDuty detector identifiers for management
392
+ f"{len(all_gd_detectors[i]['GD_Admin_Accounts'])} Member Accounts", # Member account count for hierarchy mapping
393
+ )
394
+ )
395
+ except AttributeError:
396
+ # Display standard GuardDuty detectors without administrative relationships
397
+ print(
398
+ fmt
399
+ % (
400
+ all_gd_detectors[i]["AccountId"], # Standard account identifier
401
+ all_gd_detectors[i]["Region"], # Regional security coverage context
402
+ all_gd_detectors[i]["DetectorIds"], # GuardDuty detector identifiers
403
+ "Not an Admin Account", # Administrative status classification
404
+ )
405
+ )
406
+
407
+ # Display comprehensive GuardDuty discovery summary for enterprise security reporting
408
+ print(ERASE_LINE)
409
+ print(
410
+ f"We scanned {len(AccountList)} accounts and {len(RegionList)} regions totalling {len(AllCredentials)} possible areas for resources."
411
+ )
412
+ print(f"Found {len(all_gd_invites)} Invites and {NumObjectsFound} Detectors")
413
+ print()
414
+
415
+ # Execute GuardDuty detector deletion workflow with comprehensive safety controls
416
+ # CRITICAL SECURITY OPERATION: Detector deletion is irreversible and impacts organizational security
417
+ if DeletionRun and not ForceDelete:
418
+ # Interactive confirmation for safe GuardDuty detector deletion operations
419
+ # This mandatory confirmation prevents accidental security service disruption
420
+ ReallyDelete = input("Deletion of Guard Duty detectors has been requested. Are you still sure? (y/n): ") == "y"
421
+ else:
422
+ ReallyDelete = False # Default to safe mode preventing accidental deletions
423
+
424
+ # Execute comprehensive GuardDuty cleanup operations with safety controls and audit logging
425
+ if DeletionRun and (ReallyDelete or ForceDelete):
426
+ MemberList = [] # Initialize member account tracking for deletion operations
427
+
428
+ # Begin GuardDuty invitation cleanup for organizational security coordination
429
+ logging.warning("Deleting all invites")
430
+
431
+ # Process all discovered GuardDuty invitations for comprehensive cleanup operations
432
+ for y in range(len(all_gd_invites)):
433
+ # Establish AWS session for GuardDuty invitation deletion operations
434
+ # Using pre-validated credentials from invitation discovery phase
435
+ session_gd_child = boto3.Session(
436
+ aws_access_key_id=all_gd_invites[y]["AccessKeyId"], # Account credentials for invitation management
437
+ aws_secret_access_key=all_gd_invites[y]["SecretAccessKey"], # Security credentials for API operations
438
+ aws_session_token=all_gd_invites[y]["SessionToken"], # Session token for temporary access
439
+ region_name=all_gd_invites[y]["Region"], # Regional context for invitation operations
440
+ )
441
+
442
+ # Initialize GuardDuty client for invitation deletion API operations
443
+ client_gd_child = session_gd_child.client("guardduty")
444
+
445
+ # Execute GuardDuty invitation deletion with comprehensive error handling and audit logging
446
+ try:
447
+ # Display progress for invitation deletion operations with real-time visibility
448
+ print(ERASE_LINE, f"Deleting invite for Account {all_gd_invites[y]['AccountId']}", end="\r")
449
+
450
+ # Execute invitation deletion API operation with security audit logging
451
+ Output = client_gd_child.delete_invitations(AccountIds=[all_gd_invites[y]["AccountId"]])
452
+
453
+ except Exception as e:
454
+ # Handle expected BadRequest exceptions during invitation cleanup operations
455
+ if e.response["Error"]["Code"] == "BadRequestException":
456
+ logging.warning("Caught exception 'BadRequestException', handling the exception...")
457
+ pass # Continue processing remaining invitations despite individual failures
458
+ else:
459
+ # Handle unexpected errors during GuardDuty invitation deletion operations
460
+ print("Caught unexpected error regarding deleting invites")
461
+ print(e)
462
+ sys.exit(9) # Exit with error code for operational failure handling
463
+
464
+ # Report invitation deletion completion for security audit trail
465
+ print(f"Removed {len(all_gd_invites)} GuardDuty Invites")
466
+
467
+ # Begin comprehensive GuardDuty detector deletion operations
468
+ num_of_gd_detectors = len(all_gd_detectors)
469
+
470
+ # Process all discovered GuardDuty detectors for systematic cleanup operations
471
+ for y in range(len(all_gd_detectors)):
472
+ # Log detector deletion initiation for comprehensive security audit trail
473
+ logging.info(
474
+ f"Deleting detector-id: {all_gd_detectors[y]['DetectorIds']} from account {all_gd_detectors[y]['AccountId']} in region {all_gd_detectors[y]['Region']}"
475
+ )
476
+
477
+ # Display progress for detector deletion operations with operational visibility
478
+ print(
479
+ f"Deleting detector in account {all_gd_detectors[y]['AccountId']} in region {all_gd_detectors[y]['Region']} {num_of_gd_detectors}/{len(all_gd_detectors)}"
480
+ )
481
+
482
+ # Establish AWS session for GuardDuty detector deletion operations with pre-validated credentials
483
+ session_gd_child = boto3.Session(
484
+ aws_access_key_id=all_gd_detectors[y]["AccessKeyId"], # Account credentials for detector management
485
+ aws_secret_access_key=all_gd_detectors[y]["SecretAccessKey"], # Security credentials for API operations
486
+ aws_session_token=all_gd_detectors[y]["SessionToken"], # Session token for temporary access
487
+ region_name=all_gd_detectors[y]["Region"], # Regional context for detector operations
488
+ )
489
+
490
+ # Initialize GuardDuty client for detector deletion API operations
491
+ client_gd_child = session_gd_child.client("guardduty")
492
+
493
+ # Execute member account discovery for comprehensive administrative relationship cleanup
494
+ # This is critical for proper GuardDuty hierarchy dismantling before detector deletion
495
+ Member_Dict = client_gd_child.list_members(
496
+ DetectorId=str(all_gd_detectors[y]["DetectorIds"][0]), # Primary detector identifier for member enumeration
497
+ OnlyAssociated="FALSE", # Include both associated and pending member accounts for complete cleanup
498
+ )["Members"]
499
+
500
+ # Aggregate member account list for batch disassociation operations
501
+ for i in range(len(Member_Dict)):
502
+ MemberList.append(Member_Dict[i]["AccountId"]) # Collect member accounts for comprehensive cleanup
503
+
504
+ try:
505
+ # Initialize deletion operation status tracking for operational monitoring
506
+ Output = 0
507
+
508
+ # Execute master account disassociation for proper GuardDuty hierarchy cleanup
509
+ # This critical step must precede detector deletion to prevent orphaned relationships
510
+ client_gd_child.disassociate_from_master_account(DetectorId=str(all_gd_detectors[y]["DetectorIds"][0]))
511
+ except Exception as e:
512
+ # Handle expected BadRequest exceptions during master account disassociation
513
+ if e.response["Error"]["Code"] == "BadRequestException":
514
+ logging.warning("Caught exception 'BadRequestException', handling the exception...")
515
+ pass # Continue with member disassociation despite master account errors
516
+
517
+ # Execute comprehensive member account disassociation for administrative relationship cleanup
518
+ # Critical step for proper GuardDuty hierarchy dismantling before detector deletion
519
+ if MemberList: # Process member accounts only when administrative relationships exist
520
+ # Disassociate member accounts from administrative detector for proper cleanup
521
+ client_gd_child.disassociate_members(
522
+ AccountIds=MemberList, # Member account list for batch disassociation
523
+ DetectorId=str(all_gd_detectors[y]["DetectorIds"][0]), # Administrative detector identifier
524
+ )
525
+
526
+ # Log member disassociation completion for security audit trail
527
+ logging.warning(
528
+ f"Account {str(all_gd_detectors[y]['AccountId'])} has been disassociated from master account"
529
+ )
530
+
531
+ # Execute member account deletion from administrative detector for complete cleanup
532
+ client_gd_child.delete_members(
533
+ AccountIds=[all_gd_detectors[y]["AccountId"]], # Target account for member deletion
534
+ DetectorId=str(all_gd_detectors[y]["DetectorIds"][0]), # Administrative detector context
535
+ )
536
+
537
+ # Log member deletion completion for comprehensive security audit trail
538
+ logging.warning(f"Account {str(all_gd_detectors[y]['AccountId'])} has been deleted from master account")
539
+
540
+ # Execute final GuardDuty detector deletion after all relationships are properly cleaned up
541
+ # This is the terminal operation that permanently removes the GuardDuty detector
542
+ client_gd_child.delete_detector(DetectorId=str(all_gd_detectors[y]["DetectorIds"][0]))
543
+
544
+ # Log detector deletion completion for comprehensive security audit trail and operational confirmation
545
+ logging.warning(
546
+ f"Detector {str(all_gd_detectors[y]['DetectorIds'][0])} has been deleted from child account "
547
+ f"{str(all_gd_detectors[y]['AccountId'])}"
548
+ )
549
+
550
+ # Update progress counter for operational visibility during large-scale cleanup operations
551
+ num_of_gd_detectors -= 1
552
+ # Legacy CloudFormation stack deletion code (commented out for reference)
553
+ # This was the original approach for GuardDuty cleanup via CloudFormation stacks
554
+ # Replaced with direct GuardDuty API operations for more granular control
555
+ """
556
+ if StacksFound[y][3] == 'DELETE_FAILED':
557
+ response=Inventory_Modules.delete_stack(StacksFound[y][0],StacksFound[y][1],StacksFound[y][2],RetainResources=True,ResourcesToRetain=["MasterDetector"])
558
+ else:
559
+ response=Inventory_Modules.delete_stack(StacksFound[y][0],StacksFound[y][1],StacksFound[y][2])
560
+ """
561
+
562
+ # Handle non-deletion scenarios with appropriate user messaging for operational clarity
563
+ elif not DeletionRun or (DeletionRun and not ReallyDelete):
564
+ print("Client didn't want to delete detectors... ")
565
+
566
+ print()
567
+ print("Thank you for using this tool")
568
+ print()