Storage

locals {
  app_hostname       = "https://app.example.com"
  api_hostname       = "https://api.example.com"

  bucket_ids = toset([
    "backup",
    "datasets",
    "measurements",
    "modules",
    "outputs",
    "reports",
    "safetycases",
  ])
}

Object storage

Create random strings to append to bucket names later:

resource "random_string" "suffixes" {
  for_each = local.bucket_ids

  length = 8

  special = false
  upper   = false
}

Create an encryption key to allow you to rotate at will:

resource "google_kms_key_ring" "keyring" {
  name     = local.name
  location = local.region
}

resource "google_kms_crypto_key" "key" {
  name            = local.name
  key_ring        = google_kms_key_ring.keyring.id
  rotation_period = "7776000s"
}

resource "google_kms_crypto_key_iam_binding" "binding" {
  crypto_key_id = google_kms_crypto_key.key.id
  role          = "roles/cloudkms.cryptoKeyEncrypterDecrypter"

  members = [
    "serviceAccount:${data.google_storage_project_service_account.this.email_address}",
  ]
}

We’ll be creating buckets that meet the following requirements:

  • Use the customer managed encryption key we created.

  • Public bucket access is disabled.

  • A CORS header is applied to allow dyff-frontend to access bucket objects.

  • depends_on is added to ensure the buckets are created after the encryption key is granted access to the buckets.

Create the S3 buckets:

resource "google_storage_bucket" "dyff" {
  for_each = local.bucket_ids

  name = "dyff-${each.key}-${random_string.suffixes[each.key].result}"

  location = local.region

  uniform_bucket_level_access = true

  public_access_prevention = "enforced"

  cors {
    origin          = [local.app_hostname]
    method          = ["GET", "HEAD", "PUT", "POST", "DELETE"]
    response_header = ["*"]
  }

  encryption {
    default_kms_key_name = google_kms_crypto_key.key.id
  }

  depends_on = [google_kms_crypto_key_iam_binding.binding]
}

Create a bucket access key:

resource "google_service_account" "dyff" {
  account_id   = local.name
  display_name = local.name
}

resource "google_project_iam_member" "storage_admin" {
  role    = "roles/storage.admin"
  member  = "serviceAccount:${google_service_account.dyff.email}"
}

resource "google_storage_hmac_key" "key" {
  service_account_email = google_service_account.dyff.email
}