Key lifecycle and compromise model
A derived client key has exactly one job: proving, per request, that the caller possesses the private key that Control issued at enrollment. Everything on this page follows from keeping three different lifetimes separate — the enrollment policy’s maximum key lifetime, the identity proof’s expiry, and the per-request passport TTL — and from being precise about what enrollment did and did not prove. If you have not read Two trust planes yet, start there: this page is about keys on the enrollment plane, not about per-request route-source authorization.
The lifetimes, kept separate
Section titled “The lifetimes, kept separate”Enrollment-policy maximum key lifetime
Section titled “Enrollment-policy maximum key lifetime”An Enrollment Policy carries a maximum key lifetime in seconds. It bounds the derived signing-key lifetime — the workload does not choose its own key lifetime with a CLI flag. In the current flow the bound is joint with the identity proof:
effective key expiry = earlier of (policy maximum key lifetime, proof expiry)A 30-day policy maximum does not produce a 30-day key when the proof — for example a projected ServiceAccount token — expires in one hour. Enrollment reports the resulting expiration back as non-secret metadata, alongside the key’s active status, key ID, and fingerprint, so the effective expiry is never a guess. See the OIDC JWKS enrollment runbook for where this shows up in practice.
trustplane sign --ttl — one request, never the key
Section titled “trustplane sign --ttl — one request, never the key”trustplane sign --ttl bounds one signed request/passport. It never
extends, shortens, or otherwise affects the derived key’s lifetime. A short --ttl limits how
long a single signed request remains replayable; it says nothing about how long the key that
signed it stays valid. Do not tune --ttl expecting a key-lifetime effect, and do not read a
long key lifetime as permission to mint long-lived passports.
Lifecycle states
Section titled “Lifecycle states”stateDiagram-v2 direction LR [*] --> created created --> active : activation active --> expiring : refresh window opens expiring --> renewed : re-enroll before expiry renewed --> active expiring --> expired : expiry reached active --> revoked : operator revokes expiring --> revoked : operator revokes expired --> [*] revoked --> [*]
- created → active —
trustplane enrollcreates or reuses the local Ed25519 key, submits the proof, and (with--wait-for-activation, the default) polls until the derived key is active. - active → expiring — the key approaches its effective expiry (the earlier of policy maximum and proof expiry).
- expiring → renewed — re-enrollment before expiry produces a fresh derived key; the workload keeps signing without an outage window.
- expiring → expired — a key that reaches expiry stops authorizing requests; signed requests under it are denied.
- active/expiring → revoked — an operator revokes the key in Control; revocation ends the key regardless of remaining lifetime.
Expiration
Section titled “Expiration”Expiry is enforced from the effective expiry computed at enrollment. After it, requests signed with the key are denied — key status is one of the three things that authorize a runtime request (possession, key status, route policy). Expiry is the safety net, not the rotation mechanism: plan renewal so workloads never coast into it.
Revocation
Section titled “Revocation”Revoke key in the Client Vault is a typed-confirmation action: it revokes the key and its active route grants, and Auth Site bundle propagation runs automatically. Deactivating a whole client revokes its active keys and route grants the same way. Revocation is the correct response to compromise — it does not wait for the clock.
Renewal and re-enrollment
Section titled “Renewal and re-enrollment”Renewal is re-enrollment: run trustplane enroll again with fresh
proof before the current key expires.
--refresh-skewsupports renew-before-expiry — the CLI re-enrolls when the cached enrollment state is within the skew window of expiry, so long-running workloads can run enrollment on a loop and only pay for it when renewal is actually due.--force-reenrollforces a fresh enrollment even when cached state looks current. Use it deliberately (for example, after confirming a previous attempt did not persist), not as a routine retry.- On compromise: revoke, then re-enroll. Revoke the compromised key in Control first so it stops authorizing immediately, then re-enroll the workload with fresh proof to issue a replacement.
Automated renewal (--refresh-skew) is required for production deployment for any workload
that outlives its proof token — under the current capped-lifetime model, short-lived proofs
mean short-lived keys.
What enrollment proves — and when
Section titled “What enrollment proves — and when”Enrollment validates workload evidence once, at enrollment time. A Control enrollment Trust Anchor Source verifies the proof (for example, a projected ServiceAccount token against a cluster’s OIDC JWKS), and a derived client key is issued. Enrollment does not itself prove that each subsequent request came from the original workload. After enrollment, what authorizes a runtime request is possession of the derived private key, the key’s status in Control, and route policy.
A stolen or exported derived private key may be usable from another network location until it expires or is revoked, unless runtime provenance/device binding or network restrictions are additionally enforced. Do not describe a derived key as “pod-bound” after enrollment — the enrollment proof was pod-bound; continued use of the key is bound only by possession, key status, route policy, and whatever additional controls you enforce.
Recommended controls
Section titled “Recommended controls”These controls are required for production deployment. They shrink the window and blast radius of a stolen key; none of them changes the model above.
- Short lifetimes — set the enrollment-policy maximum key lifetime low and let short proof expiry cap it further; a stolen key that expires in hours is a smaller problem than one that expires in weeks.
- Rotation — renew on a loop with
--refresh-skewso short lifetimes are operationally cheap. - Non-exportable storage where available — prefer non-exportable or tightly-permissioned
key storage; the private key file is written mode
0600inside the workload, keep it that way. - No key copies — never copy the private key off the workload: not to an operator laptop, not into a ticket, not into logs.
- Network restrictions as defense in depth — default-deny upstream ingress and restricted adapter egress limit where a stolen key can even be exercised from; see Network hardening. Network controls are defense in depth, not a substitute for expiry and revocation.
Next steps
Section titled “Next steps”- Two trust planes — the enrollment plane vs the request plane, and what each proves
- OIDC JWKS enrollment runbook — the supported end-to-end enrollment flow, including derived-key lifetime in practice
- Client Vault — key status, revocation, and propagation readiness
- Network hardening — the network layer of defense in depth
- Audit — reading the deny that a revoked or expired key produces