Terraform and secrets: keep the Sume API key out of state
Terraform's sensitive flag hides a value from logs but still writes it to state. How to handle a Sume API key and webhook signing secret without that leak.

No: marking a Terraform variable sensitive does not keep a Sume API key out of your state file. HashiCorp's page on managing sensitive data says Terraform stores sensitive values in state and plan files, and that anyone who can read those files can read the values (read 2026-10-10). The flag only redacts the value from CLI output and the HCP Terraform UI.
The safe pattern for a Sume key or webhook signing secret is to keep the value out of the configuration entirely, or to pass it as an ephemeral value or a write-only argument, which that page says Terraform omits from state and plan files. This post shows which Sume secrets you would be handling and where each one should live.
The two Sume secrets a deploy touches
A Sume integration usually has two secrets. The first is the API key your server sends on every call. Sume's API keys page says the dashboard shows the full secret only when you create a key, and tells you to store it immediately in a secure secret manager. The second is the webhook signing secret, which your receiver uses to check sume-v1 signatures.
Neither one is something Terraform needs to generate. You create the key in the dashboard, and Sume derives the signing secret for your workspace, so you read it from the Webhooks tab or from GET /v1/webhooks/signing-secret with a key that has account:read. Terraform's job is to put each value into your secret store and wire the name into the runtime, not to mint it.
| Mechanism | Value in state or plan file? | Fit for a Sume secret |
|---|---|---|
| Plain value in configuration | Yes, stored in state and plan files | No |
Variable or output with sensitive | Yes; only CLI output and the HCP Terraform UI are redacted | No, it hides the value but does not remove it |
ephemeral variable, ephemeral block | No, omitted from state and plan files | Yes, for values needed only during the run |
| Write-only argument on a managed resource | No, not persisted to state or plan files | Yes, where the resource supports it |
| Create an empty secret container, set the value outside Terraform | Not in the configuration at all | Yes, and the simplest |
A split that keeps both secrets out of state
Let Terraform own the shape and a separate step own the value. Terraform creates the secret entry and grants your function or container permission to read it. You then write the actual Sume key into that entry from your shell or a secrets tool, and the runtime reads it into the environment variable your code expects.
Use the names Sume's docs use. The signing secret is stored as SUME_COM_WEBHOOK_SIGNING_SECRET, the same name the Sume delivery worker uses, and the API key is read from SUME_API_KEY in Sume's examples. Matching names means a sample from the docs runs against your deployment with no renaming.
If you do pass a value through Terraform, use the ephemeral or write-only route from the table, and check the provider documentation for the specific resource, because support for write-only arguments differs by resource. This post does not assume any particular provider supports it.
Rotation without a Terraform apply
Sume's rotation steps are independent of your infrastructure code, which is a good reason not to bake keys into it. For an API key, the Authentication page says to create a replacement key, deploy it to your server, check it with GET /v1/me, then revoke the old one from the dashboard.
For the webhook signing secret, rotation is not a cutover. For 24 hours after POST /v1/webhooks/signing-secret/rotate, Sume signs each delivery with both the new and the previous secret and sends both in x-sume-webhook-signature, newest first. A receiver holding either secret can verify, so you can update the stored secret on your own schedule. The verifying webhooks page warns that a hand-written verifier that compares the header for equality fails on every delivery during the window, so upgrade the receiver before you rotate.
Checks to run on your repository
Four checks catch most leaks before they matter.
- Search your state backend's access list. Anyone who can read state can read any non-ephemeral value in it, per HashiCorp's page.
- Search the configuration and variable files for
sume_style key prefixes and for the signing secret, which is 64 hex characters. - Compare fingerprints, not secrets, when a signature fails. Every delivery carries
x-sume-webhook-secret-fingerprint, and the dashboard shows the same fingerprint beside the secret, so you can confirm both sides hold the same value without pasting it. - Give the key only the scope the job needs. Sume fixes a key's scopes when you create it, so a deploy that only reads job status should not share a key with one that submits paid work.
What this does not cover
This post covers where the two Sume secrets live, not a Terraform provider for Sume, and none is assumed. Sume's job and run webhooks share one signing secret, so a single stored value covers both receivers. If you run separate workspaces for staging and production, each has its own derived secret and its own key.
Sources
Related posts
More in Developers
- Compose 400: stack and overlay layout keys cannot be mixed
Fix compose_stack_takes_no_overlay_layout and its mirror: pick stack or overlay as operation, then send only the layout keys that belong to it.
- Timeline 400: first slot must start at 0 and take no transition
Fix timeline_must_start_at_zero and transition_on_first_segment: start video[0] at 0, use source_in to skip, put fades on slot two, then plan for free.
- TTS output_format: choose wav or mp3 for joins, captions and clips
Sume TTS returns mp3 by default. Choose wav when you will join, slice per sentence or feed lip-sync; mp3 is smaller but adds padding at every edge.
- Twenty image jobs, one webhook: mode webhook plus a Python verifier
Submit 20 image requests with mode webhook, receive signed job.completed callbacks, and verify them in Python. Retries, replay window and the poll fallback.
Written by Sume