|
| 1 | +locals { |
| 2 | + all_regions = keys(var.CoreSlowLambdaHost) |
| 3 | +} |
| 4 | + |
| 5 | +data "aws_caller_identity" "current" {} |
| 6 | + |
1 | 7 | resource "aws_s3_bucket" "frontend" { |
2 | | - bucket = "${var.BucketPrefix}-${var.ProjectId}" |
| 8 | + region = each.key |
| 9 | + for_each = toset(local.all_regions) |
| 10 | + bucket = "${data.aws_caller_identity.current.account_id}-${var.ProjectId}-${each.key}" |
3 | 11 | } |
4 | 12 |
|
5 | 13 | resource "aws_s3_bucket_lifecycle_configuration" "frontend" { |
6 | | - bucket = aws_s3_bucket.frontend.id |
| 14 | + for_each = toset(local.all_regions) |
| 15 | + region = each.key |
| 16 | + bucket = aws_s3_bucket.frontend[each.key].id |
7 | 17 |
|
8 | 18 | rule { |
9 | 19 | id = "AbortIncompleteMultipartUploads" |
@@ -41,13 +51,16 @@ data "archive_file" "ui" { |
41 | 51 | source_dir = "${path.module}/../../../dist_ui/" |
42 | 52 | output_path = "/tmp/ui_archive.zip" |
43 | 53 | } |
| 54 | + |
44 | 55 | resource "null_resource" "upload_frontend" { |
| 56 | + for_each = toset(local.all_regions) |
| 57 | + |
45 | 58 | triggers = { |
46 | 59 | ui_bucket_sha = data.archive_file.ui.output_sha |
47 | 60 | } |
48 | 61 |
|
49 | 62 | provisioner "local-exec" { |
50 | | - command = "aws s3 sync ${data.archive_file.ui.source_dir} s3://${aws_s3_bucket.frontend.id} --delete" |
| 63 | + command = "aws s3 sync ${data.archive_file.ui.source_dir} s3://${aws_s3_bucket.frontend[each.key].id} --region ${each.key} --delete" |
51 | 64 | } |
52 | 65 | } |
53 | 66 |
|
@@ -120,10 +133,35 @@ resource "aws_cloudfront_cache_policy" "no_cache" { |
120 | 133 |
|
121 | 134 | resource "aws_cloudfront_distribution" "app_cloudfront_distribution" { |
122 | 135 | http_version = "http2and3" |
123 | | - origin { |
124 | | - origin_id = "S3Bucket" |
125 | | - origin_access_control_id = aws_cloudfront_origin_access_control.frontend_oac.id |
126 | | - domain_name = aws_s3_bucket.frontend.bucket_regional_domain_name |
| 136 | + |
| 137 | + # Dynamic origins for each region's S3 bucket |
| 138 | + dynamic "origin" { |
| 139 | + for_each = local.all_regions |
| 140 | + content { |
| 141 | + origin_id = "S3Bucket-${origin.value}" |
| 142 | + origin_access_control_id = aws_cloudfront_origin_access_control.frontend_oac.id |
| 143 | + domain_name = aws_s3_bucket.frontend[origin.value].bucket_regional_domain_name |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + # Origin group for S3 buckets with failover |
| 148 | + origin_group { |
| 149 | + origin_id = "S3BucketGroup" |
| 150 | + |
| 151 | + failover_criteria { |
| 152 | + status_codes = [403, 404, 500, 502, 503, 504] |
| 153 | + } |
| 154 | + |
| 155 | + member { |
| 156 | + origin_id = "S3Bucket-${var.CurrentActiveRegion}" |
| 157 | + } |
| 158 | + |
| 159 | + dynamic "member" { |
| 160 | + for_each = [for region in local.all_regions : region if region != var.CurrentActiveRegion] |
| 161 | + content { |
| 162 | + origin_id = "S3Bucket-${member.value}" |
| 163 | + } |
| 164 | + } |
127 | 165 | } |
128 | 166 |
|
129 | 167 | # Dynamic origins for each region's Lambda function |
@@ -161,7 +199,7 @@ resource "aws_cloudfront_distribution" "app_cloudfront_distribution" { |
161 | 199 | is_ipv6_enabled = true |
162 | 200 | default_cache_behavior { |
163 | 201 | compress = true |
164 | | - target_origin_id = "S3Bucket" |
| 202 | + target_origin_id = "S3BucketGroup" |
165 | 203 | viewer_protocol_policy = "redirect-to-https" |
166 | 204 | allowed_methods = ["GET", "HEAD"] |
167 | 205 | cached_methods = ["GET", "HEAD"] |
@@ -329,41 +367,83 @@ function handler(event) { |
329 | 367 | EOT |
330 | 368 | } |
331 | 369 |
|
332 | | -resource "aws_s3_bucket_policy" "frontend_bucket_policy" { |
333 | | - bucket = aws_s3_bucket.frontend.id |
334 | | - policy = jsonencode(({ |
335 | | - Version = "2012-10-17" |
336 | | - Statement = [ |
337 | | - { |
338 | | - Effect = "Allow", |
339 | | - Principal = { |
340 | | - Service = "cloudfront.amazonaws.com" |
341 | | - }, |
342 | | - Action = "s3:GetObject", |
343 | | - Resource = "${aws_s3_bucket.frontend.arn}/*" |
344 | | - Condition = { |
345 | | - StringEquals = { |
346 | | - "AWS:SourceArn" = aws_cloudfront_distribution.app_cloudfront_distribution.arn |
| 370 | +resource "null_resource" "s3_bucket_policy" { |
| 371 | + for_each = toset(local.all_regions) |
| 372 | + |
| 373 | + triggers = { |
| 374 | + bucket_id = aws_s3_bucket.frontend[each.key].id |
| 375 | + distribution_arn = aws_cloudfront_distribution.app_cloudfront_distribution.arn |
| 376 | + policy_hash = md5(jsonencode({ |
| 377 | + Version = "2012-10-17" |
| 378 | + Statement = [ |
| 379 | + { |
| 380 | + Effect = "Allow", |
| 381 | + Principal = { |
| 382 | + Service = "cloudfront.amazonaws.com" |
| 383 | + }, |
| 384 | + Action = "s3:GetObject", |
| 385 | + Resource = "${aws_s3_bucket.frontend[each.key].arn}/*" |
| 386 | + Condition = { |
| 387 | + StringEquals = { |
| 388 | + "AWS:SourceArn" = aws_cloudfront_distribution.app_cloudfront_distribution.arn |
| 389 | + } |
347 | 390 | } |
348 | | - } |
349 | | - }, |
350 | | - { |
351 | | - Effect = "Allow", |
352 | | - Principal = { |
353 | | - Service = "cloudfront.amazonaws.com" |
354 | 391 | }, |
355 | | - Action = "s3:ListBucket", |
356 | | - Resource = aws_s3_bucket.frontend.arn |
357 | | - Condition = { |
358 | | - StringEquals = { |
359 | | - "AWS:SourceArn" = aws_cloudfront_distribution.app_cloudfront_distribution.arn |
| 392 | + { |
| 393 | + Effect = "Allow", |
| 394 | + Principal = { |
| 395 | + Service = "cloudfront.amazonaws.com" |
| 396 | + }, |
| 397 | + Action = "s3:ListBucket", |
| 398 | + Resource = aws_s3_bucket.frontend[each.key].arn |
| 399 | + Condition = { |
| 400 | + StringEquals = { |
| 401 | + "AWS:SourceArn" = aws_cloudfront_distribution.app_cloudfront_distribution.arn |
| 402 | + } |
360 | 403 | } |
361 | 404 | } |
362 | | - } |
363 | | - ] |
364 | | - |
365 | | - })) |
| 405 | + ] |
| 406 | + })) |
| 407 | + } |
366 | 408 |
|
| 409 | + provisioner "local-exec" { |
| 410 | + command = <<-EOT |
| 411 | + aws s3api put-bucket-policy \ |
| 412 | + --bucket ${aws_s3_bucket.frontend[each.key].id} \ |
| 413 | + --region ${each.key} \ |
| 414 | + --policy '{ |
| 415 | + "Version": "2012-10-17", |
| 416 | + "Statement": [ |
| 417 | + { |
| 418 | + "Effect": "Allow", |
| 419 | + "Principal": { |
| 420 | + "Service": "cloudfront.amazonaws.com" |
| 421 | + }, |
| 422 | + "Action": "s3:GetObject", |
| 423 | + "Resource": "${aws_s3_bucket.frontend[each.key].arn}/*", |
| 424 | + "Condition": { |
| 425 | + "StringEquals": { |
| 426 | + "AWS:SourceArn": "${aws_cloudfront_distribution.app_cloudfront_distribution.arn}" |
| 427 | + } |
| 428 | + } |
| 429 | + }, |
| 430 | + { |
| 431 | + "Effect": "Allow", |
| 432 | + "Principal": { |
| 433 | + "Service": "cloudfront.amazonaws.com" |
| 434 | + }, |
| 435 | + "Action": "s3:ListBucket", |
| 436 | + "Resource": "${aws_s3_bucket.frontend[each.key].arn}", |
| 437 | + "Condition": { |
| 438 | + "StringEquals": { |
| 439 | + "AWS:SourceArn": "${aws_cloudfront_distribution.app_cloudfront_distribution.arn}" |
| 440 | + } |
| 441 | + } |
| 442 | + } |
| 443 | + ] |
| 444 | + }' |
| 445 | + EOT |
| 446 | + } |
367 | 447 | } |
368 | 448 |
|
369 | 449 | resource "aws_cloudfront_distribution" "linkry_cloudfront_distribution" { |
|
0 commit comments