Skip to content

cloudflare_api_token: add write-only support for value attribute to prevent state exposure #6964

@josefguenther

Description

@josefguenther

Confirmation

  • This is a bug with an existing resource and is not a feature request or enhancement. Feature requests should be submitted with Cloudflare Support or your account team.
  • I have searched the issue tracker and my issue isn't already found.
  • I have replicated my issue using the latest version of the provider and it is still present.

Terraform and Cloudflare provider version

Provider version: 5.19.0

Affected resource(s)

The value attribute on cloudflare_api_token (and cloudflare_account_token) is marked as Read-Only and Sensitive, but the actual token value is stored in plaintext in the Terraform state file. There is no value_wo (write-only) alternative, meaning there is no way to create API tokens via Terraform without persisting the secret token value in state.

This is a security concern for teams that store state in S3 or other remote backends, as the token value is fully readable by anyone with access to the state file.

Terraform configuration files

resource "cloudflare_api_token" "example" {
  name = "my-scoped-token"

  policies = [{
    effect = "allow"
    permission_groups = [{
      id = "some-permission-group-id"
    }]
    resources = jsonencode({
      "com.cloudflare.api.account.zone.*" = "*"
    })
  }]
}

# The token value must be read from state — there is no write-only alternative
output "token_value" {
  value     = cloudflare_api_token.example.value
  sensitive = true
}

Link to debug output

n/a

Panic output

No response

Expected output

The token value should not be persisted in the Terraform state file. Two possible approaches:

Option A: New stateless resource variant

A new resource (e.g. cloudflare_api_token_stateless) with a value_wo write-only attribute instead of value. The token is still a managed resource tracked in state, but the secret value is only available in memory during the apply that creates it:

resource "cloudflare_api_token_stateless" "ops" {
  name     = "my-scoped-token"
  policies = [{ ... }]
}

resource "aws_secretsmanager_secret_version" "token" {
  secret_id                = aws_secretsmanager_secret.token.id
  secret_string_wo         = cloudflare_api_token_stateless.ops.value_wo
  secret_string_wo_version = 1
}

This is a non-breaking opt-in for state-sensitive workflows.

Option B: Suppress flag on existing resource

An optional flag on the existing resource that nulls out value before writing to state:

resource "cloudflare_api_token" "ops" {
  name                      = "my-scoped-token"
  suppress_value_in_state   = true
  policies                  = [{ ... }]
}

Simpler migration path, but may require Terraform plugin framework support for conditionally write-only attributes.

In both cases, the token resource itself (id, policies, status, etc.) remains in state as normal — only the secret value is excluded.

Actual output

The value attribute is the only way to access the created token. It is stored in the Terraform state file in plaintext, regardless of the sensitive = true marking. The only workaround is to create tokens outside of Terraform entirely (via API or CLI) and import them as references.

Steps to reproduce

  1. Create a cloudflare_api_token resource
  2. Run terraform apply
  3. Inspect the state file (terraform state pull | jq)
  4. Observe the value attribute contains the full token in plaintext

Additional factoids

The AWS provider already implements this pattern for aws_secretsmanager_secret_version with secret_string_wo, and for aws_iam_access_key with secret_wo. The Terraform plugin framework supports write-only attributes as of Terraform 1.11. This would bring cloudflare_api_token in line with how other providers handle generated secrets.

References

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions