CoursesAdvanced secrets managementDynamic secrets & crypto engines

Private PKI & short-lived certificates

Root/intermediate CAs, 24-hour leaf certs, cert-manager, CRL/OCSP.

Expert40 min · lesson 6 of 15

Certificates are secrets with an expiry built in, which makes short-lived PKI the cleanest form of secret management there is: a leaked 24-hour certificate is worthless tomorrow. Running your own certificate authority used to be a burden that pushed teams toward multi-year certs (the opposite of what you want); Vault’s PKI engine makes issuing thousands of minutes-to-hours certificates cheap and automatic, so short-lived becomes the default and rotation becomes a non-event.

Root and intermediate: keep the root offline

A sound PKI has an offline root CA that signs exactly one thing — an intermediate CA — and then goes back in the safe. The intermediate does all day-to-day issuance, so if it is ever compromised you revoke and re-issue the intermediate without re-rooting trust in every client. Vault models this directly: a root PKI mount (or an external offline root) signs a CSR from an intermediate PKI mount, and workloads only ever talk to the intermediate. The root’s private key ideally never lives in the online Vault at all.

terminal — intermediate signed by an offline root
# online intermediate mount produces a CSR
$ vault secrets enable -path=pki_int pki
$ vault write -field=csr pki_int/intermediate/generate/internal \
common_name="Acme Issuing CA" > int.csr
# offline root signs it (max 5y), you import the cert back:
$ vault write -field=certificate pki/root/sign-intermediate \
[email protected] format=pem_bundle ttl=43800h > int.pem
$ vault write pki_int/intermediate/set-signed [email protected]
# define a role: which names, which usages, how short:
$ vault write pki_int/roles/svc \
allowed_domains="svc.acme.internal" allow_subdomains=true \
max_ttl=24h key_type=ec key_bits=256

Short-lived leaf certs and automated renewal

With a role in place, issuing a certificate is one call that returns the cert, its private key, and the CA chain — all ephemeral. Workloads request a fresh cert on startup and renew well before expiry; because certs live hours, you rarely need a revocation list at all — expiry does the work. This is the mTLS story for service meshes and internal APIs: every service presents a short-lived cert tied to its identity, and trust flows from the shared intermediate. cert-manager’s Vault issuer automates the whole loop inside Kubernetes.

k8s — cert-manager issues from Vault, auto-renews
apiVersion: cert-manager.io/v1
kind: Certificate
metadata: { name: payments-tls, namespace: prod }
spec:
secretName: payments-tls
duration: 24h
renewBefore: 8h # renew with a third of life left
commonName: payments.svc.acme.internal
issuerRef: { name: vault-int, kind: ClusterIssuer }
# the pod always has a valid, hours-old cert; no human in the loop.
Long-lived vs short-lived PKI
long-lived (2-year) certs
manual issuance
tickets, spreadsheets
revocation matters
CRL/OCSP must work
leak = 2-year problem
race to revoke
short-lived (24h) certs
automated issuance
cert-manager / agent
expiry does the work
revocation rarely needed
leak = tomorrow it is dead
non-event
The best revocation strategy is a short lifetime. CRL/OCSP is the backstop, not the plan.

Revocation, CRL/OCSP, and the backstop

You still need revocation for the case where a short-lived cert is compromised inside its window or a role is misconfigured. Vault maintains a CRL and can serve OCSP; clients that check them can reject a revoked cert before expiry. But CRL/OCSP is notoriously fragile — soft-fail clients ignore an unreachable responder — so treat it as a backstop and let short TTLs be the primary control. For public-facing certs, ACME (including Vault’s ACME support and Let’s Encrypt) automates issuance and renewal against publicly-trusted roots.

Guard allowed_domains and key usage on every role
A PKI role that allows too-broad domains or arbitrary common names is an authority-to-impersonate anything inside your trust boundary. Scope allowed_domains, disable allow_any_name, restrict key usages and max_ttl per role, and never let a service role sign intermediates or clients it should not. The CA is a trust root — a loose issuing role hands attackers a valid certificate for names they do not own.