From 9781ef36aeab67afba9164e6990fd841f492c32e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Aufort?= Date: Thu, 17 Oct 2024 08:33:16 +0200 Subject: [PATCH 1/3] feat: add CloudFront origin and distribution --- .github/workflows/deploy.yml | 36 ++++++++++++++++++ infrastructure/20_cloudfront/backend.tf | 10 +++++ infrastructure/20_cloudfront/cloudfront.tf | 44 ++++++++++++++++++++++ infrastructure/20_cloudfront/data.tf | 1 + infrastructure/20_cloudfront/providers.tf | 10 +++++ infrastructure/20_cloudfront/s3_origin.tf | 33 ++++++++++++++++ infrastructure/20_cloudfront/variables.tf | 5 +++ infrastructure/20_cloudfront/versions.tf | 9 +++++ 8 files changed, 148 insertions(+) create mode 100644 infrastructure/20_cloudfront/backend.tf create mode 100644 infrastructure/20_cloudfront/cloudfront.tf create mode 100644 infrastructure/20_cloudfront/data.tf create mode 100644 infrastructure/20_cloudfront/providers.tf create mode 100644 infrastructure/20_cloudfront/s3_origin.tf create mode 100644 infrastructure/20_cloudfront/variables.tf create mode 100644 infrastructure/20_cloudfront/versions.tf diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 498522d..26f2653 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -38,19 +38,55 @@ jobs: - run: terraform plan -out=tfplan.out - run: terraform apply -input=false tfplan.out + terraform-20-cloudfront: + runs-on: ubuntu-latest + defaults: + run: + working-directory: infrastructure/20_cloudfront + steps: + - uses: actions/checkout@v4 + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::448878779811:role/twitch-live-1710204-my-web-site + role-session-name: github-ipppontech-my-web-site-to-aws-via-oidc + aws-region: ${{ env.AWS_REGION }} + - uses: hashicorp/setup-terraform@v3 + with: + terraform_version: "1.9.7" + terraform_wrapper: false + - run: terraform fmt -check -recursive + - run: terraform init -backend=false + - run: terraform validate + - run: terraform init + - run: terraform plan -out=tfplan.out + - run: terraform apply -input=false tfplan.out + build: needs: - terraform-10-boostrap + - terraform-20-cloudfront runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: arn:aws:iam::448878779811:role/twitch-live-1710204-my-web-site + role-session-name: github-ipppontech-my-web-site-to-aws-via-oidc + aws-region: ${{ env.AWS_REGION }} - name: Use Node.js LTS uses: actions/setup-node@v4 with: cache: 'npm' node-version: 'lts/*' registry-url: 'https://registry.npmjs.org' + - uses: unfor19/install-aws-cli-action@v1 + with: + version: 2 + verbose: false - name: build run: | npm ci npm run build + - name: copy dist folder to S3 + run: | + aws s3 cp --recursive dist s3://twitch-live-17102024-my-web-site-origin/ diff --git a/infrastructure/20_cloudfront/backend.tf b/infrastructure/20_cloudfront/backend.tf new file mode 100644 index 0000000..685148a --- /dev/null +++ b/infrastructure/20_cloudfront/backend.tf @@ -0,0 +1,10 @@ +# Note: at the moment, it's not possible to use variables in Terraform backend +terraform { + backend "s3" { + bucket = "twitch-live-17102024-tf-states" + key = "20_cloudfront/terraform.tfstate" + region = "eu-west-3" + dynamodb_table = "twitch-live-17102024-tf-states-lock" + encrypt = true + } +} diff --git a/infrastructure/20_cloudfront/cloudfront.tf b/infrastructure/20_cloudfront/cloudfront.tf new file mode 100644 index 0000000..766db04 --- /dev/null +++ b/infrastructure/20_cloudfront/cloudfront.tf @@ -0,0 +1,44 @@ +locals { + origin_id = "myOriginId" +} + +module "cdn" { + source = "terraform-aws-modules/cloudfront/aws" + + # aliases = ["cdn.example.com"] + + comment = "My awesome CloudFront" + enabled = true + is_ipv6_enabled = true + price_class = "PriceClass_All" + retain_on_delete = false + wait_for_deployment = false + + create_origin_access_identity = true + + origin_access_control = { + s3_oac = { + description = "CloudFront access to S3" + origin_type = "s3" + signing_behavior = "always" + signing_protocol = "sigv4" + } + } + + origin = { + s3_one = { + domain_name = module.s3_bucket.s3_bucket_bucket_domain_name + origin_access_control = "s3_oac" # key in `origin_access_control` + origin_id = local.origin_id + } + } + + default_cache_behavior = { + target_origin_id = local.origin_id + viewer_protocol_policy = "allow-all" + } + # viewer_certificate = { + # acm_certificate_arn = "arn:aws:acm:us-east-1:135367859851:certificate/1032b155-22da-4ae0-9f69-e206f825458b" + # ssl_support_method = "sni-only" + # } +} diff --git a/infrastructure/20_cloudfront/data.tf b/infrastructure/20_cloudfront/data.tf new file mode 100644 index 0000000..8fc4b38 --- /dev/null +++ b/infrastructure/20_cloudfront/data.tf @@ -0,0 +1 @@ +data "aws_caller_identity" "current" {} diff --git a/infrastructure/20_cloudfront/providers.tf b/infrastructure/20_cloudfront/providers.tf new file mode 100644 index 0000000..b748065 --- /dev/null +++ b/infrastructure/20_cloudfront/providers.tf @@ -0,0 +1,10 @@ +provider "aws" { + region = var.region + + default_tags { + tags = { + project = basename(abspath("${path.module}/../..")) + subproject = basename(abspath(path.module)) + } + } +} diff --git a/infrastructure/20_cloudfront/s3_origin.tf b/infrastructure/20_cloudfront/s3_origin.tf new file mode 100644 index 0000000..b5d0b84 --- /dev/null +++ b/infrastructure/20_cloudfront/s3_origin.tf @@ -0,0 +1,33 @@ +locals { + origin_bucket_name = "twitch-live-17102024-my-web-site-origin" +} + +module "s3_bucket" { + source = "terraform-aws-modules/s3-bucket/aws" + + bucket = local.origin_bucket_name + acl = "private" + + control_object_ownership = true + object_ownership = "ObjectWriter" + + server_side_encryption_configuration = { + rule = { + apply_server_side_encryption_by_default = { + sse_algorithm = "AES256" + } + } + } + + # policy = data.aws_iam_policy_document.origin_bucket_policy.json +} + + +# data "aws_iam_policy_document" "origin_bucket_policy" { +# statement { +# effect = "Allow" +# principals { +# +# } +# } +# } diff --git a/infrastructure/20_cloudfront/variables.tf b/infrastructure/20_cloudfront/variables.tf new file mode 100644 index 0000000..d5aee15 --- /dev/null +++ b/infrastructure/20_cloudfront/variables.tf @@ -0,0 +1,5 @@ +variable "region" { + description = "Default AWS region" + default = "eu-west-3" + type = string +} diff --git a/infrastructure/20_cloudfront/versions.tf b/infrastructure/20_cloudfront/versions.tf new file mode 100644 index 0000000..a8d9277 --- /dev/null +++ b/infrastructure/20_cloudfront/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = "~> 1.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} From 73e9897fec87e05360afea9ea4230446244130a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Aufort?= Date: Thu, 17 Oct 2024 10:12:36 +0200 Subject: [PATCH 2/3] fix: post live twitch implementation --- .github/workflows/deploy.yml | 29 +++++++++--- .gitignore | 24 ++++++++++ .../10_bootstrap/.terraform.lock.hcl | 25 +++++++++++ infrastructure/10_bootstrap/github_oidc.tf | 14 +----- .../20_cloudfront/.terraform.lock.hcl | 25 +++++++++++ infrastructure/20_cloudfront/cloudfront.tf | 6 ++- infrastructure/20_cloudfront/s3_origin.tf | 45 ++++++++++++++----- 7 files changed, 135 insertions(+), 33 deletions(-) create mode 100644 infrastructure/10_bootstrap/.terraform.lock.hcl create mode 100644 infrastructure/20_cloudfront/.terraform.lock.hcl diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 26f2653..ce4c463 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,6 +8,9 @@ on: env: AWS_REGION: eu-west-3 + ORIGIN_BUCKET_NAME: twitch-live-17102024-my-web-site-origin + ROLE_ARN: arn:aws:iam::448878779811:role/twitch-live-17102024-my-web-site + ROLE_SESSON_NAME: github-ipppontech-my-web-site-to-aws-via-oidc # Permission can be added at job level or workflow level permissions: @@ -24,8 +27,8 @@ jobs: - uses: actions/checkout@v4 - uses: aws-actions/configure-aws-credentials@v4 with: - role-to-assume: arn:aws:iam::448878779811:role/twitch-live-1710204-my-web-site - role-session-name: github-ipppontech-my-web-site-to-aws-via-oidc + role-to-assume: ${{ env.ROLE_ARN }} + role-session-name: ${{ env.ROLE_SESSION_NAME }} aws-region: ${{ env.AWS_REGION }} - uses: hashicorp/setup-terraform@v3 with: @@ -47,8 +50,8 @@ jobs: - uses: actions/checkout@v4 - uses: aws-actions/configure-aws-credentials@v4 with: - role-to-assume: arn:aws:iam::448878779811:role/twitch-live-1710204-my-web-site - role-session-name: github-ipppontech-my-web-site-to-aws-via-oidc + role-to-assume: ${{ env.ROLE_ARN }} + role-session-name: ${{ env.ROLE_SESSION_NAME }} aws-region: ${{ env.AWS_REGION }} - uses: hashicorp/setup-terraform@v3 with: @@ -70,8 +73,8 @@ jobs: - uses: actions/checkout@v4 - uses: aws-actions/configure-aws-credentials@v4 with: - role-to-assume: arn:aws:iam::448878779811:role/twitch-live-1710204-my-web-site - role-session-name: github-ipppontech-my-web-site-to-aws-via-oidc + role-to-assume: ${{ env.ROLE_ARN }} + role-session-name: ${{ env.ROLE_SESSION_NAME }} aws-region: ${{ env.AWS_REGION }} - name: Use Node.js LTS uses: actions/setup-node@v4 @@ -87,6 +90,18 @@ jobs: run: | npm ci npm run build + - name: clean S3 origin bucket + run: | + objects_number=$(aws s3 ls s3://twitch-live-17102024-my-web-site-origin/ --recursive | wc -l) + if [ "$objects_number" -gt "0" ]; then + aws s3api delete-objects \ + --bucket ${{ env.ORIGIN_BUCKET_NAME }} \ + --delete "$(aws s3api list-object-versions \ + --bucket ${{ env.ORIGIN_BUCKET_NAME }} \ + --output=json \ + --query='{Objects: Versions[].{Key:Key,VersionId:VersionId}}')"; + fi + - name: copy dist folder to S3 run: | - aws s3 cp --recursive dist s3://twitch-live-17102024-my-web-site-origin/ + aws s3 cp --recursive dist s3://${{ env.ORIGIN_BUCKET_NAME }}/ diff --git a/.gitignore b/.gitignore index 7dedfb5..dc6df0b 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,27 @@ !.vscode/launch.json !.vscode/extensions.json *.code-workspace + +###################### +# Terraform +###################### +# Local .terraform directories +**/.terraform/* + +# .tfstate files +*.tfstate +*.tfstate.* + +# tf plan files +**.tfplan +**.plan.json + +# Ignore CLI configuration files +.terraformrc +terraform.rc +~ +# ignore temp doc file +doc.md + +# ignore zip files generated with data_archive +*.zip diff --git a/infrastructure/10_bootstrap/.terraform.lock.hcl b/infrastructure/10_bootstrap/.terraform.lock.hcl new file mode 100644 index 0000000..d38cb8a --- /dev/null +++ b/infrastructure/10_bootstrap/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.72.1" + constraints = "~> 5.0" + hashes = [ + "h1:BkYfMmqLJIqLkLLz9sDRWJR5+7GCXTocNPN4pIHkhQo=", + "zh:0dea6843836e926d33469b48b948744079023816d16a2ff7666bcfb6aa3522d4", + "zh:195fa9513f75800a0d62797ebec75ee73e9b8c28d713fe9b63d3b1d1eec129b3", + "zh:1ed92f3961715bf0e024bcde3c12dfbdc50b00c1f8a43cc00802cfc45a256208", + "zh:2ac687e3a52606466cae4a6813e81d923042488df88d2424e28d3f8530f091bb", + "zh:32e7ca75f9314557daada3c44628fe1f3bf964a4f833bfb4b2295d833fe64b6f", + "zh:374ee0e6b4327cc6ef666908ce5d6450a3a56e90cd2b785e83c2bcfc100021d2", + "zh:5500fd6fdac44f96411fcf9c6d01691159ec35455ed127eb4c3a498e1cc92a64", + "zh:723a2dc4b064c12e7ee62ad4fbfd72fa5e025206ea47b735994ef53f3c373152", + "zh:89d97b87605f1d734f27e642567cbecf785b521af8ea81dac55c77ccde876221", + "zh:951ee1e5731e8d65d521d71b95927e55055b3c4656eef6d46fa580a63328befc", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9b2b362470b64ec227b2da64762ab8bc4111c6b80365fd9d82fc5e1e33f44038", + "zh:aa6e57d0cb974ff0da5dee5d43ad2745cbbc4a2b507d4c799839b9fa96daf688", + "zh:ba0d14c4a6b7aa844a830d47c0bf995b632e37f0795394b5b60c638b62b7fc03", + "zh:c9764065a9c5d324db0b02bd201b9e3a2118e49c4960884acdeea377173302e9", + ] +} diff --git a/infrastructure/10_bootstrap/github_oidc.tf b/infrastructure/10_bootstrap/github_oidc.tf index 36a2701..85fd88f 100644 --- a/infrastructure/10_bootstrap/github_oidc.tf +++ b/infrastructure/10_bootstrap/github_oidc.tf @@ -1,10 +1,5 @@ locals { - role_name = "twitch-live-1710204-my-web-site" -} - -import { - to = aws_iam_openid_connect_provider.github - id = "arn:aws:iam::448878779811:oidc-provider/token.actions.githubusercontent.com" + role_name = "twitch-live-17102024-my-web-site" } resource "aws_iam_openid_connect_provider" "github" { @@ -17,11 +12,6 @@ resource "aws_iam_openid_connect_provider" "github" { thumbprint_list = ["d89e3bd43d5d909b47a18977aa9d5ce36cee184c"] } -import { - to = aws_iam_role.twitch_live - id = local.role_name -} - resource "aws_iam_role" "twitch_live" { name = local.role_name description = "Role dedicated to deploy infrastructure during the Twitch Live on October 17th 2024 with Arnaud and Timothee" @@ -102,7 +92,7 @@ data "aws_iam_policy_document" "twitch_live_runner" { "iam:*" ] resources = [ - "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/twitch-live-1710204-my-web-site" + "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/twitch-live-17102024-my-web-site" ] } } diff --git a/infrastructure/20_cloudfront/.terraform.lock.hcl b/infrastructure/20_cloudfront/.terraform.lock.hcl new file mode 100644 index 0000000..f0b42db --- /dev/null +++ b/infrastructure/20_cloudfront/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.72.1" + constraints = "~> 5.0, >= 5.70.0" + hashes = [ + "h1:BkYfMmqLJIqLkLLz9sDRWJR5+7GCXTocNPN4pIHkhQo=", + "zh:0dea6843836e926d33469b48b948744079023816d16a2ff7666bcfb6aa3522d4", + "zh:195fa9513f75800a0d62797ebec75ee73e9b8c28d713fe9b63d3b1d1eec129b3", + "zh:1ed92f3961715bf0e024bcde3c12dfbdc50b00c1f8a43cc00802cfc45a256208", + "zh:2ac687e3a52606466cae4a6813e81d923042488df88d2424e28d3f8530f091bb", + "zh:32e7ca75f9314557daada3c44628fe1f3bf964a4f833bfb4b2295d833fe64b6f", + "zh:374ee0e6b4327cc6ef666908ce5d6450a3a56e90cd2b785e83c2bcfc100021d2", + "zh:5500fd6fdac44f96411fcf9c6d01691159ec35455ed127eb4c3a498e1cc92a64", + "zh:723a2dc4b064c12e7ee62ad4fbfd72fa5e025206ea47b735994ef53f3c373152", + "zh:89d97b87605f1d734f27e642567cbecf785b521af8ea81dac55c77ccde876221", + "zh:951ee1e5731e8d65d521d71b95927e55055b3c4656eef6d46fa580a63328befc", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9b2b362470b64ec227b2da64762ab8bc4111c6b80365fd9d82fc5e1e33f44038", + "zh:aa6e57d0cb974ff0da5dee5d43ad2745cbbc4a2b507d4c799839b9fa96daf688", + "zh:ba0d14c4a6b7aa844a830d47c0bf995b632e37f0795394b5b60c638b62b7fc03", + "zh:c9764065a9c5d324db0b02bd201b9e3a2118e49c4960884acdeea377173302e9", + ] +} diff --git a/infrastructure/20_cloudfront/cloudfront.tf b/infrastructure/20_cloudfront/cloudfront.tf index 766db04..8fa1c33 100644 --- a/infrastructure/20_cloudfront/cloudfront.tf +++ b/infrastructure/20_cloudfront/cloudfront.tf @@ -3,7 +3,8 @@ locals { } module "cdn" { - source = "terraform-aws-modules/cloudfront/aws" + source = "terraform-aws-modules/cloudfront/aws" + version = "3.4.1" # aliases = ["cdn.example.com"] @@ -12,7 +13,7 @@ module "cdn" { is_ipv6_enabled = true price_class = "PriceClass_All" retain_on_delete = false - wait_for_deployment = false + wait_for_deployment = true create_origin_access_identity = true @@ -37,6 +38,7 @@ module "cdn" { target_origin_id = local.origin_id viewer_protocol_policy = "allow-all" } + # viewer_certificate = { # acm_certificate_arn = "arn:aws:acm:us-east-1:135367859851:certificate/1032b155-22da-4ae0-9f69-e206f825458b" # ssl_support_method = "sni-only" diff --git a/infrastructure/20_cloudfront/s3_origin.tf b/infrastructure/20_cloudfront/s3_origin.tf index b5d0b84..6d5500b 100644 --- a/infrastructure/20_cloudfront/s3_origin.tf +++ b/infrastructure/20_cloudfront/s3_origin.tf @@ -3,13 +3,13 @@ locals { } module "s3_bucket" { - source = "terraform-aws-modules/s3-bucket/aws" + source = "terraform-aws-modules/s3-bucket/aws" + version = "4.2.1" bucket = local.origin_bucket_name - acl = "private" control_object_ownership = true - object_ownership = "ObjectWriter" + object_ownership = "BucketOwnerEnforced" server_side_encryption_configuration = { rule = { @@ -19,15 +19,36 @@ module "s3_bucket" { } } - # policy = data.aws_iam_policy_document.origin_bucket_policy.json + attach_policy = true + policy = data.aws_iam_policy_document.origin_bucket_policy.json + + # For tests only + force_destroy = true } -# data "aws_iam_policy_document" "origin_bucket_policy" { -# statement { -# effect = "Allow" -# principals { -# -# } -# } -# } +data "aws_iam_policy_document" "origin_bucket_policy" { + # Origin Access Controls + statement { + sid = "S3GetObjectsDistribution" + actions = [ + "s3:GetObject" + ] + resources = [ + "${module.s3_bucket.s3_bucket_arn}/*" + ] + + principals { + type = "Service" + identifiers = ["cloudfront.amazonaws.com"] + } + + condition { + test = "StringEquals" + variable = "aws:SourceArn" + values = [ + module.cdn.cloudfront_distribution_arn + ] + } + } +} From 1b1daa7d8fc01e256e748032b280d6b0a08f80fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Aufort?= Date: Thu, 24 Oct 2024 09:34:09 +0200 Subject: [PATCH 3/3] feat: post live twitch implementation - Update OIDC role policy - Add default root object - Add Ippon DNS for our Cloudfront and associate a custom TLS certificate - Update the origin access control - Add Cloudfront log bucket and Cloudfront logging configuration --- infrastructure/10_bootstrap/github_oidc.tf | 26 +++++++++ infrastructure/20_cloudfront/certificate.tf | 38 +++++++++++++ infrastructure/20_cloudfront/cloudfront.tf | 54 ++++++++++++++----- .../20_cloudfront/cloudfront_logs.tf | 28 ++++++++++ infrastructure/20_cloudfront/providers.tf | 12 +++++ 5 files changed, 146 insertions(+), 12 deletions(-) create mode 100644 infrastructure/20_cloudfront/certificate.tf create mode 100644 infrastructure/20_cloudfront/cloudfront_logs.tf diff --git a/infrastructure/10_bootstrap/github_oidc.tf b/infrastructure/10_bootstrap/github_oidc.tf index 85fd88f..e317e51 100644 --- a/infrastructure/10_bootstrap/github_oidc.tf +++ b/infrastructure/10_bootstrap/github_oidc.tf @@ -52,6 +52,11 @@ resource "aws_iam_role_policy_attachment" "cloudfront" { policy_arn = "arn:aws:iam::aws:policy/CloudFrontFullAccess" } +resource "aws_iam_role_policy_attachment" "acm" { + role = aws_iam_role.twitch_live.name + policy_arn = "arn:aws:iam::aws:policy/AWSCertificateManagerFullAccess" +} + resource "aws_iam_role_policy" "twitch_live_runner" { name = "${local.role_name}-runner" role = aws_iam_role.twitch_live.id @@ -95,4 +100,25 @@ data "aws_iam_policy_document" "twitch_live_runner" { "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/twitch-live-17102024-my-web-site" ] } + statement { + effect = "Allow" + actions = [ + "route53:ListHostedZones", + ] + resources = [ + "*" + ] + } + statement { + effect = "Allow" + actions = [ + "route53:GetHostedZone", + "route53:ChangeResourceRecordSets", + "route53:ListResourceRecordSets", + "route53:ListTagsForResource", + ] + resources = [ + "arn:aws:route53:::hostedzone/Z0612444205RFX4C90XIM" + ] + } } diff --git a/infrastructure/20_cloudfront/certificate.tf b/infrastructure/20_cloudfront/certificate.tf new file mode 100644 index 0000000..048716d --- /dev/null +++ b/infrastructure/20_cloudfront/certificate.tf @@ -0,0 +1,38 @@ +resource "aws_acm_certificate" "cert" { + domain_name = local.my_domain + validation_method = "DNS" + + tags = { + Environment = "my-web-site" + } + + lifecycle { + create_before_destroy = true + prevent_destroy = true + } + + provider = aws.us +} + +resource "aws_acm_certificate_validation" "cert" { + certificate_arn = aws_acm_certificate.cert.arn + validation_record_fqdns = [for record in aws_route53_record.record_validation : record.fqdn] + provider = aws.us +} + +resource "aws_route53_record" "record_validation" { + for_each = { + for dvo in aws_acm_certificate.cert.domain_validation_options : dvo.domain_name => { + name = dvo.resource_record_name + record = dvo.resource_record_value + type = dvo.resource_record_type + } + } + + allow_overwrite = true + name = each.value.name + records = [each.value.record] + ttl = 60 + type = each.value.type + zone_id = data.aws_route53_zone.ippon.zone_id +} diff --git a/infrastructure/20_cloudfront/cloudfront.tf b/infrastructure/20_cloudfront/cloudfront.tf index 8fa1c33..a4c2b7f 100644 --- a/infrastructure/20_cloudfront/cloudfront.tf +++ b/infrastructure/20_cloudfront/cloudfront.tf @@ -1,24 +1,25 @@ locals { - origin_id = "myOriginId" + origin_id = "s3_oac" + my_domain = "my-web-site.${data.aws_route53_zone.ippon.name}" } module "cdn" { source = "terraform-aws-modules/cloudfront/aws" version = "3.4.1" - # aliases = ["cdn.example.com"] - comment = "My awesome CloudFront" enabled = true is_ipv6_enabled = true price_class = "PriceClass_All" retain_on_delete = false wait_for_deployment = true + default_root_object = "index.html" create_origin_access_identity = true + create_origin_access_control = true origin_access_control = { - s3_oac = { + (local.origin_id) = { description = "CloudFront access to S3" origin_type = "s3" signing_behavior = "always" @@ -27,20 +28,49 @@ module "cdn" { } origin = { - s3_one = { + (local.origin_id) = { domain_name = module.s3_bucket.s3_bucket_bucket_domain_name - origin_access_control = "s3_oac" # key in `origin_access_control` - origin_id = local.origin_id + origin_access_control = local.origin_id # key in `origin_access_control` } } default_cache_behavior = { target_origin_id = local.origin_id - viewer_protocol_policy = "allow-all" + viewer_protocol_policy = "redirect-to-https" + } + + aliases = [ + local.my_domain + ] + + viewer_certificate = { + cloudfront_default_certificate = false + acm_certificate_arn = aws_acm_certificate.cert.arn + ssl_support_method = "sni-only" + minimum_protocol_version = "TLSv1.2_2021" } - # viewer_certificate = { - # acm_certificate_arn = "arn:aws:acm:us-east-1:135367859851:certificate/1032b155-22da-4ae0-9f69-e206f825458b" - # ssl_support_method = "sni-only" - # } + logging_config = { + bucket = module.cloudfront_log_bucket.s3_bucket_bucket_domain_name + } + + providers = { + aws = aws.us + } +} + +data "aws_route53_zone" "ippon" { + name = "sbx.aws.ippon.fr" +} + +resource "aws_route53_record" "cloudfront" { + zone_id = data.aws_route53_zone.ippon.zone_id + name = local.my_domain + type = "A" + + alias { + name = module.cdn.cloudfront_distribution_domain_name + zone_id = module.cdn.cloudfront_distribution_hosted_zone_id + evaluate_target_health = true + } } diff --git a/infrastructure/20_cloudfront/cloudfront_logs.tf b/infrastructure/20_cloudfront/cloudfront_logs.tf new file mode 100644 index 0000000..49a2895 --- /dev/null +++ b/infrastructure/20_cloudfront/cloudfront_logs.tf @@ -0,0 +1,28 @@ +data "aws_cloudfront_log_delivery_canonical_user_id" "cloudfront" {} +data "aws_canonical_user_id" "current" {} + +module "cloudfront_log_bucket" { + source = "terraform-aws-modules/s3-bucket/aws" + version = "4.2.1" + + bucket = "${local.origin_bucket_name}-cloudfront-logs" + control_object_ownership = true + object_ownership = "ObjectWriter" + + grant = [{ + type = "CanonicalUser" + permission = "FULL_CONTROL" + id = data.aws_canonical_user_id.current.id + }, { + type = "CanonicalUser" + permission = "FULL_CONTROL" + id = data.aws_cloudfront_log_delivery_canonical_user_id.cloudfront.id # Ref. https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html + } + ] + + owner = { + id = data.aws_canonical_user_id.current.id + } + + force_destroy = true +} diff --git a/infrastructure/20_cloudfront/providers.tf b/infrastructure/20_cloudfront/providers.tf index b748065..9c87a14 100644 --- a/infrastructure/20_cloudfront/providers.tf +++ b/infrastructure/20_cloudfront/providers.tf @@ -8,3 +8,15 @@ provider "aws" { } } } + +provider "aws" { + alias = "us" + region = "us-east-1" + + default_tags { + tags = { + project = basename(abspath("${path.module}/../..")) + subproject = basename(abspath(path.module)) + } + } +}