Closed5

Terraform で Cloudflare R2 の Token, Access Key ID, Secret Access Key を管理する

9sako69sako6

Cloudflare R2 のバケットに CORS 設定をしたい場合、Cloudflare Provider では実現できず、AWS Provider を使う必要があります。

AWS Provider を使って Cloudflare R2 を管理する場合、Access Key ID, Secret Access Key を発行して以下のように provider に渡す必要があります。
これらトークンも Terraform で発行することができます(後述)。

公式ドキュメントの例の抜粋:

modules/r2/main.tf
provider "aws" {
  region = "us-east-1"

  access_key = <R2 Access Key>
  secret_key = <R2 Secret Key>

  skip_credentials_validation = true
  skip_region_validation      = true
  skip_requesting_account_id  = true

  endpoints {
    s3 = "https://<account id>.r2.cloudflarestorage.com"
  }
}
9sako69sako6

Cloudflare Provider には cloudflare_api_token リソースが用意されており、API Token を発行できます。

https://registry.terraform.io/providers/cloudflare/cloudflare/latest/docs/resources/api_token

API Token を発行できるのはわかるものの、Access Key ID, Secret Access Key はどうやって作るんだと思っていたら、どうやらこのリソースの id が Access Key ID, 発行された API Token を sha256 したものが Secret Access Key でした。

9sako69sako6

後述の outputs.tf がわかりやすいです。

9sako69sako6

例:

module/cloudflare_account_token/outputs.tf
output "token" {
  value       = cloudflare_api_token.default.value
  sensitive   = true
  description = "Token value"
}

output "access_key_id" {
  value       = cloudflare_api_token.default.id
  description = "Access Key ID"
}

output "secret_access_key" {
  value       = sha256(cloudflare_api_token.default.value)
  sensitive   = true
  description = "Secret Access Key"
}

output "name" {
  value       = cloudflare_api_token.default.name
  description = "Name of the API Token"
}

module/cloudflare_account_token/main.tf
terraform {
  required_version = "~> 1.8.0"

  required_providers {
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 4.36"
    }
  }
}

resource "cloudflare_api_token" "default" {
  name = var.token_name
  policy {
    permission_groups = var.permission_groups

    resources = {
      "com.cloudflare.api.account.${var.cloudflare_account_id}" = "*"
    }
  }
}
module/cloudflare_account_token/variables.tf
variable "cloudflare_account_id" {
  description = "The Cloudflare account ID"
  type        = string
  sensitive   = true
}

variable "token_name" {
  description = "The name of the token"
  type        = string
}

variable "permission_groups" {
  description = "The permission groups for the token. https://developers.cloudflare.com/fundamentals/api/reference/permissions/"
  type        = set(string)
}

9sako69sako6

発行したトークンをどうやって provider に渡すかですが、私は R2 用 module と Token 用 module をそれぞれ用意して、R2 用 module の中に provider "aws" を書いています。

main.tf
// e.g.:
data "cloudflare_api_token_permission_groups" "all" {}

module "cloudflare_r2_token" {
  source = "../../../modules/cloudflare_account_token"

  token_name = "terraform-app-r2-management"
  permission_groups = [
    data.cloudflare_api_token_permission_groups.all.account["Workers R2 Storage Write"],
    data.cloudflare_api_token_permission_groups.all.account["Workers R2 Storage Read"],
  ]
  cloudflare_account_id = data.sops_file.secrets.data["cloudflare.account_id"]
}

module "object_storage" {
  source = "../../../modules/cloudflare_r2"

  cloudflare_r2_token             = module.cloudflare_r2_token.token
  cloudflare_r2_access_key_id     = module.cloudflare_r2_token.access_key_id
  cloudflare_r2_secret_access_key = module.cloudflare_r2_token.secret_access_key
}

modules/cloudflare_r2/main.tf
// e.g.:
provider "aws" {
  region = "APAC"

  access_key = var.cloudflare_r2_access_key_id
  secret_key = var.cloudflare_r2_secret_access_key

  skip_requesting_account_id  = true
  skip_credentials_validation = true
  skip_region_validation      = true

  endpoints {
    s3 = "https://${var.cloudflare_account_id}.r2.cloudflarestorage.com"
  }
}
このスクラップは2日前にクローズされました