Closed3

Terraform で Cloudflare R2 の custom domain を設定する方法(ワークアラウンド)

9sako69sako6

環境

  • cloudflare provider v4.36.0
  • terraform v1.8.2

問題

Cloudflare R2 のバケットを cloudflare_r2_bucket リソースで作成することはできますが、CORS やカスタムドメインの設定はできません。
CORS 設定をする場合は AWS Provider を使うことになります。
問題はカスタムドメインの設定です。
これはリソースが提供されておらず、画面をぽちぽちする以外の方法が用意されていません。

https://github.com/cloudflare/terraform-provider-cloudflare/issues/2537

解決策

カスタムドメインの設定をする際にネットワークを観察すると、ドキュメントに記載されていない API を叩けば設定できることがわかりました。

以下は Terraform で上記 API を利用してカスタムドメインを設定する例です。

modules/cloudflare_r2/main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.56"
    }
  }
}

resource "aws_s3_bucket" "public" {
  bucket = "foo-bar-demo"

  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_s3_bucket_cors_configuration" "public" {
  bucket = aws_s3_bucket.public.id

  cors_rule {
    allowed_methods = ["GET", "PUT"]
    allowed_origins = var.allowed_origins
    allowed_headers = ["*"]
    max_age_seconds = 3600
  }
}

# NOTE: Cloudflare R2 にカスタムドメインを設定するリソースがないため、ワークアラウンドとして API を叩きます。
# API はドキュメントに記載されたものではないため、いつ使えなくなってもおかしくないです。
# API が機能しなくなった場合、手動で設定してください。
# https://developers.cloudflare.com/r2/buckets/public-buckets/#connect-a-bucket-to-a-custom-domain
resource "terraform_data" "public_custom_domain" {
  triggers_replace = [
    aws_s3_bucket.public.bucket,
    var.public_bucket_custom_fqdn,
  ]

  input = {
    bucket     = aws_s3_bucket.public.bucket
    token      = var.cloudflare_r2_token
    account_id = var.cloudflare_account_id
    fqdn       = var.public_bucket_custom_fqdn
  }

  provisioner "local-exec" {
    on_failure = fail
    when       = create
    command    = <<-EOT
      curl -f -X POST \
        -H 'Authorization: Bearer ${var.cloudflare_r2_token}' \
        -d '{"domain":"${var.public_bucket_custom_fqdn}", "zoneId":"${var.cloudflare_zone_id}", "zoneName":"${var.domain}"}' \
        'https://api.cloudflare.com/client/v4/accounts/${var.cloudflare_account_id}/r2/buckets/${aws_s3_bucket.public.bucket}/custom_domains'

      curl -f -X PUT \
        -H 'Authorization: Bearer ${var.cloudflare_r2_token}' \
        'https://api.cloudflare.com/client/v4/accounts/${var.cloudflare_account_id}/r2/buckets/${aws_s3_bucket.public.bucket}/policy?cname=${var.public_bucket_custom_fqdn}&access=CnamesOnly'
    EOT
  }

  provisioner "local-exec" {
    on_failure = fail
    when       = destroy
    command    = <<-EOT
      curl -f -X DELETE \
        -H 'Authorization: Bearer ${self.input.token}' \
        'https://api.cloudflare.com/client/v4/accounts/${self.input.account_id}/r2/buckets/${self.input.bucket}/custom_domains/${self.input.fqdn}'

      curl -f -X PUT \
        -H 'Authorization: Bearer ${self.input.token}' \
        'https://api.cloudflare.com/client/v4/accounts/${self.input.account_id}/r2/buckets/${self.input.bucket}/policy?cname=&access=CnamesOnly'
    EOT
  }
}

こんな感じで設定されます。

このスクラップは6ヶ月前にクローズされました