petitviolet blog

    Terraform to provision GCP CDN for GCS backend

    2023-02-20

    TerraformGCP

    Google Cloud offers CDN(content delivery/distributed network) that can be backed by Cloud Storage, a.k.a GCS. Terraform supports provisioning CDN in GCP as always.

    As well as the previous post, in Terraform, variables should be declared in variables.tf but use locals here instead for simplicity a.

    GCP IAP protected Cloud Run Application by Terraform Terraform to build a Cloud Run Application protected by GCP Identity-Aware Proxy Google Cloud(GCP) has Identity-Aware Proxy that uses ID and contexts to protect applications and VMs from unexpected access. https://cloud.google.com/iap Thanks to IAP, it's a way easy to protect an application running on Cloud Run by requiring Google login within the organization, for example.

    locals {
        gcp_project    = "awesome-project"
        region         = "asia-northeast1"
        user_emails    = ["hoge@example.com"]
        base_domain    = "example.com"
    
        cdn_bucket_name = "hogehoge"
        cdn_bucket_cors_origins = [
            "http://localhost:3000",
        ]
    }
    

    Use google_storage_bucket resource to create a GCS bucket.

    https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket

    resource "google_storage_bucket" "cdn_bucket" {
      name          = local.cdn_bucket_name
      project       = local.gcp_project
      location      = local.region
    
      uniform_bucket_level_access = false
    
    
      cors {
        origin          = local.cdn_bucket_cors_origins
        method          = ["GET", "HEAD", "POST"]
        response_header = ["*"]
        max_age_seconds = 3600
      }
    }
    

    From the viewpoint of security, as using IAM in GCP is basically recommended, giving uniform_bucket_level_access = true would be a good practice. See the document for details.

    https://cloud.google.com/storage/docs/uniform-bucket-level-access

    Then, for being able to use the created bucket as a backend of CDN, use google_compute_backend_bucket with enable_cdn = true.

    https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_backend_bucket

    resource "google_compute_backend_bucket" "app_cdn" {
      name        = "app-cdn-backend"
      description = "backend for app-cdn bucket"
      bucket_name = local.cdn_bucket_name
      enable_cdn  = true
    }
    

    As the last step, provisioning a load balancer to point to the backend. Picking up google_compute_url_map resource to provision load balancer for the google_compute_backend_bucket backend.

    resource "google_compute_url_map" "api_url_map" {
      name            = "api-urlmap"
      default_service = xxx // whatever you want
    
      host_rule {
        hosts        = ["cdn.${local.base_domain}"]
        path_matcher = "cdn"
      }
    
      path_matcher {
        name            = "cdn"
        default_service = google_compute_backend_bucket.app_cdn.id
      }
    }
    

    It seems that having one load balancer in one google project that being backed by multiple services like GAE, Run, etc. is a good practice for the sake of maintainability and cost. There should be more resources including google_compute_target_https_proxy, google_compute_managed_ssl_certificate, and others to provision the load balancer completely, but let me skip them since it's not the main topic of this post.