runbooks 0.7.0__py3-none-any.whl → 0.7.5__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 (100) 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.5.dist-info/METADATA +606 -0
  67. {runbooks-0.7.0.dist-info → runbooks-0.7.5.dist-info}/RECORD +72 -44
  68. {runbooks-0.7.0.dist-info → runbooks-0.7.5.dist-info}/entry_points.txt +0 -1
  69. runbooks/aws/__init__.py +0 -58
  70. runbooks/aws/dynamodb_operations.py +0 -231
  71. runbooks/aws/ec2_copy_image_cross-region.py +0 -195
  72. runbooks/aws/ec2_describe_instances.py +0 -202
  73. runbooks/aws/ec2_ebs_snapshots_delete.py +0 -186
  74. runbooks/aws/ec2_run_instances.py +0 -213
  75. runbooks/aws/ec2_start_stop_instances.py +0 -212
  76. runbooks/aws/ec2_terminate_instances.py +0 -143
  77. runbooks/aws/ec2_unused_eips.py +0 -196
  78. runbooks/aws/ec2_unused_volumes.py +0 -188
  79. runbooks/aws/s3_create_bucket.py +0 -142
  80. runbooks/aws/s3_list_buckets.py +0 -152
  81. runbooks/aws/s3_list_objects.py +0 -156
  82. runbooks/aws/s3_object_operations.py +0 -183
  83. runbooks/aws/tagging_lambda_handler.py +0 -183
  84. runbooks/inventory/FAILED_SCRIPTS_TROUBLESHOOTING.md +0 -619
  85. runbooks/inventory/PASSED_SCRIPTS_GUIDE.md +0 -738
  86. runbooks/inventory/cfn_move_stack_instances.py +0 -1526
  87. runbooks/inventory/delete_s3_buckets_objects.py +0 -169
  88. runbooks/inventory/lockdown_cfn_stackset_role.py +0 -224
  89. runbooks/inventory/update_aws_actions.py +0 -173
  90. runbooks/inventory/update_cfn_stacksets.py +0 -1215
  91. runbooks/inventory/update_cloudwatch_logs_retention_policy.py +0 -294
  92. runbooks/inventory/update_iam_roles_cross_accounts.py +0 -478
  93. runbooks/inventory/update_s3_public_access_block.py +0 -539
  94. runbooks/organizations/__init__.py +0 -12
  95. runbooks/organizations/manager.py +0 -374
  96. runbooks-0.7.0.dist-info/METADATA +0 -375
  97. /runbooks/{aws → operate}/tags.json +0 -0
  98. {runbooks-0.7.0.dist-info → runbooks-0.7.5.dist-info}/WHEEL +0 -0
  99. {runbooks-0.7.0.dist-info → runbooks-0.7.5.dist-info}/licenses/LICENSE +0 -0
  100. {runbooks-0.7.0.dist-info → runbooks-0.7.5.dist-info}/top_level.txt +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