Skip to content

Commit 5736991

Browse files
committed
inital commit
0 parents  commit 5736991

File tree

5 files changed

+661
-0
lines changed

5 files changed

+661
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.scratch

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

README.md

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
# AWS CloudFront Proxy for LaunchDarkly
2+
3+
A CloudFront distribution that acts as a reverse proxy for LaunchDarkly client SDK and events APIs. For when network calls need to come from a specific URL instead of LaunchDarkly.
4+
5+
## Architecture
6+
7+
```
8+
Your Application → CloudFront Edge → LaunchDarkly APIs
9+
↓ (cached)
10+
```
11+
12+
### Endpoint Mappings
13+
14+
| **Path Pattern** | **Target Origin** | **LaunchDarkly Domain** | **Purpose** |
15+
|-----------------|-------------------|-------------------------|-------------|
16+
| `/` (default) | `LDClientSdkOrigin` | `clientsdk.launchdarkly.com` | Default flag polling |
17+
| `/eval/*` | `LDClientStreamOrigin` | `clientstream.launchdarkly.com` | 🔄 **Streaming evaluations** |
18+
| `/stream/*` | `LDClientStreamOrigin` | `clientstream.launchdarkly.com` | 🔄 **Real-time streaming** |
19+
| `/stream/eval/*` | `LDClientStreamOrigin` | `clientstream.launchdarkly.com` | 🔄 **Combined streaming** |
20+
| `/clientstream/*` | `LDClientStreamOrigin` | `clientstream.launchdarkly.com` | 🔄 **Alternative streaming** |
21+
| `/events/*` | `LDEventsOrigin` | `events.launchdarkly.com` | 📊 Event tracking |
22+
| `/goals/*` | `LDClientSdkOrigin` | `clientsdk.launchdarkly.com` | 🎯 Goal tracking |
23+
| `/sdk/eval/users/*` | `LDClientSdkOrigin` | `clientsdk.launchdarkly.com` | 👤 User-specific evaluations |
24+
| `/sdk/evalx/*` | `LDAppOrigin` | `app.launchdarkly.com` | 🔧 Extended evaluation APIs |
25+
| `/sdk/*` | `LDAppOrigin` | `app.launchdarkly.com` | ⚙️ SDK management APIs |
26+
27+
> **Note:** All streaming endpoints (`/eval/*`, `/stream/*`, `/clientstream/*`) use **no-cache policies** for real-time updates.
28+
29+
## Quick Start
30+
31+
### Prerequisites
32+
33+
1. **AWS CLI configured** with appropriate permissions
34+
2. **AWS SSO login** (if using SSO)
35+
36+
### Check AWS Authentication
37+
38+
```bash
39+
# Check if you're logged in
40+
aws sts get-caller-identity
41+
42+
# If you get "Token has expired and refresh failed", re-login:
43+
aws sso login --profile YOUR-PROFILE
44+
```
45+
46+
### Deploy the CloudFront Proxy
47+
48+
```bash
49+
cd infrastructure
50+
51+
aws cloudformation deploy \
52+
--template-file templates/cloudfront.yaml \
53+
--stack-name ld-cloudfront-proxy \
54+
--parameter-overrides \
55+
UseCustomDomain=false \
56+
PriceClass=PriceClass_100 \
57+
EnableLogging=false
58+
```
59+
60+
**⏱️ Deployment time:** ~15-20 minutes (CloudFront global propagation)
61+
62+
### Get Your Proxy URL
63+
64+
```bash
65+
aws cloudformation describe-stacks \
66+
--stack-name ld-cloudfront-proxy \
67+
--query 'Stacks[0].Outputs' \
68+
--output table
69+
```
70+
71+
This will return your CloudFront domain (e.g., `d1a2b3c4d5e6f7.cloudfront.net`)
72+
73+
## Configuration Options
74+
75+
| Parameter | Default | Options | Description |
76+
|-----------|---------|---------|-------------|
77+
| `UseCustomDomain` | `false` | `true`/`false` | Use your own domain instead of CloudFront default |
78+
| `DomainName` | `""` | Your domain | Required if UseCustomDomain=true (e.g., `flags.my-super-awesome-company.com`) |
79+
| `AcmCertificateArn` | `""` | ACM ARN | Required if UseCustomDomain=true (must be in us-east-1) |
80+
| `AutoCreateDNS` | `false` | `true`/`false` | **NEW:** Automatically create Route 53 DNS record |
81+
| `HostedZoneId` | `""` | Route 53 Zone ID | Required if AutoCreateDNS=true (e.g., `Z1D633PJN98FT9`) |
82+
| `PriceClass` | `PriceClass_100` | `PriceClass_100`/`200`/`All` | Coverage: US/Canada/Europe/Asia (100) vs Global (All) |
83+
| `EnableLogging` | `false` | `true`/`false` | Enable CloudFront access logging |
84+
| `LoggingBucket` | `""` | S3 bucket name | Required if EnableLogging=true |
85+
86+
### Price Class Options
87+
88+
- **PriceClass_100** (Recommended): US, Canada, Europe, Asia - Lowest cost
89+
- **PriceClass_200**: Adds Middle East, Africa - Medium cost
90+
- **PriceClass_All**: Global coverage - Highest cost
91+
92+
### Custom Domain Setup Options
93+
94+
**⚠️ PREREQUISITES:** Before using `UseCustomDomain=true`, you must complete the following setup:
95+
96+
#### Step 1: Get Your Route 53 Hosted Zone ID
97+
```bash
98+
# Find your hosted zone ID (replace with your domain)
99+
aws route53 list-hosted-zones --query 'HostedZones[?Name==`my-awesome-domain.com.`].[Id,Name]' --output table
100+
101+
# Example output: Zone ID like Z04794713N147BEH1NVCF
102+
```
103+
104+
#### Step 2: Create ACM Certificate (Required)
105+
```bash
106+
# Request SSL certificate (MUST be in us-east-1 for CloudFront)
107+
aws acm request-certificate \
108+
--domain-name ld.my-awesoome-domain.com \
109+
--validation-method DNS \
110+
--region us-east-1
111+
112+
# Save the Certificate ARN from the output!
113+
```
114+
115+
#### Step 3: Validate Certificate
116+
```bash
117+
# Get DNS validation record details
118+
aws acm describe-certificate --certificate-arn YOUR-CERT-ARN --region us-east-1
119+
120+
# Create validation record in Route 53 (replace with your values)
121+
aws route53 change-resource-record-sets --hosted-zone-id YOUR-ZONE-ID --change-batch '{
122+
"Changes": [{
123+
"Action": "CREATE",
124+
"ResourceRecordSet": {
125+
"Name": "_validation-string.ld.my-awesome-domain.com.",
126+
"Type": "CNAME",
127+
"TTL": 300,
128+
"ResourceRecords": [{"Value": "_validation-value.acm-validations.aws."}]
129+
}
130+
}]
131+
}'
132+
133+
# Verify certificate is issued (wait 1-2 minutes)
134+
aws acm describe-certificate --certificate-arn YOUR-CERT-ARN --region us-east-1 \
135+
--query 'Certificate.Status' --output text
136+
# Should return: ISSUED
137+
```
138+
139+
#### Option 1: Automatic DNS (Recommended)
140+
If you have a Route 53 hosted zone, the template can automatically create DNS records:
141+
142+
```bash
143+
aws cloudformation deploy \
144+
--template-file templates/cloudfront.yaml \
145+
--stack-name ld-cloudfront-proxy \
146+
--parameter-overrides \
147+
UseCustomDomain=true \
148+
DomainName=ld.my-awesome-domain.com \
149+
AcmCertificateArn=my-awesome-arn \
150+
AutoCreateDNS=true \
151+
HostedZoneId=my-awesome-hosted-zone-id \
152+
PriceClass=PriceClass_100
153+
```
154+
155+
## 📱 SDK Configuration
156+
157+
Once deployed, configure your LaunchDarkly SDKs to use your CloudFront proxy:
158+
159+
### React SDK (React Applications)
160+
```javascript
161+
const LDProvider = await asyncWithLDProvider({
162+
clientSideID: 'your-client-side-id',
163+
context: {
164+
kind: "device",
165+
key: "unique-device-id"
166+
},
167+
options: {
168+
baseUrl: 'https://ld.my-awesome-domain.com',
169+
eventsUrl: 'https://ld.my-awesome-domain.com',
170+
streamUrl: 'https://ld.my-awesome-domain.com',
171+
streaming: true
172+
}
173+
});
174+
```
175+
176+
177+
## What Gets Deployed
178+
179+
### Infrastructure Resources
180+
- **CloudFront Distribution** with 400+ global edge locations
181+
- **Cache Policies:**
182+
- Standard Cache Policy (5min default TTL, 10min max TTL) - for flag evaluations
183+
- No-Cache Policy (0-1s TTL) - for streaming endpoints
184+
- **Origin Request Policy** (forwards query strings and key headers)
185+
- **Response Headers Policy** (CORS configuration for client-side SDKs)
186+
187+
### LaunchDarkly Origins
188+
- **`clientsdk.launchdarkly.com`** - Default flag polling, goals, user evaluations
189+
- **`clientstream.launchdarkly.com`** - Real-time streaming, SSE endpoints
190+
- **`events.launchdarkly.com`** - Event tracking and analytics
191+
- **`app.launchdarkly.com`** - SDK management and extended APIs
192+
193+
## Cleanup
194+
195+
### Automated Cleanup (Recommended)
196+
```bash
197+
aws cloudformation deploy \
198+
--template-file templates/remove-cloudfront.yaml \
199+
--stack-name cleanup-ld-cloudfront \
200+
--capabilities CAPABILITY_NAMED_IAM \
201+
--parameter-overrides StackNameToDelete=ld-cloudfront-proxy
202+
```
203+
204+
### Manual Cleanup
205+
```bash
206+
aws cloudformation delete-stack --stack-name ld-cloudfront-proxy
207+
```
208+
209+
**⏱️ Deletion time:** ~15-20 minutes (CloudFront global propagation)
210+
211+
## Monitoring & Troubleshooting
212+
213+
### Check Stack Status
214+
```bash
215+
aws cloudformation describe-stack-events --stack-name ld-cloudfront-proxy --output table
216+
```
217+
218+
### Verify AWS Configuration
219+
```bash
220+
# Check current region
221+
aws configure get region
222+
223+
# List AWS profiles
224+
aws configure list-profiles
225+
226+
# Test connectivity
227+
aws cloudformation list-stacks --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE --output table
228+
```
229+
230+
## SDK Compatibility
231+
232+
| SDK Type | Supported | Notes |
233+
|----------|-----------|--------|
234+
| **Client-side SDKs** | ✅ Yes | JavaScript, React, iOS, Android, Flutter |
235+
| **Server-side SDKs** | ❌ No | Java, .NET, Python, Go, Node.js (server-side) |
236+
| **Event Tracking** | ✅ Yes | From any SDK type |
237+
238+
**Note:** Server-side SDKs use different endpoints (`sdk.launchdarkly.com`) not currently proxied by this template.
239+
240+
## Multi-Project Usage
241+
242+
Different LaunchDarkly projects within the same organization can use different configurations:
243+
244+
- **Project A**: Uses CloudFront proxy (this reverse proxy setup)
245+
- **Project B**: Connects directly to LaunchDarkly
246+
- **Project C**: Uses a different proxy or region
247+
248+
Each project configures its SDK independently using different SDK keys and base URLs.
249+
250+
## Contributing
251+
252+
1. Test changes in a development AWS account first
253+
2. Validate CloudFormation templates before committing
254+
3. Update documentation for any parameter changes

0 commit comments

Comments
 (0)