|
| 1 | +--- |
| 2 | +title: "ALB Hosting Guide" |
| 3 | +--- |
| 4 | + |
| 5 | +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. |
| 6 | +SPDX-License-Identifier: MIT-0 |
| 7 | + |
| 8 | +# ALB Hosting Guide |
| 9 | + |
| 10 | +## Overview |
| 11 | + |
| 12 | +The GenAI IDP Accelerator supports an alternative web UI hosting mode using an Application Load Balancer (ALB) with an S3 VPC Interface Endpoint, replacing CloudFront for environments that require VPC-based hosting. |
| 13 | + |
| 14 | +> **Note**: For standard deployments, CloudFront hosting (the default) is recommended. Use ALB hosting only when your environment has specific requirements that prevent using CloudFront. |
| 15 | +
|
| 16 | +## When to Use ALB Hosting |
| 17 | + |
| 18 | +ALB hosting is designed for organizations that need the full IDP web UI but cannot use CloudFront due to network or compliance constraints: |
| 19 | + |
| 20 | +- **Private network requirements** — environments where all web traffic must remain within a VPC and internet-facing CDN endpoints are not permitted |
| 21 | +- **Regulated environments** — deployments that require all traffic to traverse private network paths with VPC-level security controls (security groups, NACLs, VPC Flow Logs) |
| 22 | +- **Corporate network restrictions** — organizations where users access applications exclusively through VPN or Direct Connect, and public CDN endpoints are blocked by policy |
| 23 | +- **Air-gapped or isolated VPCs** — environments with no internet egress where CloudFront cannot function |
| 24 | + |
| 25 | +> **Note on GovCloud**: GovCloud deployments use a separate headless template (no web UI or AppSync). ALB hosting is not applicable to GovCloud — see [GovCloud Deployment](./govcloud-deployment.md) instead. |
| 26 | +
|
| 27 | +## Architecture |
| 28 | + |
| 29 | +### Standard Hosting (CloudFront) |
| 30 | + |
| 31 | +``` |
| 32 | +Internet Users → CloudFront (Edge) → S3 Origin (WebUI Bucket) |
| 33 | +``` |
| 34 | + |
| 35 | +### ALB Hosting |
| 36 | + |
| 37 | +``` |
| 38 | +VPC Users → ALB → S3 VPC Interface Endpoint → S3 (WebUI Bucket) |
| 39 | +``` |
| 40 | + |
| 41 | +The ALB hosting nested stack creates: |
| 42 | + |
| 43 | +- An Application Load Balancer (internal or internet-facing) |
| 44 | +- An S3 Interface VPC Endpoint for private connectivity to S3 |
| 45 | +- Security groups controlling traffic between ALB and VPC endpoint |
| 46 | +- Listener rules with host-header rewrite and URL rewrite transforms to serve S3 static content as a single-page application |
| 47 | +- Custom resource Lambda functions for VPC CIDR lookup and VPC endpoint target registration |
| 48 | + |
| 49 | +## Prerequisites |
| 50 | + |
| 51 | +### VPC Requirements |
| 52 | + |
| 53 | +You need an existing VPC with the following: |
| 54 | + |
| 55 | +1. **At least 2 subnets in different Availability Zones** — required by ALB. These can be: |
| 56 | + - **Private subnets** (recommended for internal ALBs) — must have a route to S3 via VPC endpoint (created by the stack) and to AWS service endpoints for SSM, CloudWatch, etc. |
| 57 | + - **Public subnets** (for internet-facing ALBs) — must have an Internet Gateway route |
| 58 | +2. **DNS resolution enabled** — the VPC must have `enableDnsSupport` and `enableDnsHostnames` set to `true` |
| 59 | +3. **Sufficient IP space** — the S3 VPC Interface Endpoint creates ENIs in each subnet (one IP per subnet) |
| 60 | + |
| 61 | +### ACM Certificate |
| 62 | + |
| 63 | +An ACM certificate is required for the ALB HTTPS listener. Options: |
| 64 | + |
| 65 | +- **ACM-issued certificate** (recommended for production) — request via ACM with DNS or email validation |
| 66 | +- **Imported certificate** — import your organization's CA-signed certificate into ACM |
| 67 | +- **Self-signed certificate** (demo/testing only) — use the provided helper script: |
| 68 | + |
| 69 | +```bash |
| 70 | +# Generate and import a self-signed certificate |
| 71 | +CERT_ARN=$(./scripts/generate_self_signed_cert.sh --region us-east-1 --domain myapp.internal) |
| 72 | +echo "Certificate ARN: $CERT_ARN" |
| 73 | + |
| 74 | +# Options: |
| 75 | +# --region AWS region for ACM import (default: from AWS config) |
| 76 | +# --domain Domain name for the certificate CN/SAN (default: self-signed.internal) |
| 77 | +# --days Certificate validity in days (default: 365) |
| 78 | +``` |
| 79 | + |
| 80 | +### Network Connectivity |
| 81 | + |
| 82 | +Users must be able to reach the ALB: |
| 83 | + |
| 84 | +- **Internal ALB**: Users need VPN, Direct Connect, or access from within the VPC (e.g., WorkSpaces, Cloud9, SSM port forwarding) |
| 85 | +- **Internet-facing ALB**: Users can access directly, but the ALB security group controls which source IPs are allowed |
| 86 | + |
| 87 | +## Deployment |
| 88 | + |
| 89 | +### Option 1: IDP CLI |
| 90 | + |
| 91 | +```bash |
| 92 | +idp-cli deploy \ |
| 93 | + --stack-name my-idp-stack \ |
| 94 | + --admin-email user@example.com \ |
| 95 | + --from-code . \ |
| 96 | + --parameters "WebUIHosting=ALB,ALBVpcId=vpc-xxxxx,ALBSubnetIds=subnet-aaaa,subnet-bbbb,ALBCertificateArn=arn:aws:acm:REGION:ACCOUNT:certificate/xxxxx,ALBScheme=internal" \ |
| 97 | + --wait |
| 98 | +``` |
| 99 | + |
| 100 | +### Option 2: CloudFormation Console |
| 101 | + |
| 102 | +When deploying via the CloudFormation console, set the following parameters in the **Web UI Hosting** and **ALB Hosting** parameter sections: |
| 103 | + |
| 104 | +| Parameter | Value | Description | |
| 105 | +|-----------|-------|-------------| |
| 106 | +| `WebUIHosting` | `ALB` | Switches from CloudFront to ALB hosting | |
| 107 | +| `ALBVpcId` | `vpc-xxxxx` | VPC for the ALB and S3 VPC endpoint | |
| 108 | +| `ALBSubnetIds` | `subnet-aaaa,subnet-bbbb` | Minimum 2 subnets in different AZs | |
| 109 | +| `ALBCertificateArn` | `arn:aws:acm:...` | ACM certificate ARN for HTTPS | |
| 110 | +| `ALBScheme` | `internal` or `internet-facing` | ALB accessibility | |
| 111 | +| `ALBAllowedCIDRs` | *(optional)* | Comma-separated CIDRs for ALB ingress. Empty = VPC CIDR | |
| 112 | + |
| 113 | +### Switching an Existing Stack |
| 114 | + |
| 115 | +You can switch an existing CloudFront-hosted stack to ALB hosting (or vice versa) by updating the stack with the new `WebUIHosting` parameter value and providing the required ALB parameters. CloudFormation will conditionally create or remove the appropriate resources. |
| 116 | + |
| 117 | +## Parameters Reference |
| 118 | + |
| 119 | +### WebUIHosting |
| 120 | + |
| 121 | +- **Type**: String |
| 122 | +- **Default**: `CloudFront` |
| 123 | +- **Allowed Values**: `CloudFront`, `ALB` |
| 124 | +- **Description**: Selects the frontend hosting method. CloudFront is the default for standard deployments. ALB is for private network deployments that require VPC-based hosting. |
| 125 | + |
| 126 | +### ALBVpcId |
| 127 | + |
| 128 | +- **Type**: String |
| 129 | +- **Required when**: `WebUIHosting=ALB` |
| 130 | +- **Description**: The VPC ID where the ALB and S3 VPC Interface Endpoint will be created. |
| 131 | + |
| 132 | +### ALBSubnetIds |
| 133 | + |
| 134 | +- **Type**: CommaDelimitedList |
| 135 | +- **Required when**: `WebUIHosting=ALB` |
| 136 | +- **Description**: At least 2 subnet IDs in different Availability Zones. Use private subnets for internal ALBs, public subnets for internet-facing ALBs. |
| 137 | + |
| 138 | +### ALBCertificateArn |
| 139 | + |
| 140 | +- **Type**: String |
| 141 | +- **Required when**: `WebUIHosting=ALB` |
| 142 | +- **Description**: ACM certificate ARN for the ALB HTTPS listener. Can be an ACM-issued certificate, an imported certificate, or a self-signed certificate (for testing). |
| 143 | + |
| 144 | +### ALBScheme |
| 145 | + |
| 146 | +- **Type**: String |
| 147 | +- **Default**: `internal` |
| 148 | +- **Allowed Values**: `internal`, `internet-facing` |
| 149 | +- **Description**: Controls ALB accessibility. Use `internal` for private network access (recommended). Use `internet-facing` for public access. |
| 150 | + |
| 151 | +### ALBAllowedCIDRs |
| 152 | + |
| 153 | +- **Type**: String |
| 154 | +- **Default**: *(empty)* |
| 155 | +- **Description**: Comma-separated CIDR ranges allowed to access the ALB on port 443. When empty, the VPC CIDR is used automatically (recommended for internal ALBs). Specify explicit CIDRs to restrict access to specific networks. |
| 156 | + |
| 157 | +## How It Works |
| 158 | + |
| 159 | +### Conditional Resource Creation |
| 160 | + |
| 161 | +When `WebUIHosting=ALB`: |
| 162 | + |
| 163 | +- CloudFront distribution, Origin Access Identity, and security headers policy are **not created** |
| 164 | +- ALB nested stack is created with all ALB infrastructure |
| 165 | +- S3 WebUI bucket omits `WebsiteConfiguration` (ALB handles routing) |
| 166 | +- S3 bucket policy grants access via `aws:sourceVpce` condition instead of CloudFront OAI |
| 167 | + |
| 168 | +When `WebUIHosting=CloudFront` (default): |
| 169 | + |
| 170 | +- ALB nested stack is **not created** |
| 171 | +- Standard CloudFront distribution with OAI is created |
| 172 | + |
| 173 | +### Request Flow (ALB Mode) |
| 174 | + |
| 175 | +1. User sends HTTPS request to the ALB |
| 176 | +2. ALB listener rule matches the path pattern |
| 177 | +3. ALB applies **host-header rewrite** transform — sets the Host header to the S3 bucket's regional endpoint (`bucket.s3.region.amazonaws.com`) |
| 178 | +4. ALB applies **URL rewrite** transform for root path (`/` → `/index.html`) to support SPA routing |
| 179 | +5. Request is forwarded to the S3 VPC Interface Endpoint ENI IPs (registered as ALB targets) |
| 180 | +6. S3 serves the content through the VPC endpoint |
| 181 | + |
| 182 | +### Automatic Integration |
| 183 | + |
| 184 | +The following are automatically configured based on the `WebUIHosting` parameter — no manual configuration is needed: |
| 185 | + |
| 186 | +- **S3 CORS origins** — all bucket CORS `AllowedOrigins` resolve to the ALB URL |
| 187 | +- **Cognito callback/logout URLs** — OAuth redirect URLs point to the ALB URL |
| 188 | +- **UI build configuration** — the `VITE_CLOUDFRONT_DOMAIN` environment variable resolves to the ALB URL |
| 189 | +- **CodeBuild post-deploy** — CloudFront cache invalidation is skipped in ALB mode |
| 190 | +- **Stack outputs** — `ApplicationWebURL` returns the ALB URL |
| 191 | + |
| 192 | +## Accessing the UI |
| 193 | + |
| 194 | +### Internal ALB |
| 195 | + |
| 196 | +For internal ALBs, you need network connectivity to the VPC. Common approaches: |
| 197 | + |
| 198 | +**VPN or Direct Connect** (recommended for production): Access the ALB DNS name directly through your organization's private network connection. |
| 199 | + |
| 200 | +**SSM Port Forwarding** (recommended for testing): |
| 201 | + |
| 202 | +1. Launch a small EC2 instance (e.g., t3.micro) in the same VPC with an IAM role that includes `AmazonSSMManagedInstanceCore` |
| 203 | +2. Start a port forwarding session: |
| 204 | + ```bash |
| 205 | + aws ssm start-session \ |
| 206 | + --target INSTANCE_ID \ |
| 207 | + --document-name AWS-StartPortForwardingSessionToRemoteHost \ |
| 208 | + --parameters '{"host":["ALB_DNS_NAME"],"portNumber":["443"],"localPortNumber":["8443"]}' |
| 209 | + ``` |
| 210 | +3. Add a local hosts file entry so the browser sends the correct Host header: |
| 211 | + ```bash |
| 212 | + echo "127.0.0.1 ALB_DNS_NAME" | sudo tee -a /etc/hosts |
| 213 | + ``` |
| 214 | +4. Open `https://ALB_DNS_NAME:8443/` in your browser (accept the certificate warning for self-signed certs) |
| 215 | +5. Remove the hosts entry when done testing |
| 216 | + |
| 217 | +### Internet-Facing ALB |
| 218 | + |
| 219 | +Access the ALB DNS name directly from the stack outputs: |
| 220 | + |
| 221 | +```bash |
| 222 | +aws cloudformation describe-stacks \ |
| 223 | + --stack-name my-idp-stack \ |
| 224 | + --query 'Stacks[0].Outputs[?OutputKey==`ApplicationWebURL`].OutputValue' \ |
| 225 | + --output text |
| 226 | +``` |
| 227 | + |
| 228 | +## Security Considerations |
| 229 | + |
| 230 | +- ALB security group restricts ingress to port 443 from the VPC CIDR (or specified CIDRs) |
| 231 | +- ALB egress is restricted to the VPC endpoint security group on port 443 only |
| 232 | +- S3 bucket policy uses `aws:sourceVpce` condition — only requests through the VPC endpoint are allowed |
| 233 | +- S3 VPC endpoint policy is scoped to the WebUI bucket ARN only |
| 234 | +- ALB enforces TLS 1.3 (`ELBSecurityPolicy-TLS13-1-2-2021-06`) |
| 235 | +- ALB drops invalid HTTP header fields (`routing.http.drop_invalid_header_fields.enabled`) |
| 236 | +- ALB access logs are written to the stack's logging bucket under `alb-access-logs/` prefix |
| 237 | +- All traffic between ALB and S3 traverses the VPC endpoint (no internet path) |
| 238 | + |
| 239 | +## Troubleshooting |
| 240 | + |
| 241 | +### 403 Forbidden |
| 242 | + |
| 243 | +- Verify the ALB target group health checks are passing (expected HTTP codes: 200, 307, 405) |
| 244 | +- Check the S3 bucket policy includes the correct VPC endpoint ID in the `aws:sourceVpce` condition |
| 245 | +- Confirm the ALB listener rules have the host-header rewrite transform configured correctly |
| 246 | + |
| 247 | +### 404 Not Found |
| 248 | + |
| 249 | +- The ALB default action returns 404 for unmatched paths. Ensure your request path matches a listener rule (`/` or `/*`) |
| 250 | +- Verify the WebUI bucket contains `index.html` and assets — check the CodeBuild project logs for build errors |
| 251 | + |
| 252 | +### Target Group Unhealthy |
| 253 | + |
| 254 | +- The custom resource Lambda registers S3 VPC endpoint ENI private IPs as ALB targets. If the VPC endpoint was recreated, targets may reference stale IPs |
| 255 | +- Verify the VPC endpoint security group allows inbound HTTPS (port 443) from the ALB security group |
| 256 | + |
| 257 | +### UI Not Loading After Deploy |
| 258 | + |
| 259 | +- The UI is built and deployed to S3 by CodeBuild during stack creation/update. Check the CodeBuild project logs for errors |
| 260 | +- Verify the `VITE_CLOUDFRONT_DOMAIN` build environment variable resolves to the ALB URL (not a CloudFront domain) |
| 261 | + |
| 262 | +## Comparison: CloudFront vs ALB Hosting |
| 263 | + |
| 264 | +| Feature | CloudFront | ALB | |
| 265 | +|---------|-----------|-----| |
| 266 | +| Global edge caching | ✅ | ❌ | |
| 267 | +| VPC-only access | ❌ | ✅ | |
| 268 | +| Custom domain (Route53) | Via CloudFront alias | Via ALB alias record | |
| 269 | +| WAF integration | ✅ (CloudFront WAF) | ✅ (Regional WAF) | |
| 270 | +| Cost model | Data transfer per GB | Hourly + data transfer | |
| 271 | +| Geo restrictions | ✅ Built-in | ❌ (use security groups/NACLs) | |
| 272 | +| SPA routing | S3 error document | ALB URL rewrite transform | |
| 273 | +| TLS termination | CloudFront edge | ALB in VPC | |
0 commit comments