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] 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)) + } + } +}