runbooks 0.6.1__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 (142) hide show
  1. jupyter-agent/.env +2 -0
  2. jupyter-agent/.gradio/certificate.pem +31 -0
  3. jupyter-agent/__main__.log +8 -0
  4. jupyter-agent/tmp/4ojbs8a02ir/jupyter-agent.ipynb +68 -0
  5. jupyter-agent/tmp/cm5iasgpm3p/jupyter-agent.ipynb +91 -0
  6. jupyter-agent/tmp/crqbsseag5/jupyter-agent.ipynb +91 -0
  7. jupyter-agent/tmp/hohanq1u097/jupyter-agent.ipynb +57 -0
  8. jupyter-agent/tmp/jns1sam29wm/jupyter-agent.ipynb +53 -0
  9. jupyter-agent/tmp/jupyter-agent.ipynb +27 -0
  10. runbooks/__init__.py +87 -37
  11. runbooks/cfat/README.md +300 -49
  12. runbooks/cfat/__init__.py +2 -2
  13. runbooks/finops/README.md +337 -0
  14. runbooks/finops/__init__.py +2 -4
  15. runbooks/finops/cli.py +1 -1
  16. runbooks/inventory/aws_organization.png +0 -0
  17. runbooks/inventory/collectors/__init__.py +8 -0
  18. runbooks/inventory/collectors/aws_management.py +791 -0
  19. runbooks/inventory/collectors/aws_networking.py +3 -3
  20. runbooks/main.py +3416 -590
  21. runbooks/operate/__init__.py +207 -0
  22. runbooks/operate/base.py +311 -0
  23. runbooks/operate/cloudformation_operations.py +619 -0
  24. runbooks/operate/cloudwatch_operations.py +496 -0
  25. runbooks/operate/dynamodb_operations.py +812 -0
  26. runbooks/operate/ec2_operations.py +926 -0
  27. runbooks/operate/iam_operations.py +569 -0
  28. runbooks/operate/s3_operations.py +1211 -0
  29. runbooks/operate/tagging_operations.py +655 -0
  30. runbooks/remediation/CLAUDE.md +100 -0
  31. runbooks/remediation/DOME9.md +218 -0
  32. runbooks/remediation/README.md +26 -0
  33. runbooks/remediation/Tests/update_policy.py +74 -0
  34. runbooks/remediation/__init__.py +95 -0
  35. runbooks/remediation/acm_cert_expired_unused.py +98 -0
  36. runbooks/remediation/acm_remediation.py +875 -0
  37. runbooks/remediation/api_gateway_list.py +167 -0
  38. runbooks/remediation/base.py +643 -0
  39. runbooks/remediation/cloudtrail_remediation.py +908 -0
  40. runbooks/remediation/cloudtrail_s3_modifications.py +296 -0
  41. runbooks/remediation/cognito_active_users.py +78 -0
  42. runbooks/remediation/cognito_remediation.py +856 -0
  43. runbooks/remediation/cognito_user_password_reset.py +163 -0
  44. runbooks/remediation/commons.py +455 -0
  45. runbooks/remediation/dynamodb_optimize.py +155 -0
  46. runbooks/remediation/dynamodb_remediation.py +744 -0
  47. runbooks/remediation/dynamodb_server_side_encryption.py +108 -0
  48. runbooks/remediation/ec2_public_ips.py +134 -0
  49. runbooks/remediation/ec2_remediation.py +892 -0
  50. runbooks/remediation/ec2_subnet_disable_auto_ip_assignment.py +72 -0
  51. runbooks/remediation/ec2_unattached_ebs_volumes.py +448 -0
  52. runbooks/remediation/ec2_unused_security_groups.py +202 -0
  53. runbooks/remediation/kms_enable_key_rotation.py +651 -0
  54. runbooks/remediation/kms_remediation.py +717 -0
  55. runbooks/remediation/lambda_list.py +243 -0
  56. runbooks/remediation/lambda_remediation.py +971 -0
  57. runbooks/remediation/multi_account.py +569 -0
  58. runbooks/remediation/rds_instance_list.py +199 -0
  59. runbooks/remediation/rds_remediation.py +873 -0
  60. runbooks/remediation/rds_snapshot_list.py +192 -0
  61. runbooks/remediation/requirements.txt +118 -0
  62. runbooks/remediation/s3_block_public_access.py +159 -0
  63. runbooks/remediation/s3_bucket_public_access.py +143 -0
  64. runbooks/remediation/s3_disable_static_website_hosting.py +74 -0
  65. runbooks/remediation/s3_downloader.py +215 -0
  66. runbooks/remediation/s3_enable_access_logging.py +562 -0
  67. runbooks/remediation/s3_encryption.py +526 -0
  68. runbooks/remediation/s3_force_ssl_secure_policy.py +143 -0
  69. runbooks/remediation/s3_list.py +141 -0
  70. runbooks/remediation/s3_object_search.py +201 -0
  71. runbooks/remediation/s3_remediation.py +816 -0
  72. runbooks/remediation/scan_for_phrase.py +425 -0
  73. runbooks/remediation/workspaces_list.py +220 -0
  74. runbooks/{security_baseline → security}/README.md +191 -68
  75. runbooks/security/__init__.py +70 -0
  76. runbooks/{security_baseline → security}/security_baseline_tester.py +5 -3
  77. runbooks-0.7.5.dist-info/METADATA +606 -0
  78. {runbooks-0.6.1.dist-info → runbooks-0.7.5.dist-info}/RECORD +115 -75
  79. {runbooks-0.6.1.dist-info → runbooks-0.7.5.dist-info}/entry_points.txt +0 -1
  80. runbooks/aws/__init__.py +0 -58
  81. runbooks/aws/dynamodb_operations.py +0 -231
  82. runbooks/aws/ec2_copy_image_cross-region.py +0 -195
  83. runbooks/aws/ec2_describe_instances.py +0 -202
  84. runbooks/aws/ec2_ebs_snapshots_delete.py +0 -186
  85. runbooks/aws/ec2_run_instances.py +0 -213
  86. runbooks/aws/ec2_start_stop_instances.py +0 -212
  87. runbooks/aws/ec2_terminate_instances.py +0 -143
  88. runbooks/aws/ec2_unused_eips.py +0 -196
  89. runbooks/aws/ec2_unused_volumes.py +0 -188
  90. runbooks/aws/s3_create_bucket.py +0 -142
  91. runbooks/aws/s3_list_buckets.py +0 -152
  92. runbooks/aws/s3_list_objects.py +0 -156
  93. runbooks/aws/s3_object_operations.py +0 -183
  94. runbooks/aws/tagging_lambda_handler.py +0 -183
  95. runbooks/inventory/cfn_move_stack_instances.py +0 -1526
  96. runbooks/inventory/delete_s3_buckets_objects.py +0 -169
  97. runbooks/inventory/lockdown_cfn_stackset_role.py +0 -224
  98. runbooks/inventory/update_aws_actions.py +0 -173
  99. runbooks/inventory/update_cfn_stacksets.py +0 -1215
  100. runbooks/inventory/update_cloudwatch_logs_retention_policy.py +0 -294
  101. runbooks/inventory/update_iam_roles_cross_accounts.py +0 -478
  102. runbooks/inventory/update_s3_public_access_block.py +0 -539
  103. runbooks/organizations/__init__.py +0 -12
  104. runbooks/organizations/manager.py +0 -374
  105. runbooks/security_baseline/requirements.txt +0 -7
  106. runbooks-0.6.1.dist-info/METADATA +0 -373
  107. /runbooks/{aws → operate}/tags.json +0 -0
  108. /runbooks/{security_baseline → remediation/Tests}/__init__.py +0 -0
  109. /runbooks/{security_baseline → security}/checklist/__init__.py +0 -0
  110. /runbooks/{security_baseline → security}/checklist/account_level_bucket_public_access.py +0 -0
  111. /runbooks/{security_baseline → security}/checklist/alternate_contacts.py +0 -0
  112. /runbooks/{security_baseline → security}/checklist/bucket_public_access.py +0 -0
  113. /runbooks/{security_baseline → security}/checklist/cloudwatch_alarm_configuration.py +0 -0
  114. /runbooks/{security_baseline → security}/checklist/direct_attached_policy.py +0 -0
  115. /runbooks/{security_baseline → security}/checklist/guardduty_enabled.py +0 -0
  116. /runbooks/{security_baseline → security}/checklist/iam_password_policy.py +0 -0
  117. /runbooks/{security_baseline → security}/checklist/iam_user_mfa.py +0 -0
  118. /runbooks/{security_baseline → security}/checklist/multi_region_instance_usage.py +0 -0
  119. /runbooks/{security_baseline → security}/checklist/multi_region_trail.py +0 -0
  120. /runbooks/{security_baseline → security}/checklist/root_access_key.py +0 -0
  121. /runbooks/{security_baseline → security}/checklist/root_mfa.py +0 -0
  122. /runbooks/{security_baseline → security}/checklist/root_usage.py +0 -0
  123. /runbooks/{security_baseline → security}/checklist/trail_enabled.py +0 -0
  124. /runbooks/{security_baseline → security}/checklist/trusted_advisor.py +0 -0
  125. /runbooks/{security_baseline → security}/config-origin.json +0 -0
  126. /runbooks/{security_baseline → security}/config.json +0 -0
  127. /runbooks/{security_baseline → security}/permission.json +0 -0
  128. /runbooks/{security_baseline → security}/report_generator.py +0 -0
  129. /runbooks/{security_baseline → security}/report_template_en.html +0 -0
  130. /runbooks/{security_baseline → security}/report_template_jp.html +0 -0
  131. /runbooks/{security_baseline → security}/report_template_kr.html +0 -0
  132. /runbooks/{security_baseline → security}/report_template_vn.html +0 -0
  133. /runbooks/{security_baseline → security}/run_script.py +0 -0
  134. /runbooks/{security_baseline → security}/utils/__init__.py +0 -0
  135. /runbooks/{security_baseline → security}/utils/common.py +0 -0
  136. /runbooks/{security_baseline → security}/utils/enums.py +0 -0
  137. /runbooks/{security_baseline → security}/utils/language.py +0 -0
  138. /runbooks/{security_baseline → security}/utils/level_const.py +0 -0
  139. /runbooks/{security_baseline → security}/utils/permission_list.py +0 -0
  140. {runbooks-0.6.1.dist-info → runbooks-0.7.5.dist-info}/WHEEL +0 -0
  141. {runbooks-0.6.1.dist-info → runbooks-0.7.5.dist-info}/licenses/LICENSE +0 -0
  142. {runbooks-0.6.1.dist-info → runbooks-0.7.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,155 @@
1
+ """
2
+ DynamoDB Cost Optimization - Analyze and optimize table settings for cost savings.
3
+ """
4
+
5
+ import logging
6
+ from datetime import datetime, timedelta
7
+ from functools import lru_cache
8
+
9
+ import click
10
+ from botocore.exceptions import ClientError
11
+
12
+ from .commons import display_aws_account_info, get_client, list_tables, write_to_csv
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ @lru_cache(maxsize=32)
18
+ def get_table_details(table_name):
19
+ """Get DynamoDB table details with error handling."""
20
+ try:
21
+ dynamodb = get_client("dynamodb")
22
+ return dynamodb.describe_table(TableName=table_name)["Table"]
23
+ except ClientError as e:
24
+ logger.error(f"Failed to get table details for {table_name}: {e}")
25
+ raise
26
+
27
+
28
+ def update_table_billing_mode(table_name, billing_mode):
29
+ """Update DynamoDB table billing mode."""
30
+ try:
31
+ dynamodb = get_client("dynamodb")
32
+ dynamodb.update_table(TableName=table_name, BillingMode=billing_mode)
33
+ logger.info(f"Updated {table_name} to {billing_mode} billing mode")
34
+ except ClientError as e:
35
+ logger.error(f"Failed to update {table_name} billing mode: {e}")
36
+ raise
37
+
38
+
39
+ @lru_cache(maxsize=32)
40
+ def analyze_table(table_name):
41
+ """Analyze table usage patterns and suggest cost optimizations."""
42
+ try:
43
+ table_details = get_table_details(table_name)
44
+
45
+ # Get basic table info
46
+ billing_mode_summary = table_details.get("BillingModeSummary", {})
47
+ billing_mode = billing_mode_summary.get("BillingMode", "PROVISIONED")
48
+ table_size_bytes = table_details.get("TableSizeBytes", 0)
49
+ table_item_count = table_details.get("ItemCount", 0)
50
+
51
+ # Get CloudWatch metrics for last 7 days
52
+ end_time = datetime.utcnow()
53
+ start_time = end_time - timedelta(days=7)
54
+
55
+ try:
56
+ cloudwatch = get_client("cloudwatch")
57
+ metrics = cloudwatch.get_metric_statistics(
58
+ Namespace="AWS/DynamoDB",
59
+ MetricName="ConsumedReadCapacityUnits",
60
+ Dimensions=[{"Name": "TableName", "Value": table_name}],
61
+ StartTime=start_time,
62
+ EndTime=end_time,
63
+ Period=86400, # Daily resolution
64
+ Statistics=["Average"],
65
+ )
66
+
67
+ # Calculate average RCU usage
68
+ datapoints = metrics.get("Datapoints", [])
69
+ average_rcu = sum(dp["Average"] for dp in datapoints) / len(datapoints) if datapoints else 0
70
+
71
+ except ClientError as e:
72
+ logger.warning(f"Could not get CloudWatch metrics for {table_name}: {e}")
73
+ average_rcu = 0
74
+
75
+ # Get provisioned capacity if applicable
76
+ provisioned_rcu = None
77
+ if billing_mode == "PROVISIONED" and "ProvisionedThroughput" in table_details:
78
+ provisioned_rcu = table_details["ProvisionedThroughput"].get("ReadCapacityUnits", 0)
79
+
80
+ # Build analysis result
81
+ analysis = {
82
+ "Table": table_name,
83
+ "Billing Mode": billing_mode,
84
+ "Table Size": f"{table_size_bytes / (1024**3):.2f} GB" if table_size_bytes else "0 GB",
85
+ "Item Count": table_item_count,
86
+ "Average RCU": round(average_rcu, 2),
87
+ "Provisioned RCU": provisioned_rcu,
88
+ "Recommendations": [],
89
+ }
90
+
91
+ # Generate recommendations
92
+ if billing_mode == "PROVISIONED" and provisioned_rcu and average_rcu < 0.9 * provisioned_rcu:
93
+ analysis["Recommendations"].append("Consider lowering provisioned RCU to match actual usage")
94
+
95
+ if average_rcu > 1000:
96
+ analysis["Recommendations"].append("Consider enabling DynamoDB Accelerator (DAX) for high read workloads")
97
+
98
+ # Storage optimization for large, infrequently accessed tables
99
+ if table_size_bytes > 10 * (1024**3) and table_item_count > 0 and average_rcu / table_item_count < 0.1:
100
+ table_class = table_details.get("TableClassSummary", {}).get("TableClass", "STANDARD")
101
+ if table_class != "STANDARD_INFREQUENT_ACCESS":
102
+ analysis["Recommendations"].append("Consider STANDARD_INFREQUENT_ACCESS for storage cost savings")
103
+
104
+ return analysis
105
+
106
+ except Exception as e:
107
+ logger.error(f"Failed to analyze table {table_name}: {e}")
108
+ return {
109
+ "Table": table_name,
110
+ "Error": str(e),
111
+ "Recommendations": ["Unable to analyze - check table permissions"],
112
+ }
113
+
114
+
115
+ @click.command()
116
+ @click.option("--apply", "-a", is_flag=True, help="Apply suggested optimizations")
117
+ @click.option("--output", "-o", default="/tmp/dynamodb_analysis.csv", help="Output CSV file path")
118
+ def dynamodb_analyze(apply=False, output="/tmp/dynamodb_analysis.csv"):
119
+ """Analyze DynamoDB tables and suggest cost optimizations."""
120
+ logger.info(f"Analyzing DynamoDB tables in {display_aws_account_info()}")
121
+
122
+ try:
123
+ table_names = list_tables()
124
+ if not table_names:
125
+ logger.info("No DynamoDB tables found")
126
+ return
127
+
128
+ logger.info(f"Found {len(table_names)} tables to analyze")
129
+
130
+ # Analyze each table
131
+ results = []
132
+ for table_name in table_names:
133
+ logger.info(f"Analyzing table: {table_name}")
134
+ result = analyze_table(table_name)
135
+ results.append(result)
136
+
137
+ # Log recommendations
138
+ if result.get("Recommendations"):
139
+ for rec in result["Recommendations"]:
140
+ logger.info(f" Recommendation: {rec}")
141
+ else:
142
+ logger.info(" No optimization recommendations")
143
+
144
+ # Save results to CSV
145
+ write_to_csv(results, output)
146
+ logger.info(f"Analysis results saved to: {output}")
147
+
148
+ # Apply optimizations if requested
149
+ if apply:
150
+ logger.info("Apply functionality not yet implemented")
151
+ # TODO: Implement safe optimization application
152
+
153
+ except Exception as e:
154
+ logger.error(f"Failed to analyze DynamoDB tables: {e}")
155
+ raise