Navigation
credential-types
TLS Certificates
TLS certificates in Vault
TLS certificates are pairs of a certificate (or certificate chain) and a private key. Vault stores them together as a single tls-certificate credential. On storage, Vault parses the certificate to extract the subject, issuer, validity period, and SANs (Subject Alternative Names), making it easy to track certificate lifecycles across your infrastructure.
Storing a TLS certificate
await vault.credentials.create({
name: 'api-tls-prod',
type: 'tls-certificate',
value: JSON.stringify({
certificate: `-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIU...
-----END CERTIFICATE-----`,
privateKey: `-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG...
-----END PRIVATE KEY-----`,
chain: `-----BEGIN CERTIFICATE-----
MIIFYjCCBEqgAwIBAgIM...
-----END CERTIFICATE-----`,
}),
metadata: {
domain: 'api.example.com',
environment: 'production',
issuer: 'lets-encrypt',
},
});
The value field contains a JSON object with certificate, privateKey, and an optional chain for intermediate certificates. All three are encrypted together.
Validation
Vault validates TLS certificates on storage:
- The certificate must be a valid PEM-encoded X.509 certificate.
- The private key must be a valid PEM-encoded key.
- The private key must match the certificate’s public key. If they do not match, the credential is rejected.
- If a certificate chain is provided, Vault verifies that the chain links correctly from the leaf certificate to the root.
Extracted metadata
Vault parses the certificate and adds these fields automatically:
| Field | Description | Example |
|---|---|---|
subject | The certificate’s Common Name (CN) | api.example.com |
issuer | The issuing Certificate Authority | Let's Encrypt Authority X3 |
notBefore | Certificate validity start date | 2026-01-01T00:00:00Z |
notAfter | Certificate expiration date | 2026-04-01T00:00:00Z |
sans | Subject Alternative Names, comma-separated | api.example.com,*.api.example.com |
serialNumber | Certificate serial number | 03:a1:b2:c3... |
signatureAlgo | Signature algorithm | SHA256-RSA |
Expiry tracking
The notAfter field from the certificate is particularly useful. You can query Vault for certificates approaching expiry:
const expiringSoon = await vault.credentials.list({
type: 'tls-certificate',
filter: {
'metadata.notAfter': { before: '2026-05-01T00:00:00Z' },
},
});
This query returns all TLS certificates that expire before May 2026. Combine this with a scheduled job to get expiry alerts before certificates go stale.
Leasing TLS certificates
TLS certificate leases follow the same model as other credential types. A common use case is granting a deployment agent short-term access to pull the certificate and configure a web server:
const lease = await vault.leases.create({
credentialName: 'api-tls-prod',
ttl: '10m',
identity: {
type: 'agent',
name: 'deploy-agent',
purpose: 'Configuring nginx with updated TLS certificate',
},
});
const { certificate, privateKey, chain } = JSON.parse(lease.value);
// Write to disk, configure the server, then clean up
Rotation
TLS certificate rotation happens when you renew or replace a certificate:
- Obtain the new certificate from your CA (Let’s Encrypt, internal PKI, etc.).
- Rotate the credential in Vault with the new certificate, private key, and chain.
- Active leases continue serving the old certificate until they expire.
- New leases receive the updated certificate.
await vault.credentials.rotate({
name: 'api-tls-prod',
newValue: JSON.stringify({
certificate: newCert,
privateKey: newKey,
chain: newChain,
}),
});
The zero-downtime rotation model described in Credential Model applies here. Servers holding an active lease continue serving the old certificate while new deployments pick up the renewed one.