Extract the first 5 issuer per-connector deep-dive pages: - vault.md (128 lines) — Vault PKI synchronous issuance, token TTL + auto-renewal loop, MaxTTL enforcement, rotation playbook - digicert.md (106 lines) — CertCentral DV/OV/EV with bounded async polling for vetting workflows - aws-acm-pca.md (165 lines) — managed private CA on AWS with full IAM policy, IRSA wiring, troubleshooting matrix - ejbca.md (116 lines) — open-source / Keyfactor EJBCA with mTLS or OAuth2 auth, mTLS keypair caching, approval-pending guidance - adcs.md (111 lines) — Active Directory Certificate Services as enterprise root via Local CA sub-CA mode, sub-CA rotation playbook Index updated with forward-list entries and the index-purpose blurb revised so the index now positions itself as 'navigate from here; deeper material lives in siblings' rather than 'docs to be extracted later'. Each per-page follows the WHAT/HOW/WHY pattern: what the connector is, how authentication and issuance work, and when to choose this vs an alternative. Cross-links to the connector index, async-ca-polling primitive, and adjacent operator runbooks. This is part 1 of 4 for the Phase 4 follow-on (per-connector page extraction) tracked in cowork/docs-overhaul-phase-2-restructure-2026-05-04/log.md. Net add: 5 files, 626 lines. No content removed from index.md (the index keeps its inline reference; per-pages add operator depth on top, matching the pattern set by apache/f5/iis/k8s/nginx in Phase 4 structural).
5.3 KiB
Vault PKI Issuer Connector — Operator Deep-Dive
Last reviewed: 2026-05-05
Operator-grade documentation for the HashiCorp Vault PKI issuer connector. For the connector-development context (interface contract, registry, ports/adapters), see the connector index.
Overview
The Vault PKI connector integrates with HashiCorp Vault's PKI secrets
engine using its native /sign API with token-based authentication.
The flow is purely synchronous — Vault returns the signed certificate
in the same HTTP response that submits the CSR — so there is no
challenge-solving or async polling on the certctl side.
Implementation lives at internal/connector/issuer/vault/. The
factory key is Vault; the registry binds it under whatever issuer
ID the operator picks (e.g. iss-vault).
When to use this connector
Use the Vault PKI connector when:
- Your organization already runs Vault as the system of record for internal certificates.
- You want a synchronous, low-latency issuance path with no challenge flow (no DNS records, no HTTP-01).
- You want certctl to manage the lifecycle (renewal scheduling, deployment, alerts) while Vault keeps the signing material.
Look elsewhere when:
- Public-trust certificates are required — Vault PKI is internal-only. Use ACME (Let's Encrypt, ZeroSSL, Sectigo) or DigiCert / Sectigo SCM for public-trust workloads.
- The Vault PKI engine is not already deployed and you don't want to run Vault. The Local CA issuer is a simpler self-contained path for small internal CAs.
Configuration
| Variable | Default | Description |
|---|---|---|
CERTCTL_VAULT_ADDR |
— | Vault server address (e.g. https://vault.internal:8200) |
CERTCTL_VAULT_TOKEN |
— | Vault auth token with permissions on the PKI mount |
CERTCTL_VAULT_MOUNT |
pki |
PKI secrets engine mount path |
CERTCTL_VAULT_ROLE |
— | PKI role name for certificate signing |
CERTCTL_VAULT_TTL |
8760h |
Certificate validity period (TTL) |
Vault issues certificates synchronously via the
/v1/{mount}/sign/{role} API with X-Vault-Token header
authentication. The issued certificate is parsed to extract serial
number, validity dates, and chain information.
Token TTL and automatic renewal
This was Top-10 fix #5 from the 2026-05-03 issuer-coverage audit.
certctl-server periodically calls POST /v1/auth/token/renew-self at
half the token's TTL to keep the integration alive without manual
rotation. The cadence is read from a one-shot lookup-self at
startup and re-derived on every successful renewal — so a short
bootstrap token that gets renewed up to a longer Max TTL shifts to
the longer cadence automatically.
The renewal loop emits the
certctl_vault_token_renewals_total{result="success"|"failure"|"not_renewable"}
Prometheus counter so operators see expiry trouble in Grafana before
issuance breaks.
When Vault returns renewable: false (configured Max TTL reached),
the loop logs a WARN, increments {result="not_renewable"}, and
exits. The operator must rotate the Vault token and either restart
certctl-server or use the GUI / MCP issuer-update path to swap the
token in place — the registry's Rebuild path re-Starts the lifecycle
on the new connector.
Per-tick failures (e.g. transient 5xx, brief network blips) bump
{result="failure"} and the loop keeps ticking. Only the explicit
renewable: false case stops it.
MaxTTL enforcement (M11c)
When a certificate profile defines a maximum TTL, the Vault connector overrides the TTL string in the signing request to ensure the issued certificate does not exceed the profile limit. This is applied before Vault's own role-level max TTL — so the effective limit is the minimum of (profile.MaxTTL, role.MaxLeaseTTL).
Revocation and CRL/OCSP
CRL and OCSP are managed by Vault itself. Clients should validate
certificate status against Vault's own CRL/OCSP endpoints
(GET /v1/{mount}/crl and Vault's OCSP responder). certctl does not
generate local CRL/OCSP for Vault-issued certificates. Revocation is
recorded locally (audit row + cert state) but Vault is the
authoritative source for relying parties.
Operator playbook
Token rotation without downtime
Two paths:
- Restart-driven. Update
CERTCTL_VAULT_TOKENenv var on the server, restart certctl-server. The renewal loop picks up the new token's lookup-self response and resumes ticking. - Hot-swap via API/GUI.
PUT /api/v1/issuers/{id}with the updated config; the registry's Rebuild path replaces the connector without restart. Use this when Vault's Max TTL has been reached and the existing token can no longer be renewed.
Diagnosing renewal failures
Watch
certctl_vault_token_renewals_total{result="not_renewable"} and
{result="failure"}. Sustained failures with no not_renewable
generally indicate Vault unreachability or token-policy drift; a
spike in not_renewable is the canonical signal that a Max TTL
boundary was hit and operator action is required.
Related docs
- Connector index — interface contract, registry, port/adapter wiring
- Issuer hierarchy primitive — how Vault sits as a sub-CA under another issuer
- Async CA polling — the bounded-polling primitive used by other issuers; Vault is synchronous so does not consume it