# Récupère toutes les permissions Cloudflare disponibles data "cloudflare_account_api_token_permission_groups_list" "all" { account_id = var.account_id } # Sélectionne uniquement les permissions demandées locals { # Simplifie le scope Cloudflare (ex: "account" depuis "com.cloudflare.api.account") permission_map = { for p in data.cloudflare_account_api_token_permission_groups_list.all.result : "${split(".", p.scopes[0])[length(split(".", p.scopes[0])) - 1]}:${p.name}" => p.id } permission_map_from_id = zipmap(values(local.permission_map), keys(local.permission_map)) # Résout les permissions (si présentes) pour chaque catégorie selected_account_permissions = var.permissions.account != null ? compact([ for name in var.permissions.account : lookup(local.permission_map, name, null) ]) : [] selected_bucket_permissions = var.bucket != null && try(var.permissions.bucket, null) != null ? compact([ for name in var.permissions.bucket : lookup(local.permission_map, name, null) ]) : [] # Validation des permissions introuvables missing_permissions = concat( [for name in coalesce(var.permissions.account, []) : name if lookup(local.permission_map, name, null) == null], [for name in coalesce(var.permissions.bucket, []) : name if lookup(local.permission_map, name, null) == null] ) # Ressources cibles account_resource = { "com.cloudflare.api.account.${var.account_id}" = "*" } bucket_resource = var.bucket != null ? { "com.cloudflare.edge.r2.bucket.${var.account_id}_${var.bucket.jurisdiction}_${var.bucket.name}" = "*" } : {} # Policies construites dynamiquement policies = [for policy in [ length(local.selected_account_permissions) > 0 ? { effect = "allow" permission_groups = [for id in local.selected_account_permissions : { id = id }] resources = local.account_resource } : null, length(local.selected_bucket_permissions) > 0 ? { effect = "allow" permission_groups = [for id in local.selected_bucket_permissions : { id = id }] resources = local.bucket_resource } : null ] : policy if policy != null] error_message = length(local.missing_permissions) > 0 ? format("Permissions introuvables : %s", join(", ", local.missing_permissions)) : "" } # Création du token resource "cloudflare_account_token" "token" { account_id = var.account_id name = var.token_name policies = local.policies expires_on = null lifecycle { ignore_changes = [expires_on, policies] # ignore permission id change as unstable replace_triggered_by = [null_resource.cloudflare_account_token_replace] # replace permission name change d precondition { condition = length(local.missing_permissions) == 0 error_message = local.error_message } } } resource "null_resource" "cloudflare_account_token_replace" { # replace token when permission names change triggers = { "account_permissions" = sha256(join("", sort([for p_id in local.selected_account_permissions : lookup(local.permission_map_from_id, p_id)]))) "bucket_permissions" = sha256(join("", sort([for p_id in local.selected_bucket_permissions : lookup(local.permission_map_from_id, p_id)]))) } }