From 83e502a361768816c5aaa4a0123341af3ea43d71 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 12 Mar 2026 14:47:28 +0000 Subject: [PATCH 1/8] from domain_name from engine environment --- .github/workflows/_deploy_lambda.yml | 4 ++-- .github/workflows/deploy_terraform.yml | 1 - infrastructure/terraform/lambda/engine/variables.tf | 4 ---- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/_deploy_lambda.yml b/.github/workflows/_deploy_lambda.yml index 3cef705e..dab98d8b 100644 --- a/.github/workflows/_deploy_lambda.yml +++ b/.github/workflows/_deploy_lambda.yml @@ -119,7 +119,7 @@ jobs: TF_VAR_domain_name: ${{ secrets.TF_VAR_domain_name }} TF_VAR_epc_auth_token: ${{ secrets.TF_VAR_epc_auth_token }} TF_VAR_google_solar_api_key: ${{ secrets.TF_VAR_google_solar_api_key }} - TF_VAR_ordnance_survey_api_key: ${{ secrets.TF_VAR_ordnance_survey_api_key}} + TF_VAR_ordnance_survey_api_key: ${{ secrets.TF_VAR_ordnance_survey_api_key }} run: | ECR_REPO_URL_VAR="" if [[ -n "${{ inputs.ecr_repo }}" ]]; then @@ -155,7 +155,7 @@ jobs: TF_VAR_domain_name: ${{ secrets.TF_VAR_domain_name }} TF_VAR_epc_auth_token: ${{ secrets.TF_VAR_epc_auth_token }} TF_VAR_google_solar_api_key: ${{ secrets.TF_VAR_google_solar_api_key }} - TF_VAR_ordnance_survey_api_key: ${{ secrets.TF_VAR_ordnance_survey_api_key}} + TF_VAR_ordnance_survey_api_key: ${{ secrets.TF_VAR_ordnance_survey_api_key }} run: | EXTRA_VARS="" if [[ -n "${{ inputs.ecr_repo }}" ]]; then diff --git a/.github/workflows/deploy_terraform.yml b/.github/workflows/deploy_terraform.yml index ef927ccb..c2ecc399 100644 --- a/.github/workflows/deploy_terraform.yml +++ b/.github/workflows/deploy_terraform.yml @@ -115,7 +115,6 @@ jobs: TF_VAR_db_port: ${{ secrets.DEV_DB_PORT }} TF_VAR_api_key: ${{ secrets.DEV_API_KEY }} TF_VAR_secret_key: ${{ secrets.DEV_SECRET_KEY }} - TF_VAR_domain_name: ${{ secrets.DEV_DOMAIN_NAME }} TF_VAR_epc_auth_token: ${{ secrets.DEV_EPC_AUTH_TOKEN }} TF_VAR_google_solar_api_key: ${{ secrets.DEV_GOOGLE_SOLAR_API_KEY }} diff --git a/infrastructure/terraform/lambda/engine/variables.tf b/infrastructure/terraform/lambda/engine/variables.tf index 0a74ad5b..bf0a42a2 100644 --- a/infrastructure/terraform/lambda/engine/variables.tf +++ b/infrastructure/terraform/lambda/engine/variables.tf @@ -65,10 +65,6 @@ variable "secret_key" { sensitive = true } -variable "domain_name" { - type = string -} - variable "epc_auth_token" { type = string sensitive = true From 3cadecfe9b9198eac9e01fd530370e6ce6e4f8a2 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 12 Mar 2026 14:47:55 +0000 Subject: [PATCH 2/8] from domain_name from engine environment --- infrastructure/terraform/lambda/engine/main.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/infrastructure/terraform/lambda/engine/main.tf b/infrastructure/terraform/lambda/engine/main.tf index 3f28933b..1f3ce017 100644 --- a/infrastructure/terraform/lambda/engine/main.tf +++ b/infrastructure/terraform/lambda/engine/main.tf @@ -44,7 +44,6 @@ module "lambda" { DB_PORT = var.db_port API_KEY = var.api_key SECRET_KEY = var.secret_key - DOMAIN_NAME = var.domain_name EPC_AUTH_TOKEN = var.epc_auth_token GOOGLE_SOLAR_API_KEY = var.google_solar_api_key From 49e544d10fce938271f8cb8a4415d97c245f9969 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 12 Mar 2026 17:29:47 +0000 Subject: [PATCH 3/8] add cloudfront for domain setting --- .../terraform/lambda/engine/variables.tf | 4 + .../terraform/lambda/fast-api/main.tf | 9 ++ .../terraform/lambda/fast-api/variables.tf | 6 +- .../terraform/modules/cloudfront-api/main.tf | 82 +++++++++++++++++++ .../modules/cloudfront-api/outputs.tf | 7 ++ .../modules/cloudfront-api/variables.tf | 9 ++ .../lambda_with_api_gateway/outputs.tf | 8 ++ 7 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 infrastructure/terraform/modules/cloudfront-api/main.tf create mode 100644 infrastructure/terraform/modules/cloudfront-api/outputs.tf create mode 100644 infrastructure/terraform/modules/cloudfront-api/variables.tf diff --git a/infrastructure/terraform/lambda/engine/variables.tf b/infrastructure/terraform/lambda/engine/variables.tf index bf0a42a2..585bce2a 100644 --- a/infrastructure/terraform/lambda/engine/variables.tf +++ b/infrastructure/terraform/lambda/engine/variables.tf @@ -81,4 +81,8 @@ locals { output "resolved_image_uri" { value = local.image_uri +} + +variable "domain_name" { + description = "Full domain name for API" } \ No newline at end of file diff --git a/infrastructure/terraform/lambda/fast-api/main.tf b/infrastructure/terraform/lambda/fast-api/main.tf index 1d5224ea..ad22a9b6 100644 --- a/infrastructure/terraform/lambda/fast-api/main.tf +++ b/infrastructure/terraform/lambda/fast-api/main.tf @@ -63,6 +63,8 @@ module "fastapi" { artifact_bucket = data.terraform_remote_state.shared.outputs.ara_fast_api_state_bucket requirements_file = "${path.root}/../../../../backend/app/requirements/requirements.txt" + domain_name = var.domain_name + # domain_name = "api.${var.domain_name}" # certificate_arn = data.aws_ssm_parameter.certificate_arn.value # route53_zone_id = data.aws_route53_zone.this.zone_id @@ -131,4 +133,11 @@ resource "aws_iam_role_policy_attachment" "fastapi_sqs_send" { resource "aws_iam_role_policy_attachment" "fastapi_s3_read_and_write" { role = module.fastapi.role_name policy_arn = data.terraform_remote_state.shared.outputs.fast_api_s3_read_and_write_arn +} + +module "fastapi_cdn" { + source = "../../modules/cloudfront-api" + + domain_name = var.domain_name + api_domain_name = module.fastapi.api_endpoint } \ No newline at end of file diff --git a/infrastructure/terraform/lambda/fast-api/variables.tf b/infrastructure/terraform/lambda/fast-api/variables.tf index d329e0ca..a3157590 100644 --- a/infrastructure/terraform/lambda/fast-api/variables.tf +++ b/infrastructure/terraform/lambda/fast-api/variables.tf @@ -29,9 +29,9 @@ variable "secret_key" { sensitive = true } -# variable "domain_name" { -# type = string -# } +variable "domain_name" { + type = string +} variable "epc_auth_token" { type = string diff --git a/infrastructure/terraform/modules/cloudfront-api/main.tf b/infrastructure/terraform/modules/cloudfront-api/main.tf new file mode 100644 index 00000000..00139de3 --- /dev/null +++ b/infrastructure/terraform/modules/cloudfront-api/main.tf @@ -0,0 +1,82 @@ +############################################ +# ACM certificate +############################################ +resource "aws_acm_certificate" "this" { + domain_name = var.domain_name + validation_method = "DNS" + + lifecycle { + create_before_destroy = true + } +} + +############################################ +# CloudFront distribution +############################################ +resource "aws_cloudfront_distribution" "this" { + + enabled = true + + aliases = [var.domain_name] + + origin { + domain_name = var.api_domain_name + origin_id = "api-gateway" + + custom_origin_config { + http_port = 80 + https_port = 443 + origin_protocol_policy = "https-only" + origin_ssl_protocols = ["TLSv1.2"] + } + } + + default_cache_behavior { + + target_origin_id = "api-gateway" + + viewer_protocol_policy = "redirect-to-https" + compress = true + + allowed_methods = [ + "GET", + "HEAD", + "OPTIONS", + "PUT", + "POST", + "PATCH", + "DELETE" + ] + + cached_methods = [ + "GET", + "HEAD" + ] + + forwarded_values { + query_string = true + headers = ["*"] + + cookies { + forward = "all" + } + } + + min_ttl = 0 + default_ttl = 0 + max_ttl = 0 + } + + price_class = "PriceClass_100" + + restrictions { + geo_restriction { + restriction_type = "none" + } + } + + viewer_certificate { + acm_certificate_arn = aws_acm_certificate.this.arn + ssl_support_method = "sni-only" + } +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/cloudfront-api/outputs.tf b/infrastructure/terraform/modules/cloudfront-api/outputs.tf new file mode 100644 index 00000000..f7c7e907 --- /dev/null +++ b/infrastructure/terraform/modules/cloudfront-api/outputs.tf @@ -0,0 +1,7 @@ +output "cloudfront_domain_name" { + value = aws_cloudfront_distribution.this.domain_name +} + +output "certificate_validation_records" { + value = aws_acm_certificate.this.domain_validation_options +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/cloudfront-api/variables.tf b/infrastructure/terraform/modules/cloudfront-api/variables.tf new file mode 100644 index 00000000..b058194f --- /dev/null +++ b/infrastructure/terraform/modules/cloudfront-api/variables.tf @@ -0,0 +1,9 @@ +variable "domain_name" { + description = "Public domain name for the API (e.g. api.dev.domna.homes)" + type = string +} + +variable "api_domain_name" { + description = "API Gateway domain (execute-api)" + type = string +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/lambda_with_api_gateway/outputs.tf b/infrastructure/terraform/modules/lambda_with_api_gateway/outputs.tf index 9ced7c8b..2d7af141 100644 --- a/infrastructure/terraform/modules/lambda_with_api_gateway/outputs.tf +++ b/infrastructure/terraform/modules/lambda_with_api_gateway/outputs.tf @@ -6,6 +6,14 @@ output "api_endpoint" { value = aws_apigatewayv2_stage.this.invoke_url } +output "cloudfront_domain" { + value = aws_cloudfront_distribution.api.domain_name +} + +output "certificate_validation_records" { + value = aws_acm_certificate.this.domain_validation_options +} + # output "custom_domain_endpoint" { # value = var.domain_name != null ? "https://${var.domain_name}" : null # } \ No newline at end of file From 6e05bd235250428627d93eab0adbc0269dc96de4 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 12 Mar 2026 17:31:59 +0000 Subject: [PATCH 4/8] delete unused stuff --- .../terraform/lambda/engine/variables.tf | 4 --- .../terraform/lambda/fast-api/main.tf | 6 +--- .../modules/lambda_with_api_gateway/main.tf | 34 ------------------- 3 files changed, 1 insertion(+), 43 deletions(-) diff --git a/infrastructure/terraform/lambda/engine/variables.tf b/infrastructure/terraform/lambda/engine/variables.tf index 585bce2a..bf0a42a2 100644 --- a/infrastructure/terraform/lambda/engine/variables.tf +++ b/infrastructure/terraform/lambda/engine/variables.tf @@ -81,8 +81,4 @@ locals { output "resolved_image_uri" { value = local.image_uri -} - -variable "domain_name" { - description = "Full domain name for API" } \ No newline at end of file diff --git a/infrastructure/terraform/lambda/fast-api/main.tf b/infrastructure/terraform/lambda/fast-api/main.tf index ad22a9b6..84880188 100644 --- a/infrastructure/terraform/lambda/fast-api/main.tf +++ b/infrastructure/terraform/lambda/fast-api/main.tf @@ -63,11 +63,7 @@ module "fastapi" { artifact_bucket = data.terraform_remote_state.shared.outputs.ara_fast_api_state_bucket requirements_file = "${path.root}/../../../../backend/app/requirements/requirements.txt" - domain_name = var.domain_name - - # domain_name = "api.${var.domain_name}" - # certificate_arn = data.aws_ssm_parameter.certificate_arn.value - # route53_zone_id = data.aws_route53_zone.this.zone_id + domain_name = "api.${var.domain_name}" environment = { ENVIRONMENT = var.stage diff --git a/infrastructure/terraform/modules/lambda_with_api_gateway/main.tf b/infrastructure/terraform/modules/lambda_with_api_gateway/main.tf index f33f8d5b..b1ee3b75 100644 --- a/infrastructure/terraform/modules/lambda_with_api_gateway/main.tf +++ b/infrastructure/terraform/modules/lambda_with_api_gateway/main.tf @@ -90,37 +90,3 @@ resource "aws_lambda_permission" "apigw_invoke" { principal = "apigateway.amazonaws.com" source_arn = "${aws_apigatewayv2_api.this.execution_arn}/*/*" } - -############################################ -# Custom domain -############################################ -# resource "aws_apigatewayv2_domain_name" "this" { -# count = var.domain_name != null ? 1 : 0 -# domain_name = var.domain_name - -# domain_name_configuration { -# certificate_arn = var.certificate_arn -# endpoint_type = "REGIONAL" -# security_policy = "TLS_1_2" -# } -# } - -# resource "aws_apigatewayv2_api_mapping" "this" { -# count = var.domain_name != null ? 1 : 0 -# api_id = aws_apigatewayv2_api.this.id -# domain_name = aws_apigatewayv2_domain_name.this[0].id -# stage = aws_apigatewayv2_stage.this.id -# } - -# resource "aws_route53_record" "this" { -# count = var.domain_name != null ? 1 : 0 -# name = aws_apigatewayv2_domain_name.this[0].domain_name -# type = "A" -# zone_id = var.route53_zone_id - -# alias { -# name = aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].target_domain_name -# zone_id = aws_apigatewayv2_domain_name.this[0].domain_name_configuration[0].hosted_zone_id -# evaluate_target_health = false -# } -# } \ No newline at end of file From aac9b784f38972771d39e92327998672f87aebed Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 12 Mar 2026 17:37:12 +0000 Subject: [PATCH 5/8] use new domain from github secrets --- .github/workflows/deploy_terraform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy_terraform.yml b/.github/workflows/deploy_terraform.yml index c2ecc399..98fd5324 100644 --- a/.github/workflows/deploy_terraform.yml +++ b/.github/workflows/deploy_terraform.yml @@ -342,7 +342,7 @@ jobs: TF_VAR_db_port: ${{ secrets.DEV_DB_PORT }} TF_VAR_api_key: ${{ secrets.FASTAPI_API_KEY }} TF_VAR_secret_key: ${{ secrets.NEXTAUTH_SECRET }} - TF_VAR_domain_name: ${{ secrets.DEV_DOMAIN_NAME }} + TF_VAR_domain_name: ${{ secrets.ARA_DEV_DOMAIN_NAME }} TF_VAR_epc_auth_token: ${{ secrets.DEV_EPC_AUTH_TOKEN }} TF_VAR_google_solar_api_key: ${{ secrets.DEV_GOOGLE_SOLAR_API_KEY }} From b7bee7486c5611b5b95bafd702018569f88976a5 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Fri, 13 Mar 2026 09:51:48 +0000 Subject: [PATCH 6/8] deploy cdn as its own job, depending on fastapi --- .github/workflows/deploy_terraform.yml | 17 +++ infrastructure/terraform/cdn/main.tf | 54 ++++++++ infrastructure/terraform/cdn/outputs.tf | 3 + infrastructure/terraform/cdn/variables.tf | 7 + .../terraform/lambda/fast-api/main.tf | 7 - .../terraform/modules/cloudfront-api/main.tf | 82 ----------- .../modules/cloudfront-api/outputs.tf | 7 - .../modules/cloudfront-api/variables.tf | 9 -- .../terraform/modules/cloudfront/main.tf | 129 ++++++++++++++---- .../terraform/modules/cloudfront/variables.tf | 33 ++--- infrastructure/terraform/shared/main.tf | 28 ++-- 11 files changed, 216 insertions(+), 160 deletions(-) create mode 100644 infrastructure/terraform/cdn/main.tf create mode 100644 infrastructure/terraform/cdn/outputs.tf create mode 100644 infrastructure/terraform/cdn/variables.tf delete mode 100644 infrastructure/terraform/modules/cloudfront-api/main.tf delete mode 100644 infrastructure/terraform/modules/cloudfront-api/outputs.tf delete mode 100644 infrastructure/terraform/modules/cloudfront-api/variables.tf diff --git a/.github/workflows/deploy_terraform.yml b/.github/workflows/deploy_terraform.yml index 98fd5324..8e2c484d 100644 --- a/.github/workflows/deploy_terraform.yml +++ b/.github/workflows/deploy_terraform.yml @@ -346,3 +346,20 @@ jobs: TF_VAR_epc_auth_token: ${{ secrets.DEV_EPC_AUTH_TOKEN }} TF_VAR_google_solar_api_key: ${{ secrets.DEV_GOOGLE_SOLAR_API_KEY }} + # ============================================================ + # Deploy Cloudfront CDN + # ============================================================ + cloudfront_cdn: + needs: [determine_stage, fast_api_lambda] + uses: ./.github/workflows/_deploy_lambda.yml + with: + lambda_name: ara_cdn + lambda_path: infrastructure/terraform/cdn + stage: ${{ needs.determine_stage.outputs.stage }} + terraform_apply: ${{ needs.determine_stage.outputs.terraform_apply }} + secrets: + AWS_ACCESS_KEY_ID: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }} + AWS_REGION: ${{ secrets.DEV_AWS_REGION }} + TF_VAR_domain_name: ${{ secrets.ARA_DEV_DOMAIN_NAME }} + diff --git a/infrastructure/terraform/cdn/main.tf b/infrastructure/terraform/cdn/main.tf new file mode 100644 index 00000000..29abe6e4 --- /dev/null +++ b/infrastructure/terraform/cdn/main.tf @@ -0,0 +1,54 @@ +############################################ +# Load Shared Terraform State +############################################ +data "terraform_remote_state" "shared" { + backend = "s3" + config = { + bucket = "assessment-model-terraform-state" + key = "env:/${var.stage}/terraform.tfstate" + region = "eu-west-2" + } +} + +############################################ +# Load FastAPI Terraform State +############################################ +data "terraform_remote_state" "fast_api" { + backend = "s3" + config = { + bucket = "assessment-model-terraform-state" + key = "env:/${var.stage}/terraform.tfstate" + region = "eu-west-2" + } +} + +############################################ +# CloudFront for API +############################################ +module "cdn" { + source = "../modules/cloudfront" + + aliases = ["domna.homes", "api.dev.domna.homes"] + + origins = [ + # ---- S3 ---- + { + origin_type = "s3" + origin_domain_name = data.terraform_remote_state.shared.outputs.retrofit_datalake_bucket_domain_name + origin_id = "s3-origin" + bucket_id = data.terraform_remote_state.shared.outputs.retrofit_datalake_bucket_id + bucket_arn = data.terraform_remote_state.shared.outputs.retrofit_datalake_bucket_arn + }, + + # ---- API Gateway ---- + { + origin_type = "api" + origin_domain_name = replace( + data.terraform_remote_state.fast_api.outputs.api_endpoint, + "https://", + "" + ) + origin_id = "api-origin" + } + ] +} \ No newline at end of file diff --git a/infrastructure/terraform/cdn/outputs.tf b/infrastructure/terraform/cdn/outputs.tf new file mode 100644 index 00000000..7c684377 --- /dev/null +++ b/infrastructure/terraform/cdn/outputs.tf @@ -0,0 +1,3 @@ +output "cloudfront_domain_name" { + value = module.api_cdn.cloudfront_domain_name +} \ No newline at end of file diff --git a/infrastructure/terraform/cdn/variables.tf b/infrastructure/terraform/cdn/variables.tf new file mode 100644 index 00000000..6fe0073b --- /dev/null +++ b/infrastructure/terraform/cdn/variables.tf @@ -0,0 +1,7 @@ +variable "stage" { + type = string +} + +variable "domain_name" { + type = string +} \ No newline at end of file diff --git a/infrastructure/terraform/lambda/fast-api/main.tf b/infrastructure/terraform/lambda/fast-api/main.tf index 84880188..5e8d2b3b 100644 --- a/infrastructure/terraform/lambda/fast-api/main.tf +++ b/infrastructure/terraform/lambda/fast-api/main.tf @@ -129,11 +129,4 @@ resource "aws_iam_role_policy_attachment" "fastapi_sqs_send" { resource "aws_iam_role_policy_attachment" "fastapi_s3_read_and_write" { role = module.fastapi.role_name policy_arn = data.terraform_remote_state.shared.outputs.fast_api_s3_read_and_write_arn -} - -module "fastapi_cdn" { - source = "../../modules/cloudfront-api" - - domain_name = var.domain_name - api_domain_name = module.fastapi.api_endpoint } \ No newline at end of file diff --git a/infrastructure/terraform/modules/cloudfront-api/main.tf b/infrastructure/terraform/modules/cloudfront-api/main.tf deleted file mode 100644 index 00139de3..00000000 --- a/infrastructure/terraform/modules/cloudfront-api/main.tf +++ /dev/null @@ -1,82 +0,0 @@ -############################################ -# ACM certificate -############################################ -resource "aws_acm_certificate" "this" { - domain_name = var.domain_name - validation_method = "DNS" - - lifecycle { - create_before_destroy = true - } -} - -############################################ -# CloudFront distribution -############################################ -resource "aws_cloudfront_distribution" "this" { - - enabled = true - - aliases = [var.domain_name] - - origin { - domain_name = var.api_domain_name - origin_id = "api-gateway" - - custom_origin_config { - http_port = 80 - https_port = 443 - origin_protocol_policy = "https-only" - origin_ssl_protocols = ["TLSv1.2"] - } - } - - default_cache_behavior { - - target_origin_id = "api-gateway" - - viewer_protocol_policy = "redirect-to-https" - compress = true - - allowed_methods = [ - "GET", - "HEAD", - "OPTIONS", - "PUT", - "POST", - "PATCH", - "DELETE" - ] - - cached_methods = [ - "GET", - "HEAD" - ] - - forwarded_values { - query_string = true - headers = ["*"] - - cookies { - forward = "all" - } - } - - min_ttl = 0 - default_ttl = 0 - max_ttl = 0 - } - - price_class = "PriceClass_100" - - restrictions { - geo_restriction { - restriction_type = "none" - } - } - - viewer_certificate { - acm_certificate_arn = aws_acm_certificate.this.arn - ssl_support_method = "sni-only" - } -} \ No newline at end of file diff --git a/infrastructure/terraform/modules/cloudfront-api/outputs.tf b/infrastructure/terraform/modules/cloudfront-api/outputs.tf deleted file mode 100644 index f7c7e907..00000000 --- a/infrastructure/terraform/modules/cloudfront-api/outputs.tf +++ /dev/null @@ -1,7 +0,0 @@ -output "cloudfront_domain_name" { - value = aws_cloudfront_distribution.this.domain_name -} - -output "certificate_validation_records" { - value = aws_acm_certificate.this.domain_validation_options -} \ No newline at end of file diff --git a/infrastructure/terraform/modules/cloudfront-api/variables.tf b/infrastructure/terraform/modules/cloudfront-api/variables.tf deleted file mode 100644 index b058194f..00000000 --- a/infrastructure/terraform/modules/cloudfront-api/variables.tf +++ /dev/null @@ -1,9 +0,0 @@ -variable "domain_name" { - description = "Public domain name for the API (e.g. api.dev.domna.homes)" - type = string -} - -variable "api_domain_name" { - description = "API Gateway domain (execute-api)" - type = string -} \ No newline at end of file diff --git a/infrastructure/terraform/modules/cloudfront/main.tf b/infrastructure/terraform/modules/cloudfront/main.tf index 281ff09f..6fa1331e 100644 --- a/infrastructure/terraform/modules/cloudfront/main.tf +++ b/infrastructure/terraform/modules/cloudfront/main.tf @@ -1,65 +1,146 @@ -resource "aws_cloudfront_distribution" "s3_distribution" { - origin { - domain_name = var.bucket_domain_name - origin_id = "S3-${var.bucket_name}" +############################################ +# CloudFront Distribution +############################################ - s3_origin_config { - origin_access_identity = aws_cloudfront_origin_access_identity.oai.cloudfront_access_identity_path +resource "aws_cloudfront_distribution" "this" { + + ########################################## + # Origins + ########################################## + + dynamic "origin" { + for_each = { for o in var.origins : o.origin_id => o } + + content { + domain_name = origin.value.origin_domain_name + origin_id = origin.value.origin_id + + ###################################### + # S3 Origin + ###################################### + dynamic "s3_origin_config" { + for_each = origin.value.origin_type == "s3" ? [1] : [] + + content { + origin_access_identity = + aws_cloudfront_origin_access_identity.oai[origin.key] + .cloudfront_access_identity_path + } + } + + ###################################### + # API Gateway Origin + ###################################### + dynamic "custom_origin_config" { + for_each = origin.value.origin_type == "api" ? [1] : [] + + content { + http_port = 80 + https_port = 443 + origin_protocol_policy = "https-only" + origin_ssl_protocols = ["TLSv1.2"] + } + } } } enabled = true + aliases = var.aliases + + ########################################## + # Default Cache Behavior + ########################################## default_cache_behavior { - allowed_methods = ["GET", "HEAD"] - cached_methods = ["GET", "HEAD"] - target_origin_id = "S3-${var.bucket_name}" + target_origin_id = var.origins[0].origin_id + viewer_protocol_policy = "redirect-to-https" - compress = true + + allowed_methods = [ + "GET", + "HEAD" + ] + + cached_methods = [ + "GET", + "HEAD" + ] forwarded_values { - query_string = false + query_string = true + headers = ["*"] + cookies { - forward = "none" + forward = "all" } } - min_ttl = 0 - default_ttl = 86400 - max_ttl = 31536000 + compress = true + min_ttl = 0 + default_ttl = 3600 + max_ttl = 86400 } price_class = "PriceClass_All" + ########################################## + # Geo Restrictions + ########################################## + restrictions { geo_restriction { restriction_type = "none" } } + ########################################## + # SSL Certificate + ########################################## + viewer_certificate { - cloudfront_default_certificate = true + acm_certificate_arn = var.acm_certificate_arn + ssl_support_method = "sni-only" + cloudfront_default_certificate = var.acm_certificate_arn == null } } +############################################ +# Origin Access Identities (S3 only) +############################################ + resource "aws_cloudfront_origin_access_identity" "oai" { - comment = "OAI for ${var.bucket_name}" + for_each = { + for o in var.origins : o.origin_id => o + if o.origin_type == "s3" + } + + comment = "OAI for ${each.key}" } +############################################ +# S3 Bucket Policy (S3 only) +############################################ + resource "aws_s3_bucket_policy" "bucket_policy" { - bucket = var.bucket_id + for_each = { + for o in var.origins : o.origin_id => o + if o.origin_type == "s3" + } + + bucket = each.value.bucket_id policy = jsonencode({ - Version = "2012-10-17" + Version = "2012-10-17" Statement = [ { - Effect = "Allow" + Effect = "Allow" Principal = { - AWS = "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${aws_cloudfront_origin_access_identity.oai.id}" + AWS = aws_cloudfront_origin_access_identity.oai[each.key] + .iam_arn } Action = "s3:GetObject" - Resource = "${var.bucket_arn}/*" - }, + Resource = "${each.value.bucket_arn}/*" + } ] }) -} +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/cloudfront/variables.tf b/infrastructure/terraform/modules/cloudfront/variables.tf index 88f770a8..92ba2347 100644 --- a/infrastructure/terraform/modules/cloudfront/variables.tf +++ b/infrastructure/terraform/modules/cloudfront/variables.tf @@ -1,24 +1,19 @@ -variable "bucket_name" { - description = "The name of the bucket" - type = string +variable "origins" { + type = list(object({ + origin_type = string # "s3" or "api" + origin_domain_name = string + origin_id = string + + bucket_id = optional(string) + bucket_arn = optional(string) + })) } -variable "stage" { - description = "The deployment stage" - type = string +variable "aliases" { + type = list(string) } -variable "bucket_id" { - description = "The ID of the S3 bucket" - type = string -} - -variable "bucket_arn" { - description = "The ARN of the S3 bucket" - type = string -} - -variable "bucket_domain_name" { - description = "The regional domain name of the S3 bucket" - type = string +variable "acm_certificate_arn" { + type = string + default = null } \ No newline at end of file diff --git a/infrastructure/terraform/shared/main.tf b/infrastructure/terraform/shared/main.tf index 0a6dfe3f..1de2031f 100644 --- a/infrastructure/terraform/shared/main.tf +++ b/infrastructure/terraform/shared/main.tf @@ -127,6 +127,22 @@ module "s3" { allowed_origins = var.allowed_origins } +output "retrofit_datalake_bucket_id" { + value = module.s3.bucket_id +} + +output "retrofit_datalake_bucket_arn" { + value = module.s3.bucket_arn +} + +output "retrofit_datalake_bucket_domain_name" { + value = module.s3.bucket_domain_name +} + +output "retrofit_datalake_bucket_name" { + value = module.s3.bucket_name +} + module "model_directory" { source = "../modules/s3" bucketname = "retrofit-model-directory-${var.stage}" @@ -311,18 +327,6 @@ module "sap_baseline_ecr" { source = "../modules/ecr" } -############################################## -# CDN - Cloudfront -############################################## -module "cloudfront_distribution" { - source = "../modules/cloudfront" - bucket_name = module.s3.bucket_name - bucket_id = module.s3.bucket_id - bucket_arn = module.s3.bucket_arn - bucket_domain_name = module.s3.bucket_domain_name - stage = var.stage -} - ################################################ # SES - Email sending ################################################ From 33406ff67881d6f406d1c01eb3b2977067abdff6 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Fri, 13 Mar 2026 09:53:40 +0000 Subject: [PATCH 7/8] cdn depends on shared --- .github/workflows/deploy_terraform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy_terraform.yml b/.github/workflows/deploy_terraform.yml index 8e2c484d..506f11f6 100644 --- a/.github/workflows/deploy_terraform.yml +++ b/.github/workflows/deploy_terraform.yml @@ -350,7 +350,7 @@ jobs: # Deploy Cloudfront CDN # ============================================================ cloudfront_cdn: - needs: [determine_stage, fast_api_lambda] + needs: [determine_stage, shared_terraform, fast_api_lambda] uses: ./.github/workflows/_deploy_lambda.yml with: lambda_name: ara_cdn From ddcfa75a03e4283bb51b324c8aeede06ea3874dd Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Fri, 13 Mar 2026 11:16:41 +0000 Subject: [PATCH 8/8] address PR --- .github/workflows/deploy_terraform.yml | 1 - infrastructure/terraform/cdn/main.tf | 3 ++- infrastructure/terraform/cdn/variables.tf | 4 ---- infrastructure/terraform/lambda/fast-api/main.tf | 8 -------- infrastructure/terraform/lambda/fast-api/outputs.tf | 7 +++++++ infrastructure/terraform/modules/cloudfront/main.tf | 4 +--- infrastructure/terraform/modules/cloudfront/variables.tf | 7 +------ 7 files changed, 11 insertions(+), 23 deletions(-) create mode 100644 infrastructure/terraform/lambda/fast-api/outputs.tf diff --git a/.github/workflows/deploy_terraform.yml b/.github/workflows/deploy_terraform.yml index 506f11f6..1d84505b 100644 --- a/.github/workflows/deploy_terraform.yml +++ b/.github/workflows/deploy_terraform.yml @@ -361,5 +361,4 @@ jobs: AWS_ACCESS_KEY_ID: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }} AWS_REGION: ${{ secrets.DEV_AWS_REGION }} - TF_VAR_domain_name: ${{ secrets.ARA_DEV_DOMAIN_NAME }} diff --git a/infrastructure/terraform/cdn/main.tf b/infrastructure/terraform/cdn/main.tf index 29abe6e4..daa3b0f1 100644 --- a/infrastructure/terraform/cdn/main.tf +++ b/infrastructure/terraform/cdn/main.tf @@ -28,7 +28,8 @@ data "terraform_remote_state" "fast_api" { module "cdn" { source = "../modules/cloudfront" - aliases = ["domna.homes", "api.dev.domna.homes"] + # Comment out temporarily just to see what happens + # aliases = [data.terraform_remote_state.fast_api.outputs.domain_name] origins = [ # ---- S3 ---- diff --git a/infrastructure/terraform/cdn/variables.tf b/infrastructure/terraform/cdn/variables.tf index 6fe0073b..423f0b0f 100644 --- a/infrastructure/terraform/cdn/variables.tf +++ b/infrastructure/terraform/cdn/variables.tf @@ -1,7 +1,3 @@ variable "stage" { type = string -} - -variable "domain_name" { - type = string } \ No newline at end of file diff --git a/infrastructure/terraform/lambda/fast-api/main.tf b/infrastructure/terraform/lambda/fast-api/main.tf index 5e8d2b3b..f71b6f60 100644 --- a/infrastructure/terraform/lambda/fast-api/main.tf +++ b/infrastructure/terraform/lambda/fast-api/main.tf @@ -39,14 +39,6 @@ locals { db_credentials = jsondecode(data.aws_secretsmanager_secret_version.db_credentials.secret_string) } -# data "aws_ssm_parameter" "certificate_arn" { -# name = "/ssl_certificate_arn" -# } - -# data "aws_route53_zone" "this" { -# name = var.domain_name -# } - ############################################ # FastAPI Lambda + API Gateway ############################################ diff --git a/infrastructure/terraform/lambda/fast-api/outputs.tf b/infrastructure/terraform/lambda/fast-api/outputs.tf new file mode 100644 index 00000000..d3d9dbaa --- /dev/null +++ b/infrastructure/terraform/lambda/fast-api/outputs.tf @@ -0,0 +1,7 @@ +output "domain_name" { + value = module.fastapi.domain_name +} + +output "api_endpoint" { + value = module.fastapi.api_endpoint +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/cloudfront/main.tf b/infrastructure/terraform/modules/cloudfront/main.tf index 6fa1331e..02b64606 100644 --- a/infrastructure/terraform/modules/cloudfront/main.tf +++ b/infrastructure/terraform/modules/cloudfront/main.tf @@ -98,9 +98,7 @@ resource "aws_cloudfront_distribution" "this" { ########################################## viewer_certificate { - acm_certificate_arn = var.acm_certificate_arn - ssl_support_method = "sni-only" - cloudfront_default_certificate = var.acm_certificate_arn == null + cloudfront_default_certificate = true } } diff --git a/infrastructure/terraform/modules/cloudfront/variables.tf b/infrastructure/terraform/modules/cloudfront/variables.tf index 92ba2347..feff2faa 100644 --- a/infrastructure/terraform/modules/cloudfront/variables.tf +++ b/infrastructure/terraform/modules/cloudfront/variables.tf @@ -3,7 +3,7 @@ variable "origins" { origin_type = string # "s3" or "api" origin_domain_name = string origin_id = string - + bucket_id = optional(string) bucket_arn = optional(string) })) @@ -11,9 +11,4 @@ variable "origins" { variable "aliases" { type = list(string) -} - -variable "acm_certificate_arn" { - type = string - default = null } \ No newline at end of file