cdk-factory 0.19.7__tar.gz → 0.19.14__tar.gz

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 (166) hide show
  1. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/PKG-INFO +1 -1
  2. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/pyproject.toml +1 -1
  3. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/lambda_edge.py +17 -3
  4. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/cloudfront/cloudfront_stack.py +14 -11
  5. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/ecs/ecs_service_stack.py +34 -0
  6. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/lambda_edge/lambda_edge_stack.py +205 -29
  7. cdk_factory-0.19.14/src/cdk_factory/version.py +1 -0
  8. cdk_factory-0.19.7/src/cdk_factory/version.py +0 -1
  9. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/.gitignore +0 -0
  10. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/.windsurfrules +0 -0
  11. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/LICENSE +0 -0
  12. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/README.md +0 -0
  13. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/REFACTORING_PLAN.md +0 -0
  14. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/archive/README.md +0 -0
  15. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/archive/migrate_to_enhanced_ssm.py +0 -0
  16. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/examples/json-imports/README.md +0 -0
  17. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/examples/separate-api-gateway/README.md +0 -0
  18. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/examples/separate-api-gateway/api-gateway-stack.json +0 -0
  19. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/examples/separate-api-gateway/config.json +0 -0
  20. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/examples/separate-api-gateway/lambda-stack.json +0 -0
  21. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/mypy.ini +0 -0
  22. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/publish_to_pypi.py +0 -0
  23. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/publish_to_pypi.sh +0 -0
  24. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/pysetup.py +0 -0
  25. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/pysetup.sh +0 -0
  26. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/requirements.dev.txt +0 -0
  27. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/requirements.tests.txt +0 -0
  28. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/requirements.txt +0 -0
  29. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/run-checks.sh +0 -0
  30. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/run-tests-clean-venv.sh +0 -0
  31. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/run-tests.sh +0 -0
  32. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/scripts/cloudfront-cleanup.sh +0 -0
  33. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/__init__.py +0 -0
  34. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/app.py +0 -0
  35. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/builds/README.md +0 -0
  36. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/cdk.json +0 -0
  37. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/cli.py +0 -0
  38. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/commands/command_loader.py +0 -0
  39. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/base_config.py +0 -0
  40. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/cdk_config.py +0 -0
  41. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/deployment.py +0 -0
  42. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/deployment_wave.py +0 -0
  43. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/devops.py +0 -0
  44. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/enhanced_base_config.py +0 -0
  45. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/enhanced_ssm_config.py +0 -0
  46. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/management.py +0 -0
  47. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/pipeline.py +0 -0
  48. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/pipeline_stage.py +0 -0
  49. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/_resources.py +0 -0
  50. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/acm.py +0 -0
  51. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/api_gateway.py +0 -0
  52. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/apigateway_route_config.py +0 -0
  53. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/auto_scaling.py +0 -0
  54. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/cloudfront.py +0 -0
  55. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/cloudwatch_widget.py +0 -0
  56. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/code_artifact.py +0 -0
  57. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/code_artifact_login.py +0 -0
  58. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/code_repository.py +0 -0
  59. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/cognito.py +0 -0
  60. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/docker.py +0 -0
  61. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/dynamodb.py +0 -0
  62. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/ecr.py +0 -0
  63. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/ecs_cluster.py +0 -0
  64. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/ecs_service.py +0 -0
  65. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/exisiting.py +0 -0
  66. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/lambda_function.py +0 -0
  67. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/lambda_layers.py +0 -0
  68. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/lambda_triggers.py +0 -0
  69. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/load_balancer.py +0 -0
  70. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/monitoring.py +0 -0
  71. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/rds.py +0 -0
  72. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/resource_mapping.py +0 -0
  73. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/resource_naming.py +0 -0
  74. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/resource_types.py +0 -0
  75. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/route53.py +0 -0
  76. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/route53_hosted_zone.py +0 -0
  77. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/rum.py +0 -0
  78. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/s3.py +0 -0
  79. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/security_group.py +0 -0
  80. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/security_group_full_stack.py +0 -0
  81. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/sqs.py +0 -0
  82. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/resources/vpc.py +0 -0
  83. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/stack.py +0 -0
  84. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/configurations/workload.py +0 -0
  85. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/cloudfront/cloudfront_distribution_construct.py +0 -0
  86. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/ecr/ecr_construct.py +0 -0
  87. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/lambdas/lambda_function_construct.py +0 -0
  88. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/lambdas/lambda_function_docker_construct.py +0 -0
  89. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/lambdas/lambda_function_role_construct.py +0 -0
  90. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/lambdas/policies/policy_docs.py +0 -0
  91. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/lambdas/policies/policy_statements.py +0 -0
  92. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/s3_buckets/s3_bucket_construct.py +0 -0
  93. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/s3_buckets/s3_bucket_replication_destination_construct.py +0 -0
  94. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/s3_buckets/s3_bucket_replication_source_construct.py +0 -0
  95. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/constructs/sqs/policies/sqs_policies.py +0 -0
  96. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/interfaces/istack.py +0 -0
  97. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/interfaces/live_ssm_resolver.py +0 -0
  98. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/interfaces/networked_stack_mixin.py +0 -0
  99. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/interfaces/standardized_ssm_mixin.py +0 -0
  100. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/interfaces/vpc_provider_mixin.py +0 -0
  101. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/lambdas/edge/ip_gate/handler.py +0 -0
  102. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/lambdas/health_handler.py +0 -0
  103. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/pipeline/path_utils.py +0 -0
  104. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/pipeline/pipeline_factory.py +0 -0
  105. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/pipeline/security/policies.py +0 -0
  106. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/pipeline/security/roles.py +0 -0
  107. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/pipeline/stage.py +0 -0
  108. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack/istack.py +0 -0
  109. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack/stack_factory.py +0 -0
  110. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack/stack_module_loader.py +0 -0
  111. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack/stack_module_registry.py +0 -0
  112. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack/stack_modules.py +0 -0
  113. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/__init__.py +0 -0
  114. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/acm/__init__.py +0 -0
  115. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/acm/acm_stack.py +0 -0
  116. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/api_gateway/api_gateway_stack.py +0 -0
  117. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/auto_scaling/__init__.py +0 -0
  118. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/auto_scaling/auto_scaling_stack.py +0 -0
  119. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/aws_lambdas/lambda_stack.py +0 -0
  120. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/buckets/README.md +0 -0
  121. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/buckets/bucket_stack.py +0 -0
  122. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/cloudfront/__init__.py +0 -0
  123. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/code_artifact/code_artifact_stack.py +0 -0
  124. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/cognito/cognito_stack.py +0 -0
  125. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/dynamodb/dynamodb_stack.py +0 -0
  126. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/ecr/README.md +0 -0
  127. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/ecr/ecr_stack.py +0 -0
  128. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/ecs/__init__.py +0 -0
  129. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/ecs/ecs_cluster_stack.py +0 -0
  130. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/lambda_edge/__init__.py +0 -0
  131. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/load_balancer/__init__.py +0 -0
  132. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/load_balancer/load_balancer_stack.py +0 -0
  133. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/monitoring/__init__.py +0 -0
  134. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/monitoring/monitoring_stack.py +0 -0
  135. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/rds/__init__.py +0 -0
  136. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/rds/rds_stack.py +0 -0
  137. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/route53/__init__.py +0 -0
  138. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/route53/route53_stack.py +0 -0
  139. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/rum/__init__.py +0 -0
  140. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/rum/rum_stack.py +0 -0
  141. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/security_group/__init__.py +0 -0
  142. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/security_group/security_group_full_stack.py +0 -0
  143. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/security_group/security_group_stack.py +0 -0
  144. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/simple_queue_service/sqs_stack.py +0 -0
  145. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/stack_base.py +0 -0
  146. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/vpc/__init__.py +0 -0
  147. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/vpc/vpc_stack.py +0 -0
  148. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stack_library/websites/static_website_stack.py +0 -0
  149. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/stages/websites/static_website_stage.py +0 -0
  150. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/templates/README.md +0 -0
  151. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/templates/app.py.template +0 -0
  152. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/templates/cdk.json.template +0 -0
  153. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utilities/api_gateway_integration_utility.py +0 -0
  154. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utilities/commandline_args.py +0 -0
  155. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utilities/configuration_loader.py +0 -0
  156. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utilities/docker_utilities.py +0 -0
  157. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utilities/environment_services.py +0 -0
  158. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utilities/file_operations.py +0 -0
  159. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utilities/git_utilities.py +0 -0
  160. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utilities/json_loading_utility.py +0 -0
  161. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utilities/lambda_function_utilities.py +0 -0
  162. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utilities/os_execute.py +0 -0
  163. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/utils/api_gateway_utilities.py +0 -0
  164. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/validation/config_validator.py +0 -0
  165. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/cdk_factory/workload/workload_factory.py +0 -0
  166. {cdk_factory-0.19.7 → cdk_factory-0.19.14}/src/handlers/test/handler.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cdk_factory
3
- Version: 0.19.7
3
+ Version: 0.19.14
4
4
  Summary: CDK Factory. A QuickStarter and best practices setup for CDK projects
5
5
  Author-email: Eric Wilson <eric.wilson@geekcafe.com>
6
6
  License: MIT License
@@ -33,7 +33,7 @@ markers = [
33
33
  [project]
34
34
 
35
35
  name = "cdk_factory"
36
- version = "0.19.7"
36
+ version = "0.19.14"
37
37
  authors = [
38
38
  { name="Eric Wilson", email="eric.wilson@geekcafe.com" }
39
39
  ]
@@ -49,10 +49,24 @@ class LambdaEdgeConfig(EnhancedBaseConfig):
49
49
 
50
50
  @property
51
51
  def timeout(self) -> int:
52
- """Timeout in seconds (max 5 for origin-request)"""
52
+ """Timeout in seconds
53
+ viewer-request: 5s
54
+ viewer-response: 5s
55
+ ---
56
+ origin-request: 30s
57
+ origin-response: 30s
58
+
59
+
60
+ """
53
61
  timeout = int(self._config.get("timeout", 5))
54
- if timeout > 5:
55
- raise ValueError("Lambda@Edge origin-request timeout cannot exceed 5 seconds. Value was set to {}".format(timeout))
62
+
63
+ event_type = self.event_type
64
+ if event_type == "viewer-request" or event_type == "viewer-response":
65
+ if timeout > 5:
66
+ raise ValueError("Lambda@Edge viewer timeout cannot exceed 5 seconds. Value was set to {}".format(timeout))
67
+ else:
68
+ if timeout > 30:
69
+ raise ValueError("Lambda@Edge origin timeout cannot exceed 30 seconds. Value was set to {}".format(timeout))
56
70
  return timeout
57
71
 
58
72
  @property
@@ -145,7 +145,7 @@ class CloudFrontStack(IStack):
145
145
  return
146
146
 
147
147
  # Check if certificate ARN is provided
148
- cert_arn = cert_config.get("arn")
148
+ cert_arn = self.resolve_ssm_value(self, cert_config.get("arn"), "CertificateARN")
149
149
  if cert_arn:
150
150
  self.certificate = acm.Certificate.from_certificate_arn(
151
151
  self, "Certificate", certificate_arn=cert_arn
@@ -173,14 +173,14 @@ class CloudFrontStack(IStack):
173
173
  "CloudFront certificates must be created in us-east-1"
174
174
  )
175
175
  return
176
-
176
+
177
177
  # Create the certificate
178
178
  # Get hosted zone from SSM imports
179
179
  hosted_zone_id = cert_config.get("hosted_zone_id")
180
180
  hosted_zone = route53.HostedZone.from_hosted_zone_id(
181
181
  self, "HostedZone", hosted_zone_id
182
182
  )
183
-
183
+
184
184
  self.certificate = acm.Certificate(
185
185
  self,
186
186
  "Certificate",
@@ -223,7 +223,9 @@ class CloudFrontStack(IStack):
223
223
 
224
224
  def _create_custom_origin(self, config: Dict[str, Any]) -> cloudfront.IOrigin:
225
225
  """Create custom origin (ALB, API Gateway, etc.)"""
226
- domain_name = self.resolve_ssm_value(self, config.get("domain_name"), config.get("domain_name"))
226
+ domain_name = self.resolve_ssm_value(
227
+ self, config.get("domain_name"), config.get("domain_name")
228
+ )
227
229
  origin_id = config.get("id")
228
230
 
229
231
  if not domain_name:
@@ -297,21 +299,22 @@ class CloudFrontStack(IStack):
297
299
 
298
300
  def _create_s3_origin(self, config: Dict[str, Any]) -> cloudfront.IOrigin:
299
301
  """Create S3 origin"""
300
- bucket_name = self.resolve_ssm_value(self, config.get("bucket_name"), config.get("bucket_name"))
301
-
302
+ bucket_name = self.resolve_ssm_value(
303
+ self, config.get("bucket_name"), config.get("bucket_name")
304
+ )
302
305
 
303
306
  origin_path = config.get("origin_path", "")
304
-
307
+
305
308
  if not bucket_name:
306
309
  raise ValueError("S3 origin requires 'bucket_name' configuration")
307
-
310
+
308
311
  # For S3 origins, we need to import the bucket by name
309
312
  bucket = s3.Bucket.from_bucket_name(
310
313
  self,
311
314
  id=f"S3OriginBucket-{config.get('id', 'unknown')}",
312
- bucket_name=bucket_name
315
+ bucket_name=bucket_name,
313
316
  )
314
-
317
+
315
318
  # Create S3 origin with OAC (Origin Access Control) for security
316
319
  origin = origins.S3BucketOrigin.with_origin_access_control(
317
320
  bucket,
@@ -321,7 +324,7 @@ class CloudFrontStack(IStack):
321
324
  cloudfront.AccessLevel.LIST,
322
325
  ],
323
326
  )
324
-
327
+
325
328
  return origin
326
329
 
327
330
  def _create_distribution(self) -> None:
@@ -226,6 +226,9 @@ class EcsServiceStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
226
226
  "CloudWatchAgentServerPolicy"
227
227
  )
228
228
  )
229
+
230
+ # add any custom policies
231
+ self._add_custom_task_policies(task_role)
229
232
 
230
233
  # Create task definition based on launch type
231
234
  if self.ecs_config.launch_type == "EC2":
@@ -257,6 +260,37 @@ class EcsServiceStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
257
260
  # Add containers
258
261
  self._add_containers_to_task()
259
262
 
263
+ def _add_custom_task_policies(self, task_role: iam.Role) -> None:
264
+ """
265
+ Add custom task policies to the task definition.
266
+ """
267
+ for policy in self.ecs_config.task_definition.get("policies", []):
268
+
269
+ effect = policy.get("effect", "Allow")
270
+ action = policy.get("action", None)
271
+ actions = policy.get("actions", [])
272
+ if action:
273
+ actions.append(action)
274
+ resources = policy.get("resources", [])
275
+ resource = policy.get("resource", None)
276
+ if resource:
277
+ resources.append(resource)
278
+
279
+ if effect == "Allow" and actions:
280
+ effect = iam.Effect.ALLOW
281
+ if effect == "Deny" and actions:
282
+ effect = iam.Effect.DENY
283
+
284
+ sid = policy.get("sid", None)
285
+ task_role.add_to_policy(
286
+ iam.PolicyStatement(
287
+ effect=effect,
288
+ actions=actions,
289
+ resources=resources,
290
+ sid=sid,
291
+ )
292
+ )
293
+
260
294
  def _add_volumes_to_task(self) -> None:
261
295
  """
262
296
  Add volumes to the task definition.
@@ -53,6 +53,8 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
53
53
  self.workload: Optional[WorkloadConfig] = None
54
54
  self.function: Optional[_lambda.Function] = None
55
55
  self.function_version: Optional[_lambda.Version] = None
56
+ # Cache for resolved environment variables to prevent duplicate construct creation
57
+ self._resolved_env_cache: Optional[Dict[str, str]] = None
56
58
 
57
59
  def build(
58
60
  self,
@@ -98,15 +100,38 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
98
100
  # Create version (required for Lambda@Edge)
99
101
  self._create_function_version(function_name)
100
102
 
103
+ # Configure edge log retention for regional logs
104
+ self._configure_edge_log_retention(function_name)
105
+
101
106
  # Add outputs
102
107
  self._add_outputs(function_name)
103
108
 
109
+ def _sanitize_construct_name(self, name: str) -> str:
110
+ """
111
+ Create a deterministic, valid CDK construct name from any string.
112
+ Replaces non-alphanumeric characters with dashes and limits length.
113
+ """
114
+ # Replace non-alphanumeric characters with dashes
115
+ sanitized = ''.join(c if c.isalnum() else '-' for c in name)
116
+ # Remove consecutive dashes
117
+ while '--' in sanitized:
118
+ sanitized = sanitized.replace('--', '-')
119
+ # Remove leading/trailing dashes
120
+ sanitized = sanitized.strip('-')
121
+ # Limit to 255 characters (CDK limit)
122
+ return sanitized[:255]
123
+
104
124
  def _resolve_environment_variables(self) -> Dict[str, str]:
105
125
  """
106
126
  Resolve environment variables, including SSM parameter references.
107
127
  Supports {{ssm:parameter-path}} syntax for dynamic SSM lookups.
108
128
  Uses CDK tokens that resolve at deployment time, not synthesis time.
129
+ Caches results to prevent duplicate construct creation.
109
130
  """
131
+ # Return cached result if available
132
+ if self._resolved_env_cache is not None:
133
+ return self._resolved_env_cache
134
+
110
135
  resolved_env = {}
111
136
 
112
137
  for key, value in self.edge_config.environment.items():
@@ -115,18 +140,23 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
115
140
  # Extract SSM parameter path
116
141
  ssm_param_path = value[6:-2] # Remove {{ssm: and }}
117
142
 
143
+ # Create deterministic construct name from parameter path
144
+ construct_name = self._sanitize_construct_name(f"env-{key}-{ssm_param_path}")
145
+
118
146
  # Import SSM parameter - this creates a token that resolves at deployment time
119
147
  param = ssm.StringParameter.from_string_parameter_name(
120
148
  self,
121
- f"env-{key}-{hash(ssm_param_path) % 10000}",
149
+ construct_name,
122
150
  ssm_param_path
123
151
  )
124
152
  resolved_value = param.string_value
125
- logger.info(f"Resolved environment variable {key} from SSM {ssm_param_path}")
153
+ logger.info(f"Resolved environment variable {key} from SSM {ssm_param_path} as {construct_name}")
126
154
  resolved_env[key] = resolved_value
127
155
  else:
128
156
  resolved_env[key] = value
129
157
 
158
+ # Cache the result
159
+ self._resolved_env_cache = resolved_env
130
160
  return resolved_env
131
161
 
132
162
  def _create_lambda_function(self, function_name: str) -> None:
@@ -185,10 +215,12 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
185
215
  # Create runtime configuration file for Lambda@Edge
186
216
  # Since Lambda@Edge doesn't support environment variables, we bundle a config file
187
217
  # Use the full function_name (e.g., "tech-talk-dev-ip-gate") not just the base name
218
+ resolved_env = self._resolve_environment_variables()
188
219
  runtime_config = {
189
220
  'environment': self.deployment.environment,
190
221
  'function_name': function_name,
191
- 'region': self.deployment.region
222
+ 'region': self.deployment.region,
223
+ 'environment_variables': resolved_env # Add actual environment variables
192
224
  }
193
225
 
194
226
  runtime_config_path = temp_code_dir / 'runtime_config.json'
@@ -216,19 +248,12 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
216
248
  self.edge_config.runtime,
217
249
  _lambda.Runtime.PYTHON_3_11
218
250
  )
219
-
220
- # Lambda@Edge does NOT support environment variables
221
- # Configuration must be handled via:
222
- # 1. Hardcoded in the function code
223
- # 2. Fetched from SSM Parameter Store at runtime
224
- # 3. Other configuration mechanisms
225
-
251
+
226
252
  # Log warning if environment variables are configured
227
253
  if self.edge_config.environment:
228
254
  logger.warning(
229
255
  f"Lambda@Edge function '{function_name}' has environment variables configured, "
230
- "but Lambda@Edge does not support environment variables. "
231
- "The function must fetch these values from SSM Parameter Store at runtime."
256
+ "but Lambda@Edge does not support environment variables. The function must fetch these values from SSM Parameter Store at runtime."
232
257
  )
233
258
  for key, value in self.edge_config.environment.items():
234
259
  logger.warning(f" - {key}: {value}")
@@ -239,7 +264,8 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
239
264
  f"{function_name}-Role",
240
265
  assumed_by=iam.CompositePrincipal(
241
266
  iam.ServicePrincipal("lambda.amazonaws.com"),
242
- iam.ServicePrincipal("edgelambda.amazonaws.com")
267
+ iam.ServicePrincipal("edgelambda.amazonaws.com"),
268
+ iam.ServicePrincipal("cloudfront.amazonaws.com") # Add CloudFront service principal
243
269
  ),
244
270
  description=f"Execution role for Lambda@Edge function {function_name}",
245
271
  managed_policies=[
@@ -264,8 +290,8 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
264
290
  ]
265
291
  )
266
292
  )
293
+
267
294
 
268
- # Create the Lambda function WITHOUT environment variables
269
295
  self.function = _lambda.Function(
270
296
  self,
271
297
  function_name,
@@ -278,6 +304,7 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
278
304
  description=self.edge_config.description,
279
305
  role=execution_role,
280
306
  # Lambda@Edge does NOT support environment variables
307
+ # Configuration must be fetched from SSM at runtime
281
308
  log_retention=logs.RetentionDays.ONE_WEEK,
282
309
  )
283
310
 
@@ -285,6 +312,36 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
285
312
  for key, value in self.edge_config.tags.items():
286
313
  cdk.Tags.of(self.function).add(key, value)
287
314
 
315
+ # Add resource-based policy allowing CloudFront to invoke the Lambda function
316
+ # This is REQUIRED for Lambda@Edge to work properly
317
+ permission_kwargs = {
318
+ "principal": iam.ServicePrincipal("cloudfront.amazonaws.com"),
319
+ "action": "lambda:InvokeFunction",
320
+ }
321
+
322
+ # Optional: Add source ARN restriction if CloudFront distribution ARN is available
323
+ # This provides more secure permission scoping
324
+ distribution_arn_path = f"/{self.deployment.environment}/{self.workload.name}/cloudfront/arn"
325
+ try:
326
+ distribution_arn = ssm.StringParameter.from_string_parameter_name(
327
+ self,
328
+ "cloudfront-distribution-arn",
329
+ distribution_arn_path
330
+ ).string_value
331
+
332
+ # Add source ARN condition for more secure permission scoping
333
+ permission_kwargs["source_arn"] = distribution_arn
334
+ logger.info(f"Adding CloudFront permission with source ARN restriction: {distribution_arn}")
335
+ except Exception:
336
+ # Distribution ARN not available (common during initial deployment)
337
+ # CloudFront will scope the permission appropriately when it associates the Lambda
338
+ logger.warning(f"CloudFront distribution ARN not found at {distribution_arn_path}, using open permission")
339
+
340
+ self.function.add_permission(
341
+ "CloudFrontInvokePermission",
342
+ **permission_kwargs
343
+ )
344
+
288
345
  def _create_function_version(self, function_name: str) -> None:
289
346
  """
290
347
  Create a version of the Lambda function.
@@ -300,6 +357,57 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
300
357
  f"Version for Lambda@Edge deployment - {self.edge_config.description}"
301
358
  )
302
359
 
360
+ def _configure_edge_log_retention(self, function_name: str) -> None:
361
+ """
362
+ Configure log retention for Lambda@Edge regional logs.
363
+
364
+ Lambda@Edge creates log groups in multiple regions that need
365
+ separate retention configuration from the primary log group.
366
+ """
367
+ from aws_cdk import custom_resources as cr
368
+
369
+ # Get edge log retention from config (default to same as primary logs)
370
+ edge_retention_days = self.edge_config.dictionary.get("edge_log_retention_days", 7)
371
+
372
+ # List of common Lambda@Edge regions
373
+ edge_regions = [
374
+ 'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2',
375
+ 'eu-west-1', 'eu-west-2', 'eu-central-1',
376
+ 'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1',
377
+ 'ca-central-1', 'sa-east-1'
378
+ ]
379
+
380
+ # Create custom resource to set log retention for each region
381
+ for region in edge_regions:
382
+ log_group_name = f"/aws/lambda/{region}.{function_name}"
383
+
384
+ # Use AwsCustomResource to set log retention
385
+ cr.AwsCustomResource(
386
+ self, f"EdgeLogRetention-{region}",
387
+ on_update={
388
+ "service": "Logs",
389
+ "action": "putRetentionPolicy",
390
+ "parameters": {
391
+ "logGroupName": log_group_name,
392
+ "retentionInDays": edge_retention_days
393
+ },
394
+ "physical_resource_id": cr.PhysicalResourceId.from_response("logGroupName")
395
+ },
396
+ on_delete={
397
+ "service": "Logs",
398
+ "action": "deleteRetentionPolicy",
399
+ "parameters": {
400
+ "logGroupName": log_group_name
401
+ },
402
+ "physical_resource_id": cr.PhysicalResourceId.from_response("logGroupName")
403
+ },
404
+ policy=cr.AwsCustomResourcePolicy.from_sdk_calls(
405
+ resources=[f"arn:aws:logs:{region}:*:log-group:{log_group_name}*"]
406
+ )
407
+ )
408
+
409
+ logger.info(f"Configured edge log retention to {edge_retention_days} days for {len(edge_regions)} regions")
410
+
303
411
  def _add_outputs(self, function_name: str) -> None:
304
412
  """Add CloudFormation outputs and SSM exports"""
305
413
 
@@ -335,18 +443,86 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
335
443
 
336
444
  # If no explicit environment_ssm_exports, create default SSM paths
337
445
  if not env_ssm_exports:
338
- # Auto-generate SSM parameter names based on environment variable names
339
- for env_key in self.edge_config.environment.keys():
340
- # Use snake_case version of the key for SSM path
341
- ssm_key = env_key.lower().replace('_', '-')
342
- env_ssm_exports[env_key] = f"/{self.deployment.environment}/{function_name}/{ssm_key}"
446
+ env_ssm_exports = {
447
+ key: f"/{self.deployment.environment}/{self.workload.name}/lambda-edge/{key.lower()}"
448
+ for key in self.edge_config.environment.keys()
449
+ }
343
450
 
344
- # Resolve and export environment variables to SSM
345
- resolved_env = self._resolve_environment_variables()
346
- for env_key, ssm_path in env_ssm_exports.items():
347
- if env_key in resolved_env:
348
- env_value = resolved_env[env_key]
349
-
451
+ # Export each environment variable to SSM
452
+ for var_name, var_value in self.edge_config.environment.items():
453
+ ssm_path = env_ssm_exports.get(var_name, f"/{self.deployment.environment}/{self.workload.name}/lambda-edge/{var_name.lower()}")
454
+ self.export_ssm_parameter(
455
+ self,
456
+ f"{var_name}-env-param",
457
+ var_value,
458
+ ssm_path,
459
+ description=f"Lambda@Edge environment variable: {var_name} for {function_name}"
460
+ )
461
+
462
+ # Export the complete configuration as a single SSM parameter for dynamic updates
463
+ config_ssm_path = f"/{self.deployment.environment}/{self.workload.name}/lambda-edge/config"
464
+ full_config = {
465
+ "environment_variables": self.edge_config.environment or {}
466
+ }
467
+
468
+ self.export_ssm_parameter(
469
+ self,
470
+ "full-config-param",
471
+ json.dumps(full_config),
472
+ config_ssm_path,
473
+ description=f"Complete Lambda@Edge configuration for {function_name} - update this for dynamic changes"
474
+ )
475
+
476
+ # Export cache TTL parameter for dynamic cache control
477
+ cache_ttl_ssm_path = f"/{self.deployment.environment}/{self.workload.name}/lambda-edge/cache-ttl"
478
+ default_cache_ttl = self.edge_config.dictionary.get("cache_ttl_seconds", 300) # Default 5 minutes
479
+
480
+ self.export_ssm_parameter(
481
+ self,
482
+ "cache-ttl-param",
483
+ str(default_cache_ttl),
484
+ cache_ttl_ssm_path,
485
+ description=f"Lambda@Edge configuration cache TTL in seconds for {function_name} - adjust for maintenance windows (30-3600)"
486
+ )
487
+
488
+ # Create additional default parameters if configured
489
+ default_params = self.edge_config.dictionary.get("default_parameters", {})
490
+ if default_params:
491
+ logger.info(f"Creating {len(default_params)} default SSM parameters")
492
+
493
+ for param_name, param_value in default_params.items():
494
+ param_path = f"/{self.deployment.environment}/{self.workload.name}/lambda-edge/defaults/{param_name}"
495
+
496
+ # Create descriptive parameter description
497
+ descriptions = {
498
+ "CACHE_TTL": f"Configuration cache TTL in seconds for {function_name}",
499
+ "HEALTH_CHECK_TIMEOUT": f"ALB health check timeout in seconds for {function_name}",
500
+ "HEALTH_CHECK_CACHE_TTL": f"Health check result cache TTL in seconds for {function_name}",
501
+ "MAINTENANCE_MODE": f"Maintenance mode toggle for {function_name}",
502
+ "GATE_ENABLED": f"IP gate toggle for {function_name}",
503
+ "ALLOW_CIDRS": f"Allowed CIDR blocks for {function_name}",
504
+ "HEALTH_CHECK_PATH": f"Health check endpoint path for {function_name}",
505
+ "ALB_DOMAIN": f"ALB DNS name for {function_name}",
506
+ "DEBUG_MODE": f"Debug mode toggle for {function_name}",
507
+ "CIRCUIT_BREAKER_THRESHOLD": f"Circuit breaker failure threshold for {function_name}",
508
+ "CIRCUIT_BREAKER_TIMEOUT": f"Circuit breaker timeout in seconds for {function_name}"
509
+ }
510
+
511
+ description = descriptions.get(param_name, f"Default parameter '{param_name}' for Lambda@Edge function {function_name}")
512
+
513
+ self.export_ssm_parameter(
514
+ scope=self,
515
+ id=f"default-{param_name.lower()}-param",
516
+ value=str(param_value),
517
+ parameter_name=param_path,
518
+ description=description
519
+ )
520
+
521
+ # Resolve and export environment variables to SSM
522
+ resolved_env = self._resolve_environment_variables()
523
+ for env_key, env_value in resolved_env.items():
524
+ if env_key in resolved_env:
525
+ env_value = resolved_env[env_key]
350
526
  # Handle empty values - SSM doesn't allow empty strings
351
527
  # Use sentinel value "NONE" to indicate explicitly unset
352
528
  if not env_value or (isinstance(env_value, str) and env_value.strip() == ""):
@@ -357,9 +533,9 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
357
533
  )
358
534
 
359
535
  self.export_ssm_parameter(
360
- self,
361
- f"env-{env_key}-param",
362
- env_value,
363
- ssm_path,
536
+ scope=self,
537
+ id=f"env-{env_key}-param",
538
+ value=env_value,
539
+ parameter_name=ssm_path,
364
540
  description=f"Configuration for Lambda@Edge: {env_key}"
365
541
  )
@@ -0,0 +1 @@
1
+ __version__ = "0.19.14"
@@ -1 +0,0 @@
1
- __version__ = "0.19.7"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes