runbooks 0.7.0__py3-none-any.whl → 0.7.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. runbooks/__init__.py +87 -37
  2. runbooks/cfat/README.md +300 -49
  3. runbooks/cfat/__init__.py +2 -2
  4. runbooks/finops/__init__.py +1 -1
  5. runbooks/finops/cli.py +1 -1
  6. runbooks/inventory/collectors/__init__.py +8 -0
  7. runbooks/inventory/collectors/aws_management.py +791 -0
  8. runbooks/inventory/collectors/aws_networking.py +3 -3
  9. runbooks/main.py +3389 -782
  10. runbooks/operate/__init__.py +207 -0
  11. runbooks/operate/base.py +311 -0
  12. runbooks/operate/cloudformation_operations.py +619 -0
  13. runbooks/operate/cloudwatch_operations.py +496 -0
  14. runbooks/operate/dynamodb_operations.py +812 -0
  15. runbooks/operate/ec2_operations.py +926 -0
  16. runbooks/operate/iam_operations.py +569 -0
  17. runbooks/operate/s3_operations.py +1211 -0
  18. runbooks/operate/tagging_operations.py +655 -0
  19. runbooks/remediation/CLAUDE.md +100 -0
  20. runbooks/remediation/DOME9.md +218 -0
  21. runbooks/remediation/README.md +26 -0
  22. runbooks/remediation/Tests/__init__.py +0 -0
  23. runbooks/remediation/Tests/update_policy.py +74 -0
  24. runbooks/remediation/__init__.py +95 -0
  25. runbooks/remediation/acm_cert_expired_unused.py +98 -0
  26. runbooks/remediation/acm_remediation.py +875 -0
  27. runbooks/remediation/api_gateway_list.py +167 -0
  28. runbooks/remediation/base.py +643 -0
  29. runbooks/remediation/cloudtrail_remediation.py +908 -0
  30. runbooks/remediation/cloudtrail_s3_modifications.py +296 -0
  31. runbooks/remediation/cognito_active_users.py +78 -0
  32. runbooks/remediation/cognito_remediation.py +856 -0
  33. runbooks/remediation/cognito_user_password_reset.py +163 -0
  34. runbooks/remediation/commons.py +455 -0
  35. runbooks/remediation/dynamodb_optimize.py +155 -0
  36. runbooks/remediation/dynamodb_remediation.py +744 -0
  37. runbooks/remediation/dynamodb_server_side_encryption.py +108 -0
  38. runbooks/remediation/ec2_public_ips.py +134 -0
  39. runbooks/remediation/ec2_remediation.py +892 -0
  40. runbooks/remediation/ec2_subnet_disable_auto_ip_assignment.py +72 -0
  41. runbooks/remediation/ec2_unattached_ebs_volumes.py +448 -0
  42. runbooks/remediation/ec2_unused_security_groups.py +202 -0
  43. runbooks/remediation/kms_enable_key_rotation.py +651 -0
  44. runbooks/remediation/kms_remediation.py +717 -0
  45. runbooks/remediation/lambda_list.py +243 -0
  46. runbooks/remediation/lambda_remediation.py +971 -0
  47. runbooks/remediation/multi_account.py +569 -0
  48. runbooks/remediation/rds_instance_list.py +199 -0
  49. runbooks/remediation/rds_remediation.py +873 -0
  50. runbooks/remediation/rds_snapshot_list.py +192 -0
  51. runbooks/remediation/requirements.txt +118 -0
  52. runbooks/remediation/s3_block_public_access.py +159 -0
  53. runbooks/remediation/s3_bucket_public_access.py +143 -0
  54. runbooks/remediation/s3_disable_static_website_hosting.py +74 -0
  55. runbooks/remediation/s3_downloader.py +215 -0
  56. runbooks/remediation/s3_enable_access_logging.py +562 -0
  57. runbooks/remediation/s3_encryption.py +526 -0
  58. runbooks/remediation/s3_force_ssl_secure_policy.py +143 -0
  59. runbooks/remediation/s3_list.py +141 -0
  60. runbooks/remediation/s3_object_search.py +201 -0
  61. runbooks/remediation/s3_remediation.py +816 -0
  62. runbooks/remediation/scan_for_phrase.py +425 -0
  63. runbooks/remediation/workspaces_list.py +220 -0
  64. runbooks/security/__init__.py +9 -10
  65. runbooks/security/security_baseline_tester.py +4 -2
  66. runbooks-0.7.6.dist-info/METADATA +608 -0
  67. {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/RECORD +84 -76
  68. {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/entry_points.txt +0 -1
  69. {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/top_level.txt +0 -1
  70. jupyter-agent/.env +0 -2
  71. jupyter-agent/.env.template +0 -2
  72. jupyter-agent/.gitattributes +0 -35
  73. jupyter-agent/.gradio/certificate.pem +0 -31
  74. jupyter-agent/README.md +0 -16
  75. jupyter-agent/__main__.log +0 -8
  76. jupyter-agent/app.py +0 -256
  77. jupyter-agent/cloudops-agent.png +0 -0
  78. jupyter-agent/ds-system-prompt.txt +0 -154
  79. jupyter-agent/jupyter-agent.png +0 -0
  80. jupyter-agent/llama3_template.jinja +0 -123
  81. jupyter-agent/requirements.txt +0 -9
  82. jupyter-agent/tmp/4ojbs8a02ir/jupyter-agent.ipynb +0 -68
  83. jupyter-agent/tmp/cm5iasgpm3p/jupyter-agent.ipynb +0 -91
  84. jupyter-agent/tmp/crqbsseag5/jupyter-agent.ipynb +0 -91
  85. jupyter-agent/tmp/hohanq1u097/jupyter-agent.ipynb +0 -57
  86. jupyter-agent/tmp/jns1sam29wm/jupyter-agent.ipynb +0 -53
  87. jupyter-agent/tmp/jupyter-agent.ipynb +0 -27
  88. jupyter-agent/utils.py +0 -409
  89. runbooks/aws/__init__.py +0 -58
  90. runbooks/aws/dynamodb_operations.py +0 -231
  91. runbooks/aws/ec2_copy_image_cross-region.py +0 -195
  92. runbooks/aws/ec2_describe_instances.py +0 -202
  93. runbooks/aws/ec2_ebs_snapshots_delete.py +0 -186
  94. runbooks/aws/ec2_run_instances.py +0 -213
  95. runbooks/aws/ec2_start_stop_instances.py +0 -212
  96. runbooks/aws/ec2_terminate_instances.py +0 -143
  97. runbooks/aws/ec2_unused_eips.py +0 -196
  98. runbooks/aws/ec2_unused_volumes.py +0 -188
  99. runbooks/aws/s3_create_bucket.py +0 -142
  100. runbooks/aws/s3_list_buckets.py +0 -152
  101. runbooks/aws/s3_list_objects.py +0 -156
  102. runbooks/aws/s3_object_operations.py +0 -183
  103. runbooks/aws/tagging_lambda_handler.py +0 -183
  104. runbooks/inventory/FAILED_SCRIPTS_TROUBLESHOOTING.md +0 -619
  105. runbooks/inventory/PASSED_SCRIPTS_GUIDE.md +0 -738
  106. runbooks/inventory/aws_organization.png +0 -0
  107. runbooks/inventory/cfn_move_stack_instances.py +0 -1526
  108. runbooks/inventory/delete_s3_buckets_objects.py +0 -169
  109. runbooks/inventory/lockdown_cfn_stackset_role.py +0 -224
  110. runbooks/inventory/update_aws_actions.py +0 -173
  111. runbooks/inventory/update_cfn_stacksets.py +0 -1215
  112. runbooks/inventory/update_cloudwatch_logs_retention_policy.py +0 -294
  113. runbooks/inventory/update_iam_roles_cross_accounts.py +0 -478
  114. runbooks/inventory/update_s3_public_access_block.py +0 -539
  115. runbooks/organizations/__init__.py +0 -12
  116. runbooks/organizations/manager.py +0 -374
  117. runbooks-0.7.0.dist-info/METADATA +0 -375
  118. /runbooks/inventory/{tests → Tests}/common_test_data.py +0 -0
  119. /runbooks/inventory/{tests → Tests}/common_test_functions.py +0 -0
  120. /runbooks/inventory/{tests → Tests}/script_test_data.py +0 -0
  121. /runbooks/inventory/{tests → Tests}/setup.py +0 -0
  122. /runbooks/inventory/{tests → Tests}/src.py +0 -0
  123. /runbooks/inventory/{tests/test_inventory_modules.py → Tests/test_Inventory_Modules.py} +0 -0
  124. /runbooks/inventory/{tests → Tests}/test_cfn_describe_stacks.py +0 -0
  125. /runbooks/inventory/{tests → Tests}/test_ec2_describe_instances.py +0 -0
  126. /runbooks/inventory/{tests → Tests}/test_lambda_list_functions.py +0 -0
  127. /runbooks/inventory/{tests → Tests}/test_moto_integration_example.py +0 -0
  128. /runbooks/inventory/{tests → Tests}/test_org_list_accounts.py +0 -0
  129. /runbooks/inventory/{Inventory_Modules.py → inventory_modules.py} +0 -0
  130. /runbooks/{aws → operate}/tags.json +0 -0
  131. {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/WHEEL +0 -0
  132. {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/licenses/LICENSE +0 -0
@@ -1,169 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- AWS S3 Bucket Object Deletion and Bucket Management Tool
4
-
5
- A specialized utility for safely emptying and optionally deleting S3 buckets,
6
- including all object versions and delete markers. Essential for bucket lifecycle
7
- management and compliance with data retention policies.
8
-
9
- **AWS API Mapping**:
10
- - `boto3.resource('s3').Bucket.object_versions.delete()`
11
- - `boto3.resource('s3').Bucket.delete()`
12
-
13
- **SECURITY WARNING**: This script performs DESTRUCTIVE operations:
14
- - Permanently deletes ALL objects and versions from specified bucket
15
- - Can delete the bucket itself with --force-delete flag
16
- - Cannot be undone - ensure proper backups before execution
17
- - May affect compliance with data retention requirements
18
-
19
- Features:
20
- - Complete object version deletion (including delete markers)
21
- - Interactive bucket deletion confirmation
22
- - Force deletion mode for automation scenarios
23
- - Comprehensive error handling and logging
24
- - Single-bucket targeted operation for safety
25
-
26
- Security Controls:
27
- - Requires explicit bucket name parameter
28
- - Interactive confirmation for bucket deletion
29
- - Force flag available for automated scenarios
30
- - Detailed logging of all destructive operations
31
-
32
- Compliance Considerations:
33
- - Verify data retention policy compliance before execution
34
- - Ensure proper backup procedures are in place
35
- - Document destruction for audit trails
36
- - Consider legal hold and litigation requirements
37
-
38
- Example:
39
- Empty bucket but keep it:
40
- ```bash
41
- python delete_s3_buckets_objects.py --profile my-profile --bucket my-bucket
42
- ```
43
-
44
- Empty and delete bucket with confirmation:
45
- ```bash
46
- python delete_s3_buckets_objects.py --profile my-profile --bucket my-bucket +delete
47
- ```
48
-
49
- Requirements:
50
- - IAM permissions: `s3:DeleteObject`, `s3:DeleteObjectVersion`, `s3:DeleteBucket`
51
- - Bucket must be in accessible region
52
- - Python 3.8+ with required dependencies
53
-
54
- Author:
55
- AWS Cloud Foundations Team
56
-
57
- Version:
58
- 2023.05.04
59
- """
60
-
61
- import logging
62
-
63
- from account_class import aws_acct_access
64
- from ArgumentsClass import CommonArguments
65
-
66
- __version__ = "2023.05.04"
67
-
68
- parser = CommonArguments()
69
- parser.singleprofile()
70
- parser.singleregion()
71
- parser.verbosity()
72
- parser.version(__version__)
73
- parser.my_parser.add_argument(
74
- "-b",
75
- "--bucket",
76
- dest="pBucketName",
77
- metavar="bucket to empty and delete",
78
- required=True,
79
- help="To specify a bucket, use this parameter.",
80
- )
81
- parser.my_parser.add_argument(
82
- "+delete",
83
- "+force-delete",
84
- help="Whether or not to delete the bucket after it's been emptied",
85
- action="store_const",
86
- dest="pForceQuit",
87
- const=True,
88
- default=False,
89
- )
90
- args = parser.my_parser.parse_args()
91
-
92
- pProfile = args.Profile
93
- pRegion = args.Region
94
- pBucketDelete = args.pForceQuit
95
- pBucketName = args.pBucketName
96
- verbose = args.loglevel
97
- logging.basicConfig(level=args.loglevel, format="[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s")
98
-
99
- # Establish AWS session and S3 resource connection
100
- # Uses the specified profile to access S3 services
101
- aws_acct = aws_acct_access(pProfile)
102
- s3 = aws_acct.session.resource(service_name="s3")
103
-
104
- # CRITICAL WARNING: Display destructive operation warning
105
- # This ensures users understand the irreversible nature of this operation
106
- print()
107
- print(f"This script is about to delete all versions of all objects from bucket {pBucketName}")
108
- print()
109
-
110
- # Create S3 bucket resource for the specified bucket
111
- # This provides access to bucket operations and object management
112
- bucket = s3.Bucket(pBucketName)
113
-
114
- try:
115
- # DESTRUCTIVE OPERATION: Delete all object versions and delete markers
116
- # This includes:
117
- # - All current object versions
118
- # - All historical object versions (if versioning enabled)
119
- # - All delete markers
120
- # - Cannot be undone once executed
121
- logging.info(f"Starting deletion of all object versions in bucket {pBucketName}")
122
- bucket.object_versions.delete()
123
- logging.info(f"Successfully deleted all object versions from bucket {pBucketName}")
124
-
125
- except Exception as my_Error:
126
- # Handle S3 API errors during object deletion
127
- # Common errors: AccessDenied, NoSuchBucket, InvalidBucketState
128
- logging.error(f"Failed to delete objects from bucket {pBucketName}: {my_Error}")
129
- print(f"Error message: {my_Error}")
130
-
131
- # Handle bucket deletion with safety controls
132
- # Provides both automated and interactive deletion modes
133
- DeleteBucket = False
134
-
135
- if pBucketDelete:
136
- # Force deletion mode: Delete bucket without additional confirmation
137
- # Used for automated scenarios where confirmation is handled externally
138
- print(f"As per your request, we're deleting the bucket {pBucketName}")
139
- logging.warning(f"Force deleting bucket {pBucketName} as requested")
140
-
141
- try:
142
- bucket.delete()
143
- print(f"Bucket: {pBucketName} has been deleted")
144
- logging.info(f"Successfully deleted bucket {pBucketName}")
145
- except Exception as delete_error:
146
- logging.error(f"Failed to delete bucket {pBucketName}: {delete_error}")
147
- print(f"Failed to delete bucket: {delete_error}")
148
-
149
- else:
150
- # Interactive deletion mode: Prompt user for confirmation
151
- # Provides additional safety control for manual operations
152
- DeleteBucket = input("Now that the bucket is empty, do you want to delete the bucket? (y/n): ") in ["y", "Y"]
153
-
154
- if DeleteBucket:
155
- try:
156
- bucket.delete()
157
- print(f"Bucket: {pBucketName} has been deleted")
158
- logging.info(f"User confirmed deletion of bucket {pBucketName}")
159
- except Exception as delete_error:
160
- logging.error(f"Failed to delete bucket {pBucketName}: {delete_error}")
161
- print(f"Failed to delete bucket: {delete_error}")
162
- else:
163
- print(f"Bucket: {pBucketName} has NOT been deleted")
164
- logging.info(f"User chose to preserve bucket {pBucketName}")
165
- # Operation completion notification
166
- print()
167
- print("Thanks for using this script...")
168
- logging.info("S3 bucket operation completed successfully")
169
- print()
@@ -1,224 +0,0 @@
1
- #!/usr/bin/env python3
2
-
3
- import logging
4
- import sys
5
-
6
- import boto3
7
- import Inventory_Modules
8
- import simplejson as json
9
- from account_class import aws_acct_access
10
- from ArgumentsClass import CommonArguments
11
- from botocore.exceptions import ClientError
12
-
13
- __version__ = "2023.05.04"
14
-
15
- parser = CommonArguments()
16
- parser.singleprofile()
17
- parser.singleregion()
18
- parser.verbosity()
19
- parser.version(__version__)
20
- parser.my_parser.add_argument(
21
- "-R",
22
- "--access_rolename",
23
- dest="pAccessRole",
24
- default="AWSCloudFormationStackSetExecutionRole",
25
- metavar="role to use for access to child accounts",
26
- help="This parameter specifies the role that will allow this script to have access to the children accounts.",
27
- )
28
- parser.my_parser.add_argument(
29
- "-t",
30
- "--target_rolename",
31
- dest="pTargetRole",
32
- default="AWSCloudFormationStackSetExecutionRole",
33
- metavar="role to change",
34
- help="This parameter specifies the role to have its Trust Policy changed.",
35
- )
36
- parser.my_parser.add_argument(
37
- "+f",
38
- "--fix",
39
- "+fix",
40
- dest="pFix",
41
- action="store_const",
42
- const=True,
43
- default=False,
44
- help="This parameter determines whether to make any changes in child accounts.",
45
- )
46
- parser.my_parser.add_argument(
47
- "+l",
48
- "--lock",
49
- "+lock",
50
- dest="pLock",
51
- action="store_const",
52
- const=True,
53
- default=False,
54
- help="This parameter determines whether to lock the Trust Policy.",
55
- )
56
- parser.my_parser.add_argument(
57
- "-s",
58
- "--safety",
59
- dest="pSafety",
60
- action="store_const",
61
- const=False,
62
- default=True,
63
- help="Adding this parameter will 'remove the safety' - by not including the principle running this script, which might mean you get locked out of making further changes.",
64
- )
65
- args = parser.my_parser.parse_args()
66
-
67
- pProfile = args.Profile
68
- pTargetRole = args.pTargetRole
69
- pAccessRole = args.pAccessRole
70
- pLock = args.pLock
71
- pSafety = args.pSafety
72
- pFix = args.pFix
73
- verbose = args.loglevel
74
- logging.basicConfig(level=args.loglevel, format="[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s")
75
-
76
- aws_acct = aws_acct_access(pProfile)
77
-
78
- if not aws_acct.AccountType.lower() == "root":
79
- print()
80
- print(f"The profile {pProfile} does not represent an Org")
81
- print("This script only works with org accounts.")
82
- print()
83
- sys.exit(1)
84
- ##########################
85
- ERASE_LINE = "\x1b[2K"
86
- ##########################
87
-
88
- print(f"We're using the {pAccessRole} role to gain access to the child accounts")
89
- print(f"We're targeting the {pTargetRole} role to change its Trust Policy")
90
-
91
- """
92
- 1. Collect SSM parameters with the ARNs that should be in the permission
93
- 2. Create the TrustPolicy in JSON
94
- 3. Get a listing of all accounts that need to be updated
95
- 4. Connect to each account, and update the existing trust policy with the new policy
96
- """
97
- # 1. Collect parameters with the ARNs that should be in the permission
98
- # lock_down_arns_list=[]
99
- allowed_arns = []
100
- ssm_client = aws_acct.session.client("ssm")
101
- param_list = ssm_client.describe_parameters(
102
- ParameterFilters=[{"Key": "Name", "Option": "Contains", "Values": ["lock_down_role_arns_list"]}]
103
- )["Parameters"]
104
- if len(param_list) == 0:
105
- print("You need to set the region (-r|--region) to the default region where the SSM parameters are stored.")
106
- print("Otherwise, with no *allowed* arns, we would lock everything out from this role.")
107
- print("Exiting...")
108
- sys.exit(2)
109
- for i in param_list:
110
- response = param = ssm_client.get_parameter(Name=i["Name"])
111
- logging.info(f"Adding {response['Parameter']['Value']} to the list for i: {i['Name']}")
112
- allowed_arns.append(response["Parameter"]["Value"])
113
-
114
- # 1.5 Find who is running the script and add their credential as a safety
115
- Creds = Inventory_Modules.find_calling_identity(pProfile)
116
- if pSafety:
117
- allowed_arns.append(Creds["Arn"])
118
- # 2. Create the Trust Policy in JSON
119
-
120
- if pLock:
121
- if pSafety and pFix:
122
- logging.error("Locking down the Trust Policy to *only* the Lambda functions.")
123
- elif pFix:
124
- logging.error(f"Locking down the Trust Policy to the Lambda functions and {Creds['Arn']}.")
125
- else:
126
- logging.critical(
127
- "While you asked us to lock things down, You didn't use the '+f' parameter, so we're not changing a thing."
128
- )
129
- Trust_Policy = {
130
- "Version": "2012-10-17",
131
- "Statement": [
132
- {"Sid": "LambdaAccess", "Effect": "Allow", "Principal": {"AWS": allowed_arns}, "Action": "sts:AssumeRole"}
133
- ],
134
- }
135
- else:
136
- Trust_Policy = {
137
- "Version": "2012-10-17",
138
- "Statement": [
139
- {"Sid": "LambdaAccess", "Effect": "Allow", "Principal": {"AWS": allowed_arns}, "Action": "sts:AssumeRole"},
140
- {
141
- "Sid": "DevAccess",
142
- "Effect": "Allow",
143
- "Principal": {"AWS": [f"arn:aws:iam::{aws_acct.MgmtAccount}:root"]},
144
- "Action": "sts:AssumeRole",
145
- },
146
- ],
147
- }
148
- Trust_Policy_json = json.dumps(Trust_Policy)
149
- # 3. Get a listing of all accounts that need to be updated and then ...
150
-
151
-
152
- # 4. Connect to each account, and detach the existing policy, and apply the new policy
153
- sts_client = aws_acct.session.client("sts")
154
- TrustPoliciesChanged = 0
155
- ErroredAccounts = []
156
- for acct in aws_acct.ChildAccounts:
157
- ConnectionSuccess = False
158
- try:
159
- role_arn = f"arn:aws:iam::{acct['AccountId']}:role/{pAccessRole}"
160
- account_credentials = sts_client.assume_role(RoleArn=role_arn, RoleSessionName="RegistrationScript")[
161
- "Credentials"
162
- ]
163
- account_credentials["Account"] = acct["AccountId"]
164
- logging.warning(f"Accessed Account {acct['AccountId']} using rolename {pAccessRole}")
165
- ConnectionSuccess = True
166
- except ClientError as my_Error:
167
- logging.error(
168
- f"Account {acct['AccountId']}, role {pTargetRole} was unavailable to change, so we couldn't access the role's Trust Policy"
169
- )
170
- logging.warning(my_Error)
171
- ErroredAccounts.append(acct["AccountId"])
172
- pass
173
- if ConnectionSuccess:
174
- try:
175
- # detach policy from the role and attach the new policy
176
- iam_session = boto3.Session(
177
- aws_access_key_id=account_credentials["AccessKeyId"],
178
- aws_secret_access_key=account_credentials["SecretAccessKey"],
179
- aws_session_token=account_credentials["SessionToken"],
180
- )
181
- iam_client = iam_session.client("iam")
182
- trustpolicyexisting = iam_client.get_role(RoleName=pTargetRole)
183
- logging.info(
184
- "Found Trust Policy %s in account %s for role %s"
185
- % (json.dumps(trustpolicyexisting["Role"]["AssumeRolePolicyDocument"]), acct["AccountId"], pTargetRole)
186
- )
187
- if pFix:
188
- trustpolicyupdate = iam_client.update_assume_role_policy(
189
- RoleName=pTargetRole, PolicyDocument=Trust_Policy_json
190
- )
191
- TrustPoliciesChanged += 1
192
- logging.error(f"Updated Trust Policy in Account {acct['AccountId']} for role {pTargetRole}")
193
- trustpolicyexisting = iam_client.get_role(RoleName=pTargetRole)
194
- logging.info(
195
- "Updated Trust Policy %s in account %s for role %s"
196
- % (
197
- json.dumps(trustpolicyexisting["Role"]["AssumeRolePolicyDocument"]),
198
- acct["AccountId"],
199
- pTargetRole,
200
- )
201
- )
202
- else:
203
- logging.error(f"Account {acct['AccountId']} - no changes made")
204
- except ClientError as my_Error:
205
- logging.warning(my_Error)
206
- pass
207
-
208
- print(ERASE_LINE)
209
- print(f"We found {len(aws_acct.ChildAccounts)} accounts under your organization")
210
- if pLock and pFix:
211
- print(f"We locked {TrustPoliciesChanged} Trust Policies")
212
- elif not pLock and pFix:
213
- print(f"We unlocked {TrustPoliciesChanged} Trust Policies")
214
- else:
215
- print(f"We didn't change {TrustPoliciesChanged} Trust Policies")
216
- if len(ErroredAccounts) > 0:
217
- print(f"We weren't able to access {len(ErroredAccounts)} accounts.")
218
- if verbose < 50:
219
- print("Here are the accounts that were not updated")
220
- for i in ErroredAccounts:
221
- print(i)
222
- print()
223
- print("Thanks for using the tool.")
224
- print()
@@ -1,173 +0,0 @@
1
- import logging
2
- import sys
3
- from datetime import datetime
4
- from os.path import split
5
- from queue import Queue
6
- from threading import Thread
7
- from time import time
8
-
9
- import boto3
10
- from ArgumentsClass import CommonArguments
11
- from colorama import Fore, Style, init
12
- from tqdm.auto import tqdm, trange
13
-
14
- __version__ = "2024.04.24"
15
-
16
- from tqdm import trange
17
-
18
- init()
19
-
20
-
21
- ##################
22
- # Functions
23
- ##################
24
-
25
-
26
- def parse_args(f_arguments):
27
- """
28
- Description: Parses the arguments passed into the script
29
- @param f_arguments: args represents the list of arguments passed in
30
- @return: returns an object namespace that contains the individualized parameters passed in
31
- """
32
- script_path, script_name = split(sys.argv[0])
33
- parser = CommonArguments()
34
- parser.my_parser.description = "We're going to find all API actions within the available AWS services."
35
- parser.timing()
36
- parser.save_to_file()
37
- parser.verbosity()
38
- parser.version(__version__)
39
- local = parser.my_parser.add_argument_group(script_name, "Parameters specific to this script")
40
- # local.add_argument(
41
- # "-s", "--status",
42
- # dest="pStatus",
43
- # choices=['running', 'stopped'],
44
- # type=str,
45
- # default=None,
46
- # help="Whether you want to limit the instances returned to either 'running', 'stopped'. Default is both")
47
- return parser.my_parser.parse_args(f_arguments)
48
-
49
-
50
- def random_string(stringLength=10):
51
- """
52
- Description: Generates a random string
53
- @param stringLength: to determine the length of the random number generated
54
- @return: returns a random string of characters of length "stringlength"
55
- """
56
- import random
57
- import string
58
-
59
- # Generate a random string of fixed length
60
- letters = string.ascii_lowercase
61
- randomstring = "".join(random.choice(letters) for _ in range(stringLength))
62
- return randomstring
63
-
64
-
65
- def get_aws_actions():
66
- """
67
- Description: Gets all the actions for all the services in AWS
68
- @return: list of actions
69
- """
70
-
71
- class AWSActionThread(Thread):
72
- def __init__(self, queue):
73
- Thread.__init__(self)
74
- self.queue = queue
75
-
76
- def run(self):
77
- while True:
78
- # existing code to get actions for a service
79
- c_service = self.queue.get()
80
- client = boto3.client(c_service)
81
- try:
82
- list_of_operations = client.meta.method_to_api_mapping.keys()
83
- # print(f"{ERASE_LINE}Checking actions for {c_service}", end='\r', flush=True)
84
- for operation in tqdm(list_of_operations, desc=f"actions for {c_service}", leave=False):
85
- action_list.append({"Service": c_service, "Operation": operation})
86
- except AttributeError as myError:
87
- print(myError)
88
- action_list.append({"Service": c_service, "Operation": None})
89
- pass
90
- finally:
91
- self.queue.task_done()
92
-
93
- checkqueue = Queue()
94
- action_list = []
95
- workerthreads = 10
96
-
97
- for x in trange(
98
- workerthreads,
99
- desc=f"Creating {workerthreads} worker threads",
100
- leave=False,
101
- # , position=0
102
- ):
103
- worker = AWSActionThread(checkqueue)
104
- worker.daemon = True
105
- worker.start()
106
-
107
- # Create a thread for every service.
108
- print(f"Capturing all available AWS Services...")
109
- for service in tqdm(
110
- list_of_services,
111
- desc=f"Checking actions for each service",
112
- # , position=0
113
- ):
114
- # for service in list_of_services:
115
- checkqueue.put(service)
116
- checkqueue.join()
117
-
118
- return action_list
119
-
120
-
121
- def save_file(file_to_save_to: str = None, input_data: list = None):
122
- """
123
- Description: Saves the data to a file
124
- @param file_to_save_to:
125
- @param input_data:
126
- @return: None
127
- """
128
- if input_data is None:
129
- print(f"Input data cannot be none. Exiting...")
130
- raise SystemExit(1)
131
- elif len(input_data) == 0:
132
- print(f"No data to save. Exiting...")
133
- raise SystemExit(1)
134
-
135
- if file_to_save_to is None:
136
- print(f"No filename provided to save data.\nUsing a randomized name.")
137
- file_to_save_to = random_string(15) + ".txt"
138
- else:
139
- logging.info(f"Saving data to {file_to_save_to}")
140
- with open(file_to_save_to, "w", encoding="utf-8") as f:
141
- for item in input_data:
142
- f.write(f"{item['Service']}:{item['Operation']}\n")
143
- return file_to_save_to
144
-
145
-
146
- ##################
147
- # Main
148
- ##################
149
- ERASE_LINE = "\x1b[2K"
150
- begin_time = time()
151
-
152
- if __name__ == "__main__":
153
- arguments = parse_args(sys.argv[1:])
154
- pTiming = arguments.Time
155
- file_to_save = arguments.Filename
156
- verbose = arguments.loglevel
157
- logging.basicConfig(level=verbose, format="[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s")
158
- logging.getLogger("boto3").setLevel(logging.CRITICAL)
159
- logging.getLogger("botocore").setLevel(logging.CRITICAL)
160
- logging.getLogger("s3transfer").setLevel(logging.CRITICAL)
161
- logging.getLogger("urllib3").setLevel(logging.CRITICAL)
162
-
163
- list_of_services = boto3.Session().get_available_services()
164
- all_actions = get_aws_actions()
165
- if pTiming:
166
- print(ERASE_LINE)
167
- print(f"{Fore.GREEN}This script took {time() - begin_time:.2f} seconds{Fore.RESET}")
168
- print(ERASE_LINE)
169
- print(f"Found {len(all_actions)} actions across {len(list_of_services)} services")
170
- filename = save_file(file_to_save, all_actions)
171
- print(f"Saved to {filename}")
172
- print("Thank you for using this script")
173
- print()