From 49e544d10fce938271f8cb8a4415d97c245f9969 Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Thu, 12 Mar 2026 17:29:47 +0000 Subject: [PATCH] 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