Closed3
Terraform で Cloudflare R2 の custom domain を設定する方法(ワークアラウンド)
環境
- cloudflare provider v4.36.0
- terraform v1.8.2
問題
Cloudflare R2 のバケットを cloudflare_r2_bucket
リソースで作成することはできますが、CORS やカスタムドメインの設定はできません。
CORS 設定をする場合は AWS Provider を使うことになります。
問題はカスタムドメインの設定です。
これはリソースが提供されておらず、画面をぽちぽちする以外の方法が用意されていません。
解決策
カスタムドメインの設定をする際にネットワークを観察すると、ドキュメントに記載されていない 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
}
}
こんな感じで設定されます。
余談
Cloudflare R2 の Access Key ID, Secret Access Key も Terraform 管理できることを発見したのでぶら下げておきます。
issue にお気持ち表明をしておいた。
このスクラップは5ヶ月前にクローズされました