HashiCorp Vault — Root & Intermediate CA
Build a proper two-tier PKI hierarchy: a root CA that signs an intermediate CA, which in turn issues end-entity certificates.
Step 1 — Generate Root CA
# Generate root CA (key stays inside Vault)
vault write pki/root/generate/internal \
common_name="My Organization Root CA" \
issuer_name="root-2024" \
ttl=87600h \
key_bits=4096
Expected output:
Key Value
--- -----
certificate -----BEGIN CERTIFICATE-----
MIIFaz...
-----END CERTIFICATE-----
expiration 1895587200
issuer_id abc123
issuer_name root-2024
issuing_ca -----BEGIN CERTIFICATE-----...
key_id def456
serial_number 12:34:56:78:...
Configure CA URLs
vault write pki/config/urls \
issuing_certificates="$VAULT_ADDR/v1/pki/ca" \
crl_distribution_points="$VAULT_ADDR/v1/pki/crl"
Step 2 — Generate Intermediate CA
# Generate CSR for intermediate CA
vault write -format=json pki_int/intermediate/generate/internal \
common_name="My Organization Intermediate CA" \
issuer_name="intermediate-2024" \
key_bits=4096 | jq -r '.data.csr' > /tmp/pki_int.csr
Step 3 — Sign Intermediate with Root
# Root CA signs the intermediate CSR
vault write -format=json pki/root/sign-intermediate \
issuer_ref="root-2024" \
csr=@/tmp/pki_int.csr \
format=pem_bundle \
ttl=26280h | jq -r '.data.certificate' > /tmp/intermediate.cert.pem
Step 4 — Import Signed Intermediate
# Import the signed certificate back into the intermediate mount
vault write pki_int/intermediate/set-signed \
certificate=@/tmp/intermediate.cert.pem
Configure Intermediate URLs
vault write pki_int/config/urls \
issuing_certificates="$VAULT_ADDR/v1/pki_int/ca" \
crl_distribution_points="$VAULT_ADDR/v1/pki_int/crl"
Verify the Hierarchy
# Read root CA
vault read -field=certificate pki/ca/pem > /tmp/root-ca.pem
# Read intermediate CA
vault read -field=certificate pki_int/ca/pem > /tmp/int-ca.pem
# Verify chain
openssl verify -CAfile /tmp/root-ca.pem /tmp/int-ca.pem
# /tmp/int-ca.pem: OK
Using an External Root CA
If your organization already has a root CA:
# 1. Generate CSR from Vault
vault write -format=json pki_int/intermediate/generate/internal \
common_name="Vault Intermediate CA" | jq -r '.data.csr' > vault-int.csr
# 2. Sign the CSR with your external CA (outside Vault)
# openssl, cfssl, or your CA tooling
# 3. Import the signed cert
vault write pki_int/intermediate/set-signed \
certificate=@signed-intermediate.pem
Complete Setup Script
#!/bin/bash
# setup-pki.sh — Complete PKI hierarchy setup
set -e
echo "=== Setting up Root CA ==="
vault secrets enable pki
vault secrets tune -max-lease-ttl=87600h pki
vault write pki/root/generate/internal \
common_name="My Org Root CA" \
issuer_name="root-2024" \
ttl=87600h
vault write pki/config/urls \
issuing_certificates="$VAULT_ADDR/v1/pki/ca" \
crl_distribution_points="$VAULT_ADDR/v1/pki/crl"
echo "=== Setting up Intermediate CA ==="
vault secrets enable -path=pki_int pki
vault secrets tune -max-lease-ttl=26280h pki_int
vault write -format=json pki_int/intermediate/generate/internal \
common_name="My Org Intermediate CA" \
issuer_name="intermediate-2024" | jq -r '.data.csr' > /tmp/pki_int.csr
vault write -format=json pki/root/sign-intermediate \
issuer_ref="root-2024" \
csr=@/tmp/pki_int.csr \
format=pem_bundle \
ttl=26280h | jq -r '.data.certificate' > /tmp/intermediate.cert.pem
vault write pki_int/intermediate/set-signed \
certificate=@/tmp/intermediate.cert.pem
vault write pki_int/config/urls \
issuing_certificates="$VAULT_ADDR/v1/pki_int/ca" \
crl_distribution_points="$VAULT_ADDR/v1/pki_int/crl"
echo "=== PKI Hierarchy Ready ==="
rm -f /tmp/pki_int.csr /tmp/intermediate.cert.pem
Quick Reference
| Command | Description |
|---|---|
vault write pki/root/generate/internal ... |
Generate root CA |
vault write pki_int/intermediate/generate/internal ... |
Generate intermediate CSR |
vault write pki/root/sign-intermediate ... |
Sign intermediate |
vault write pki_int/intermediate/set-signed ... |
Import signed cert |
Next: Issuing Certificates