cdk-factory 0.16.15__py3-none-any.whl → 0.20.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.

Potentially problematic release.


This version of cdk-factory might be problematic. Click here for more details.

Files changed (66) hide show
  1. cdk_factory/configurations/base_config.py +23 -24
  2. cdk_factory/configurations/cdk_config.py +1 -1
  3. cdk_factory/configurations/deployment.py +12 -0
  4. cdk_factory/configurations/devops.py +1 -1
  5. cdk_factory/configurations/resources/acm.py +9 -2
  6. cdk_factory/configurations/resources/auto_scaling.py +7 -5
  7. cdk_factory/configurations/resources/cloudfront.py +7 -2
  8. cdk_factory/configurations/resources/ecr.py +1 -1
  9. cdk_factory/configurations/resources/ecs_cluster.py +12 -5
  10. cdk_factory/configurations/resources/ecs_service.py +30 -3
  11. cdk_factory/configurations/resources/lambda_edge.py +18 -4
  12. cdk_factory/configurations/resources/load_balancer.py +8 -9
  13. cdk_factory/configurations/resources/monitoring.py +8 -3
  14. cdk_factory/configurations/resources/rds.py +8 -9
  15. cdk_factory/configurations/resources/route53.py +5 -0
  16. cdk_factory/configurations/resources/rum.py +7 -2
  17. cdk_factory/configurations/resources/s3.py +10 -2
  18. cdk_factory/configurations/resources/security_group_full_stack.py +7 -8
  19. cdk_factory/configurations/resources/vpc.py +19 -0
  20. cdk_factory/configurations/workload.py +32 -2
  21. cdk_factory/constructs/cloudfront/cloudfront_distribution_construct.py +1 -1
  22. cdk_factory/constructs/ecr/ecr_construct.py +9 -2
  23. cdk_factory/constructs/lambdas/policies/policy_docs.py +4 -4
  24. cdk_factory/interfaces/istack.py +4 -4
  25. cdk_factory/interfaces/networked_stack_mixin.py +6 -6
  26. cdk_factory/interfaces/standardized_ssm_mixin.py +684 -0
  27. cdk_factory/interfaces/vpc_provider_mixin.py +64 -33
  28. cdk_factory/lambdas/edge/ip_gate/handler.py +42 -40
  29. cdk_factory/pipeline/pipeline_factory.py +3 -3
  30. cdk_factory/stack_library/__init__.py +3 -2
  31. cdk_factory/stack_library/acm/acm_stack.py +7 -17
  32. cdk_factory/stack_library/api_gateway/api_gateway_stack.py +84 -59
  33. cdk_factory/stack_library/auto_scaling/auto_scaling_stack.py +454 -537
  34. cdk_factory/stack_library/cloudfront/cloudfront_stack.py +76 -22
  35. cdk_factory/stack_library/code_artifact/code_artifact_stack.py +5 -27
  36. cdk_factory/stack_library/cognito/cognito_stack.py +152 -92
  37. cdk_factory/stack_library/dynamodb/dynamodb_stack.py +19 -15
  38. cdk_factory/stack_library/ecr/ecr_stack.py +2 -2
  39. cdk_factory/stack_library/ecs/__init__.py +1 -3
  40. cdk_factory/stack_library/ecs/ecs_cluster_stack.py +159 -75
  41. cdk_factory/stack_library/ecs/ecs_service_stack.py +59 -52
  42. cdk_factory/stack_library/lambda_edge/EDGE_LOG_RETENTION_TODO.md +226 -0
  43. cdk_factory/stack_library/lambda_edge/LAMBDA_EDGE_LOG_RETENTION_BLOG.md +215 -0
  44. cdk_factory/stack_library/lambda_edge/lambda_edge_stack.py +240 -83
  45. cdk_factory/stack_library/load_balancer/load_balancer_stack.py +139 -212
  46. cdk_factory/stack_library/rds/rds_stack.py +74 -98
  47. cdk_factory/stack_library/route53/route53_stack.py +246 -40
  48. cdk_factory/stack_library/rum/rum_stack.py +108 -91
  49. cdk_factory/stack_library/security_group/security_group_full_stack.py +10 -53
  50. cdk_factory/stack_library/security_group/security_group_stack.py +12 -19
  51. cdk_factory/stack_library/simple_queue_service/sqs_stack.py +1 -34
  52. cdk_factory/stack_library/stack_base.py +5 -0
  53. cdk_factory/stack_library/vpc/vpc_stack.py +171 -130
  54. cdk_factory/stack_library/websites/static_website_stack.py +7 -3
  55. cdk_factory/utilities/api_gateway_integration_utility.py +24 -16
  56. cdk_factory/utilities/environment_services.py +5 -5
  57. cdk_factory/utilities/json_loading_utility.py +1 -1
  58. cdk_factory/validation/config_validator.py +483 -0
  59. cdk_factory/version.py +1 -1
  60. {cdk_factory-0.16.15.dist-info → cdk_factory-0.20.0.dist-info}/METADATA +1 -1
  61. {cdk_factory-0.16.15.dist-info → cdk_factory-0.20.0.dist-info}/RECORD +64 -62
  62. cdk_factory/interfaces/enhanced_ssm_parameter_mixin.py +0 -321
  63. cdk_factory/interfaces/ssm_parameter_mixin.py +0 -454
  64. {cdk_factory-0.16.15.dist-info → cdk_factory-0.20.0.dist-info}/WHEEL +0 -0
  65. {cdk_factory-0.16.15.dist-info → cdk_factory-0.20.0.dist-info}/entry_points.txt +0 -0
  66. {cdk_factory-0.16.15.dist-info → cdk_factory-0.20.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,226 @@
1
+ # Lambda@Edge Log Retention - Implementation Plan
2
+
3
+ ## 🚨 Current Status: DISABLED
4
+
5
+ Lambda@Edge log retention configuration has been **disabled** because edge log groups are created on-demand when the function is invoked at edge locations, not during CloudFormation deployment.
6
+
7
+ ## 🔍 Problem Analysis
8
+
9
+ ### Why Deployment-Time Configuration Fails
10
+ 1. **On-Demand Creation**: Lambda@Edge log groups are created only when the function is actually invoked at edge locations
11
+ 2. **Timing Issue**: CloudFormation deployment happens before any edge invocations occur
12
+ 3. **Error**: `The specified log group does not exist` when trying to set retention policies
13
+
14
+ ### Log Group Naming Pattern
15
+ ```
16
+ Pattern: /aws/lambda/{edge-region}.{function-name}
17
+ Example: /aws/lambda/eu-central-1.trav-talks-blue-green-edge-function
18
+ Location: All edge log groups are created in us-east-1
19
+ ```
20
+
21
+ ## 💡 Proposed Solutions
22
+
23
+ ### Solution 1: EventBridge + Lambda (Recommended)
24
+ ```yaml
25
+ # EventBridge rule to detect log group creation
26
+ EventPattern:
27
+ source: ["aws.logs"]
28
+ detail-type: ["AWS API Call via CloudTrail"]
29
+ detail:
30
+ eventSource: ["logs.amazonaws.com"]
31
+ eventName: ["CreateLogGroup"]
32
+ requestParameters:
33
+ logGroupName: ["/aws/lambda/*.edge-function"]
34
+ ```
35
+
36
+ **Implementation:**
37
+ 1. Create EventBridge rule that triggers on log group creation
38
+ 2. Lambda function receives event and sets retention policy
39
+ 3. Automatic handling of new edge log groups
40
+
41
+ **Pros:**
42
+ - Automatic and real-time
43
+ - No manual intervention required
44
+ - Handles all edge regions
45
+
46
+ **Cons:**
47
+ - Additional Lambda function to maintain
48
+ - Requires CloudTrail enabled for CloudWatch Logs
49
+
50
+ ### Solution 2: Periodic Lambda Function
51
+ ```python
52
+ def lambda_handler(event, context):
53
+ # Scan for edge log groups
54
+ log_groups = logs.describe_log_groups(
55
+ logGroupNamePrefix='/aws/lambda/eu-central-1.trav-talks-blue-green-edge-function'
56
+ )
57
+
58
+ # Apply retention policy
59
+ for log_group in log_groups['logGroups']:
60
+ logs.put_retention_policy(
61
+ logGroupName=log_group['logGroupName'],
62
+ retentionInDays=7
63
+ )
64
+ ```
65
+
66
+ **Implementation:**
67
+ 1. Create Lambda function on schedule (e.g., every hour)
68
+ 2. Scan for edge log groups with function name pattern
69
+ 3. Apply retention policy if not already set
70
+
71
+ **Pros:**
72
+ - Simple to implement
73
+ - No CloudTrail dependency
74
+ - Can handle existing log groups
75
+
76
+ **Cons:**
77
+ - Not real-time (delayed retention)
78
+ - Runs periodically even when not needed
79
+
80
+ ### Solution 3: Post-Deployment Script
81
+ ```bash
82
+ #!/bin/bash
83
+ # Wait for edge log groups to appear
84
+ function_name="trav-talks-blue-green-edge-function"
85
+ edge_regions=("eu-central-1" "eu-west-1" "ap-southeast-1")
86
+
87
+ for region in "${edge_regions[@]}"; do
88
+ log_group="/aws/lambda/${region}.${function_name}"
89
+
90
+ # Wait for log group to exist
91
+ until aws logs describe-log-groups --log-group-name-prefix "$log_group" --region us-east-1; do
92
+ echo "Waiting for log group: $log_group"
93
+ sleep 30
94
+ done
95
+
96
+ # Set retention policy
97
+ aws logs put-retention-policy --log-group-name "$log_group" --retention-in-days 7 --region us-east-1
98
+ done
99
+ ```
100
+
101
+ **Implementation:**
102
+ 1. Script runs after Lambda@Edge deployment
103
+ 2. Waits for edge log groups to be created
104
+ 3. Sets retention policies when they appear
105
+
106
+ **Pros:**
107
+ - Direct control over timing
108
+ - No additional AWS resources needed
109
+
110
+ **Cons:**
111
+ - Manual process
112
+ - Hard to determine when log groups will appear
113
+ - Not automated
114
+
115
+ ### Solution 4: CloudWatch Logs Subscription
116
+ ```python
117
+ # Lambda triggered by log group creation via subscription filter
118
+ def lambda_handler(event, context):
119
+ for record in event['Records']:
120
+ log_group = record['logGroup']
121
+ if 'edge-function' in log_group:
122
+ # Set retention policy
123
+ logs.put_retention_policy(
124
+ logGroupName=log_group,
125
+ retentionInDays=7
126
+ )
127
+ ```
128
+
129
+ **Implementation:**
130
+ 1. Create subscription filter on log group pattern
131
+ 2. Lambda function triggered by log events
132
+ 3. Set retention policy on first log event
133
+
134
+ **Pros:**
135
+ - Event-driven
136
+ - No CloudTrail needed
137
+
138
+ **Cons:**
139
+ - Requires log group to exist first
140
+ - Complex subscription filter setup
141
+
142
+ ## 🎯 Recommended Implementation
143
+
144
+ ### Phase 1: Quick Win (Solution 2)
145
+ Implement periodic Lambda function as temporary solution:
146
+ - Easy to implement quickly
147
+ - Solves immediate problem
148
+ - Can be replaced later with better solution
149
+
150
+ ### Phase 2: Production Solution (Solution 1)
151
+ Implement EventBridge + Lambda for production:
152
+ - Real-time response
153
+ - Automatic handling
154
+ - Best long-term solution
155
+
156
+ ## 📋 Implementation Steps for Solution 1
157
+
158
+ ### 1. Create EventBridge Rule
159
+ ```python
160
+ event_rule = events.Rule(
161
+ self, "EdgeLogGroupRule",
162
+ event_pattern=events.EventPattern(
163
+ source=["aws.logs"],
164
+ detail_type=["AWS API Call via CloudTrail"],
165
+ detail={
166
+ "eventSource": ["logs.amazonaws.com"],
167
+ "eventName": ["CreateLogGroup"],
168
+ "requestParameters": {
169
+ "logGroupName": [{"prefix": "/aws/lambda/"}]
170
+ }
171
+ }
172
+ )
173
+ )
174
+ ```
175
+
176
+ ### 2. Create Lambda Function
177
+ ```python
178
+ retention_handler = _lambda.Function(
179
+ self, "EdgeLogRetentionHandler",
180
+ runtime=_lambda.Runtime.PYTHON_3_9,
181
+ handler="handler.lambda_handler",
182
+ code=_lambda.Code.from_asset("lambda/edge_log_retention"),
183
+ environment={
184
+ "RETENTION_DAYS": "7",
185
+ "FUNCTION_NAME_PATTERN": "*edge-function"
186
+ }
187
+ )
188
+ ```
189
+
190
+ ### 3. Add Permissions
191
+ ```python
192
+ retention_handler.add_to_role_policy(
193
+ iam.PolicyStatement(
194
+ actions=["logs:PutRetentionPolicy", "logs:DescribeLogGroups"],
195
+ resources=["*"]
196
+ )
197
+ )
198
+ ```
199
+
200
+ ### 4. Connect EventBridge to Lambda
201
+ ```python
202
+ event_rule.add_target(targets.LambdaFunction(retention_handler))
203
+ ```
204
+
205
+ ## 🔧 Current Configuration
206
+
207
+ The edge log retention configuration is currently **disabled** in the Lambda Edge stack:
208
+
209
+ ```python
210
+ def _configure_edge_log_retention(self, function_name: str) -> None:
211
+ # DISABLED: See implementation plan above
212
+ logger.warning("Edge log retention disabled - see TODO for implementation")
213
+ return
214
+ ```
215
+
216
+ ## 📊 Configuration Impact
217
+
218
+ | Setting | Current Behavior | Target Behavior |
219
+ |---------|------------------|-----------------|
220
+ | `edge_log_retention_days` | Warning logged, no action applied | Retention policy set on all edge log groups |
221
+ | Edge log groups | Created with default retention (never expire) | Created with specified retention (e.g., 7 days) |
222
+ | Cost impact | Potential high log storage costs | Controlled log storage costs |
223
+
224
+ ---
225
+
226
+ **Status**: Ready for implementation when edge log retention is required.
@@ -0,0 +1,215 @@
1
+ # The Lambda@Edge Log Retention Nightmare: A Tale of CloudFormation Frustration
2
+
3
+ ## 🎭 The Setup
4
+
5
+ You've just built an amazing Lambda@Edge function. It's deployed globally, handling requests at the edge with lightning speed. You're feeling proud - until you get the AWS bill and realize those edge logs are costing you a fortune because they never expire.
6
+
7
+ "No problem," you think. "I'll just set a log retention policy in my CloudFormation template."
8
+
9
+ Famous last words.
10
+
11
+ ## 🚨 The Problem: "The specified log group does not exist"
12
+
13
+ Your deployment starts, and then you see it:
14
+
15
+ ```
16
+ EdgeLogRetentioneucentral180637808 - FAILED
17
+ Received response status [FAILED] from custom resource.
18
+ Message returned: The specified log group does not exist.
19
+ ```
20
+
21
+ Wait, what? How can the log group not exist? I'm deploying a Lambda function!
22
+
23
+ ## 🔍 The Investigation: Understanding Lambda@Edge Logging
24
+
25
+ After hours of digging through AWS documentation and Stack Overflow posts, you discover the truth:
26
+
27
+ **Lambda@Edge log groups are created on-demand.**
28
+
29
+ Not during deployment. Not when you create the function. Only when the function is actually invoked at an edge location.
30
+
31
+ This means:
32
+ - Your CloudFormation template runs
33
+ - Lambda@Edge function gets deployed to edge locations
34
+ - Custom resource tries to set log retention
35
+ - **FAILS** because log groups don't exist yet
36
+ - Log groups get created later when someone actually uses your function
37
+
38
+ ## 🤯 The Mind-Bending Architecture
39
+
40
+ Here's where it gets even more confusing:
41
+
42
+ ```bash
43
+ # Log group naming pattern
44
+ /aws/lambda/{edge-region}.{function-name}
45
+
46
+ # Examples
47
+ /aws/lambda/eu-central-1.my-edge-function
48
+ /aws/lambda/ap-southeast-1.my-edge-function
49
+ /aws/lambda/us-west-2.my-edge-function
50
+
51
+ # BUT THEY'RE ALL IN us-east-1!
52
+ arn:aws:logs:us-east-1:123456789:log-group:/aws/lambda/eu-central-1.my-edge-function
53
+ ```
54
+
55
+ Yes, you read that right. A log group named `/aws/lambda/eu-central-1.my-function` is physically located in `us-east-1`. This makes perfect sense to someone at AWS, apparently.
56
+
57
+ ## 💡 The Failed Attempts
58
+
59
+ ### Attempt 1: Custom Resource with SDK Calls
60
+ ```python
61
+ cr.AwsCustomResource(
62
+ self, "EdgeLogRetention",
63
+ on_update={
64
+ "service": "CloudWatchLogs",
65
+ "action": "putRetentionPolicy",
66
+ "parameters": {
67
+ "logGroupName": "/aws/lambda/eu-central-1.my-function",
68
+ "retentionInDays": 7
69
+ }
70
+ }
71
+ )
72
+ ```
73
+ **Result**: "The specified log group does not exist"
74
+
75
+ ### Attempt 2: Fix the Service Name
76
+ ```
77
+ Package @aws-sdk/client-logs does not exist
78
+ ```
79
+ Oh, it's `CloudWatchLogs` not `Logs`. Easy fix!
80
+
81
+ **Result**: Still "The specified log group does not exist"
82
+
83
+ ### Attempt 3: Fix IAM Permissions
84
+ ```python
85
+ policy=cr.AwsCustomResourcePolicy.from_statements([
86
+ iam.PolicyStatement(
87
+ actions=["logs:PutRetentionPolicy", "logs:DeleteRetentionPolicy"],
88
+ resources=["arn:aws:logs:us-east-1:*:log-group:/aws/lambda/eu-central-1.my-function*"]
89
+ )
90
+ ])
91
+ ```
92
+ **Result**: "User is not authorized to perform: logs:PutRetentionPolicy"
93
+
94
+ ### Attempt 4: Fix Region and Permissions
95
+ ```python
96
+ # All edge log groups are in us-east-1, not the edge region!
97
+ resources=["arn:aws:logs:us-east-1:*:log-group:/aws/lambda/eu-central-1.my-function*"]
98
+ ```
99
+ **Result**: "The specified log group does not exist"
100
+
101
+ ## 🎭 The Realization
102
+
103
+ You finally understand: **You're trying to set retention on something that doesn't exist yet.**
104
+
105
+ It's like trying to put a roof on a house before the foundation is poured. Lambda@Edge log groups are created when the function is first invoked at that edge location, which could be minutes, hours, or days after deployment.
106
+
107
+ ## 🤔 The Solutions We Considered
108
+
109
+ ### Solution 1: EventBridge + Lambda (The "Proper" Way)
110
+ ```yaml
111
+ EventPattern:
112
+ source: ["aws.logs"]
113
+ detail-type: ["AWS API Call via CloudTrail"]
114
+ detail:
115
+ eventSource: ["logs.amazonaws.com"]
116
+ eventName: ["CreateLogGroup"]
117
+ ```
118
+
119
+ **Pros**: Real-time, automatic, handles all edge regions
120
+ **Cons**: Requires CloudTrail, another Lambda to maintain, complex setup
121
+
122
+ ### Solution 2: Periodic Lambda Function (The "Good Enough" Way)
123
+ ```python
124
+ def lambda_handler(event, context):
125
+ # Scan for edge log groups every hour
126
+ # Apply retention if needed
127
+ ```
128
+
129
+ **Pros**: Simple, no CloudTrail dependency
130
+ **Cons**: Not real-time, runs even when not needed
131
+
132
+ ### Solution 3: Post-Deployment Script (The "Manual" Way)
133
+ ```bash
134
+ # Wait for log groups to appear
135
+ until aws logs describe-log-groups --log-group-name-prefix "/aws/lambda/eu-central-1.my-function"; do
136
+ sleep 30
137
+ done
138
+ ```
139
+
140
+ **Pros**: Direct control, no extra resources
141
+ **Cons**: Manual, timing issues, not scalable
142
+
143
+ ### Solution 4: CloudWatch Subscription (The "Overkill" Way)
144
+ **Pros**: Event-driven
145
+ **Cons**: Complex, requires log group to exist first
146
+
147
+ ## 🏳️ The Decision: We're Tabling This
148
+
149
+ After weighing all options, we decided to **disable edge log retention for now**:
150
+
151
+ ```python
152
+ def _configure_edge_log_retention(self, function_name: str) -> None:
153
+ # DISABLED: Edge log groups don't exist during deployment
154
+ logger.warning("Edge log retention disabled - log groups are created on-demand")
155
+ return
156
+ ```
157
+
158
+ Why?
159
+
160
+ 1. **Complexity vs. Benefit**: The solutions are complex for what should be a simple configuration
161
+ 2. **Cost Impact**: We'll monitor costs and implement something if it becomes a problem
162
+ 3. **AWS Responsibility**: This feels like something AWS should handle better
163
+ 4. **Time Constraints**: We have features to ship, not logging architecture to perfect
164
+
165
+ ## 🤷‍♂️ The Frustration
166
+
167
+ Here's what frustrates us most:
168
+
169
+ 1. **No Clear Documentation**: AWS doesn't clearly document this limitation
170
+ 2. **Misleading Error Messages**: "Log group does not exist" doesn't explain WHY
171
+ 3. **Counterintuitive Architecture**: Why are edge logs in us-east-1?
172
+ 4. **No Built-in Solution**: AWS should provide a way to set default retention
173
+
174
+ ## 📣 The Call for Help
175
+
176
+ **We're throwing this out to the community:**
177
+
178
+ Has anyone solved this elegantly? Are we missing something obvious? Is there a magical CloudFormation feature we don't know about?
179
+
180
+ ### What We Tried:
181
+ - ✅ Custom resources with proper IAM permissions
182
+ - ✅ Correct service names (`CloudWatchLogs` not `Logs`)
183
+ - ✅ Right region targeting (`us-east-1` for all edge logs)
184
+ - ✅ Multiple deployment approaches
185
+
186
+ ### What We Need:
187
+ - 🤔 A way to set retention policies on edge log groups during deployment
188
+ - 🤔 Or a clean post-deployment solution that doesn't require manual intervention
189
+ - 🤔 Or confirmation that this is impossible and we should stop trying
190
+
191
+ ## 🎯 The Current State
192
+
193
+ For now, our Lambda@Edge functions deploy successfully with a warning:
194
+
195
+ ```
196
+ Edge log retention configuration disabled - log groups are created on-demand.
197
+ Desired retention: 7 days. See TODO for implementation approach.
198
+ ```
199
+
200
+ We'll monitor the costs and implement one of the solutions if it becomes a real problem. But for now, we're choosing **shipping features over perfect logging architecture**.
201
+
202
+ ## 🔮 The Future
203
+
204
+ Hopefully, AWS will:
205
+ 1. **Document this limitation** clearly
206
+ 2. **Provide a built-in solution** for edge log retention
207
+ 3. **Fix the confusing architecture** (or at least explain it better)
208
+
209
+ Until then, we'll keep an eye on our logging costs and hope someone in the community has a better solution.
210
+
211
+ ---
212
+
213
+ **Have you solved this? Drop your solutions in the comments! Let's save the next developer from this nightmare.**
214
+
215
+ #AWS #Lambda #CloudFormation #EdgeComputing #Frustration #LoggingNightmare