cdk-factory 0.13.0__tar.gz → 0.13.1__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.
Potentially problematic release.
This version of cdk-factory might be problematic. Click here for more details.
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/.gitignore +4 -1
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/PKG-INFO +1 -1
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/pyproject.toml +1 -1
- cdk_factory-0.13.1/src/cdk_factory/lambdas/edge/ip_gate/handler.py +187 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/lambda_edge/lambda_edge_stack.py +15 -1
- cdk_factory-0.13.1/src/cdk_factory/version.py +1 -0
- cdk_factory-0.13.0/src/cdk_factory/lambdas/edge/ip_gate/handler.py +0 -104
- cdk_factory-0.13.0/src/cdk_factory/version.py +0 -1
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/.windsurfrules +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/LICENSE +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/README.md +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/archive/README.md +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/archive/migrate_to_enhanced_ssm.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/examples/json-imports/README.md +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/examples/separate-api-gateway/README.md +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/examples/separate-api-gateway/api-gateway-stack.json +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/examples/separate-api-gateway/config.json +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/examples/separate-api-gateway/lambda-stack.json +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/mypy.ini +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/publish_to_pypi.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/publish_to_pypi.sh +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/pysetup.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/pysetup.sh +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/requirements.dev.txt +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/requirements.tests.txt +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/requirements.txt +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/run-checks.sh +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/run-tests-clean-venv.sh +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/run-tests.sh +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/app.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/builds/README.md +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/cdk.json +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/cli.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/commands/command_loader.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/base_config.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/cdk_config.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/deployment.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/deployment_wave.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/devops.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/enhanced_base_config.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/enhanced_ssm_config.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/management.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/pipeline.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/pipeline_stage.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/_resources.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/api_gateway.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/apigateway_route_config.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/auto_scaling.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/cloudfront.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/cloudwatch_widget.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/code_artifact.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/code_artifact_login.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/code_repository.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/cognito.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/docker.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/dynamodb.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/ecr.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/ecs_service.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/exisiting.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/lambda_edge.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/lambda_function.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/lambda_layers.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/lambda_triggers.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/load_balancer.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/monitoring.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/rds.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/resource_mapping.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/resource_naming.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/resource_types.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/route53.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/route53_hosted_zone.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/rum.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/s3.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/security_group.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/security_group_full_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/sqs.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/vpc.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/workload.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/cloudfront/cloudfront_distribution_construct.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/ecr/ecr_construct.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/lambdas/lambda_function_construct.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/lambdas/lambda_function_docker_construct.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/lambdas/lambda_function_role_construct.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/lambdas/policies/policy_docs.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/lambdas/policies/policy_statements.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/s3_buckets/s3_bucket_construct.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/s3_buckets/s3_bucket_replication_destination_construct.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/s3_buckets/s3_bucket_replication_source_construct.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/sqs/policies/sqs_policies.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/interfaces/enhanced_ssm_parameter_mixin.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/interfaces/istack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/interfaces/live_ssm_resolver.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/interfaces/ssm_parameter_mixin.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/lambdas/health_handler.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/pipeline/path_utils.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/pipeline/pipeline_factory.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/pipeline/security/policies.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/pipeline/security/roles.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/pipeline/stage.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack/istack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack/stack_factory.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack/stack_module_loader.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack/stack_module_registry.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack/stack_modules.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/api_gateway/api_gateway_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/auto_scaling/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/auto_scaling/auto_scaling_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/aws_lambdas/lambda_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/buckets/README.md +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/buckets/bucket_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/cloudfront/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/cloudfront/cloudfront_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/code_artifact/code_artifact_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/cognito/cognito_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/dynamodb/dynamodb_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/ecr/README.md +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/ecr/ecr_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/ecs/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/ecs/ecs_service_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/lambda_edge/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/load_balancer/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/load_balancer/load_balancer_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/monitoring/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/monitoring/monitoring_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/rds/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/rds/rds_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/route53/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/route53/route53_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/rum/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/rum/rum_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/security_group/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/security_group/security_group_full_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/security_group/security_group_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/simple_queue_service/sqs_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/stack_base.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/vpc/__init__.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/vpc/vpc_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/websites/static_website_stack.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stages/websites/static_website_stage.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/templates/README.md +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/templates/app.py.template +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/templates/cdk.json.template +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/api_gateway_integration_utility.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/commandline_args.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/configuration_loader.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/docker_utilities.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/environment_services.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/file_operations.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/git_utilities.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/json_loading_utility.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/lambda_function_utilities.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/os_execute.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utils/api_gateway_utilities.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/workload/workload_factory.py +0 -0
- {cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/handlers/test/handler.py +0 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Lambda@Edge function for IP-based access gating.
|
|
3
|
+
Geek Cafe, LLC
|
|
4
|
+
Maintainers: Eric Wilson
|
|
5
|
+
|
|
6
|
+
Since Lambda@Edge does not support environment variables, configuration
|
|
7
|
+
is fetched from SSM Parameter Store at runtime (with caching).
|
|
8
|
+
"""
|
|
9
|
+
import json
|
|
10
|
+
import ipaddress
|
|
11
|
+
import boto3
|
|
12
|
+
from functools import lru_cache
|
|
13
|
+
|
|
14
|
+
# SSM client - will be created in the region where the function executes
|
|
15
|
+
ssm = None
|
|
16
|
+
|
|
17
|
+
@lru_cache(maxsize=128)
|
|
18
|
+
def get_ssm_parameter(parameter_name: str, region: str = 'us-east-1') -> str:
|
|
19
|
+
"""
|
|
20
|
+
Fetch SSM parameter with caching.
|
|
21
|
+
Lambda@Edge cannot use environment variables, so we fetch from SSM.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
parameter_name: Name of the SSM parameter
|
|
25
|
+
region: AWS region (default us-east-1)
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Parameter value
|
|
29
|
+
"""
|
|
30
|
+
global ssm
|
|
31
|
+
if ssm is None:
|
|
32
|
+
ssm = boto3.client('ssm', region_name=region)
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
response = ssm.get_parameter(Name=parameter_name, WithDecryption=False)
|
|
36
|
+
return response['Parameter']['Value']
|
|
37
|
+
except Exception as e:
|
|
38
|
+
print(f"Error fetching SSM parameter {parameter_name}: {str(e)}")
|
|
39
|
+
raise
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def get_client_ip(request):
|
|
43
|
+
"""Extract client IP from CloudFront request."""
|
|
44
|
+
if 'clientIp' in request:
|
|
45
|
+
return request['clientIp']
|
|
46
|
+
|
|
47
|
+
# Fallback to headers
|
|
48
|
+
headers = request.get('headers', {})
|
|
49
|
+
if 'x-forwarded-for' in headers:
|
|
50
|
+
xff = headers['x-forwarded-for'][0]['value']
|
|
51
|
+
return xff.split(',')[0].strip()
|
|
52
|
+
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def is_ip_allowed(client_ip: str, allowed_cidrs: list) -> bool:
|
|
57
|
+
"""
|
|
58
|
+
Check if client IP is in any of the allowed CIDR ranges.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
client_ip: Client IP address
|
|
62
|
+
allowed_cidrs: List of CIDR ranges (e.g., ['10.0.0.0/8', '192.168.1.0/24'])
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
True if IP is allowed, False otherwise
|
|
66
|
+
"""
|
|
67
|
+
if not client_ip:
|
|
68
|
+
return False
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
client_ip_obj = ipaddress.ip_address(client_ip)
|
|
72
|
+
except ValueError as e:
|
|
73
|
+
print(f"Invalid client IP address: {e}")
|
|
74
|
+
return False
|
|
75
|
+
|
|
76
|
+
# Check each CIDR individually, skipping invalid ones
|
|
77
|
+
for cidr in allowed_cidrs:
|
|
78
|
+
try:
|
|
79
|
+
network = ipaddress.ip_network(cidr.strip(), strict=False)
|
|
80
|
+
if client_ip_obj in network:
|
|
81
|
+
return True
|
|
82
|
+
except ValueError as e:
|
|
83
|
+
# Invalid CIDR, log and continue checking others
|
|
84
|
+
print(f"Invalid CIDR '{cidr}': {e}")
|
|
85
|
+
continue
|
|
86
|
+
|
|
87
|
+
return False
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def lambda_handler(event, context):
|
|
91
|
+
"""
|
|
92
|
+
Lambda@Edge function for IP-based gating.
|
|
93
|
+
|
|
94
|
+
Configuration (fetched from SSM Parameter Store):
|
|
95
|
+
- GATE_ENABLED: Whether IP gating is enabled (true/false)
|
|
96
|
+
- ALLOW_CIDRS: Comma-separated list of allowed CIDR ranges
|
|
97
|
+
- MAINT_CF_HOST: CloudFront domain for maintenance/lockout page
|
|
98
|
+
|
|
99
|
+
Runtime configuration is bundled in runtime_config.json by CDK.
|
|
100
|
+
SSM parameter paths are auto-generated by CDK as:
|
|
101
|
+
/{environment}/{full-function-name}/{env-var-name-kebab-case}
|
|
102
|
+
"""
|
|
103
|
+
request = event['Records'][0]['cf']['request']
|
|
104
|
+
|
|
105
|
+
# Load runtime configuration bundled by CDK
|
|
106
|
+
# This file is created during deployment and contains environment, function name, etc.
|
|
107
|
+
try:
|
|
108
|
+
with open('runtime_config.json', 'r') as f:
|
|
109
|
+
runtime_config = json.load(f)
|
|
110
|
+
|
|
111
|
+
env = runtime_config.get('environment', 'dev')
|
|
112
|
+
function_base_name = runtime_config.get('function_name', 'ip-gate')
|
|
113
|
+
|
|
114
|
+
print(f"Runtime config loaded: environment={env}, function_name={function_base_name}")
|
|
115
|
+
except FileNotFoundError:
|
|
116
|
+
# Fallback: extract from Lambda context (less reliable)
|
|
117
|
+
print("Warning: runtime_config.json not found, falling back to function name parsing")
|
|
118
|
+
function_full_name = context.function_name
|
|
119
|
+
|
|
120
|
+
# Parse environment from function name as fallback
|
|
121
|
+
parts = function_full_name.split('-')
|
|
122
|
+
common_envs = ['dev', 'prod', 'staging', 'test', 'qa', 'uat']
|
|
123
|
+
env = 'dev'
|
|
124
|
+
|
|
125
|
+
for part in parts:
|
|
126
|
+
if part in common_envs:
|
|
127
|
+
env = part
|
|
128
|
+
break
|
|
129
|
+
|
|
130
|
+
function_base_name = 'ip-gate'
|
|
131
|
+
print(f"Fallback: environment={env}, function_name={function_base_name}")
|
|
132
|
+
|
|
133
|
+
# Full function name for SSM paths
|
|
134
|
+
function_name = context.function_name
|
|
135
|
+
print(f"Lambda function ARN: {context.invoked_function_arn}")
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
# Fetch configuration from SSM Parameter Store
|
|
139
|
+
# Auto-generated paths: /{env}/{function-name}/{key}
|
|
140
|
+
gate_enabled = get_ssm_parameter(f'/{env}/{function_name}/gate-enabled', 'us-east-1')
|
|
141
|
+
|
|
142
|
+
# If gating is disabled, allow all traffic
|
|
143
|
+
if gate_enabled.lower() not in ('true', '1', 'yes'):
|
|
144
|
+
print(f"IP gating is disabled (GATE_ENABLED={gate_enabled})")
|
|
145
|
+
return request
|
|
146
|
+
|
|
147
|
+
# Get allowed CIDRs and maintenance host
|
|
148
|
+
allow_cidrs_str = get_ssm_parameter(f'/{env}/{function_name}/allow-cidrs', 'us-east-1')
|
|
149
|
+
maint_cf_host = get_ssm_parameter(f'/{env}/{function_name}/maint-cf-host', 'us-east-1')
|
|
150
|
+
|
|
151
|
+
# Parse allowed CIDRs
|
|
152
|
+
allowed_cidrs = [cidr.strip() for cidr in allow_cidrs_str.split(',') if cidr.strip()]
|
|
153
|
+
|
|
154
|
+
# Get client IP
|
|
155
|
+
client_ip = get_client_ip(request)
|
|
156
|
+
print(f"Client IP: {client_ip}")
|
|
157
|
+
|
|
158
|
+
# Check if IP is allowed
|
|
159
|
+
if is_ip_allowed(client_ip, allowed_cidrs):
|
|
160
|
+
print(f"IP {client_ip} is allowed")
|
|
161
|
+
return request
|
|
162
|
+
|
|
163
|
+
# IP not allowed - redirect to maintenance page
|
|
164
|
+
print(f"IP {client_ip} is NOT allowed, redirecting to {maint_cf_host}")
|
|
165
|
+
|
|
166
|
+
response = {
|
|
167
|
+
'status': '302',
|
|
168
|
+
'statusDescription': 'Found',
|
|
169
|
+
'headers': {
|
|
170
|
+
'location': [{
|
|
171
|
+
'key': 'Location',
|
|
172
|
+
'value': f'https://{maint_cf_host}'
|
|
173
|
+
}],
|
|
174
|
+
'cache-control': [{
|
|
175
|
+
'key': 'Cache-Control',
|
|
176
|
+
'value': 'no-cache, no-store, must-revalidate'
|
|
177
|
+
}]
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return response
|
|
182
|
+
|
|
183
|
+
except Exception as e:
|
|
184
|
+
print(f"Error in IP gating function: {str(e)}")
|
|
185
|
+
# On error, allow the request to proceed (fail open)
|
|
186
|
+
# Change this to fail closed if preferred
|
|
187
|
+
return request
|
|
@@ -9,6 +9,8 @@ MIT License. See Project Root for the license information.
|
|
|
9
9
|
from typing import Optional, Dict
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
import json
|
|
12
|
+
import tempfile
|
|
13
|
+
import shutil
|
|
12
14
|
|
|
13
15
|
import aws_cdk as cdk
|
|
14
16
|
from aws_cdk import aws_lambda as _lambda
|
|
@@ -140,6 +142,15 @@ class LambdaEdgeStack(IStack, EnhancedSsmParameterMixin):
|
|
|
140
142
|
|
|
141
143
|
logger.info(f"Loading Lambda code from: {code_path}")
|
|
142
144
|
|
|
145
|
+
# Create isolated temp directory for this function instance
|
|
146
|
+
# This prevents conflicts when multiple functions use the same handler code
|
|
147
|
+
temp_code_dir = Path(tempfile.mkdtemp(prefix=f"{function_name.replace('/', '-')}-"))
|
|
148
|
+
logger.info(f"Creating isolated code directory at: {temp_code_dir}")
|
|
149
|
+
|
|
150
|
+
# Copy source code to temp directory
|
|
151
|
+
shutil.copytree(code_path, temp_code_dir, dirs_exist_ok=True)
|
|
152
|
+
logger.info(f"Copied code from {code_path} to {temp_code_dir}")
|
|
153
|
+
|
|
143
154
|
# Create runtime configuration file for Lambda@Edge
|
|
144
155
|
# Since Lambda@Edge doesn't support environment variables, we bundle a config file
|
|
145
156
|
runtime_config = {
|
|
@@ -148,7 +159,7 @@ class LambdaEdgeStack(IStack, EnhancedSsmParameterMixin):
|
|
|
148
159
|
'region': self.deployment.region
|
|
149
160
|
}
|
|
150
161
|
|
|
151
|
-
runtime_config_path =
|
|
162
|
+
runtime_config_path = temp_code_dir / 'runtime_config.json'
|
|
152
163
|
logger.info(f"Creating runtime config at: {runtime_config_path}")
|
|
153
164
|
|
|
154
165
|
with open(runtime_config_path, 'w') as f:
|
|
@@ -156,6 +167,9 @@ class LambdaEdgeStack(IStack, EnhancedSsmParameterMixin):
|
|
|
156
167
|
|
|
157
168
|
logger.info(f"Runtime config: {runtime_config}")
|
|
158
169
|
|
|
170
|
+
# Use the temp directory for the Lambda code asset
|
|
171
|
+
code_path = temp_code_dir
|
|
172
|
+
|
|
159
173
|
# Map runtime string to CDK Runtime
|
|
160
174
|
runtime_map = {
|
|
161
175
|
"python3.11": _lambda.Runtime.PYTHON_3_11,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.13.1"
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Lambda@Edge Origin-Request Handler for IP-based Access Gating
|
|
3
|
-
Geek Cafe, LLC
|
|
4
|
-
Maintainers: Eric Wilson
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import ipaddress
|
|
8
|
-
import json
|
|
9
|
-
import os
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def lambda_handler(event, context):
|
|
13
|
-
"""
|
|
14
|
-
Lambda@Edge origin-request handler that implements IP-based gating
|
|
15
|
-
with maintenance site fallback.
|
|
16
|
-
|
|
17
|
-
Features:
|
|
18
|
-
- Inject X-Viewer-IP header for origin visibility
|
|
19
|
-
- Check viewer IP against allowlist when gate is enabled
|
|
20
|
-
- Rewrite blocked IPs to maintenance CloudFront distribution, and serve up maintenance site
|
|
21
|
-
- Toggle via GATE_ENABLED environment variable
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
# Extract request from CloudFront event
|
|
25
|
-
request = event['Records'][0]['cf']['request']
|
|
26
|
-
client_ip = request['clientIp']
|
|
27
|
-
|
|
28
|
-
# Configuration from environment variables
|
|
29
|
-
gate_enabled = os.environ.get('GATE_ENABLED', 'false').lower() == 'true'
|
|
30
|
-
allow_cidrs_str = os.environ.get('ALLOW_CIDRS', '')
|
|
31
|
-
maint_cf_host = os.environ.get('MAINT_CF_HOST', '')
|
|
32
|
-
|
|
33
|
-
# Parse allowed CIDRs
|
|
34
|
-
allow_cidrs = [cidr.strip() for cidr in allow_cidrs_str.split(',') if cidr.strip()]
|
|
35
|
-
|
|
36
|
-
# Always inject viewer IP header
|
|
37
|
-
if 'headers' not in request:
|
|
38
|
-
request['headers'] = {}
|
|
39
|
-
|
|
40
|
-
request['headers']['x-viewer-ip'] = [{
|
|
41
|
-
'key': 'X-Viewer-IP',
|
|
42
|
-
'value': client_ip
|
|
43
|
-
}]
|
|
44
|
-
|
|
45
|
-
# If gate is disabled, pass through to origin
|
|
46
|
-
if not gate_enabled:
|
|
47
|
-
return request
|
|
48
|
-
|
|
49
|
-
# Check if IP is in allowlist
|
|
50
|
-
ip_allowed = False
|
|
51
|
-
try:
|
|
52
|
-
client_ip_obj = ipaddress.ip_address(client_ip)
|
|
53
|
-
for cidr in allow_cidrs:
|
|
54
|
-
try:
|
|
55
|
-
network = ipaddress.ip_network(cidr, strict=False)
|
|
56
|
-
if client_ip_obj in network:
|
|
57
|
-
ip_allowed = True
|
|
58
|
-
break
|
|
59
|
-
except (ValueError, ipaddress.AddressValueError):
|
|
60
|
-
# Invalid CIDR, skip
|
|
61
|
-
continue
|
|
62
|
-
except (ValueError, ipaddress.AddressValueError):
|
|
63
|
-
# Invalid client IP, block by default
|
|
64
|
-
ip_allowed = False
|
|
65
|
-
|
|
66
|
-
# If IP is allowed, pass through to origin
|
|
67
|
-
if ip_allowed:
|
|
68
|
-
return request
|
|
69
|
-
|
|
70
|
-
# IP not allowed - redirect to maintenance site
|
|
71
|
-
if not maint_cf_host:
|
|
72
|
-
# Safety: if maintenance host not configured, pass through with warning
|
|
73
|
-
# In production, you might want to return a fixed error response instead
|
|
74
|
-
return request
|
|
75
|
-
|
|
76
|
-
# Rewrite origin to maintenance CloudFront distribution
|
|
77
|
-
request['origin'] = {
|
|
78
|
-
'custom': {
|
|
79
|
-
'domainName': maint_cf_host,
|
|
80
|
-
'port': 443,
|
|
81
|
-
'protocol': 'https',
|
|
82
|
-
'path': '',
|
|
83
|
-
'sslProtocols': ['TLSv1.2'],
|
|
84
|
-
'readTimeout': 30,
|
|
85
|
-
'keepaliveTimeout': 5,
|
|
86
|
-
'customHeaders': {}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
# Update Host header to match new origin
|
|
91
|
-
request['headers']['host'] = [{
|
|
92
|
-
'key': 'Host',
|
|
93
|
-
'value': maint_cf_host
|
|
94
|
-
}]
|
|
95
|
-
|
|
96
|
-
# Normalize URI - redirect directory requests to index.html
|
|
97
|
-
uri = request.get('uri', '/')
|
|
98
|
-
if uri.endswith('/'):
|
|
99
|
-
request['uri'] = uri + 'index.html'
|
|
100
|
-
elif '.' not in uri.split('/')[-1]:
|
|
101
|
-
# No file extension, likely a directory
|
|
102
|
-
request['uri'] = uri + '/index.html'
|
|
103
|
-
|
|
104
|
-
return request
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.13.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/examples/separate-api-gateway/api-gateway-stack.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/enhanced_base_config.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/enhanced_ssm_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/_resources.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/api_gateway.py
RENAMED
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/auto_scaling.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/cloudfront.py
RENAMED
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/code_artifact.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/cognito.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/docker.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/dynamodb.py
RENAMED
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/ecs_service.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/exisiting.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/lambda_edge.py
RENAMED
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/lambda_layers.py
RENAMED
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/load_balancer.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/monitoring.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/resource_types.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/route53.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/configurations/resources/security_group.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/lambdas/policies/policy_docs.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/constructs/sqs/policies/sqs_policies.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/interfaces/enhanced_ssm_parameter_mixin.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/auto_scaling/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/aws_lambdas/lambda_stack.py
RENAMED
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/buckets/bucket_stack.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/cloudfront/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/cognito/cognito_stack.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/dynamodb/dynamodb_stack.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/ecs/ecs_service_stack.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/lambda_edge/__init__.py
RENAMED
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/load_balancer/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/monitoring/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/route53/route53_stack.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stack_library/security_group/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/stages/websites/static_website_stage.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cdk_factory-0.13.0 → cdk_factory-0.13.1}/src/cdk_factory/utilities/lambda_function_utilities.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|