Skip to main content

Field binding (AAD)

Field binding is defence-in-depth for the credential and key material CertAutoPilot stores for you: ACME account keys and EAB keys, certificate private keys, DNS, discovery-DNS, MSCA and module credentials, notification channel config, project variables, and TOTP secrets. It ties those values to the exact (collection, field) they live in, using AES-GCM Additional Authenticated Data, so once binding is enabled and your data has been rotated, such a value no longer decrypts if it is moved to a different field.

Two qualifications, both deliberate. Values written before binding was enabled keep their previous form until a rotation re-seals them, and they stay readable throughout. And a few encrypted fields are outside the covered set — the license material and the syslog TLS material — so they are rotated normally but never bound.

It is layered on top of — not a substitute for — protecting database access.

Enabling it — order matters

Binding is controlled by a single setting, off by default:

encryption:
aad_binding: false # env: CERTAUTOPILOT_ENCRYPTION_AAD_BINDING

Reads always understand both bound and legacy (unbound) values, so turning binding on never makes existing data unreadable. Only the write side is gated. This lets you roll it out safely on a multi-replica / HA fleet:

  1. Upgrade the whole fleet to a binding-capable build with aad_binding still off. Every replica can now read bound values; none writes them yet.
  2. Once no older build remains, set aad_binding: true and restart. New writes are now bound.
  3. Run a KEK rotation (certautopilot kek rotate --to-version=<N>) — it re-seals the covered fields into the bound form as it goes. Fields outside the covered set are rotated normally and keep their existing form, so finding unbound envelopes afterwards is expected, not a sign the rollout failed.

:::warning Do not skip step 1 If you turn aad_binding on while an older build is still running (for example mid–rolling-upgrade), that older replica cannot read a bound value a newer replica writes, and operations touching it will fail until the fleet is uniform. Keep it off until every process is upgraded. :::

Rolling back to the previous build is safe as long as aad_binding was never turned on — nothing bound was written. Once binding has been enabled and data rotated, a downgrade to a build that predates field binding is not supported.