WebApp Stack¶
The WebApp class is the main CDK stack for deploying containerized web applications.
Overview¶
WebApp is a complete AWS CDK Stack that creates and configures all resources needed to run a containerized web application, including:
- ECS Fargate cluster and service
- Application Load Balancer with HTTPS
- Route53 DNS records and ACM certificates
- Optional Cognito authentication
- WAF integration
- CloudWatch logging
WebApp¶
gds_idea_cdk_constructs.web_app.stack.WebApp
¶
Bases: BaseWebStack
A configurable web application stack with a simplified API for authentication.
Source code in src/gds_idea_cdk_constructs/web_app/stack.py
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | |
__init__
¶
__init__(
scope: Construct,
deployment_config: DeploymentConfig,
app_config: AppConfig,
authentication: AuthType = AuthType.COGNITO,
docker_context_path: str = ".",
dockerfile_path: str = "app_src/Dockerfile",
container_props: WebAppContainerProperties
| None = None,
task_role: Role | None = None,
disable_waf: bool = False,
cross_account_access: bool = False,
enable_usage_dashboard: bool = True,
dashboard_properties: DashboardProperties | None = None,
) -> None
Initialize a WebApp stack with containerized application infrastructure.
Creates a complete web application deployment including ECS Fargate service, Application Load Balancer with HTTPS, Route53 DNS records, ACM certificate, and optional Cognito authentication.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope
|
Construct
|
The CDK app or stack to create this stack within. |
required |
deployment_config
|
DeploymentConfig
|
Environment-specific configuration including VPC, domain name, and AWS resource identifiers. |
required |
app_config
|
AppConfig
|
Application configuration including name, framework, and health check settings. |
required |
authentication
|
AuthType
|
Authentication strategy to use. Defaults to AuthType.COGNITO. Options: COGNITO, INTERNAL_ACCESS, or NONE. |
COGNITO
|
docker_context_path
|
str
|
Path to the Docker build context directory. Defaults to current directory ("."). |
'.'
|
dockerfile_path
|
str
|
Path to the Dockerfile relative to docker_context_path. Defaults to "app_src/Dockerfile". |
'app_src/Dockerfile'
|
container_props
|
WebAppContainerProperties | None
|
Custom container configuration (CPU, memory, count, etc.). If None, uses default values from WebAppContainerProperties. |
None
|
task_role
|
Role | None
|
Custom IAM role for the ECS task. If None, a minimal role will be created with permissions required by the authentication strategy. If provided, the strategy will augment it with necessary permissions. |
None
|
disable_waf
|
bool
|
Disable WAF association with the ALB. Defaults to False. When True, the Web Application Firewall will NOT be associated with the Application Load Balancer. WARNING: This should ONLY be used for short-term debugging when WAF rules are blocking legitimate traffic. Never use in production. Disabling WAF removes critical security protections against common web exploits. |
False
|
cross_account_access
|
bool
|
Enable cross-account access to production resources. Defaults to False. When True and deploying to a non-production environment, grants the task role sts:AssumeRole permission on the cross-account role and injects CROSS_ACCOUNT_ROLE_ARN as a container environment variable. |
False
|
enable_usage_dashboard
|
bool
|
When |
True
|
dashboard_properties
|
DashboardProperties | None
|
Optional overrides for the usage dashboard —
name, per-user email disclosure, log filter pattern and extra
widgets. See :class: |
None
|
Example
Basic usage with Cognito authentication::
app = App()
deployment_config = DeploymentConfig(cdk_env)
app_config = AppConfig.from_pyproject()
WebApp(
app,
deployment_config,
app_config,
authentication=AuthType.COGNITO,
docker_context_path=".",
dockerfile_path="Dockerfile",
)
Note
The stack automatically creates all required infrastructure including VPC subnets lookup, DNS hosted zone, SSL certificate, load balancer, ECS cluster lookup, Fargate task definition and service, and optional Cognito user pool client configuration.
Source code in src/gds_idea_cdk_constructs/web_app/stack.py
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | |
Usage Examples¶
Minimal Example¶
from aws_cdk import App
from gds_idea_cdk_constructs.config import DeploymentConfig, AppConfig
from gds_idea_cdk_constructs.web_app import WebApp, AuthType
app = App()
deployment_config = DeploymentConfig(cdk_env)
app_config = AppConfig(app_name="simple-app", framework="streamlit")
WebApp(
app,
deployment_config=deployment_config,
app_config=app_config,
authentication=AuthType.INTERNAL_ACCESS,
docker_context_path=".",
dockerfile_path="Dockerfile",
)
app.synth()
Public Application¶
WebApp(
app,
deployment_config=deployment_config,
app_config=app_config,
authentication=AuthType.NONE, # No authentication
docker_context_path="./app",
dockerfile_path="app/Dockerfile",
)
Advanced Configuration¶
from gds_idea_cdk_constructs.web_app import WebAppContainerProperties
import aws_cdk.aws_iam as iam
# Custom container configuration
container_props = WebAppContainerProperties(
cpu=512,
memory_limit_mib=1024,
desired_count=2,
container_port=8501,
health_check_path="/_stcore/health",
environment_variables={
"LOG_LEVEL": "INFO",
"DATABASE_URL": "postgresql://...",
},
)
class MyBackEnd(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs):
super().__init__(scope, construct_id, **kwargs)
# ... creation of backend
# Create custom role
self.task_role = iam.Role(
self,
"CustomTaskRole",
assumed_by=iam.ServicePrincipal("ecs-tasks.amazonaws.com"),
)
# Grant S3 access
task_role.add_to_policy(
iam.PolicyStatement(
actions=["s3:GetObject", "s3:PutObject"],
resources=["arn:aws:s3:::my-bucket/*"],
)
)
backend = MyBackEnd(app, "MyBackEnd")
# Create stack with advanced options
WebApp(
app,
deployment_config=deployment_config,
app_config=app_config,
authentication=AuthType.INTERNAL_ACCESS,
docker_context_path=".",
dockerfile_path="Dockerfile",
container_props=container_props,
task_role=task_role,
)
Debugging with WAF Disabled¶
Security Warning
Only for debugging - Never use disable_waf=True in production environments. This removes critical security protections against web exploits.
When troubleshooting WAF rule blocks during development, you can temporarily disable WAF:
# TEMPORARY DEBUGGING ONLY
WebApp(
app,
deployment_config=deployment_config,
app_config=app_config,
authentication=AuthType.INTERNAL_ACCESS,
docker_context_path=".",
dockerfile_path="Dockerfile",
disable_waf=True, # WARNING: Removes security protections!
)
Use cases: - Debugging legitimate traffic being blocked by WAF rules - Isolating whether issues are caused by WAF vs application code - Short-term testing during WAF rule development
Best practices:
- Time-box usage (e.g., "disable for 1 hour while testing")
- Never commit disable_waf=True to version control
- Re-enable immediately after debugging
- Consider adjusting WAF rules instead of disabling entirely
Created Resources¶
When you create a WebApp, the following AWS resources are automatically created:
Networking¶
- VPC (imported) - Uses existing VPC from deployment config
- Subnets - Uses public subnets for Fargate tasks
- Security Groups - Automatically configured for ALB and ECS
Compute¶
- ECS Cluster - Fargate cluster for running containers
- Task Definition - Container configuration
- Fargate Service - Managed service with desired count
Load Balancing¶
- Application Load Balancer - Internet-facing ALB
- Target Group - Routes traffic to ECS tasks
- Listeners:
- HTTP (port 80) - Redirects to HTTPS
- HTTPS (port 443) - Forwards to target group
DNS & TLS¶
- Route53 Hosted Zone - Subdomain for your application
- NS Record - Links subdomain to parent hosted zone
- A Record - Points domain to load balancer
- ACM Certificate - TLS certificate with DNS validation
Authentication (Cognito only)¶
- User Pool Client - OAuth2 client for ALB authentication
- Secrets Manager Secret - Stores client credentials
Security¶
-
WAF Association (optional) - By default, links the environment's WAF Web ACL to the Application Load Balancer, providing protection against common web exploits including:
- SQL injection attacks
- Cross-site scripting (XSS)
- HTTP floods and DDoS attempts
- Known malicious IP addresses
The WAF can be temporarily disabled using
disable_waf=Truefor debugging purposes. Never disable WAF in production environments. -
IAM Roles:
- Task Role - For application permissions (can be custom or auto-generated)
- Execution Role - For ECS to pull images and write logs
-
TLS/HTTPS Enforcement - All HTTP traffic is automatically redirected to HTTPS
-
Security Groups - Automatically configured with least-privilege access
Monitoring¶
- CloudWatch Log Group - Container logs
- S3 Access Logs - ALB access logs
CloudFormation Outputs¶
The stack creates the following outputs:
- ApplicationURL - HTTPS URL for your application
- TaskRoleARN - ARN of the ECS task role (can be assumed in DEV)
- CognitoClientId (Cognito only) - OAuth2 client ID
Development Features¶
Dev Environment Assume Role¶
In the development environment, the task role can be assumed by developers with *-poweraccess or *-admin roles. This enables:
- Local testing with AWS credentials
- Debugging with production-like IAM permissions
- Development without modifying production policies
This feature is disabled in production environments.
Cross-Account Access¶
When cross_account_access=True is set, the construct enables the ECS task to assume
a cross-account role for accessing production data resources from non-production
environments.
WebApp(
app,
deployment_config=deployment_config,
app_config=app_config,
cross_account_access=True,
)
What it does (non-production only):
- Grants
sts:AssumeRolepermission to the task role for the cross-account role - Injects
CROSS_ACCOUNT_ROLE_ARNenvironment variable into the container
In production: No action is taken regardless of the flag value — the task role should have direct access to resources via IAM policies.
App-side usage: Applications should read CROSS_ACCOUNT_ROLE_ARN from the
environment and assume the role when creating boto3 sessions. When the variable is
not set (production), a default session with direct credentials is used instead.