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.
- runbooks/__init__.py +87 -37
- runbooks/cfat/README.md +300 -49
- runbooks/cfat/__init__.py +2 -2
- runbooks/finops/__init__.py +1 -1
- runbooks/finops/cli.py +1 -1
- runbooks/inventory/collectors/__init__.py +8 -0
- runbooks/inventory/collectors/aws_management.py +791 -0
- runbooks/inventory/collectors/aws_networking.py +3 -3
- runbooks/main.py +3389 -782
- runbooks/operate/__init__.py +207 -0
- runbooks/operate/base.py +311 -0
- runbooks/operate/cloudformation_operations.py +619 -0
- runbooks/operate/cloudwatch_operations.py +496 -0
- runbooks/operate/dynamodb_operations.py +812 -0
- runbooks/operate/ec2_operations.py +926 -0
- runbooks/operate/iam_operations.py +569 -0
- runbooks/operate/s3_operations.py +1211 -0
- runbooks/operate/tagging_operations.py +655 -0
- runbooks/remediation/CLAUDE.md +100 -0
- runbooks/remediation/DOME9.md +218 -0
- runbooks/remediation/README.md +26 -0
- runbooks/remediation/Tests/__init__.py +0 -0
- runbooks/remediation/Tests/update_policy.py +74 -0
- runbooks/remediation/__init__.py +95 -0
- runbooks/remediation/acm_cert_expired_unused.py +98 -0
- runbooks/remediation/acm_remediation.py +875 -0
- runbooks/remediation/api_gateway_list.py +167 -0
- runbooks/remediation/base.py +643 -0
- runbooks/remediation/cloudtrail_remediation.py +908 -0
- runbooks/remediation/cloudtrail_s3_modifications.py +296 -0
- runbooks/remediation/cognito_active_users.py +78 -0
- runbooks/remediation/cognito_remediation.py +856 -0
- runbooks/remediation/cognito_user_password_reset.py +163 -0
- runbooks/remediation/commons.py +455 -0
- runbooks/remediation/dynamodb_optimize.py +155 -0
- runbooks/remediation/dynamodb_remediation.py +744 -0
- runbooks/remediation/dynamodb_server_side_encryption.py +108 -0
- runbooks/remediation/ec2_public_ips.py +134 -0
- runbooks/remediation/ec2_remediation.py +892 -0
- runbooks/remediation/ec2_subnet_disable_auto_ip_assignment.py +72 -0
- runbooks/remediation/ec2_unattached_ebs_volumes.py +448 -0
- runbooks/remediation/ec2_unused_security_groups.py +202 -0
- runbooks/remediation/kms_enable_key_rotation.py +651 -0
- runbooks/remediation/kms_remediation.py +717 -0
- runbooks/remediation/lambda_list.py +243 -0
- runbooks/remediation/lambda_remediation.py +971 -0
- runbooks/remediation/multi_account.py +569 -0
- runbooks/remediation/rds_instance_list.py +199 -0
- runbooks/remediation/rds_remediation.py +873 -0
- runbooks/remediation/rds_snapshot_list.py +192 -0
- runbooks/remediation/requirements.txt +118 -0
- runbooks/remediation/s3_block_public_access.py +159 -0
- runbooks/remediation/s3_bucket_public_access.py +143 -0
- runbooks/remediation/s3_disable_static_website_hosting.py +74 -0
- runbooks/remediation/s3_downloader.py +215 -0
- runbooks/remediation/s3_enable_access_logging.py +562 -0
- runbooks/remediation/s3_encryption.py +526 -0
- runbooks/remediation/s3_force_ssl_secure_policy.py +143 -0
- runbooks/remediation/s3_list.py +141 -0
- runbooks/remediation/s3_object_search.py +201 -0
- runbooks/remediation/s3_remediation.py +816 -0
- runbooks/remediation/scan_for_phrase.py +425 -0
- runbooks/remediation/workspaces_list.py +220 -0
- runbooks/security/__init__.py +9 -10
- runbooks/security/security_baseline_tester.py +4 -2
- runbooks-0.7.6.dist-info/METADATA +608 -0
- {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/RECORD +84 -76
- {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/entry_points.txt +0 -1
- {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/top_level.txt +0 -1
- jupyter-agent/.env +0 -2
- jupyter-agent/.env.template +0 -2
- jupyter-agent/.gitattributes +0 -35
- jupyter-agent/.gradio/certificate.pem +0 -31
- jupyter-agent/README.md +0 -16
- jupyter-agent/__main__.log +0 -8
- jupyter-agent/app.py +0 -256
- jupyter-agent/cloudops-agent.png +0 -0
- jupyter-agent/ds-system-prompt.txt +0 -154
- jupyter-agent/jupyter-agent.png +0 -0
- jupyter-agent/llama3_template.jinja +0 -123
- jupyter-agent/requirements.txt +0 -9
- jupyter-agent/tmp/4ojbs8a02ir/jupyter-agent.ipynb +0 -68
- jupyter-agent/tmp/cm5iasgpm3p/jupyter-agent.ipynb +0 -91
- jupyter-agent/tmp/crqbsseag5/jupyter-agent.ipynb +0 -91
- jupyter-agent/tmp/hohanq1u097/jupyter-agent.ipynb +0 -57
- jupyter-agent/tmp/jns1sam29wm/jupyter-agent.ipynb +0 -53
- jupyter-agent/tmp/jupyter-agent.ipynb +0 -27
- jupyter-agent/utils.py +0 -409
- runbooks/aws/__init__.py +0 -58
- runbooks/aws/dynamodb_operations.py +0 -231
- runbooks/aws/ec2_copy_image_cross-region.py +0 -195
- runbooks/aws/ec2_describe_instances.py +0 -202
- runbooks/aws/ec2_ebs_snapshots_delete.py +0 -186
- runbooks/aws/ec2_run_instances.py +0 -213
- runbooks/aws/ec2_start_stop_instances.py +0 -212
- runbooks/aws/ec2_terminate_instances.py +0 -143
- runbooks/aws/ec2_unused_eips.py +0 -196
- runbooks/aws/ec2_unused_volumes.py +0 -188
- runbooks/aws/s3_create_bucket.py +0 -142
- runbooks/aws/s3_list_buckets.py +0 -152
- runbooks/aws/s3_list_objects.py +0 -156
- runbooks/aws/s3_object_operations.py +0 -183
- runbooks/aws/tagging_lambda_handler.py +0 -183
- runbooks/inventory/FAILED_SCRIPTS_TROUBLESHOOTING.md +0 -619
- runbooks/inventory/PASSED_SCRIPTS_GUIDE.md +0 -738
- runbooks/inventory/aws_organization.png +0 -0
- runbooks/inventory/cfn_move_stack_instances.py +0 -1526
- runbooks/inventory/delete_s3_buckets_objects.py +0 -169
- runbooks/inventory/lockdown_cfn_stackset_role.py +0 -224
- runbooks/inventory/update_aws_actions.py +0 -173
- runbooks/inventory/update_cfn_stacksets.py +0 -1215
- runbooks/inventory/update_cloudwatch_logs_retention_policy.py +0 -294
- runbooks/inventory/update_iam_roles_cross_accounts.py +0 -478
- runbooks/inventory/update_s3_public_access_block.py +0 -539
- runbooks/organizations/__init__.py +0 -12
- runbooks/organizations/manager.py +0 -374
- runbooks-0.7.0.dist-info/METADATA +0 -375
- /runbooks/inventory/{tests → Tests}/common_test_data.py +0 -0
- /runbooks/inventory/{tests → Tests}/common_test_functions.py +0 -0
- /runbooks/inventory/{tests → Tests}/script_test_data.py +0 -0
- /runbooks/inventory/{tests → Tests}/setup.py +0 -0
- /runbooks/inventory/{tests → Tests}/src.py +0 -0
- /runbooks/inventory/{tests/test_inventory_modules.py → Tests/test_Inventory_Modules.py} +0 -0
- /runbooks/inventory/{tests → Tests}/test_cfn_describe_stacks.py +0 -0
- /runbooks/inventory/{tests → Tests}/test_ec2_describe_instances.py +0 -0
- /runbooks/inventory/{tests → Tests}/test_lambda_list_functions.py +0 -0
- /runbooks/inventory/{tests → Tests}/test_moto_integration_example.py +0 -0
- /runbooks/inventory/{tests → Tests}/test_org_list_accounts.py +0 -0
- /runbooks/inventory/{Inventory_Modules.py → inventory_modules.py} +0 -0
- /runbooks/{aws → operate}/tags.json +0 -0
- {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/WHEEL +0 -0
- {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,167 @@
|
|
1
|
+
"""
|
2
|
+
API Gateway Inventory - List and analyze API Gateway configurations.
|
3
|
+
"""
|
4
|
+
|
5
|
+
import logging
|
6
|
+
import re
|
7
|
+
|
8
|
+
import click
|
9
|
+
from botocore.exceptions import ClientError
|
10
|
+
|
11
|
+
from .commons import (
|
12
|
+
get_api_gateway_calls,
|
13
|
+
get_api_gateways,
|
14
|
+
get_client,
|
15
|
+
get_lambda_invocations,
|
16
|
+
get_log_group_from_lambda,
|
17
|
+
get_method_details,
|
18
|
+
get_resources,
|
19
|
+
get_stages,
|
20
|
+
write_to_csv,
|
21
|
+
)
|
22
|
+
|
23
|
+
logger = logging.getLogger(__name__)
|
24
|
+
|
25
|
+
|
26
|
+
@click.command()
|
27
|
+
@click.option("--output-file", default="api_gateway_inventory.csv", help="Output CSV file path")
|
28
|
+
def list_api_gateways(output_file):
|
29
|
+
"""List all API Gateways and their configuration details."""
|
30
|
+
logger.info("Collecting API Gateway inventory")
|
31
|
+
|
32
|
+
try:
|
33
|
+
# Create API Gateway and Lambda clients
|
34
|
+
client_apigateway = get_client("apigateway")
|
35
|
+
client_lambda = get_client("lambda")
|
36
|
+
|
37
|
+
# Get all REST APIs
|
38
|
+
rest_apis = get_api_gateways(client_apigateway)
|
39
|
+
|
40
|
+
if not rest_apis:
|
41
|
+
logger.info("No API Gateways found")
|
42
|
+
return
|
43
|
+
|
44
|
+
logger.info(f"Found {len(rest_apis)} API Gateways to analyze")
|
45
|
+
|
46
|
+
data = []
|
47
|
+
for rest_api in rest_apis:
|
48
|
+
rest_api_id = rest_api["id"]
|
49
|
+
# logger.info(f"API Gateway: {rest_api['name']} ({rest_api_id})")
|
50
|
+
|
51
|
+
stages = get_stages(client_apigateway, rest_api_id)
|
52
|
+
|
53
|
+
for stage in stages:
|
54
|
+
stage_name = stage["stageName"]
|
55
|
+
# logger.info(f" Stage: {stage_name}")
|
56
|
+
# Retrieve stage-level logging configuration
|
57
|
+
log_group_arn = None
|
58
|
+
if stage.get("accessLogSettings"):
|
59
|
+
log_group_arn = stage["accessLogSettings"].get("destinationArn")
|
60
|
+
|
61
|
+
resources = get_resources(client_apigateway, rest_api_id)
|
62
|
+
|
63
|
+
for resource in resources:
|
64
|
+
resource_id = resource["id"]
|
65
|
+
|
66
|
+
integration_type = None
|
67
|
+
uri = None
|
68
|
+
integration_line = " - No Integration Found"
|
69
|
+
function_name = None
|
70
|
+
log_group = None
|
71
|
+
for http_method in [
|
72
|
+
"GET",
|
73
|
+
"POST",
|
74
|
+
"PUT",
|
75
|
+
"DELETE",
|
76
|
+
"OPTIONS", # Add more as needed
|
77
|
+
"HEAD",
|
78
|
+
"PATCH",
|
79
|
+
"ANY",
|
80
|
+
]:
|
81
|
+
try:
|
82
|
+
response = client_apigateway.get_integration(
|
83
|
+
restApiId=rest_api_id, resourceId=resource_id, httpMethod=http_method
|
84
|
+
)
|
85
|
+
|
86
|
+
integration_type = response["type"] # Possible values: HTTP, AWS, MOCK, AWS_PROXY
|
87
|
+
|
88
|
+
if integration_type == "AWS":
|
89
|
+
# Lambda integration
|
90
|
+
uri = response["uri"]
|
91
|
+
if uri.startswith("arn:aws:apigateway:"):
|
92
|
+
match = re.search(r"function:(\w+-\w+)", uri)
|
93
|
+
function_name = match.group(1) if match else None
|
94
|
+
integration_line = f" - Lambda Integration: {function_name}"
|
95
|
+
|
96
|
+
elif integration_type == "HTTP" or integration_type == "AWS_PROXY":
|
97
|
+
# HTTP Endpoint or HTTP Proxy (could be S3, etc.)
|
98
|
+
uri = response["uri"]
|
99
|
+
match = re.search(r"function:(.+?)/", uri)
|
100
|
+
function_name = match.group(1) if match else None
|
101
|
+
integration_line = f" - HTTP/Proxy Integration: {uri}"
|
102
|
+
|
103
|
+
elif integration_type == "MOCK":
|
104
|
+
integration_line = f" - Mock Integration"
|
105
|
+
|
106
|
+
except client_apigateway.exceptions.NotFoundException:
|
107
|
+
pass
|
108
|
+
|
109
|
+
response = get_method_details(client_apigateway, rest_api_id, resource_id, http_method)
|
110
|
+
|
111
|
+
# Check caching status
|
112
|
+
if response and "methodResponses" in response and "200" in response["methodResponses"]:
|
113
|
+
caching_enabled = response["methodResponses"]["200"].get("cachingEnabled", False)
|
114
|
+
logger.info(f"API Gateway: {rest_api['name']} ({rest_api_id})")
|
115
|
+
logger.info(f" Stage: {stage_name}")
|
116
|
+
logger.info(
|
117
|
+
f" {http_method} Method (Resource: {resource['path']}) - Cache Enabled: {caching_enabled}"
|
118
|
+
)
|
119
|
+
logger.info(f"{integration_line}")
|
120
|
+
log_group_name = None
|
121
|
+
if log_group_arn:
|
122
|
+
log_group_name = log_group_arn.split(":")[-1] # Extract from ARN
|
123
|
+
logger.info(f" Access Log Group: {log_group_name}")
|
124
|
+
|
125
|
+
if function_name:
|
126
|
+
log_group = get_log_group_from_lambda(client_lambda, function_name)
|
127
|
+
if log_group:
|
128
|
+
logger.info(f" Log Group: {log_group}")
|
129
|
+
else:
|
130
|
+
logger.info(f" Log Group could not be determined from configuration.")
|
131
|
+
|
132
|
+
data.append(
|
133
|
+
{
|
134
|
+
"API Gateway": rest_api["name"],
|
135
|
+
"Rest API ID": rest_api_id, # Added rest api id to the output
|
136
|
+
"Resource": resource["path"], # Added resource path to the output
|
137
|
+
"Stage": stage_name,
|
138
|
+
"Method": http_method,
|
139
|
+
"Access Log Group": log_group_name,
|
140
|
+
"Cache Enabled": caching_enabled,
|
141
|
+
"Integration Type": integration_type,
|
142
|
+
"Integration details": integration_line.strip(), # Added integration details to the output
|
143
|
+
"URI": uri,
|
144
|
+
"Function Name": function_name,
|
145
|
+
"Log Group of Function": log_group,
|
146
|
+
"API gateway (includes all http methods) calls in last 360 days": get_api_gateway_calls(
|
147
|
+
rest_api["name"], 360
|
148
|
+
),
|
149
|
+
"Lambda function invocations in last 360 days": get_lambda_invocations(
|
150
|
+
function_name, 360
|
151
|
+
)
|
152
|
+
if function_name
|
153
|
+
else None,
|
154
|
+
}
|
155
|
+
)
|
156
|
+
|
157
|
+
# Export results to CSV
|
158
|
+
write_to_csv(data, output_file)
|
159
|
+
logger.info(f"API Gateway inventory exported to: {output_file}")
|
160
|
+
logger.info(f"Processed {len(data)} API Gateway configurations")
|
161
|
+
|
162
|
+
except ClientError as e:
|
163
|
+
logger.error(f"Failed to collect API Gateway inventory: {e}")
|
164
|
+
raise
|
165
|
+
except Exception as e:
|
166
|
+
logger.error(f"Unexpected error: {e}")
|
167
|
+
raise
|