-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdeploy-cloudfront.ps1
More file actions
302 lines (263 loc) · 11.7 KB
/
Copy pathdeploy-cloudfront.ps1
File metadata and controls
302 lines (263 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
300
301
302
#!/usr/bin/env pwsh
# Deploy CloudFront Distribution for HDB Multi-Agent Advisor
# This script creates a CloudFront distribution for global content delivery
param(
[string]$ProjectPrefix = "hdbma",
[string]$Environment = "dev",
[string]$Version = "v1",
[string]$Region = "ap-southeast-2"
)
Write-Host "=== HDB Multi-Agent Advisor - CloudFront Deployment ===" -ForegroundColor Cyan
Write-Host "Project: $ProjectPrefix-$Environment-$Version" -ForegroundColor Yellow
Write-Host "Region: $Region" -ForegroundColor Yellow
Write-Host ""
# 1. Check prerequisites
Write-Host "Checking prerequisites..." -ForegroundColor Yellow
if (-not (Get-Command aws -ErrorAction SilentlyContinue)) {
Write-Host "[ERROR] AWS CLI not found. Please install AWS CLI." -ForegroundColor Red
exit 1
}
try {
$awsAccount = aws sts get-caller-identity --query Account --output text 2>$null
if (-not $awsAccount) {
throw "AWS credentials not configured"
}
Write-Host "[OK] AWS CLI configured (Account: $awsAccount)" -ForegroundColor Green
} catch {
Write-Host "[ERROR] AWS credentials not configured. Run 'aws configure'." -ForegroundColor Red
exit 1
}
# 2. Get existing S3 bucket name from Phase 1 stack
Write-Host "Getting S3 bucket name from Phase 1 stack..." -ForegroundColor Yellow
$stackName = "$ProjectPrefix-phase1-$Environment-$Version"
try {
$s3BucketName = aws cloudformation describe-stacks --stack-name $stackName --query "Stacks[0].Outputs[?OutputKey=='S3BucketName'].OutputValue" --output text --region $Region 2>$null
if (-not $s3BucketName -or $s3BucketName -eq "None") {
throw "S3 bucket not found"
}
Write-Host "[OK] Found S3 bucket: $s3BucketName" -ForegroundColor Green
} catch {
Write-Host "[ERROR] Could not find S3 bucket from Phase 1 stack: $stackName" -ForegroundColor Red
Write-Host "Make sure Phase 1 is deployed first with: .\deploy-phase1.ps1" -ForegroundColor Yellow
exit 1
}
# 3. Get API Gateway endpoint from Phase 1 stack
Write-Host "Getting API Gateway endpoint..." -ForegroundColor Yellow
try {
$apiEndpoint = aws cloudformation describe-stacks --stack-name $stackName --query "Stacks[0].Outputs[?OutputKey=='ApiGatewayEndpoint'].OutputValue" --output text --region $Region 2>$null
if (-not $apiEndpoint -or $apiEndpoint -eq "None") {
throw "API endpoint not found"
}
Write-Host "[OK] Found API endpoint: $apiEndpoint" -ForegroundColor Green
} catch {
Write-Host "[ERROR] Could not find API Gateway endpoint from Phase 1 stack" -ForegroundColor Red
exit 1
}
# 4. Update index.html with API endpoint and upload to S3
Write-Host "Updating and uploading index.html..." -ForegroundColor Yellow
if (-not (Test-Path "web/index.html")) {
Write-Host "[ERROR] web/index.html not found" -ForegroundColor Red
exit 1
}
# Construct full API endpoint like deploy-phase1.ps1 does
$apiStageName = $Environment
$apiRoutePath = "/chat"
$fullApiEndpoint = "$apiEndpoint/$apiStageName$apiRoutePath"
Write-Host "[INFO] Full API Endpoint: $fullApiEndpoint" -ForegroundColor Cyan
# Read and update index.html
$indexContent = Get-Content "web/index.html" -Raw
$updatedContent = $indexContent -replace "YOUR_AGENTCORE_ENDPOINT_HERE", $fullApiEndpoint
$updatedContent = $updatedContent -replace "PLACEHOLDER_NOT_REPLACED", "CONFIGURED_ENDPOINT"
# Upload to S3
try {
$updatedContent | Out-File -FilePath "web/index_updated.html" -Encoding UTF8
aws s3 cp "web/index_updated.html" "s3://$s3BucketName/index.html" --content-type "text/html" --region $Region
Remove-Item "web/index_updated.html" -Force
Write-Host "[OK] Updated index.html uploaded to S3" -ForegroundColor Green
} catch {
Write-Host "[ERROR] Failed to upload index.html to S3" -ForegroundColor Red
exit 1
}
# 5. Create CloudFront stack
Write-Host "Creating CloudFront distribution..." -ForegroundColor Yellow
$cloudFrontStackName = "$ProjectPrefix-cloudfront-$Environment-$Version"
# Create CloudFormation template for CloudFront
$cloudFrontTemplate = @"
AWSTemplateFormatVersion: '2010-09-09'
Description: 'CloudFront Distribution for HDB Multi-Agent Advisor'
Parameters:
ProjectPrefix:
Type: String
Default: $ProjectPrefix
Description: The project prefix for resource naming.
EnvironmentName:
Type: String
Default: $Environment
Description: The environment name (dev, test, prod).
VersionTag:
Type: String
Default: $Version
Description: The version tag for the deployment.
S3BucketName:
Type: String
Default: $s3BucketName
Description: The S3 bucket name for the website.
Resources:
# CloudFront Origin Access Control
OriginAccessControl:
Type: AWS::CloudFront::OriginAccessControl
Properties:
OriginAccessControlConfig:
Name: !Sub "`${ProjectPrefix}-oac-`${EnvironmentName}-`${VersionTag}"
OriginAccessControlOriginType: s3
SigningBehavior: always
SigningProtocol: sigv4
# CloudFront Distribution
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Comment: !Sub "`${ProjectPrefix} HDB Assistant - `${EnvironmentName}"
DefaultCacheBehavior:
TargetOriginId: S3Origin
ViewerProtocolPolicy: redirect-to-https
CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # Managed-CachingOptimized
OriginRequestPolicyId: 88a5eaf4-2fd4-4709-b370-b4c650ea3fcf # Managed-CORS-S3Origin
ResponseHeadersPolicyId: 67f7725c-6f97-4210-82d7-5512b31e9d03 # Managed-SecurityHeadersPolicy
DefaultRootObject: index.html
Enabled: true
HttpVersion: http2
IPV6Enabled: true
Origins:
- Id: S3Origin
DomainName: !Sub "`${S3BucketName}.s3.`${AWS::Region}.amazonaws.com"
S3OriginConfig:
OriginAccessIdentity: ""
OriginAccessControlId: !Ref OriginAccessControl
PriceClass: PriceClass_100 # Use only North America and Europe edge locations for cost optimization
CustomErrorResponses:
- ErrorCode: 403
ResponseCode: 200
ResponsePagePath: /index.html
- ErrorCode: 404
ResponseCode: 200
ResponsePagePath: /index.html
Tags:
- Key: Project
Value: !Ref ProjectPrefix
- Key: Environment
Value: !Ref EnvironmentName
- Key: Version
Value: !Ref VersionTag
# S3 Bucket Policy for CloudFront OAC
S3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref S3BucketName
PolicyDocument:
Statement:
- Sid: AllowCloudFrontServicePrincipal
Effect: Allow
Principal:
Service: cloudfront.amazonaws.com
Action: s3:GetObject
Resource: !Sub "arn:aws:s3:::`${S3BucketName}/*"
Condition:
StringEquals:
"AWS:SourceArn": !Sub "arn:aws:cloudfront::`${AWS::AccountId}:distribution/`${CloudFrontDistribution}"
Outputs:
CloudFrontDomainName:
Description: CloudFront Distribution Domain Name
Value: !GetAtt CloudFrontDistribution.DomainName
Export:
Name: !Sub "`${ProjectPrefix}-cloudfront-domain-`${EnvironmentName}-`${VersionTag}"
CloudFrontDistributionId:
Description: CloudFront Distribution ID
Value: !Ref CloudFrontDistribution
Export:
Name: !Sub "`${ProjectPrefix}-cloudfront-id-`${EnvironmentName}-`${VersionTag}"
WebsiteURL:
Description: Website URL via CloudFront
Value: !Sub "https://`${CloudFrontDistribution.DomainName}"
Export:
Name: !Sub "`${ProjectPrefix}-website-url-`${EnvironmentName}-`${VersionTag}"
"@
# Save template to file
$cloudFrontTemplate | Out-File -FilePath "infrastructure/cloudfront-stack.yaml" -Encoding UTF8
# Deploy CloudFront stack
try {
Write-Host "Deploying CloudFront stack: $cloudFrontStackName" -ForegroundColor Yellow
aws cloudformation deploy `
--template-file "infrastructure/cloudfront-stack.yaml" `
--stack-name $cloudFrontStackName `
--parameter-overrides `
ProjectPrefix=$ProjectPrefix `
EnvironmentName=$Environment `
VersionTag=$Version `
S3BucketName=$s3BucketName `
--capabilities CAPABILITY_IAM `
--region $Region `
--no-fail-on-empty-changeset
if ($LASTEXITCODE -ne 0) {
throw "CloudFormation deployment failed"
}
Write-Host "[OK] CloudFront stack deployed successfully" -ForegroundColor Green
} catch {
Write-Host "[ERROR] Failed to deploy CloudFront stack: $($_.Exception.Message)" -ForegroundColor Red
exit 1
}
# 6. Get CloudFront outputs
Write-Host "Getting CloudFront distribution details..." -ForegroundColor Yellow
try {
$cloudFrontDomain = aws cloudformation describe-stacks --stack-name $cloudFrontStackName --query "Stacks[0].Outputs[?OutputKey=='CloudFrontDomainName'].OutputValue" --output text --region $Region
$websiteURL = aws cloudformation describe-stacks --stack-name $cloudFrontStackName --query "Stacks[0].Outputs[?OutputKey=='WebsiteURL'].OutputValue" --output text --region $Region
$distributionId = aws cloudformation describe-stacks --stack-name $cloudFrontStackName --query "Stacks[0].Outputs[?OutputKey=='CloudFrontDistributionId'].OutputValue" --output text --region $Region
Write-Host "[OK] CloudFront distribution created" -ForegroundColor Green
} catch {
Write-Host "[ERROR] Failed to get CloudFront outputs" -ForegroundColor Red
exit 1
}
# 7. Create invalidation to refresh cache
Write-Host "Creating CloudFront invalidation..." -ForegroundColor Yellow
try {
$invalidationId = aws cloudfront create-invalidation --distribution-id $distributionId --paths "/*" --query "Invalidation.Id" --output text
Write-Host "[OK] CloudFront invalidation created: $invalidationId" -ForegroundColor Green
} catch {
Write-Host "[WARNING] Failed to create CloudFront invalidation, but deployment succeeded" -ForegroundColor Yellow
}
# 8. Display results
Write-Host ""
Write-Host "=== CloudFront Deployment Complete ===" -ForegroundColor Green
Write-Host ""
Write-Host "CloudFront Distribution:" -ForegroundColor Cyan
Write-Host " Domain: $cloudFrontDomain" -ForegroundColor White
Write-Host " Distribution ID: $distributionId" -ForegroundColor White
Write-Host ""
Write-Host "Website URLs:" -ForegroundColor Cyan
Write-Host " CloudFront (Global): $websiteURL" -ForegroundColor White
Write-Host " S3 Direct: https://$s3BucketName.s3-website-$Region.amazonaws.com" -ForegroundColor White
Write-Host ""
Write-Host "Next Steps:" -ForegroundColor Yellow
Write-Host "1. Wait 5-15 minutes for CloudFront distribution to deploy globally" -ForegroundColor White
Write-Host "2. Visit: $websiteURL" -ForegroundColor White
Write-Host "3. Test all 3 phase examples in the UI" -ForegroundColor White
Write-Host ""
Write-Host "CloudFront Benefits:" -ForegroundColor Cyan
Write-Host "• Global edge locations for faster loading" -ForegroundColor White
Write-Host "• HTTPS by default with AWS certificate" -ForegroundColor White
Write-Host "• Caching for better performance" -ForegroundColor White
Write-Host "• Custom error pages (SPA routing support)" -ForegroundColor White
Write-Host ""
# 9. Optional: Open website in browser
$openBrowser = Read-Host "Open website in browser? (y/N)"
if ($openBrowser -eq "y" -or $openBrowser -eq "Y") {
try {
Start-Process $websiteURL
Write-Host "[OK] Website opened in browser" -ForegroundColor Green
} catch {
Write-Host "[WARNING] Could not open browser automatically" -ForegroundColor Yellow
Write-Host "Please visit: $websiteURL" -ForegroundColor White
}
}
Write-Host ""
Write-Host "[OK] CloudFront deployment completed successfully!" -ForegroundColor Green