diff --git a/.github/workflows/deploy_terraform.yml b/.github/workflows/deploy_terraform.yml index 501fe30f..e41534e6 100644 --- a/.github/workflows/deploy_terraform.yml +++ b/.github/workflows/deploy_terraform.yml @@ -346,11 +346,56 @@ jobs: TF_VAR_epc_auth_token: ${{ secrets.DEV_EPC_AUTH_TOKEN }} TF_VAR_google_solar_api_key: ${{ secrets.DEV_GOOGLE_SOLAR_API_KEY }} + # ============================================================ + # Deploy ACM Certificate for Cloudfront + # ============================================================ + cloudfront_acm: + needs: [determine_stage, shared_terraform, fast_api_lambda] + runs-on: ubuntu-latest + + env: + STAGE: ${{ needs.determine_stage.outputs.stage }} + TERRAFORM_APPLY: ${{ needs.determine_stage.outputs.terraform_apply }} + + steps: + - uses: actions/checkout@v4 + + - uses: aws-actions/configure-aws-credentials@v4 + with: + 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 }} + + - uses: hashicorp/setup-terraform@v3 + + - name: Terraform Init + working-directory: infrastructure/terraform/cdn_certificate + run: terraform init -reconfigure + + - name: Terraform Workspace + working-directory: infrastructure/terraform/cdn_certificate + run: | + terraform workspace select $STAGE \ + || terraform workspace new $STAGE + + - name: Terraform Plan + working-directory: infrastructure/terraform/cdn_certificate + run: | + terraform plan \ + -var="stage=${STAGE}" \ + -out=tfplan + + - name: Terraform Apply + if: env.TERRAFORM_APPLY == 'true' + working-directory: infrastructure/terraform/cdn_certificate + run: terraform apply -auto-approve tfplan + + # ============================================================ # Deploy Cloudfront CDN # ============================================================ cloudfront_cdn: - needs: [determine_stage, shared_terraform, fast_api_lambda] + needs: [determine_stage, cloudfront_acm] runs-on: ubuntu-latest env: diff --git a/infrastructure/terraform/cdn/main.tf b/infrastructure/terraform/cdn/main.tf index 7ef58e19..7e4c7cd7 100644 --- a/infrastructure/terraform/cdn/main.tf +++ b/infrastructure/terraform/cdn/main.tf @@ -16,7 +16,19 @@ data "terraform_remote_state" "shared" { data "terraform_remote_state" "fast_api" { backend = "s3" config = { - bucket = "ara-fast-api-terraform-state" + bucket = data.terraform_remote_state.shared.ara_fast_api_state_bucket + key = "env:/${var.stage}/terraform.tfstate" + region = "eu-west-2" + } +} + +############################################ +# Load CDN Certificate Terraform State +############################################ +data "terraform_remote_state" "cdn_certificate" { + backend = "s3" + config = { + bucket = data.terraform_remote_state.shared.cdn_certificate_state_bucket key = "env:/${var.stage}/terraform.tfstate" region = "eu-west-2" } @@ -28,8 +40,9 @@ data "terraform_remote_state" "fast_api" { module "cdn" { source = "../modules/cloudfront" - aliases = [] -# aliases = [data.terraform_remote_state.fast_api.outputs.domain_name] + aliases = [data.terraform_remote_state.fast_api.outputs.domain_name] + + acm_certificate_arn = data.terraform_remote_state.cdn_certificate.outputs.certificate_arn origins = [ # ---- S3 ---- diff --git a/infrastructure/terraform/cdn_certificate/main.tf b/infrastructure/terraform/cdn_certificate/main.tf new file mode 100644 index 00000000..5c0c178c --- /dev/null +++ b/infrastructure/terraform/cdn_certificate/main.tf @@ -0,0 +1,28 @@ +############################################ +# Load FastAPI Terraform State +############################################ +data "terraform_remote_state" "fast_api" { + backend = "s3" + config = { + bucket = "ara-fast-api-terraform-state" + key = "env:/${var.stage}/terraform.tfstate" + region = "eu-west-2" + } +} + +############################################ +# Define Certificate +############################################ +module "cdn_certificate" { + source = "../modules/acm_certificate" + + providers = { + aws = aws.us_east_1 + } + + domain_name = data.terraform_remote_state.fast_api.outputs.domain_name + + tags = { + Environment = var.stage + } +} \ No newline at end of file diff --git a/infrastructure/terraform/cdn_certificate/outputs.tf b/infrastructure/terraform/cdn_certificate/outputs.tf new file mode 100644 index 00000000..e72c6e13 --- /dev/null +++ b/infrastructure/terraform/cdn_certificate/outputs.tf @@ -0,0 +1,3 @@ +output "certificate_arn" { + value = module.cdn_certificate.certificate_arn +} \ No newline at end of file diff --git a/infrastructure/terraform/cdn_certificate/provider.tf b/infrastructure/terraform/cdn_certificate/provider.tf new file mode 100644 index 00000000..84d88438 --- /dev/null +++ b/infrastructure/terraform/cdn_certificate/provider.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.0" + } + } +} + +provider "aws" { + region = var.region +} + +provider "aws" { + alias = "us_east_1" + region = "us-east-1" +} \ No newline at end of file diff --git a/infrastructure/terraform/cdn_certificate/variables.tf b/infrastructure/terraform/cdn_certificate/variables.tf new file mode 100644 index 00000000..423f0b0f --- /dev/null +++ b/infrastructure/terraform/cdn_certificate/variables.tf @@ -0,0 +1,3 @@ +variable "stage" { + type = string +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/acm_certificate/main.tf b/infrastructure/terraform/modules/acm_certificate/main.tf new file mode 100644 index 00000000..13d39556 --- /dev/null +++ b/infrastructure/terraform/modules/acm_certificate/main.tf @@ -0,0 +1,11 @@ +resource "aws_acm_certificate" "this" { + domain_name = var.domain_name + subject_alternative_names = var.subject_alternative_names + validation_method = "DNS" + + lifecycle { + create_before_destroy = true + } + + tags = var.tags +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/acm_certificate/outputs.tf b/infrastructure/terraform/modules/acm_certificate/outputs.tf new file mode 100644 index 00000000..990a6db9 --- /dev/null +++ b/infrastructure/terraform/modules/acm_certificate/outputs.tf @@ -0,0 +1,7 @@ +output "certificate_arn" { + value = aws_acm_certificate.this.arn +} + +output "domain_validation_options" { + value = aws_acm_certificate.this.domain_validation_options +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/acm_certificate/variables.tf b/infrastructure/terraform/modules/acm_certificate/variables.tf new file mode 100644 index 00000000..bd30501f --- /dev/null +++ b/infrastructure/terraform/modules/acm_certificate/variables.tf @@ -0,0 +1,16 @@ +variable "domain_name" { + description = "Primary domain name for the certificate" + type = string +} + +variable "subject_alternative_names" { + description = "Additional domains for the certificate" + type = list(string) + default = [] +} + +variable "tags" { + description = "Tags to apply to the certificate" + type = map(string) + default = {} +} \ No newline at end of file diff --git a/infrastructure/terraform/modules/cloudfront/main.tf b/infrastructure/terraform/modules/cloudfront/main.tf index 261352a8..03082604 100644 --- a/infrastructure/terraform/modules/cloudfront/main.tf +++ b/infrastructure/terraform/modules/cloudfront/main.tf @@ -1,3 +1,6 @@ +############################################# +# Use Managed Caching and Forwarding Policies +############################################# data "aws_cloudfront_cache_policy" "caching_disabled" { name = "Managed-CachingDisabled" } @@ -113,7 +116,11 @@ resource "aws_cloudfront_distribution" "this" { ########################################## viewer_certificate { - cloudfront_default_certificate = true + acm_certificate_arn = var.acm_certificate_arn + ssl_support_method = var.acm_certificate_arn != null ? "sni-only" : null + minimum_protocol_version = var.acm_certificate_arn != null ? "TLSv1.2_2021" : null + + cloudfront_default_certificate = var.acm_certificate_arn == null } } diff --git a/infrastructure/terraform/modules/cloudfront/variables.tf b/infrastructure/terraform/modules/cloudfront/variables.tf index feff2faa..4721d3d1 100644 --- a/infrastructure/terraform/modules/cloudfront/variables.tf +++ b/infrastructure/terraform/modules/cloudfront/variables.tf @@ -11,4 +11,10 @@ variable "origins" { variable "aliases" { type = list(string) +} + +variable "acm_certificate_arn" { + description = "ACM certificate ARN for custom aliases" + 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 1de2031f..486f79ca 100644 --- a/infrastructure/terraform/shared/main.tf +++ b/infrastructure/terraform/shared/main.tf @@ -562,4 +562,15 @@ output "fast_api_s3_read_and_write_arn" { value = module.fast_api_s3_read_and_write.policy_arn } +################################################ +# CDN Certificate +################################################ +module "cdn_certificate_state_bucket" { + source = "../modules/tf_state_bucket" + bucket_name = "cdn-certificate-terraform-state" +} + +output "cdn_certificate_state_bucket" { + value = module.cdn_certificate_state_bucket.bucket_name +}