From 5678df87d0114b5ac173f7095de8609e68bc727d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksa=20Siri=C5=A1ki?= <31509435+aleksasiriski@users.noreply.github.com> Date: Thu, 25 Apr 2024 17:20:05 +0200 Subject: [PATCH 1/5] feat: started creating modules for frontend --- aws/dev/backend/main.tf | 7 +- aws/dev/backend/region_eu_central_1.tf | 6 +- aws/modules/backend/s3/main.tf | 29 -------- aws/modules/backend/s3/outputs.tf | 15 ----- aws/modules/backend/s3/upload.tf | 13 ---- aws/modules/frontend/cloudfront/cache.tf | 67 +++++++++++++++++++ aws/modules/frontend/cloudfront/main.tf | 56 ++++++++++++++++ .../frontend/cloudfront/route53_records.tf | 23 +++++++ aws/modules/frontend/cloudfront/variables.tf | 52 ++++++++++++++ .../acm => frontend/cloudfront}/versions.tf | 0 aws/modules/frontend/env_replacer/main.tf | 21 ++++++ aws/modules/frontend/env_replacer/outputs.tf | 3 + .../frontend/env_replacer/variables.tf | 14 ++++ aws/modules/frontend/env_replacer/versions.tf | 9 +++ aws/modules/frontend/lambda@edge/main.tf | 17 +++++ aws/modules/frontend/lambda@edge/outputs.tf | 7 ++ aws/modules/frontend/lambda@edge/variables.tf | 52 ++++++++++++++ .../lambda@edge}/versions.tf | 0 aws/modules/frontend/s3_assets/locals.tf | 9 +++ aws/modules/frontend/s3_assets/main.tf | 39 +++++++++++ aws/modules/frontend/s3_assets/outputs.tf | 15 +++++ aws/modules/frontend/s3_assets/upload.tf | 9 +++ .../s3 => frontend/s3_assets}/variables.tf | 5 +- aws/modules/frontend/s3_assets/versions.tf | 9 +++ .../{backend => universal}/acm/main.tf | 0 .../{backend => universal}/acm/outputs.tf | 0 .../{backend => universal}/acm/variables.tf | 0 aws/modules/universal/acm/versions.tf | 9 +++ aws/modules/universal/lambda_iam/locals.tf | 4 ++ .../{backend => universal}/lambda_iam/main.tf | 8 +-- .../lambda_iam/outputs.tf | 0 aws/modules/universal/lambda_iam/variables.tf | 17 +++++ aws/modules/universal/lambda_iam/versions.tf | 9 +++ .../s3 => universal/s3_source_code}/locals.tf | 5 +- aws/modules/universal/s3_source_code/main.tf | 29 ++++++++ .../universal/s3_source_code/outputs.tf | 15 +++++ .../universal/s3_source_code/upload.tf | 13 ++++ .../universal/s3_source_code/variables.tf | 18 +++++ .../s3_source_code}/versions.tf | 0 aws/prod/backend/main.tf | 7 +- aws/prod/backend/region_af_south_1.tf | 6 +- aws/prod/backend/region_ap_east_1.tf | 6 +- aws/prod/backend/region_ap_northeast_1.tf | 6 +- aws/prod/backend/region_ap_northeast_2.tf | 6 +- aws/prod/backend/region_ap_south_1.tf | 6 +- aws/prod/backend/region_ap_southeast_1.tf | 6 +- aws/prod/backend/region_ap_southeast_2.tf | 6 +- aws/prod/backend/region_ca_central_1.tf | 6 +- aws/prod/backend/region_eu_central_1.tf | 6 +- aws/prod/backend/region_eu_central_2.tf | 6 +- aws/prod/backend/region_eu_north_1.tf | 6 +- aws/prod/backend/region_eu_south_1.tf | 6 +- aws/prod/backend/region_eu_south_2.tf | 6 +- aws/prod/backend/region_eu_west_1.tf | 6 +- aws/prod/backend/region_eu_west_2.tf | 6 +- aws/prod/backend/region_eu_west_3.tf | 6 +- aws/prod/backend/region_me_south_1.tf | 6 +- aws/prod/backend/region_sa_east_1.tf | 6 +- aws/prod/backend/region_us_east_1.tf | 6 +- aws/prod/backend/region_us_east_2.tf | 6 +- aws/prod/backend/region_us_west_1.tf | 6 +- aws/prod/backend/region_us_west_2.tf | 6 +- todo.md | 5 ++ 63 files changed, 631 insertions(+), 117 deletions(-) delete mode 100644 aws/modules/backend/s3/main.tf delete mode 100644 aws/modules/backend/s3/outputs.tf delete mode 100644 aws/modules/backend/s3/upload.tf create mode 100644 aws/modules/frontend/cloudfront/cache.tf create mode 100644 aws/modules/frontend/cloudfront/main.tf create mode 100644 aws/modules/frontend/cloudfront/route53_records.tf create mode 100644 aws/modules/frontend/cloudfront/variables.tf rename aws/modules/{backend/acm => frontend/cloudfront}/versions.tf (100%) create mode 100644 aws/modules/frontend/env_replacer/main.tf create mode 100644 aws/modules/frontend/env_replacer/outputs.tf create mode 100644 aws/modules/frontend/env_replacer/variables.tf create mode 100644 aws/modules/frontend/env_replacer/versions.tf create mode 100644 aws/modules/frontend/lambda@edge/main.tf create mode 100644 aws/modules/frontend/lambda@edge/outputs.tf create mode 100644 aws/modules/frontend/lambda@edge/variables.tf rename aws/modules/{backend/lambda_iam => frontend/lambda@edge}/versions.tf (100%) create mode 100644 aws/modules/frontend/s3_assets/locals.tf create mode 100644 aws/modules/frontend/s3_assets/main.tf create mode 100644 aws/modules/frontend/s3_assets/outputs.tf create mode 100644 aws/modules/frontend/s3_assets/upload.tf rename aws/modules/{backend/s3 => frontend/s3_assets}/variables.tf (60%) create mode 100644 aws/modules/frontend/s3_assets/versions.tf rename aws/modules/{backend => universal}/acm/main.tf (100%) rename aws/modules/{backend => universal}/acm/outputs.tf (100%) rename aws/modules/{backend => universal}/acm/variables.tf (100%) create mode 100644 aws/modules/universal/acm/versions.tf create mode 100644 aws/modules/universal/lambda_iam/locals.tf rename aws/modules/{backend => universal}/lambda_iam/main.tf (83%) rename aws/modules/{backend => universal}/lambda_iam/outputs.tf (100%) create mode 100644 aws/modules/universal/lambda_iam/variables.tf create mode 100644 aws/modules/universal/lambda_iam/versions.tf rename aws/modules/{backend/s3 => universal/s3_source_code}/locals.tf (66%) create mode 100644 aws/modules/universal/s3_source_code/main.tf create mode 100644 aws/modules/universal/s3_source_code/outputs.tf create mode 100644 aws/modules/universal/s3_source_code/upload.tf create mode 100644 aws/modules/universal/s3_source_code/variables.tf rename aws/modules/{backend/s3 => universal/s3_source_code}/versions.tf (100%) create mode 100644 todo.md diff --git a/aws/dev/backend/main.tf b/aws/dev/backend/main.tf index 13c315a..200a86b 100644 --- a/aws/dev/backend/main.tf +++ b/aws/dev/backend/main.tf @@ -29,7 +29,10 @@ module "salt" { ### IAM for lambda execution and logging module "lambda_iam" { - source = "../../modules/backend/lambda_iam" + source = "../../modules/universal/lambda_iam" + + role_name = "aws-iam-role-exec-hearchco-api" + policy_name = "hearchco_api_logging" } ## Cloudfront @@ -42,7 +45,7 @@ provider "aws" { ### Certificate for the Cloudfront distribution module "hearchco_cdn_certificate" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/dev/backend/region_eu_central_1.tf b/aws/dev/backend/region_eu_central_1.tf index ecfa9ad..f181f3e 100644 --- a/aws/dev/backend/region_eu_central_1.tf +++ b/aws/dev/backend/region_eu_central_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_eu_central_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.eu-central-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_eu_central_1" { } module "hearchco_certificate_eu_central_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/modules/backend/s3/main.tf b/aws/modules/backend/s3/main.tf deleted file mode 100644 index e162485..0000000 --- a/aws/modules/backend/s3/main.tf +++ /dev/null @@ -1,29 +0,0 @@ -resource "aws_s3_bucket" "binary" { - bucket = local.bucket_name -} - -# Ownership -resource "aws_s3_bucket_ownership_controls" "binary" { - bucket = aws_s3_bucket.binary.id - - rule { - object_ownership = "BucketOwnerPreferred" - } -} - -# Visibility -resource "aws_s3_bucket_acl" "binary" { - bucket = aws_s3_bucket.binary.id - acl = "private" - - depends_on = [aws_s3_bucket_ownership_controls.binary] -} - -# Versioning -resource "aws_s3_bucket_versioning" "binary" { - bucket = aws_s3_bucket.binary.id - - versioning_configuration { - status = "Enabled" - } -} diff --git a/aws/modules/backend/s3/outputs.tf b/aws/modules/backend/s3/outputs.tf deleted file mode 100644 index 9e0939e..0000000 --- a/aws/modules/backend/s3/outputs.tf +++ /dev/null @@ -1,15 +0,0 @@ -output "bucket_id" { - value = aws_s3_bucket.binary.id -} - -output "bucket_arn" { - value = aws_s3_bucket.binary.arn -} - -output "s3_key" { - value = aws_s3_object.binary.key -} - -output "source_code_hash" { - value = aws_s3_object.binary.source_hash -} diff --git a/aws/modules/backend/s3/upload.tf b/aws/modules/backend/s3/upload.tf deleted file mode 100644 index c556602..0000000 --- a/aws/modules/backend/s3/upload.tf +++ /dev/null @@ -1,13 +0,0 @@ -// Upload new file -data "archive_file" "binary" { - type = "zip" - source_file = local.source_file - output_path = local.output_path -} - -resource "aws_s3_object" "binary" { - key = local.binary_key - bucket = aws_s3_bucket.binary.id - source = data.archive_file.binary.output_path - source_hash = data.archive_file.binary.output_base64sha256 -} diff --git a/aws/modules/frontend/cloudfront/cache.tf b/aws/modules/frontend/cloudfront/cache.tf new file mode 100644 index 0000000..a7a0dbe --- /dev/null +++ b/aws/modules/frontend/cloudfront/cache.tf @@ -0,0 +1,67 @@ +resource "aws_cloudfront_cache_policy" "default_cache_policy" { + name = "default-cache-policy" + min_ttl = var.default_cache.min_ttl + default_ttl = var.default_cache.default_ttl + max_ttl = var.default_cache.max_ttl + + parameters_in_cache_key_and_forwarded_to_origin { + enable_accept_encoding_brotli = true + enable_accept_encoding_gzip = true + + cookies_config { + cookie_behavior = "none" + } + + headers_config { + header_behavior = "whitelist" + headers { + items = [ + "Accept", + "Accept-Language", + "Access-Control-Request-Headers", + "Access-Control-Request-Method", + "Origin", + ] + } + } + + query_strings_config { + query_string_behavior = "all" + } + } +} + +resource "aws_cloudfront_cache_policy" "cache_policy" { + for_each = var.paths_cache + + name = "cache-policy${replace(each.key, "/", "-")}" + min_ttl = each.value.min_ttl + default_ttl = each.value.default_ttl + max_ttl = each.value.max_ttl + + parameters_in_cache_key_and_forwarded_to_origin { + enable_accept_encoding_brotli = true + enable_accept_encoding_gzip = true + + cookies_config { + cookie_behavior = "none" + } + + headers_config { + header_behavior = "whitelist" + headers { + items = [ + "Accept", + "Accept-Language", + "Access-Control-Request-Headers", + "Access-Control-Request-Method", + "Origin", + ] + } + } + + query_strings_config { + query_string_behavior = "all" + } + } +} diff --git a/aws/modules/frontend/cloudfront/main.tf b/aws/modules/frontend/cloudfront/main.tf new file mode 100644 index 0000000..4b4656b --- /dev/null +++ b/aws/modules/frontend/cloudfront/main.tf @@ -0,0 +1,56 @@ +locals { + origin_id = "api-gateway" +} + +resource "aws_cloudfront_distribution" "api_gateway_distribution" { + enabled = true + is_ipv6_enabled = true + wait_for_deployment = true + price_class = var.price_class + aliases = [var.domain_name] + + origin { + origin_id = local.origin_id + domain_name = var.target_domain_name + + custom_origin_config { + http_port = 80 + https_port = 443 + origin_protocol_policy = "https-only" + origin_ssl_protocols = ["TLSv1.2"] + } + } + + default_cache_behavior { + allowed_methods = var.allowed_methods + cached_methods = var.cached_methods + target_origin_id = local.origin_id + viewer_protocol_policy = "redirect-to-https" + compress = true + cache_policy_id = aws_cloudfront_cache_policy.default_cache_policy.id + } + + dynamic "ordered_cache_behavior" { + for_each = var.paths_cache + content { + path_pattern = ordered_cache_behavior.key + allowed_methods = var.allowed_methods + cached_methods = var.cached_methods + target_origin_id = local.origin_id + viewer_protocol_policy = "redirect-to-https" + compress = true + cache_policy_id = aws_cloudfront_cache_policy.cache_policy[ordered_cache_behavior.key].id + } + } + + viewer_certificate { + acm_certificate_arn = var.acm_certificate_arn + ssl_support_method = "sni-only" + } + + restrictions { + geo_restriction { + restriction_type = "none" + } + } +} diff --git a/aws/modules/frontend/cloudfront/route53_records.tf b/aws/modules/frontend/cloudfront/route53_records.tf new file mode 100644 index 0000000..6722c6e --- /dev/null +++ b/aws/modules/frontend/cloudfront/route53_records.tf @@ -0,0 +1,23 @@ +resource "aws_route53_record" "record" { + name = var.domain_name + type = "A" + zone_id = var.hosted_zone_id + + alias { + name = aws_cloudfront_distribution.api_gateway_distribution.domain_name + zone_id = aws_cloudfront_distribution.api_gateway_distribution.hosted_zone_id + evaluate_target_health = true + } +} + +resource "aws_route53_record" "record_v6" { + name = var.domain_name + type = "AAAA" + zone_id = var.hosted_zone_id + + alias { + name = aws_cloudfront_distribution.api_gateway_distribution.domain_name + zone_id = aws_cloudfront_distribution.api_gateway_distribution.hosted_zone_id + evaluate_target_health = true + } +} diff --git a/aws/modules/frontend/cloudfront/variables.tf b/aws/modules/frontend/cloudfront/variables.tf new file mode 100644 index 0000000..9feceaa --- /dev/null +++ b/aws/modules/frontend/cloudfront/variables.tf @@ -0,0 +1,52 @@ +variable "domain_name" { + type = string +} + +variable "target_domain_name" { + type = string +} + +variable "price_class" { + type = string + default = "PriceClass_All" +} + +variable "hosted_zone_id" { + type = string +} + +variable "acm_certificate_arn" { + type = string +} + +variable "allowed_methods" { + type = set(string) + default = ["HEAD", "DELETE", "POST", "GET", "OPTIONS", "PUT", "PATCH"] +} + +variable "cached_methods" { + type = set(string) + default = ["HEAD", "GET"] +} + +variable "default_cache" { + type = object({ + min_ttl = number + default_ttl = number + max_ttl = number + }) + default = { + min_ttl = 60 // 1 minute + default_ttl = 21600 // 6 hours + max_ttl = 86400 // 1 day + } +} + +variable "paths_cache" { + type = map(object({ + min_ttl = number + default_ttl = number + max_ttl = number + })) + default = {} +} diff --git a/aws/modules/backend/acm/versions.tf b/aws/modules/frontend/cloudfront/versions.tf similarity index 100% rename from aws/modules/backend/acm/versions.tf rename to aws/modules/frontend/cloudfront/versions.tf diff --git a/aws/modules/frontend/env_replacer/main.tf b/aws/modules/frontend/env_replacer/main.tf new file mode 100644 index 0000000..911ee7c --- /dev/null +++ b/aws/modules/frontend/env_replacer/main.tf @@ -0,0 +1,21 @@ +data "local_file" "source_file" { + filename = var.source_file +} + +locals { + environment_string = jsonencode(var.environment) + source_content = data.local_file.source_file.content + substitude_source_content = replace(local.source_content, var.placeholder, local.environment_string) +} + +resource "local_file" "backup_file" { + content = local.source_content + filename = var.source_file + ".bak" +} + +resource "local_file" "output_file" { + content = local.substitude_source_content + filename = var.source_file + + depends_on = [local_file.original_file] +} diff --git a/aws/modules/frontend/env_replacer/outputs.tf b/aws/modules/frontend/env_replacer/outputs.tf new file mode 100644 index 0000000..bd95c06 --- /dev/null +++ b/aws/modules/frontend/env_replacer/outputs.tf @@ -0,0 +1,3 @@ +output "output_file" { + value = local_file.output_file.filename +} diff --git a/aws/modules/frontend/env_replacer/variables.tf b/aws/modules/frontend/env_replacer/variables.tf new file mode 100644 index 0000000..5a0559d --- /dev/null +++ b/aws/modules/frontend/env_replacer/variables.tf @@ -0,0 +1,14 @@ +variable "source_file" { + type = string + default = "tmp/lambda/index.mjs" +} + +variable "placeholder" { + type = string + default = "'{{_EDGE_FUNCTION_ENVIRONMENT_}}'" +} + +variable "environment" { + type = map(string) + default = {} +} diff --git a/aws/modules/frontend/env_replacer/versions.tf b/aws/modules/frontend/env_replacer/versions.tf new file mode 100644 index 0000000..146cb2c --- /dev/null +++ b/aws/modules/frontend/env_replacer/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.5" + required_providers { + local = { + source = "hashicorp/local" + version = "~> 2.0" + } + } +} diff --git a/aws/modules/frontend/lambda@edge/main.tf b/aws/modules/frontend/lambda@edge/main.tf new file mode 100644 index 0000000..48720ea --- /dev/null +++ b/aws/modules/frontend/lambda@edge/main.tf @@ -0,0 +1,17 @@ +resource "aws_lambda_function" "api_lambda" { + function_name = var.function_name + handler = var.handler + runtime = var.runtime + role = var.role + + s3_bucket = var.s3_bucket + s3_key = var.s3_key + source_code_hash = var.source_code_hash + + architectures = var.architectures + memory_size = var.memory_size + timeout = var.timeout + + // needed for Lambda@Edge + publish = true +} diff --git a/aws/modules/frontend/lambda@edge/outputs.tf b/aws/modules/frontend/lambda@edge/outputs.tf new file mode 100644 index 0000000..f447a4f --- /dev/null +++ b/aws/modules/frontend/lambda@edge/outputs.tf @@ -0,0 +1,7 @@ +output "function_name" { + value = aws_lambda_function.api_lambda.function_name +} + +output "invoke_arn" { + value = aws_lambda_function.api_lambda.qualified_arn // needed for Lambda@Edge +} diff --git a/aws/modules/frontend/lambda@edge/variables.tf b/aws/modules/frontend/lambda@edge/variables.tf new file mode 100644 index 0000000..eb5d0c5 --- /dev/null +++ b/aws/modules/frontend/lambda@edge/variables.tf @@ -0,0 +1,52 @@ +variable "function_name" { + type = string + default = "hearchco-ssr-lambda" +} + +# has to correspond to file.function format in the source code +variable "handler" { + type = string + default = "index.handler" +} + +variable "runtime" { + type = string + default = "nodejs20.x" +} + +variable "role" { + type = string +} + +variable "s3_bucket" { + type = string +} + +variable "s3_key" { + type = string +} + +variable "source_code_hash" { + type = string +} + +// since Lambda@Edge doesn't support enviroment variables, it's required to pass them as a part of the function +# variable "environment" { +# type = map(string) +# default = {} +# } + +variable "architectures" { + type = list(string) + default = ["arm64"] +} + +variable "memory_size" { + type = number + default = 128 +} + +variable "timeout" { + type = number + default = 5 +} diff --git a/aws/modules/backend/lambda_iam/versions.tf b/aws/modules/frontend/lambda@edge/versions.tf similarity index 100% rename from aws/modules/backend/lambda_iam/versions.tf rename to aws/modules/frontend/lambda@edge/versions.tf diff --git a/aws/modules/frontend/s3_assets/locals.tf b/aws/modules/frontend/s3_assets/locals.tf new file mode 100644 index 0000000..8bc263a --- /dev/null +++ b/aws/modules/frontend/s3_assets/locals.tf @@ -0,0 +1,9 @@ +data "aws_region" "current" {} +data "aws_caller_identity" "current" {} + +locals { + bucket_name = "${var.bucket_name}-${data.aws_region.current.name}-${data.aws_caller_identity.current.account_id}" + + assets = fileset(var.path, "**/*") + top_level_assets = toset([for asset in local.assets : split("/", asset)[0]]) +} diff --git a/aws/modules/frontend/s3_assets/main.tf b/aws/modules/frontend/s3_assets/main.tf new file mode 100644 index 0000000..75344e4 --- /dev/null +++ b/aws/modules/frontend/s3_assets/main.tf @@ -0,0 +1,39 @@ +resource "aws_s3_bucket" "assets" { + bucket = local.bucket_name +} + +# Ownership +resource "aws_s3_bucket_ownership_controls" "assets" { + bucket = aws_s3_bucket.assets.id + + rule { + object_ownership = "BucketOwnerPreferred" + } +} + +# Visibility +resource "aws_s3_bucket_public_access_block" "assets" { + bucket = aws_s3_bucket.assets.id + block_public_acls = false + block_public_policy = false + ignore_public_acls = false + restrict_public_buckets = false + + depends_on = [aws_s3_bucket_ownership_controls.assets] +} + +resource "aws_s3_bucket_acl" "assets" { + bucket = aws_s3_bucket.assets.id + acl = "public-read" + + depends_on = [aws_s3_bucket_public_access_block.assets] +} + +# Versioning +resource "aws_s3_bucket_versioning" "assets" { + bucket = aws_s3_bucket.assets.id + + versioning_configuration { + status = "Enabled" + } +} diff --git a/aws/modules/frontend/s3_assets/outputs.tf b/aws/modules/frontend/s3_assets/outputs.tf new file mode 100644 index 0000000..d426a80 --- /dev/null +++ b/aws/modules/frontend/s3_assets/outputs.tf @@ -0,0 +1,15 @@ +output "bucket_id" { + value = aws_s3_bucket.assets.id +} + +output "bucket_arn" { + value = aws_s3_bucket.assets.arn +} + +output "assets" { + value = local.assets +} + +output "top_level_assets" { + value = local.top_level_assets +} diff --git a/aws/modules/frontend/s3_assets/upload.tf b/aws/modules/frontend/s3_assets/upload.tf new file mode 100644 index 0000000..c75a146 --- /dev/null +++ b/aws/modules/frontend/s3_assets/upload.tf @@ -0,0 +1,9 @@ +// Upload new file +resource "aws_s3_object" "assets" { + for_each = local.assets + + key = each.key + bucket = aws_s3_bucket.assets.id + source = each.key + source_hash = filebase64sha256(each.key) +} diff --git a/aws/modules/backend/s3/variables.tf b/aws/modules/frontend/s3_assets/variables.tf similarity index 60% rename from aws/modules/backend/s3/variables.tf rename to aws/modules/frontend/s3_assets/variables.tf index 7ced39d..e61deaa 100644 --- a/aws/modules/backend/s3/variables.tf +++ b/aws/modules/frontend/s3_assets/variables.tf @@ -1,10 +1,9 @@ // this will get appended to region name variable "bucket_name" { - type = string - default = "hearchco-api-binary" + type = string } variable "path" { type = string - default = "tmp" + default = "tmp/s3" } diff --git a/aws/modules/frontend/s3_assets/versions.tf b/aws/modules/frontend/s3_assets/versions.tf new file mode 100644 index 0000000..847f2ab --- /dev/null +++ b/aws/modules/frontend/s3_assets/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.5" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/aws/modules/backend/acm/main.tf b/aws/modules/universal/acm/main.tf similarity index 100% rename from aws/modules/backend/acm/main.tf rename to aws/modules/universal/acm/main.tf diff --git a/aws/modules/backend/acm/outputs.tf b/aws/modules/universal/acm/outputs.tf similarity index 100% rename from aws/modules/backend/acm/outputs.tf rename to aws/modules/universal/acm/outputs.tf diff --git a/aws/modules/backend/acm/variables.tf b/aws/modules/universal/acm/variables.tf similarity index 100% rename from aws/modules/backend/acm/variables.tf rename to aws/modules/universal/acm/variables.tf diff --git a/aws/modules/universal/acm/versions.tf b/aws/modules/universal/acm/versions.tf new file mode 100644 index 0000000..847f2ab --- /dev/null +++ b/aws/modules/universal/acm/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.5" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/aws/modules/universal/lambda_iam/locals.tf b/aws/modules/universal/lambda_iam/locals.tf new file mode 100644 index 0000000..7281fdc --- /dev/null +++ b/aws/modules/universal/lambda_iam/locals.tf @@ -0,0 +1,4 @@ +locals { + default_identifiers = toset(var.edge ? ["lambda.amazonaws.com", "edgelambda.amazonaws.com"] : ["lambda.amazonaws.com"]) + identifiers = toset(merge(var.identifiers, local.default_identifiers)) +} diff --git a/aws/modules/backend/lambda_iam/main.tf b/aws/modules/universal/lambda_iam/main.tf similarity index 83% rename from aws/modules/backend/lambda_iam/main.tf rename to aws/modules/universal/lambda_iam/main.tf index 9a07a25..f6215ab 100644 --- a/aws/modules/backend/lambda_iam/main.tf +++ b/aws/modules/universal/lambda_iam/main.tf @@ -5,7 +5,7 @@ data "aws_iam_policy_document" "assume_role" { principals { type = "Service" - identifiers = ["lambda.amazonaws.com"] + identifiers = local.identifiers } actions = ["sts:AssumeRole"] @@ -13,7 +13,7 @@ data "aws_iam_policy_document" "assume_role" { } resource "aws_iam_role" "aws_iam_role_exec_lambda" { - name = "aws-iam-role-exec-lambda" + name = var.role_name assume_role_policy = data.aws_iam_policy_document.assume_role.json } @@ -33,9 +33,9 @@ data "aws_iam_policy_document" "lambda_logging" { } resource "aws_iam_policy" "lambda_logging" { - name = "lambda_logging" + name = var.policy_name path = "/" - description = "IAM policy for logging from a lambda" + description = "IAM policy for logging from a lambda@edge" policy = data.aws_iam_policy_document.lambda_logging.json } diff --git a/aws/modules/backend/lambda_iam/outputs.tf b/aws/modules/universal/lambda_iam/outputs.tf similarity index 100% rename from aws/modules/backend/lambda_iam/outputs.tf rename to aws/modules/universal/lambda_iam/outputs.tf diff --git a/aws/modules/universal/lambda_iam/variables.tf b/aws/modules/universal/lambda_iam/variables.tf new file mode 100644 index 0000000..5322c1f --- /dev/null +++ b/aws/modules/universal/lambda_iam/variables.tf @@ -0,0 +1,17 @@ +variable "role_name" { + type = string +} + +variable "policy_name" { + type = string +} + +variable "identifiers" { + type = set(string) + default = [] +} + +variable "edge" { + type = bool + default = false +} diff --git a/aws/modules/universal/lambda_iam/versions.tf b/aws/modules/universal/lambda_iam/versions.tf new file mode 100644 index 0000000..847f2ab --- /dev/null +++ b/aws/modules/universal/lambda_iam/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.5" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/aws/modules/backend/s3/locals.tf b/aws/modules/universal/s3_source_code/locals.tf similarity index 66% rename from aws/modules/backend/s3/locals.tf rename to aws/modules/universal/s3_source_code/locals.tf index fbda9e6..de2a4b0 100644 --- a/aws/modules/backend/s3/locals.tf +++ b/aws/modules/universal/s3_source_code/locals.tf @@ -3,8 +3,7 @@ data "aws_caller_identity" "current" {} locals { bucket_name = "${var.bucket_name}-${data.aws_region.current.name}-${data.aws_caller_identity.current.account_id}" - binary_name = "bootstrap" - binary_key = "${local.binary_name}.zip" - source_file = "${var.path}/${local.binary_name}" + source_key = "${var.source_name}.zip" + source_file = "${var.path}/${var.source_name}" output_path = "${local.source_file}.zip" } diff --git a/aws/modules/universal/s3_source_code/main.tf b/aws/modules/universal/s3_source_code/main.tf new file mode 100644 index 0000000..d405789 --- /dev/null +++ b/aws/modules/universal/s3_source_code/main.tf @@ -0,0 +1,29 @@ +resource "aws_s3_bucket" "source_code" { + bucket = local.bucket_name +} + +# Ownership +resource "aws_s3_bucket_ownership_controls" "source_code" { + bucket = aws_s3_bucket.source_code.id + + rule { + object_ownership = "BucketOwnerPreferred" + } +} + +# Visibility +resource "aws_s3_bucket_acl" "source_code" { + bucket = aws_s3_bucket.source_code.id + acl = "private" + + depends_on = [aws_s3_bucket_ownership_controls.source_code] +} + +# Versioning +resource "aws_s3_bucket_versioning" "source_code" { + bucket = aws_s3_bucket.source_code.id + + versioning_configuration { + status = "Enabled" + } +} diff --git a/aws/modules/universal/s3_source_code/outputs.tf b/aws/modules/universal/s3_source_code/outputs.tf new file mode 100644 index 0000000..e7ad673 --- /dev/null +++ b/aws/modules/universal/s3_source_code/outputs.tf @@ -0,0 +1,15 @@ +output "bucket_id" { + value = aws_s3_bucket.source_code.id +} + +output "bucket_arn" { + value = aws_s3_bucket.source_code.arn +} + +output "s3_key" { + value = aws_s3_object.source_code.key +} + +output "source_code_hash" { + value = aws_s3_object.source_code.source_hash +} diff --git a/aws/modules/universal/s3_source_code/upload.tf b/aws/modules/universal/s3_source_code/upload.tf new file mode 100644 index 0000000..d811b87 --- /dev/null +++ b/aws/modules/universal/s3_source_code/upload.tf @@ -0,0 +1,13 @@ +// Upload new file +data "archive_file" "source_code" { + type = "zip" + source_file = local.source_file + output_path = local.output_path +} + +resource "aws_s3_object" "source_code" { + key = local.source_key + bucket = aws_s3_bucket.source_code.id + source = data.archive_file.source_code.output_path + source_hash = data.archive_file.source_code.output_base64sha256 +} diff --git a/aws/modules/universal/s3_source_code/variables.tf b/aws/modules/universal/s3_source_code/variables.tf new file mode 100644 index 0000000..af1355a --- /dev/null +++ b/aws/modules/universal/s3_source_code/variables.tf @@ -0,0 +1,18 @@ +// this will get appended to region name +variable "bucket_name" { + type = string +} + +variable "path" { + type = string + default = "tmp" +} + +variable "source_name" { + type = string + + validation { + condition = var.source_name == "bootstrap" || var.source_name == "index.mjs" + error_message = "Only 'bootstrap' or 'index.mjs' are allowed" + } +} diff --git a/aws/modules/backend/s3/versions.tf b/aws/modules/universal/s3_source_code/versions.tf similarity index 100% rename from aws/modules/backend/s3/versions.tf rename to aws/modules/universal/s3_source_code/versions.tf diff --git a/aws/prod/backend/main.tf b/aws/prod/backend/main.tf index e259513..e4abdc6 100644 --- a/aws/prod/backend/main.tf +++ b/aws/prod/backend/main.tf @@ -29,7 +29,10 @@ module "salt" { ### IAM for lambda execution and logging module "lambda_iam" { - source = "../../modules/backend/lambda_iam" + source = "../../modules/universal/lambda_iam" + + role_name = "aws-iam-role-exec-hearchco-api" + policy_name = "hearchco_api_logging" } ## Cloudfront @@ -42,7 +45,7 @@ provider "aws" { ### Certificate for the Cloudfront distribution module "hearchco_cdn_certificate" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_af_south_1.tf b/aws/prod/backend/region_af_south_1.tf index d31cd69..7d9bc8c 100644 --- a/aws/prod/backend/region_af_south_1.tf +++ b/aws/prod/backend/region_af_south_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_af_south_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.af-south-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_af_south_1" { } module "hearchco_certificate_af_south_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_ap_east_1.tf b/aws/prod/backend/region_ap_east_1.tf index 9985366..153578b 100644 --- a/aws/prod/backend/region_ap_east_1.tf +++ b/aws/prod/backend/region_ap_east_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_ap_east_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.ap-east-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_ap_east_1" { } module "hearchco_certificate_ap_east_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_ap_northeast_1.tf b/aws/prod/backend/region_ap_northeast_1.tf index 6e8ee3f..24ae04e 100644 --- a/aws/prod/backend/region_ap_northeast_1.tf +++ b/aws/prod/backend/region_ap_northeast_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_ap_northeast_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.ap-northeast-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_ap_northeast_1" { } module "hearchco_certificate_ap_northeast_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_ap_northeast_2.tf b/aws/prod/backend/region_ap_northeast_2.tf index 1fed28a..d8e8c4e 100644 --- a/aws/prod/backend/region_ap_northeast_2.tf +++ b/aws/prod/backend/region_ap_northeast_2.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_ap_northeast_2" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.ap-northeast-2 @@ -31,7 +33,7 @@ module "hearchco_lambda_ap_northeast_2" { } module "hearchco_certificate_ap_northeast_2" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_ap_south_1.tf b/aws/prod/backend/region_ap_south_1.tf index a992743..6fdbdd7 100644 --- a/aws/prod/backend/region_ap_south_1.tf +++ b/aws/prod/backend/region_ap_south_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_ap_south_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.ap-south-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_ap_south_1" { } module "hearchco_certificate_ap_south_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_ap_southeast_1.tf b/aws/prod/backend/region_ap_southeast_1.tf index 6ac665f..98d8b5e 100644 --- a/aws/prod/backend/region_ap_southeast_1.tf +++ b/aws/prod/backend/region_ap_southeast_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_ap_southeast_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.ap-southeast-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_ap_southeast_1" { } module "hearchco_certificate_ap_southeast_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_ap_southeast_2.tf b/aws/prod/backend/region_ap_southeast_2.tf index 7e8356d..be45f92 100644 --- a/aws/prod/backend/region_ap_southeast_2.tf +++ b/aws/prod/backend/region_ap_southeast_2.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_ap_southeast_2" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.ap-southeast-2 @@ -31,7 +33,7 @@ module "hearchco_lambda_ap_southeast_2" { } module "hearchco_certificate_ap_southeast_2" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_ca_central_1.tf b/aws/prod/backend/region_ca_central_1.tf index bff261d..9859bac 100644 --- a/aws/prod/backend/region_ca_central_1.tf +++ b/aws/prod/backend/region_ca_central_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_ca_central_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.ca-central-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_ca_central_1" { } module "hearchco_certificate_ca_central_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_eu_central_1.tf b/aws/prod/backend/region_eu_central_1.tf index ecfa9ad..f181f3e 100644 --- a/aws/prod/backend/region_eu_central_1.tf +++ b/aws/prod/backend/region_eu_central_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_eu_central_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.eu-central-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_eu_central_1" { } module "hearchco_certificate_eu_central_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_eu_central_2.tf b/aws/prod/backend/region_eu_central_2.tf index b351aa9..64ed3c6 100644 --- a/aws/prod/backend/region_eu_central_2.tf +++ b/aws/prod/backend/region_eu_central_2.tf @@ -11,7 +11,9 @@ provider "aws" { # CURRENTLY THIS REGION DOESN'T SUPPORT HTTP API GATEWAY # module "hearchco_s3_eu_central_2" { -# source = "../../modules/backend/s3" +# source = "../../modules/universal/s3_source_code" +source_name = "bootstrap" +bucket_name = "hearchco-api-binary" # providers = { # aws = aws.eu-central-2 @@ -33,7 +35,7 @@ provider "aws" { # } # module "hearchco_certificate_eu_central_2" { -# source = "../../modules/backend/acm" +# source = "../../modules/universal/acm" # domain_name = local.api_gateway_domain_name # hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_eu_north_1.tf b/aws/prod/backend/region_eu_north_1.tf index 014370e..12c9f50 100644 --- a/aws/prod/backend/region_eu_north_1.tf +++ b/aws/prod/backend/region_eu_north_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_eu_north_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.eu-north-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_eu_north_1" { } module "hearchco_certificate_eu_north_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_eu_south_1.tf b/aws/prod/backend/region_eu_south_1.tf index beae646..44eff1c 100644 --- a/aws/prod/backend/region_eu_south_1.tf +++ b/aws/prod/backend/region_eu_south_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_eu_south_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.eu-south-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_eu_south_1" { } module "hearchco_certificate_eu_south_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_eu_south_2.tf b/aws/prod/backend/region_eu_south_2.tf index 136213e..6f56420 100644 --- a/aws/prod/backend/region_eu_south_2.tf +++ b/aws/prod/backend/region_eu_south_2.tf @@ -11,7 +11,9 @@ provider "aws" { # CURRENTLY THIS REGION DOESN'T SUPPORT HTTP API GATEWAY # module "hearchco_s3_eu_south_2" { -# source = "../../modules/backend/s3" +# source = "../../modules/universal/s3_source_code" +source_name = "bootstrap" +bucket_name = "hearchco-api-binary" # providers = { # aws = aws.eu-south-2 @@ -33,7 +35,7 @@ provider "aws" { # } # module "hearchco_certificate_eu_south_2" { -# source = "../../modules/backend/acm" +# source = "../../modules/universal/acm" # domain_name = local.api_gateway_domain_name # hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_eu_west_1.tf b/aws/prod/backend/region_eu_west_1.tf index 3b1b96b..eadf4ac 100644 --- a/aws/prod/backend/region_eu_west_1.tf +++ b/aws/prod/backend/region_eu_west_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_eu_west_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.eu-west-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_eu_west_1" { } module "hearchco_certificate_eu_west_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_eu_west_2.tf b/aws/prod/backend/region_eu_west_2.tf index 8943093..bcbab55 100644 --- a/aws/prod/backend/region_eu_west_2.tf +++ b/aws/prod/backend/region_eu_west_2.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_eu_west_2" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.eu-west-2 @@ -31,7 +33,7 @@ module "hearchco_lambda_eu_west_2" { } module "hearchco_certificate_eu_west_2" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_eu_west_3.tf b/aws/prod/backend/region_eu_west_3.tf index 0d0b742..9fe43b8 100644 --- a/aws/prod/backend/region_eu_west_3.tf +++ b/aws/prod/backend/region_eu_west_3.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_eu_west_3" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.eu-west-3 @@ -31,7 +33,7 @@ module "hearchco_lambda_eu_west_3" { } module "hearchco_certificate_eu_west_3" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_me_south_1.tf b/aws/prod/backend/region_me_south_1.tf index 84e0cb2..a51fa81 100644 --- a/aws/prod/backend/region_me_south_1.tf +++ b/aws/prod/backend/region_me_south_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_me_south_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.me-south-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_me_south_1" { } module "hearchco_certificate_me_south_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_sa_east_1.tf b/aws/prod/backend/region_sa_east_1.tf index 9208928..49b56b5 100644 --- a/aws/prod/backend/region_sa_east_1.tf +++ b/aws/prod/backend/region_sa_east_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_sa_east_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.sa-east-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_sa_east_1" { } module "hearchco_certificate_sa_east_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_us_east_1.tf b/aws/prod/backend/region_us_east_1.tf index 3398fe6..9e274ad 100644 --- a/aws/prod/backend/region_us_east_1.tf +++ b/aws/prod/backend/region_us_east_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_us_east_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.us-east-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_us_east_1" { } module "hearchco_certificate_us_east_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_us_east_2.tf b/aws/prod/backend/region_us_east_2.tf index d1cd650..58e9a3e 100644 --- a/aws/prod/backend/region_us_east_2.tf +++ b/aws/prod/backend/region_us_east_2.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_us_east_2" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.us-east-2 @@ -31,7 +33,7 @@ module "hearchco_lambda_us_east_2" { } module "hearchco_certificate_us_east_2" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_us_west_1.tf b/aws/prod/backend/region_us_west_1.tf index df1f192..e01c292 100644 --- a/aws/prod/backend/region_us_west_1.tf +++ b/aws/prod/backend/region_us_west_1.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_us_west_1" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.us-west-1 @@ -31,7 +33,7 @@ module "hearchco_lambda_us_west_1" { } module "hearchco_certificate_us_west_1" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/aws/prod/backend/region_us_west_2.tf b/aws/prod/backend/region_us_west_2.tf index 8bce27e..26710fb 100644 --- a/aws/prod/backend/region_us_west_2.tf +++ b/aws/prod/backend/region_us_west_2.tf @@ -9,7 +9,9 @@ provider "aws" { } module "hearchco_s3_us_west_2" { - source = "../../modules/backend/s3" + source = "../../modules/universal/s3_source_code" + source_name = "bootstrap" + bucket_name = "hearchco-api-binary" providers = { aws = aws.us-west-2 @@ -31,7 +33,7 @@ module "hearchco_lambda_us_west_2" { } module "hearchco_certificate_us_west_2" { - source = "../../modules/backend/acm" + source = "../../modules/universal/acm" domain_name = local.api_gateway_domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id diff --git a/todo.md b/todo.md new file mode 100644 index 0000000..2914544 --- /dev/null +++ b/todo.md @@ -0,0 +1,5 @@ +- create lambda or edge function, grant readwrite perm to S3 bucket # why write? +- s3: copy client dir with cache, \_app is versioned +- s3: copy prerendered w/o cache +- behaviors: if edge: attach to cloudfront and use S3 as origin -> else: use lambda as origin +- create 1 behavior for each top level asset file (name) or folder (name/\*) with origin s3 From 7bf0b4d06081e2d684478f50cd0874e1cd95c8b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksa=20Siri=C5=A1ki?= <31509435+aleksasiriski@users.noreply.github.com> Date: Fri, 26 Apr 2024 03:29:15 +0200 Subject: [PATCH 2/5] fix: cloudfront too many cache policies --- aws/dev/frontend/cloudfront.tf | 51 +++++++++++++++++++ aws/dev/frontend/lambda.tf | 39 ++++++++++++++ aws/dev/frontend/locals.tf | 15 ++++++ aws/dev/frontend/main.tf | 27 ++++++++++ aws/dev/frontend/s3.tf | 8 +++ aws/dev/frontend/variables.tf | 9 ++++ .../lambda@edge => dev/frontend}/versions.tf | 0 aws/modules/backend/cloudfront/cache.tf | 4 +- aws/modules/frontend/cloudfront/cache.tf | 37 +++++++++++++- aws/modules/frontend/cloudfront/function.tf | 6 +++ aws/modules/frontend/cloudfront/main.tf | 51 ++++++++++++++++--- .../frontend/cloudfront/route53_records.tf | 8 +-- aws/modules/frontend/cloudfront/variables.tf | 41 +++++++++++++++ .../{env_replacer => env_injection}/main.tf | 4 +- .../outputs.tf | 0 .../variables.tf | 0 .../versions.tf | 0 aws/modules/frontend/lambda@edge/outputs.tf | 7 --- .../{lambda@edge => lambda_edge}/main.tf | 2 +- aws/modules/frontend/lambda_edge/outputs.tf | 7 +++ .../{lambda@edge => lambda_edge}/variables.tf | 2 +- aws/modules/frontend/lambda_edge/versions.tf | 9 ++++ aws/modules/frontend/s3_assets/locals.tf | 16 +++++- aws/modules/frontend/s3_assets/main.tf | 14 +---- aws/modules/frontend/s3_assets/oai.tf | 21 ++++++++ aws/modules/frontend/s3_assets/outputs.tf | 12 ++--- aws/modules/frontend/s3_assets/upload.tf | 11 ++-- aws/modules/frontend/s3_assets/variables.tf | 24 +++++++++ aws/modules/universal/lambda_iam/locals.tf | 2 +- aws/prod/dns/main.tf | 7 --- aws/prod/frontend/cloudfront.tf | 39 ++++++++++++++ aws/prod/frontend/lambda.tf | 39 ++++++++++++++ aws/prod/frontend/locals.tf | 15 ++++++ aws/prod/frontend/main.tf | 27 ++++++++++ aws/prod/frontend/s3.tf | 8 +++ aws/prod/frontend/variables.tf | 9 ++++ aws/prod/frontend/versions.tf | 9 ++++ todo.md | 5 -- 38 files changed, 521 insertions(+), 64 deletions(-) create mode 100644 aws/dev/frontend/cloudfront.tf create mode 100644 aws/dev/frontend/lambda.tf create mode 100644 aws/dev/frontend/locals.tf create mode 100644 aws/dev/frontend/main.tf create mode 100644 aws/dev/frontend/s3.tf create mode 100644 aws/dev/frontend/variables.tf rename aws/{modules/frontend/lambda@edge => dev/frontend}/versions.tf (100%) create mode 100644 aws/modules/frontend/cloudfront/function.tf rename aws/modules/frontend/{env_replacer => env_injection}/main.tf (86%) rename aws/modules/frontend/{env_replacer => env_injection}/outputs.tf (100%) rename aws/modules/frontend/{env_replacer => env_injection}/variables.tf (100%) rename aws/modules/frontend/{env_replacer => env_injection}/versions.tf (100%) delete mode 100644 aws/modules/frontend/lambda@edge/outputs.tf rename aws/modules/frontend/{lambda@edge => lambda_edge}/main.tf (89%) create mode 100644 aws/modules/frontend/lambda_edge/outputs.tf rename aws/modules/frontend/{lambda@edge => lambda_edge}/variables.tf (97%) create mode 100644 aws/modules/frontend/lambda_edge/versions.tf create mode 100644 aws/modules/frontend/s3_assets/oai.tf create mode 100644 aws/prod/frontend/cloudfront.tf create mode 100644 aws/prod/frontend/lambda.tf create mode 100644 aws/prod/frontend/locals.tf create mode 100644 aws/prod/frontend/main.tf create mode 100644 aws/prod/frontend/s3.tf create mode 100644 aws/prod/frontend/variables.tf create mode 100644 aws/prod/frontend/versions.tf delete mode 100644 todo.md diff --git a/aws/dev/frontend/cloudfront.tf b/aws/dev/frontend/cloudfront.tf new file mode 100644 index 0000000..f84ff17 --- /dev/null +++ b/aws/dev/frontend/cloudfront.tf @@ -0,0 +1,51 @@ +module "hearchco_cdn_certificate" { + source = "../../modules/universal/acm" + domain_name = var.domain_name + hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id + + providers = { + aws = aws.us-east-1-cdn + } +} + +module "hearchco_cloudfront" { + source = "../../modules/frontend/cloudfront" + domain_name = var.domain_name + hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id + target_domain_name = module.hearchco_s3_assets.bucket_regional_domain_name + oai_id = module.hearchco_s3_assets.oai + lambda_edge_arn = module.hearchco_lambda_edge.invoke_arn + acm_certificate_arn = module.hearchco_cdn_certificate.cert_arn + price_class = "PriceClass_100" + + top_level_assets = module.hearchco_s3_assets.top_level_assets + + default_cache = { + min_ttl = 0 + default_ttl = 0 + max_ttl = 1 + } + + default_asset_cache = { + min_ttl = 0 + default_ttl = 0 + max_ttl = 1 + } + + paths_cache = { + "/search" = { + min_ttl = 0 + default_ttl = 0 + max_ttl = 1 + }, + "/proxy" = { + min_ttl = 5 + default_ttl = 30 + max_ttl = 60 + }, + } + + providers = { + aws = aws.us-east-1-cdn + } +} diff --git a/aws/dev/frontend/lambda.tf b/aws/dev/frontend/lambda.tf new file mode 100644 index 0000000..d930b7a --- /dev/null +++ b/aws/dev/frontend/lambda.tf @@ -0,0 +1,39 @@ +module "hearchco_env_injection" { + source = "../../modules/frontend/env_injection" + environment = local.environment +} + +module "hearchco_s3_source_code" { + source = "../../modules/universal/s3_source_code" + source_name = "index.mjs" + bucket_name = "hearchco-ssr-function" + path = "tmp/lambda" + + depends_on = [module.hearchco_env_injection] + + providers = { + aws = aws.us-east-1-cdn + } +} + +module "lambda_iam" { + source = "../../modules/universal/lambda_iam" + + role_name = "aws-iam-role-exec-hearchco-ssr" + policy_name = "hearchco_ssr_logging" + edge = true +} + +### Lambda@Edge for SSR (us-east-1 for Cloudfront) +module "hearchco_lambda_edge" { + source = "../../modules/frontend/lambda_edge" + role = module.lambda_iam.role_arn + s3_bucket = module.hearchco_s3_source_code.bucket_id + s3_key = module.hearchco_s3_source_code.s3_key + source_code_hash = module.hearchco_s3_source_code.source_code_hash + # environment = local.environment # Not supported by Lambda@Edge + + providers = { + aws = aws.us-east-1-cdn + } +} diff --git a/aws/dev/frontend/locals.tf b/aws/dev/frontend/locals.tf new file mode 100644 index 0000000..c1e82b7 --- /dev/null +++ b/aws/dev/frontend/locals.tf @@ -0,0 +1,15 @@ +locals { + api_domain_name = "api.${var.domain_name}" + + # Lambda + environment = tomap({ + API_URI = "https://${local.api_domain_name}" + PUBLIC_API_URI = "https://${local.api_domain_name}" + }) + + # Cloudfront + routes = toset([ + "/search", + "/proxy", + ]) +} diff --git a/aws/dev/frontend/main.tf b/aws/dev/frontend/main.tf new file mode 100644 index 0000000..0bff9ab --- /dev/null +++ b/aws/dev/frontend/main.tf @@ -0,0 +1,27 @@ +terraform { + backend "s3" { + profile = "992382822186_TFStateLock" + region = "eu-central-1" + dynamodb_table = "hearchco-shared-tf-state" + bucket = "hearchco-shared-tf-state" + key = "aws/dev/frontend/terraform.tfstate" + encrypt = "true" + } +} + +provider "aws" { + profile = var.aws_profile + region = "eu-central-1" +} + +# us-east-1 region required for Cloudfront's certificate and Lambda@Edge +provider "aws" { + profile = var.aws_profile + region = "us-east-1" + alias = "us-east-1-cdn" +} + +# Route53 DNS +data "aws_route53_zone" "hearchco_route53" { + name = var.domain_name +} diff --git a/aws/dev/frontend/s3.tf b/aws/dev/frontend/s3.tf new file mode 100644 index 0000000..6a679ab --- /dev/null +++ b/aws/dev/frontend/s3.tf @@ -0,0 +1,8 @@ +module "hearchco_s3_assets" { + source = "../../modules/frontend/s3_assets" + bucket_name = "hearchco-assets" + + providers = { + aws = aws.us-east-1-cdn + } +} diff --git a/aws/dev/frontend/variables.tf b/aws/dev/frontend/variables.tf new file mode 100644 index 0000000..038b99a --- /dev/null +++ b/aws/dev/frontend/variables.tf @@ -0,0 +1,9 @@ +variable "aws_profile" { + type = string + default = "891377085136_Admin" +} + +variable "domain_name" { + type = string + default = "dev.hearch.co" +} diff --git a/aws/modules/frontend/lambda@edge/versions.tf b/aws/dev/frontend/versions.tf similarity index 100% rename from aws/modules/frontend/lambda@edge/versions.tf rename to aws/dev/frontend/versions.tf diff --git a/aws/modules/backend/cloudfront/cache.tf b/aws/modules/backend/cloudfront/cache.tf index a7a0dbe..7d7d1aa 100644 --- a/aws/modules/backend/cloudfront/cache.tf +++ b/aws/modules/backend/cloudfront/cache.tf @@ -1,5 +1,5 @@ resource "aws_cloudfront_cache_policy" "default_cache_policy" { - name = "default-cache-policy" + name = "api-default-cache-policy" min_ttl = var.default_cache.min_ttl default_ttl = var.default_cache.default_ttl max_ttl = var.default_cache.max_ttl @@ -34,7 +34,7 @@ resource "aws_cloudfront_cache_policy" "default_cache_policy" { resource "aws_cloudfront_cache_policy" "cache_policy" { for_each = var.paths_cache - name = "cache-policy${replace(each.key, "/", "-")}" + name = "api-cache-policy${replace(each.key, "/", "-")}" min_ttl = each.value.min_ttl default_ttl = each.value.default_ttl max_ttl = each.value.max_ttl diff --git a/aws/modules/frontend/cloudfront/cache.tf b/aws/modules/frontend/cloudfront/cache.tf index a7a0dbe..b2eba07 100644 --- a/aws/modules/frontend/cloudfront/cache.tf +++ b/aws/modules/frontend/cloudfront/cache.tf @@ -1,5 +1,5 @@ resource "aws_cloudfront_cache_policy" "default_cache_policy" { - name = "default-cache-policy" + name = "ssr-default-cache-policy" min_ttl = var.default_cache.min_ttl default_ttl = var.default_cache.default_ttl max_ttl = var.default_cache.max_ttl @@ -31,10 +31,43 @@ resource "aws_cloudfront_cache_policy" "default_cache_policy" { } } +resource "aws_cloudfront_cache_policy" "cache_policy_s3" { + name = "ssr-cache-policy-assets" + min_ttl = var.default_asset_cache.min_ttl + default_ttl = var.default_asset_cache.default_ttl + max_ttl = var.default_asset_cache.max_ttl + + parameters_in_cache_key_and_forwarded_to_origin { + enable_accept_encoding_brotli = true + enable_accept_encoding_gzip = true + + cookies_config { + cookie_behavior = "none" + } + + headers_config { + header_behavior = "whitelist" + headers { + items = [ + "Accept", + "Accept-Language", + "Access-Control-Request-Headers", + "Access-Control-Request-Method", + "Origin", + ] + } + } + + query_strings_config { + query_string_behavior = "none" + } + } +} + resource "aws_cloudfront_cache_policy" "cache_policy" { for_each = var.paths_cache - name = "cache-policy${replace(each.key, "/", "-")}" + name = "ssr-cache-policy${replace(each.key, "/", "-")}" min_ttl = each.value.min_ttl default_ttl = each.value.default_ttl max_ttl = each.value.max_ttl diff --git a/aws/modules/frontend/cloudfront/function.tf b/aws/modules/frontend/cloudfront/function.tf new file mode 100644 index 0000000..7e9afb0 --- /dev/null +++ b/aws/modules/frontend/cloudfront/function.tf @@ -0,0 +1,6 @@ +resource "aws_cloudfront_function" "sveltekit-rewriter" { + name = "sveltekit-rewriter" + runtime = "cloudfront-js-2.0" + publish = true + code = file(var.function_path) +} diff --git a/aws/modules/frontend/cloudfront/main.tf b/aws/modules/frontend/cloudfront/main.tf index 4b4656b..814b635 100644 --- a/aws/modules/frontend/cloudfront/main.tf +++ b/aws/modules/frontend/cloudfront/main.tf @@ -1,8 +1,8 @@ locals { - origin_id = "api-gateway" + origin_id = "s3-origin" } -resource "aws_cloudfront_distribution" "api_gateway_distribution" { +resource "aws_cloudfront_distribution" "sveltekit_distribution" { enabled = true is_ipv6_enabled = true wait_for_deployment = true @@ -13,11 +13,8 @@ resource "aws_cloudfront_distribution" "api_gateway_distribution" { origin_id = local.origin_id domain_name = var.target_domain_name - custom_origin_config { - http_port = 80 - https_port = 443 - origin_protocol_policy = "https-only" - origin_ssl_protocols = ["TLSv1.2"] + s3_origin_config { + origin_access_identity = "origin-access-identity/cloudfront/${var.oai_id}" } } @@ -28,6 +25,35 @@ resource "aws_cloudfront_distribution" "api_gateway_distribution" { viewer_protocol_policy = "redirect-to-https" compress = true cache_policy_id = aws_cloudfront_cache_policy.default_cache_policy.id + + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.sveltekit-rewriter.arn + } + + lambda_function_association { + event_type = "origin-request" + lambda_arn = var.lambda_edge_arn + include_body = true + } + } + + dynamic "ordered_cache_behavior" { + for_each = var.top_level_assets + content { + path_pattern = ordered_cache_behavior.key + allowed_methods = var.allowed_methods_s3 + cached_methods = var.cached_methods_s3 + target_origin_id = local.origin_id + viewer_protocol_policy = "redirect-to-https" + compress = true + cache_policy_id = aws_cloudfront_cache_policy.cache_policy_s3.id + + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.sveltekit-rewriter.arn + } + } } dynamic "ordered_cache_behavior" { @@ -40,6 +66,17 @@ resource "aws_cloudfront_distribution" "api_gateway_distribution" { viewer_protocol_policy = "redirect-to-https" compress = true cache_policy_id = aws_cloudfront_cache_policy.cache_policy[ordered_cache_behavior.key].id + + function_association { + event_type = "viewer-request" + function_arn = aws_cloudfront_function.sveltekit-rewriter.arn + } + + lambda_function_association { + event_type = "origin-request" + lambda_arn = var.lambda_edge_arn + include_body = true + } } } diff --git a/aws/modules/frontend/cloudfront/route53_records.tf b/aws/modules/frontend/cloudfront/route53_records.tf index 6722c6e..56c2ede 100644 --- a/aws/modules/frontend/cloudfront/route53_records.tf +++ b/aws/modules/frontend/cloudfront/route53_records.tf @@ -4,8 +4,8 @@ resource "aws_route53_record" "record" { zone_id = var.hosted_zone_id alias { - name = aws_cloudfront_distribution.api_gateway_distribution.domain_name - zone_id = aws_cloudfront_distribution.api_gateway_distribution.hosted_zone_id + name = aws_cloudfront_distribution.sveltekit_distribution.domain_name + zone_id = aws_cloudfront_distribution.sveltekit_distribution.hosted_zone_id evaluate_target_health = true } } @@ -16,8 +16,8 @@ resource "aws_route53_record" "record_v6" { zone_id = var.hosted_zone_id alias { - name = aws_cloudfront_distribution.api_gateway_distribution.domain_name - zone_id = aws_cloudfront_distribution.api_gateway_distribution.hosted_zone_id + name = aws_cloudfront_distribution.sveltekit_distribution.domain_name + zone_id = aws_cloudfront_distribution.sveltekit_distribution.hosted_zone_id evaluate_target_health = true } } diff --git a/aws/modules/frontend/cloudfront/variables.tf b/aws/modules/frontend/cloudfront/variables.tf index 9feceaa..4d9fcd5 100644 --- a/aws/modules/frontend/cloudfront/variables.tf +++ b/aws/modules/frontend/cloudfront/variables.tf @@ -6,6 +6,19 @@ variable "target_domain_name" { type = string } +variable "oai_id" { + type = string +} + +variable "function_path" { + type = string + default = "tmp/cloudfront/index.js" +} + +variable "lambda_edge_arn" { + type = string +} + variable "price_class" { type = string default = "PriceClass_All" @@ -29,6 +42,16 @@ variable "cached_methods" { default = ["HEAD", "GET"] } +variable "allowed_methods_s3" { + type = set(string) + default = ["HEAD", "GET", "OPTIONS"] +} + +variable "cached_methods_s3" { + type = set(string) + default = ["HEAD", "GET"] +} + variable "default_cache" { type = object({ min_ttl = number @@ -42,6 +65,24 @@ variable "default_cache" { } } +variable "default_asset_cache" { + type = object({ + min_ttl = number + default_ttl = number + max_ttl = number + }) + default = { + min_ttl = 60 // 1 minute + default_ttl = 21600 // 6 hours + max_ttl = 86400 // 1 day + } +} + +variable "top_level_assets" { + type = set(string) + default = [] +} + variable "paths_cache" { type = map(object({ min_ttl = number diff --git a/aws/modules/frontend/env_replacer/main.tf b/aws/modules/frontend/env_injection/main.tf similarity index 86% rename from aws/modules/frontend/env_replacer/main.tf rename to aws/modules/frontend/env_injection/main.tf index 911ee7c..99cf9b5 100644 --- a/aws/modules/frontend/env_replacer/main.tf +++ b/aws/modules/frontend/env_injection/main.tf @@ -10,12 +10,12 @@ locals { resource "local_file" "backup_file" { content = local.source_content - filename = var.source_file + ".bak" + filename = "${var.source_file}.bak" } resource "local_file" "output_file" { content = local.substitude_source_content filename = var.source_file - depends_on = [local_file.original_file] + depends_on = [local_file.backup_file] } diff --git a/aws/modules/frontend/env_replacer/outputs.tf b/aws/modules/frontend/env_injection/outputs.tf similarity index 100% rename from aws/modules/frontend/env_replacer/outputs.tf rename to aws/modules/frontend/env_injection/outputs.tf diff --git a/aws/modules/frontend/env_replacer/variables.tf b/aws/modules/frontend/env_injection/variables.tf similarity index 100% rename from aws/modules/frontend/env_replacer/variables.tf rename to aws/modules/frontend/env_injection/variables.tf diff --git a/aws/modules/frontend/env_replacer/versions.tf b/aws/modules/frontend/env_injection/versions.tf similarity index 100% rename from aws/modules/frontend/env_replacer/versions.tf rename to aws/modules/frontend/env_injection/versions.tf diff --git a/aws/modules/frontend/lambda@edge/outputs.tf b/aws/modules/frontend/lambda@edge/outputs.tf deleted file mode 100644 index f447a4f..0000000 --- a/aws/modules/frontend/lambda@edge/outputs.tf +++ /dev/null @@ -1,7 +0,0 @@ -output "function_name" { - value = aws_lambda_function.api_lambda.function_name -} - -output "invoke_arn" { - value = aws_lambda_function.api_lambda.qualified_arn // needed for Lambda@Edge -} diff --git a/aws/modules/frontend/lambda@edge/main.tf b/aws/modules/frontend/lambda_edge/main.tf similarity index 89% rename from aws/modules/frontend/lambda@edge/main.tf rename to aws/modules/frontend/lambda_edge/main.tf index 48720ea..84bde82 100644 --- a/aws/modules/frontend/lambda@edge/main.tf +++ b/aws/modules/frontend/lambda_edge/main.tf @@ -1,4 +1,4 @@ -resource "aws_lambda_function" "api_lambda" { +resource "aws_lambda_function" "ssr_lambda" { function_name = var.function_name handler = var.handler runtime = var.runtime diff --git a/aws/modules/frontend/lambda_edge/outputs.tf b/aws/modules/frontend/lambda_edge/outputs.tf new file mode 100644 index 0000000..b72ef17 --- /dev/null +++ b/aws/modules/frontend/lambda_edge/outputs.tf @@ -0,0 +1,7 @@ +output "function_name" { + value = aws_lambda_function.ssr_lambda.function_name +} + +output "invoke_arn" { + value = aws_lambda_function.ssr_lambda.qualified_arn // needed for Lambda@Edge +} diff --git a/aws/modules/frontend/lambda@edge/variables.tf b/aws/modules/frontend/lambda_edge/variables.tf similarity index 97% rename from aws/modules/frontend/lambda@edge/variables.tf rename to aws/modules/frontend/lambda_edge/variables.tf index eb5d0c5..3ec6039 100644 --- a/aws/modules/frontend/lambda@edge/variables.tf +++ b/aws/modules/frontend/lambda_edge/variables.tf @@ -38,7 +38,7 @@ variable "source_code_hash" { variable "architectures" { type = list(string) - default = ["arm64"] + default = ["x86_64"] } variable "memory_size" { diff --git a/aws/modules/frontend/lambda_edge/versions.tf b/aws/modules/frontend/lambda_edge/versions.tf new file mode 100644 index 0000000..847f2ab --- /dev/null +++ b/aws/modules/frontend/lambda_edge/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.5" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/aws/modules/frontend/s3_assets/locals.tf b/aws/modules/frontend/s3_assets/locals.tf index 8bc263a..d6872a1 100644 --- a/aws/modules/frontend/s3_assets/locals.tf +++ b/aws/modules/frontend/s3_assets/locals.tf @@ -4,6 +4,18 @@ data "aws_caller_identity" "current" {} locals { bucket_name = "${var.bucket_name}-${data.aws_region.current.name}-${data.aws_caller_identity.current.account_id}" - assets = fileset(var.path, "**/*") - top_level_assets = toset([for asset in local.assets : split("/", asset)[0]]) + assets = fileset(var.path, "**/*") + + assets_with_content_type = { + for asset in local.assets : + asset => lookup(var.content_types, ".${split(".", asset)[length(split(".", asset)) - 1]}", "application/octet-stream") + } + + // Top level files and folders (e.g. index.html, images/*) + top_level_assets = toset([ + for asset in local.assets : + length(split("/", asset)) == 1 ? + "/${split("/", asset)[0]}" : + "/${split("/", asset)[0]}/*" + ]) } diff --git a/aws/modules/frontend/s3_assets/main.tf b/aws/modules/frontend/s3_assets/main.tf index 75344e4..8f0ca81 100644 --- a/aws/modules/frontend/s3_assets/main.tf +++ b/aws/modules/frontend/s3_assets/main.tf @@ -12,21 +12,11 @@ resource "aws_s3_bucket_ownership_controls" "assets" { } # Visibility -resource "aws_s3_bucket_public_access_block" "assets" { - bucket = aws_s3_bucket.assets.id - block_public_acls = false - block_public_policy = false - ignore_public_acls = false - restrict_public_buckets = false - - depends_on = [aws_s3_bucket_ownership_controls.assets] -} - resource "aws_s3_bucket_acl" "assets" { bucket = aws_s3_bucket.assets.id - acl = "public-read" + acl = "private" - depends_on = [aws_s3_bucket_public_access_block.assets] + depends_on = [aws_s3_bucket_ownership_controls.assets] } # Versioning diff --git a/aws/modules/frontend/s3_assets/oai.tf b/aws/modules/frontend/s3_assets/oai.tf new file mode 100644 index 0000000..72366fb --- /dev/null +++ b/aws/modules/frontend/s3_assets/oai.tf @@ -0,0 +1,21 @@ +resource "aws_cloudfront_origin_access_identity" "oai" { + comment = "OAI for accessing S3 bucket" +} + +resource "aws_s3_bucket_policy" "bucket_policy" { + bucket = aws_s3_bucket.assets.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "s3:GetObject" + Effect = "Allow" + Resource = "${aws_s3_bucket.assets.arn}/*" + Principal = { + AWS = "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${aws_cloudfront_origin_access_identity.oai.id}" + } + }, + ] + }) +} diff --git a/aws/modules/frontend/s3_assets/outputs.tf b/aws/modules/frontend/s3_assets/outputs.tf index d426a80..6830a40 100644 --- a/aws/modules/frontend/s3_assets/outputs.tf +++ b/aws/modules/frontend/s3_assets/outputs.tf @@ -1,9 +1,5 @@ -output "bucket_id" { - value = aws_s3_bucket.assets.id -} - -output "bucket_arn" { - value = aws_s3_bucket.assets.arn +output "bucket_regional_domain_name" { + value = aws_s3_bucket.assets.bucket_regional_domain_name } output "assets" { @@ -13,3 +9,7 @@ output "assets" { output "top_level_assets" { value = local.top_level_assets } + +output "oai" { + value = aws_cloudfront_origin_access_identity.oai.id +} diff --git a/aws/modules/frontend/s3_assets/upload.tf b/aws/modules/frontend/s3_assets/upload.tf index c75a146..f4a2a63 100644 --- a/aws/modules/frontend/s3_assets/upload.tf +++ b/aws/modules/frontend/s3_assets/upload.tf @@ -1,9 +1,10 @@ // Upload new file resource "aws_s3_object" "assets" { - for_each = local.assets + for_each = local.assets_with_content_type - key = each.key - bucket = aws_s3_bucket.assets.id - source = each.key - source_hash = filebase64sha256(each.key) + key = each.key + bucket = aws_s3_bucket.assets.id + source = "${var.path}/${each.key}" + source_hash = filebase64sha256("${var.path}/${each.key}") + content_type = each.value } diff --git a/aws/modules/frontend/s3_assets/variables.tf b/aws/modules/frontend/s3_assets/variables.tf index e61deaa..017917f 100644 --- a/aws/modules/frontend/s3_assets/variables.tf +++ b/aws/modules/frontend/s3_assets/variables.tf @@ -7,3 +7,27 @@ variable "path" { type = string default = "tmp/s3" } + +variable "content_types" { + type = map(string) + default = { + ".html" = "text/html" + ".css" = "text/css" + ".js" = "application/javascript" + ".json" = "application/json" + ".png" = "image/png" + ".jpg" = "image/jpeg" + ".jpeg" = "image/jpeg" + ".gif" = "image/gif" + ".svg" = "image/svg+xml" + ".ico" = "image/x-icon" + ".woff" = "font/woff" + ".woff2" = "font/woff2" + ".ttf" = "font/ttf" + ".otf" = "font/otf" + ".eot" = "application/vnd.ms-fontobject" + ".xml" = "application/xml" + ".txt" = "text/plain" + ".webmanifest" = "application/manifest+json" + } +} diff --git a/aws/modules/universal/lambda_iam/locals.tf b/aws/modules/universal/lambda_iam/locals.tf index 7281fdc..a30d9b8 100644 --- a/aws/modules/universal/lambda_iam/locals.tf +++ b/aws/modules/universal/lambda_iam/locals.tf @@ -1,4 +1,4 @@ locals { default_identifiers = toset(var.edge ? ["lambda.amazonaws.com", "edgelambda.amazonaws.com"] : ["lambda.amazonaws.com"]) - identifiers = toset(merge(var.identifiers, local.default_identifiers)) + identifiers = toset(setunion(var.identifiers, local.default_identifiers)) } diff --git a/aws/prod/dns/main.tf b/aws/prod/dns/main.tf index 6ff8925..1174578 100644 --- a/aws/prod/dns/main.tf +++ b/aws/prod/dns/main.tf @@ -19,13 +19,6 @@ module "hearchco_route53" { domain_name = var.domain_name additional_records = [ - // vercel - { - name = "", - type = "A", - ttl = 3600, - records = ["76.76.21.21"] - }, // email { name = "", diff --git a/aws/prod/frontend/cloudfront.tf b/aws/prod/frontend/cloudfront.tf new file mode 100644 index 0000000..9e09ca3 --- /dev/null +++ b/aws/prod/frontend/cloudfront.tf @@ -0,0 +1,39 @@ +module "hearchco_cdn_certificate" { + source = "../../modules/universal/acm" + domain_name = var.domain_name + hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id + + providers = { + aws = aws.us-east-1-cdn + } +} + +module "hearchco_cloudfront" { + source = "../../modules/frontend/cloudfront" + domain_name = var.domain_name + hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id + target_domain_name = module.hearchco_s3_assets.bucket_regional_domain_name + oai_id = module.hearchco_s3_assets.oai + lambda_edge_arn = module.hearchco_lambda_edge.invoke_arn + acm_certificate_arn = module.hearchco_cdn_certificate.cert_arn + price_class = "PriceClass_All" + + top_level_assets = module.hearchco_s3_assets.top_level_assets + + paths_cache = { + "/search" = { + min_ttl = 600 // 10 minutes + default_ttl = 86400 // 1 day + max_ttl = 259200 // 3 days + }, + "/proxy" = { + min_ttl = 86400 // 1 day + default_ttl = 1296000 // 15 days + max_ttl = 2592000 // 30 days + }, + } + + providers = { + aws = aws.us-east-1-cdn + } +} diff --git a/aws/prod/frontend/lambda.tf b/aws/prod/frontend/lambda.tf new file mode 100644 index 0000000..d930b7a --- /dev/null +++ b/aws/prod/frontend/lambda.tf @@ -0,0 +1,39 @@ +module "hearchco_env_injection" { + source = "../../modules/frontend/env_injection" + environment = local.environment +} + +module "hearchco_s3_source_code" { + source = "../../modules/universal/s3_source_code" + source_name = "index.mjs" + bucket_name = "hearchco-ssr-function" + path = "tmp/lambda" + + depends_on = [module.hearchco_env_injection] + + providers = { + aws = aws.us-east-1-cdn + } +} + +module "lambda_iam" { + source = "../../modules/universal/lambda_iam" + + role_name = "aws-iam-role-exec-hearchco-ssr" + policy_name = "hearchco_ssr_logging" + edge = true +} + +### Lambda@Edge for SSR (us-east-1 for Cloudfront) +module "hearchco_lambda_edge" { + source = "../../modules/frontend/lambda_edge" + role = module.lambda_iam.role_arn + s3_bucket = module.hearchco_s3_source_code.bucket_id + s3_key = module.hearchco_s3_source_code.s3_key + source_code_hash = module.hearchco_s3_source_code.source_code_hash + # environment = local.environment # Not supported by Lambda@Edge + + providers = { + aws = aws.us-east-1-cdn + } +} diff --git a/aws/prod/frontend/locals.tf b/aws/prod/frontend/locals.tf new file mode 100644 index 0000000..c1e82b7 --- /dev/null +++ b/aws/prod/frontend/locals.tf @@ -0,0 +1,15 @@ +locals { + api_domain_name = "api.${var.domain_name}" + + # Lambda + environment = tomap({ + API_URI = "https://${local.api_domain_name}" + PUBLIC_API_URI = "https://${local.api_domain_name}" + }) + + # Cloudfront + routes = toset([ + "/search", + "/proxy", + ]) +} diff --git a/aws/prod/frontend/main.tf b/aws/prod/frontend/main.tf new file mode 100644 index 0000000..0cab6dc --- /dev/null +++ b/aws/prod/frontend/main.tf @@ -0,0 +1,27 @@ +terraform { + backend "s3" { + profile = "992382822186_TFStateLock" + region = "eu-central-1" + dynamodb_table = "hearchco-shared-tf-state" + bucket = "hearchco-shared-tf-state" + key = "aws/prod/frontend/terraform.tfstate" + encrypt = "true" + } +} + +provider "aws" { + profile = var.aws_profile + region = "eu-central-1" +} + +# us-east-1 region required for Cloudfront's certificate and Lambda@Edge +provider "aws" { + profile = var.aws_profile + region = "us-east-1" + alias = "us-east-1-cdn" +} + +# Route53 DNS +data "aws_route53_zone" "hearchco_route53" { + name = var.domain_name +} diff --git a/aws/prod/frontend/s3.tf b/aws/prod/frontend/s3.tf new file mode 100644 index 0000000..6a679ab --- /dev/null +++ b/aws/prod/frontend/s3.tf @@ -0,0 +1,8 @@ +module "hearchco_s3_assets" { + source = "../../modules/frontend/s3_assets" + bucket_name = "hearchco-assets" + + providers = { + aws = aws.us-east-1-cdn + } +} diff --git a/aws/prod/frontend/variables.tf b/aws/prod/frontend/variables.tf new file mode 100644 index 0000000..d6cef3a --- /dev/null +++ b/aws/prod/frontend/variables.tf @@ -0,0 +1,9 @@ +variable "aws_profile" { + type = string + default = "730335356331_Admin" +} + +variable "domain_name" { + type = string + default = "hearch.co" +} diff --git a/aws/prod/frontend/versions.tf b/aws/prod/frontend/versions.tf new file mode 100644 index 0000000..847f2ab --- /dev/null +++ b/aws/prod/frontend/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.5" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} diff --git a/todo.md b/todo.md deleted file mode 100644 index 2914544..0000000 --- a/todo.md +++ /dev/null @@ -1,5 +0,0 @@ -- create lambda or edge function, grant readwrite perm to S3 bucket # why write? -- s3: copy client dir with cache, \_app is versioned -- s3: copy prerendered w/o cache -- behaviors: if edge: attach to cloudfront and use S3 as origin -> else: use lambda as origin -- create 1 behavior for each top level asset file (name) or folder (name/\*) with origin s3 From e5314edc7ac443bf09ffc660df965240d57ca45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksa=20Siri=C5=A1ki?= <31509435+aleksasiriski@users.noreply.github.com> Date: Fri, 26 Apr 2024 03:30:27 +0200 Subject: [PATCH 3/5] fix: backend accidental find and replace --- aws/prod/backend/region_eu_central_2.tf | 4 ++-- aws/prod/backend/region_eu_south_2.tf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aws/prod/backend/region_eu_central_2.tf b/aws/prod/backend/region_eu_central_2.tf index 64ed3c6..d28e185 100644 --- a/aws/prod/backend/region_eu_central_2.tf +++ b/aws/prod/backend/region_eu_central_2.tf @@ -12,8 +12,8 @@ provider "aws" { # module "hearchco_s3_eu_central_2" { # source = "../../modules/universal/s3_source_code" -source_name = "bootstrap" -bucket_name = "hearchco-api-binary" +# source_name = "bootstrap" +# bucket_name = "hearchco-api-binary" # providers = { # aws = aws.eu-central-2 diff --git a/aws/prod/backend/region_eu_south_2.tf b/aws/prod/backend/region_eu_south_2.tf index 6f56420..db79d00 100644 --- a/aws/prod/backend/region_eu_south_2.tf +++ b/aws/prod/backend/region_eu_south_2.tf @@ -12,8 +12,8 @@ provider "aws" { # module "hearchco_s3_eu_south_2" { # source = "../../modules/universal/s3_source_code" -source_name = "bootstrap" -bucket_name = "hearchco-api-binary" +# source_name = "bootstrap" +# bucket_name = "hearchco-api-binary" # providers = { # aws = aws.eu-south-2 From c23ecb01f8e75c11f5d8e4b0e3f3b1844ae2ffa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksa=20Siri=C5=A1ki?= <31509435+aleksasiriski@users.noreply.github.com> Date: Fri, 26 Apr 2024 14:33:28 +0200 Subject: [PATCH 4/5] fix: switch to non-regional domain name for assets --- aws/dev/frontend/cloudfront.tf | 2 +- aws/modules/frontend/s3_assets/outputs.tf | 4 ++-- aws/prod/frontend/cloudfront.tf | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aws/dev/frontend/cloudfront.tf b/aws/dev/frontend/cloudfront.tf index f84ff17..eec9bf3 100644 --- a/aws/dev/frontend/cloudfront.tf +++ b/aws/dev/frontend/cloudfront.tf @@ -12,7 +12,7 @@ module "hearchco_cloudfront" { source = "../../modules/frontend/cloudfront" domain_name = var.domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id - target_domain_name = module.hearchco_s3_assets.bucket_regional_domain_name + target_domain_name = module.hearchco_s3_assets.bucket_domain_name oai_id = module.hearchco_s3_assets.oai lambda_edge_arn = module.hearchco_lambda_edge.invoke_arn acm_certificate_arn = module.hearchco_cdn_certificate.cert_arn diff --git a/aws/modules/frontend/s3_assets/outputs.tf b/aws/modules/frontend/s3_assets/outputs.tf index 6830a40..16955ae 100644 --- a/aws/modules/frontend/s3_assets/outputs.tf +++ b/aws/modules/frontend/s3_assets/outputs.tf @@ -1,5 +1,5 @@ -output "bucket_regional_domain_name" { - value = aws_s3_bucket.assets.bucket_regional_domain_name +output "bucket_domain_name" { + value = aws_s3_bucket.assets.bucket_domain_name } output "assets" { diff --git a/aws/prod/frontend/cloudfront.tf b/aws/prod/frontend/cloudfront.tf index 9e09ca3..5fc98c5 100644 --- a/aws/prod/frontend/cloudfront.tf +++ b/aws/prod/frontend/cloudfront.tf @@ -12,7 +12,7 @@ module "hearchco_cloudfront" { source = "../../modules/frontend/cloudfront" domain_name = var.domain_name hosted_zone_id = data.aws_route53_zone.hearchco_route53.zone_id - target_domain_name = module.hearchco_s3_assets.bucket_regional_domain_name + target_domain_name = module.hearchco_s3_assets.bucket_domain_name oai_id = module.hearchco_s3_assets.oai lambda_edge_arn = module.hearchco_lambda_edge.invoke_arn acm_certificate_arn = module.hearchco_cdn_certificate.cert_arn From ad762c706ace4bd175ed744edbc17c4f50702988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksa=20Siri=C5=A1ki?= <31509435+aleksasiriski@users.noreply.github.com> Date: Sat, 27 Apr 2024 00:05:52 +0200 Subject: [PATCH 5/5] fix: few adjustements --- aws/dev/backend/locals.tf | 1 + aws/dev/backend/main.tf | 17 ++++++++----- aws/dev/backend/region_eu_central_1.tf | 2 +- aws/dev/frontend/cloudfront.tf | 24 +++++-------------- aws/dev/frontend/lambda.tf | 4 ++-- aws/dev/frontend/locals.tf | 6 ----- aws/modules/backend/lambda/variables.tf | 2 +- aws/modules/frontend/cloudfront/main.tf | 5 ---- aws/modules/frontend/env_injection/main.tf | 11 ++------- aws/modules/frontend/env_injection/outputs.tf | 10 ++++++-- .../frontend/env_injection/variables.tf | 7 +++++- aws/modules/frontend/lambda_edge/variables.tf | 3 ++- .../universal/s3_source_code/locals.tf | 9 ------- aws/modules/universal/s3_source_code/main.tf | 5 +++- .../universal/s3_source_code/upload.tf | 10 +++++--- .../universal/s3_source_code/variables.tf | 4 ++-- aws/prod/backend/locals.tf | 1 + aws/prod/backend/main.tf | 7 +++++- aws/prod/backend/region_af_south_1.tf | 2 +- aws/prod/backend/region_ap_east_1.tf | 2 +- aws/prod/backend/region_ap_northeast_1.tf | 2 +- aws/prod/backend/region_ap_northeast_2.tf | 2 +- aws/prod/backend/region_ap_south_1.tf | 2 +- aws/prod/backend/region_ap_southeast_1.tf | 2 +- aws/prod/backend/region_ap_southeast_2.tf | 2 +- aws/prod/backend/region_ca_central_1.tf | 2 +- aws/prod/backend/region_eu_central_1.tf | 2 +- aws/prod/backend/region_eu_central_2.tf | 2 +- aws/prod/backend/region_eu_north_1.tf | 2 +- aws/prod/backend/region_eu_south_1.tf | 2 +- aws/prod/backend/region_eu_south_2.tf | 2 +- aws/prod/backend/region_eu_west_1.tf | 2 +- aws/prod/backend/region_eu_west_2.tf | 2 +- aws/prod/backend/region_eu_west_3.tf | 2 +- aws/prod/backend/region_me_south_1.tf | 2 +- aws/prod/backend/region_sa_east_1.tf | 2 +- aws/prod/backend/region_us_east_1.tf | 2 +- aws/prod/backend/region_us_east_2.tf | 2 +- aws/prod/backend/region_us_west_1.tf | 2 +- aws/prod/backend/region_us_west_2.tf | 2 +- aws/prod/frontend/cloudfront.tf | 10 ++++---- aws/prod/frontend/lambda.tf | 6 +++-- aws/prod/frontend/locals.tf | 6 ----- 43 files changed, 91 insertions(+), 103 deletions(-) delete mode 100644 aws/modules/universal/s3_source_code/locals.tf diff --git a/aws/dev/backend/locals.tf b/aws/dev/backend/locals.tf index f495906..2ff5400 100644 --- a/aws/dev/backend/locals.tf +++ b/aws/dev/backend/locals.tf @@ -13,5 +13,6 @@ locals { routes = toset([ "/search", "/proxy", + "/healthz" ]) } diff --git a/aws/dev/backend/main.tf b/aws/dev/backend/main.tf index 200a86b..777c049 100644 --- a/aws/dev/backend/main.tf +++ b/aws/dev/backend/main.tf @@ -65,14 +65,19 @@ module "hearchco_cloudfront" { paths_cache = { "/search" = { - min_ttl = 0 - default_ttl = 0 - max_ttl = 1 + min_ttl = 60 // 1 minute + default_ttl = 600 // 10 minutes + max_ttl = 3600 // 1 hour }, "/proxy" = { - min_ttl = 5 - default_ttl = 30 - max_ttl = 60 + min_ttl = 3600 // 1 hour + default_ttl = 86400 // 1 day + max_ttl = 259200 // 3 days + }, + "/healthz" = { + min_ttl = 0 + default_ttl = 0 + max_ttl = 5 }, } diff --git a/aws/dev/backend/region_eu_central_1.tf b/aws/dev/backend/region_eu_central_1.tf index f181f3e..7b8bd56 100644 --- a/aws/dev/backend/region_eu_central_1.tf +++ b/aws/dev/backend/region_eu_central_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_eu_central_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/dev/frontend/cloudfront.tf b/aws/dev/frontend/cloudfront.tf index eec9bf3..53ac171 100644 --- a/aws/dev/frontend/cloudfront.tf +++ b/aws/dev/frontend/cloudfront.tf @@ -20,28 +20,16 @@ module "hearchco_cloudfront" { top_level_assets = module.hearchco_s3_assets.top_level_assets - default_cache = { - min_ttl = 0 - default_ttl = 0 - max_ttl = 1 - } - - default_asset_cache = { - min_ttl = 0 - default_ttl = 0 - max_ttl = 1 - } - paths_cache = { "/search" = { + min_ttl = 60 // 1 minute + default_ttl = 600 // 10 minutes + max_ttl = 3600 // 1 hour + }, + "/healthz" = { min_ttl = 0 default_ttl = 0 - max_ttl = 1 - }, - "/proxy" = { - min_ttl = 5 - default_ttl = 30 - max_ttl = 60 + max_ttl = 5 }, } diff --git a/aws/dev/frontend/lambda.tf b/aws/dev/frontend/lambda.tf index d930b7a..2bafcf2 100644 --- a/aws/dev/frontend/lambda.tf +++ b/aws/dev/frontend/lambda.tf @@ -5,9 +5,9 @@ module "hearchco_env_injection" { module "hearchco_s3_source_code" { source = "../../modules/universal/s3_source_code" - source_name = "index.mjs" bucket_name = "hearchco-ssr-function" - path = "tmp/lambda" + filename = module.hearchco_env_injection.filename + path = module.hearchco_env_injection.path depends_on = [module.hearchco_env_injection] diff --git a/aws/dev/frontend/locals.tf b/aws/dev/frontend/locals.tf index c1e82b7..34492ee 100644 --- a/aws/dev/frontend/locals.tf +++ b/aws/dev/frontend/locals.tf @@ -6,10 +6,4 @@ locals { API_URI = "https://${local.api_domain_name}" PUBLIC_API_URI = "https://${local.api_domain_name}" }) - - # Cloudfront - routes = toset([ - "/search", - "/proxy", - ]) } diff --git a/aws/modules/backend/lambda/variables.tf b/aws/modules/backend/lambda/variables.tf index 62be3be..ef06e0e 100644 --- a/aws/modules/backend/lambda/variables.tf +++ b/aws/modules/backend/lambda/variables.tf @@ -62,5 +62,5 @@ variable "memory_size" { variable "timeout" { type = number - default = 5 + default = 4 } diff --git a/aws/modules/frontend/cloudfront/main.tf b/aws/modules/frontend/cloudfront/main.tf index 814b635..f594dc9 100644 --- a/aws/modules/frontend/cloudfront/main.tf +++ b/aws/modules/frontend/cloudfront/main.tf @@ -48,11 +48,6 @@ resource "aws_cloudfront_distribution" "sveltekit_distribution" { viewer_protocol_policy = "redirect-to-https" compress = true cache_policy_id = aws_cloudfront_cache_policy.cache_policy_s3.id - - function_association { - event_type = "viewer-request" - function_arn = aws_cloudfront_function.sveltekit-rewriter.arn - } } } diff --git a/aws/modules/frontend/env_injection/main.tf b/aws/modules/frontend/env_injection/main.tf index 99cf9b5..f3ee06e 100644 --- a/aws/modules/frontend/env_injection/main.tf +++ b/aws/modules/frontend/env_injection/main.tf @@ -1,5 +1,5 @@ data "local_file" "source_file" { - filename = var.source_file + filename = "${var.path}/${var.source_file}" } locals { @@ -8,14 +8,7 @@ locals { substitude_source_content = replace(local.source_content, var.placeholder, local.environment_string) } -resource "local_file" "backup_file" { - content = local.source_content - filename = "${var.source_file}.bak" -} - resource "local_file" "output_file" { content = local.substitude_source_content - filename = var.source_file - - depends_on = [local_file.backup_file] + filename = "${var.path}/injected/${var.source_file}" } diff --git a/aws/modules/frontend/env_injection/outputs.tf b/aws/modules/frontend/env_injection/outputs.tf index bd95c06..d3eeabd 100644 --- a/aws/modules/frontend/env_injection/outputs.tf +++ b/aws/modules/frontend/env_injection/outputs.tf @@ -1,3 +1,9 @@ -output "output_file" { - value = local_file.output_file.filename +// last part of the path (divided by /) +output "filename" { + value = split("/", local_file.output_file.filename)[length(split("/", local_file.output_file.filename)) - 1] +} + +// everything except the last part of the path (divided by /) +output "path" { + value = join("/", slice(split("/", local_file.output_file.filename), 0, length(split("/", local_file.output_file.filename)) - 1)) } diff --git a/aws/modules/frontend/env_injection/variables.tf b/aws/modules/frontend/env_injection/variables.tf index 5a0559d..72eca1d 100644 --- a/aws/modules/frontend/env_injection/variables.tf +++ b/aws/modules/frontend/env_injection/variables.tf @@ -1,6 +1,11 @@ +variable "path" { + type = string + default = "tmp/lambda" +} + variable "source_file" { type = string - default = "tmp/lambda/index.mjs" + default = "index.mjs" } variable "placeholder" { diff --git a/aws/modules/frontend/lambda_edge/variables.tf b/aws/modules/frontend/lambda_edge/variables.tf index 3ec6039..69ab53c 100644 --- a/aws/modules/frontend/lambda_edge/variables.tf +++ b/aws/modules/frontend/lambda_edge/variables.tf @@ -41,9 +41,10 @@ variable "architectures" { default = ["x86_64"] } +# SvelteKit used around 114MB and crashed, so it's better to have it at least 160MB variable "memory_size" { type = number - default = 128 + default = 160 } variable "timeout" { diff --git a/aws/modules/universal/s3_source_code/locals.tf b/aws/modules/universal/s3_source_code/locals.tf deleted file mode 100644 index de2a4b0..0000000 --- a/aws/modules/universal/s3_source_code/locals.tf +++ /dev/null @@ -1,9 +0,0 @@ -data "aws_region" "current" {} -data "aws_caller_identity" "current" {} - -locals { - bucket_name = "${var.bucket_name}-${data.aws_region.current.name}-${data.aws_caller_identity.current.account_id}" - source_key = "${var.source_name}.zip" - source_file = "${var.path}/${var.source_name}" - output_path = "${local.source_file}.zip" -} diff --git a/aws/modules/universal/s3_source_code/main.tf b/aws/modules/universal/s3_source_code/main.tf index d405789..d2c1c6c 100644 --- a/aws/modules/universal/s3_source_code/main.tf +++ b/aws/modules/universal/s3_source_code/main.tf @@ -1,5 +1,8 @@ +data "aws_region" "current" {} +data "aws_caller_identity" "current" {} + resource "aws_s3_bucket" "source_code" { - bucket = local.bucket_name + bucket = "${var.bucket_name}-${data.aws_region.current.name}-${data.aws_caller_identity.current.account_id}" } # Ownership diff --git a/aws/modules/universal/s3_source_code/upload.tf b/aws/modules/universal/s3_source_code/upload.tf index d811b87..546f7c9 100644 --- a/aws/modules/universal/s3_source_code/upload.tf +++ b/aws/modules/universal/s3_source_code/upload.tf @@ -1,13 +1,17 @@ // Upload new file data "archive_file" "source_code" { type = "zip" - source_file = local.source_file - output_path = local.output_path + source_file = "${var.path}/${var.filename}" + output_path = "${var.path}/${var.filename}.zip" } resource "aws_s3_object" "source_code" { - key = local.source_key + key = "${var.filename}.zip" bucket = aws_s3_bucket.source_code.id source = data.archive_file.source_code.output_path source_hash = data.archive_file.source_code.output_base64sha256 + + lifecycle { + create_before_destroy = true + } } diff --git a/aws/modules/universal/s3_source_code/variables.tf b/aws/modules/universal/s3_source_code/variables.tf index af1355a..db55d86 100644 --- a/aws/modules/universal/s3_source_code/variables.tf +++ b/aws/modules/universal/s3_source_code/variables.tf @@ -8,11 +8,11 @@ variable "path" { default = "tmp" } -variable "source_name" { +variable "filename" { type = string validation { - condition = var.source_name == "bootstrap" || var.source_name == "index.mjs" + condition = var.filename == "bootstrap" || var.filename == "index.mjs" error_message = "Only 'bootstrap' or 'index.mjs' are allowed" } } diff --git a/aws/prod/backend/locals.tf b/aws/prod/backend/locals.tf index f495906..2ff5400 100644 --- a/aws/prod/backend/locals.tf +++ b/aws/prod/backend/locals.tf @@ -13,5 +13,6 @@ locals { routes = toset([ "/search", "/proxy", + "/healthz" ]) } diff --git a/aws/prod/backend/main.tf b/aws/prod/backend/main.tf index e4abdc6..701453a 100644 --- a/aws/prod/backend/main.tf +++ b/aws/prod/backend/main.tf @@ -65,7 +65,7 @@ module "hearchco_cloudfront" { paths_cache = { "/search" = { - min_ttl = 600 // 10 minutes + min_ttl = 3600 // 1 hour default_ttl = 86400 // 1 day max_ttl = 259200 // 3 days }, @@ -74,6 +74,11 @@ module "hearchco_cloudfront" { default_ttl = 1296000 // 15 days max_ttl = 2592000 // 30 days }, + "/healthz" = { + min_ttl = 0 + default_ttl = 0 + max_ttl = 5 + }, } providers = { diff --git a/aws/prod/backend/region_af_south_1.tf b/aws/prod/backend/region_af_south_1.tf index 7d9bc8c..197e7e8 100644 --- a/aws/prod/backend/region_af_south_1.tf +++ b/aws/prod/backend/region_af_south_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_af_south_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_ap_east_1.tf b/aws/prod/backend/region_ap_east_1.tf index 153578b..d41e4ad 100644 --- a/aws/prod/backend/region_ap_east_1.tf +++ b/aws/prod/backend/region_ap_east_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_ap_east_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_ap_northeast_1.tf b/aws/prod/backend/region_ap_northeast_1.tf index 24ae04e..94b9a56 100644 --- a/aws/prod/backend/region_ap_northeast_1.tf +++ b/aws/prod/backend/region_ap_northeast_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_ap_northeast_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_ap_northeast_2.tf b/aws/prod/backend/region_ap_northeast_2.tf index d8e8c4e..c544502 100644 --- a/aws/prod/backend/region_ap_northeast_2.tf +++ b/aws/prod/backend/region_ap_northeast_2.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_ap_northeast_2" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_ap_south_1.tf b/aws/prod/backend/region_ap_south_1.tf index 6fdbdd7..caa5398 100644 --- a/aws/prod/backend/region_ap_south_1.tf +++ b/aws/prod/backend/region_ap_south_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_ap_south_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_ap_southeast_1.tf b/aws/prod/backend/region_ap_southeast_1.tf index 98d8b5e..54bbdb8 100644 --- a/aws/prod/backend/region_ap_southeast_1.tf +++ b/aws/prod/backend/region_ap_southeast_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_ap_southeast_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_ap_southeast_2.tf b/aws/prod/backend/region_ap_southeast_2.tf index be45f92..02ab14a 100644 --- a/aws/prod/backend/region_ap_southeast_2.tf +++ b/aws/prod/backend/region_ap_southeast_2.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_ap_southeast_2" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_ca_central_1.tf b/aws/prod/backend/region_ca_central_1.tf index 9859bac..b9cc511 100644 --- a/aws/prod/backend/region_ca_central_1.tf +++ b/aws/prod/backend/region_ca_central_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_ca_central_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_eu_central_1.tf b/aws/prod/backend/region_eu_central_1.tf index f181f3e..7b8bd56 100644 --- a/aws/prod/backend/region_eu_central_1.tf +++ b/aws/prod/backend/region_eu_central_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_eu_central_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_eu_central_2.tf b/aws/prod/backend/region_eu_central_2.tf index d28e185..e32f4aa 100644 --- a/aws/prod/backend/region_eu_central_2.tf +++ b/aws/prod/backend/region_eu_central_2.tf @@ -12,7 +12,7 @@ provider "aws" { # module "hearchco_s3_eu_central_2" { # source = "../../modules/universal/s3_source_code" -# source_name = "bootstrap" +# filename = "bootstrap" # bucket_name = "hearchco-api-binary" # providers = { diff --git a/aws/prod/backend/region_eu_north_1.tf b/aws/prod/backend/region_eu_north_1.tf index 12c9f50..98c5ff4 100644 --- a/aws/prod/backend/region_eu_north_1.tf +++ b/aws/prod/backend/region_eu_north_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_eu_north_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_eu_south_1.tf b/aws/prod/backend/region_eu_south_1.tf index 44eff1c..6e16a59 100644 --- a/aws/prod/backend/region_eu_south_1.tf +++ b/aws/prod/backend/region_eu_south_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_eu_south_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_eu_south_2.tf b/aws/prod/backend/region_eu_south_2.tf index db79d00..5c62b8a 100644 --- a/aws/prod/backend/region_eu_south_2.tf +++ b/aws/prod/backend/region_eu_south_2.tf @@ -12,7 +12,7 @@ provider "aws" { # module "hearchco_s3_eu_south_2" { # source = "../../modules/universal/s3_source_code" -# source_name = "bootstrap" +# filename = "bootstrap" # bucket_name = "hearchco-api-binary" # providers = { diff --git a/aws/prod/backend/region_eu_west_1.tf b/aws/prod/backend/region_eu_west_1.tf index eadf4ac..8129e63 100644 --- a/aws/prod/backend/region_eu_west_1.tf +++ b/aws/prod/backend/region_eu_west_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_eu_west_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_eu_west_2.tf b/aws/prod/backend/region_eu_west_2.tf index bcbab55..f04bb46 100644 --- a/aws/prod/backend/region_eu_west_2.tf +++ b/aws/prod/backend/region_eu_west_2.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_eu_west_2" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_eu_west_3.tf b/aws/prod/backend/region_eu_west_3.tf index 9fe43b8..a2c992d 100644 --- a/aws/prod/backend/region_eu_west_3.tf +++ b/aws/prod/backend/region_eu_west_3.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_eu_west_3" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_me_south_1.tf b/aws/prod/backend/region_me_south_1.tf index a51fa81..46d771c 100644 --- a/aws/prod/backend/region_me_south_1.tf +++ b/aws/prod/backend/region_me_south_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_me_south_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_sa_east_1.tf b/aws/prod/backend/region_sa_east_1.tf index 49b56b5..eb558ca 100644 --- a/aws/prod/backend/region_sa_east_1.tf +++ b/aws/prod/backend/region_sa_east_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_sa_east_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_us_east_1.tf b/aws/prod/backend/region_us_east_1.tf index 9e274ad..3421f7f 100644 --- a/aws/prod/backend/region_us_east_1.tf +++ b/aws/prod/backend/region_us_east_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_us_east_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_us_east_2.tf b/aws/prod/backend/region_us_east_2.tf index 58e9a3e..fa87ae6 100644 --- a/aws/prod/backend/region_us_east_2.tf +++ b/aws/prod/backend/region_us_east_2.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_us_east_2" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_us_west_1.tf b/aws/prod/backend/region_us_west_1.tf index e01c292..55cbd8f 100644 --- a/aws/prod/backend/region_us_west_1.tf +++ b/aws/prod/backend/region_us_west_1.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_us_west_1" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/backend/region_us_west_2.tf b/aws/prod/backend/region_us_west_2.tf index 26710fb..b958fd6 100644 --- a/aws/prod/backend/region_us_west_2.tf +++ b/aws/prod/backend/region_us_west_2.tf @@ -10,7 +10,7 @@ provider "aws" { module "hearchco_s3_us_west_2" { source = "../../modules/universal/s3_source_code" - source_name = "bootstrap" + filename = "bootstrap" bucket_name = "hearchco-api-binary" providers = { diff --git a/aws/prod/frontend/cloudfront.tf b/aws/prod/frontend/cloudfront.tf index 5fc98c5..cc37a5f 100644 --- a/aws/prod/frontend/cloudfront.tf +++ b/aws/prod/frontend/cloudfront.tf @@ -22,14 +22,14 @@ module "hearchco_cloudfront" { paths_cache = { "/search" = { - min_ttl = 600 // 10 minutes + min_ttl = 3600 // 1 hour default_ttl = 86400 // 1 day max_ttl = 259200 // 3 days }, - "/proxy" = { - min_ttl = 86400 // 1 day - default_ttl = 1296000 // 15 days - max_ttl = 2592000 // 30 days + "/healthz" = { + min_ttl = 0 + default_ttl = 0 + max_ttl = 5 }, } diff --git a/aws/prod/frontend/lambda.tf b/aws/prod/frontend/lambda.tf index d930b7a..3b2110e 100644 --- a/aws/prod/frontend/lambda.tf +++ b/aws/prod/frontend/lambda.tf @@ -5,9 +5,9 @@ module "hearchco_env_injection" { module "hearchco_s3_source_code" { source = "../../modules/universal/s3_source_code" - source_name = "index.mjs" bucket_name = "hearchco-ssr-function" - path = "tmp/lambda" + filename = module.hearchco_env_injection.filename + path = module.hearchco_env_injection.path depends_on = [module.hearchco_env_injection] @@ -33,6 +33,8 @@ module "hearchco_lambda_edge" { source_code_hash = module.hearchco_s3_source_code.source_code_hash # environment = local.environment # Not supported by Lambda@Edge + depends_on = [module.hearchco_s3_source_code] + providers = { aws = aws.us-east-1-cdn } diff --git a/aws/prod/frontend/locals.tf b/aws/prod/frontend/locals.tf index c1e82b7..34492ee 100644 --- a/aws/prod/frontend/locals.tf +++ b/aws/prod/frontend/locals.tf @@ -6,10 +6,4 @@ locals { API_URI = "https://${local.api_domain_name}" PUBLIC_API_URI = "https://${local.api_domain_name}" }) - - # Cloudfront - routes = toset([ - "/search", - "/proxy", - ]) }