Skip to main content

Vault PKI CLI

1. Generate Root Certificate

Enable pki_ca path

vault secrets enable -path=pki_ca pki
# Success! Enabled the pki secrets engine at: pki_ca/

Modify the TTL

tip

It is essential to increase the values of -max-lease-ttl and -default-lease-ttl to extend the lifetime of certificates, otherwise ttl and max_ttl will not apply and may appear as a bug.

vault secrets tune -max-lease-ttl=87600h -default-lease-ttl=87600h pki_ca
# Success! Tuned the secrets engine at: pki_ca/

Generate the certificate

vault write -field=certificate pki_ca/root/generate/internal \
max_path_length=1 common_name="My Root CA" ttl=87600h \
key_bits=2048 > ca.crt

Certificate verification

openssl x509 -in ca.crt -text -noout
# cat CA_cert.crt
-----BEGIN CERTIFICATE-----
MIIDJjCCAg6gAwIBAgIUTMR1ILXw5KCUsB+fAzCIZIdos4UwDQYJKoZIhvcNAQEL
BQAwGTEXMBUGA1UEAxMOR2VuZ2FyIFJvb3QgQ0EwHhcNMjUwNDI4MTEyMjE5WhcN
MzUwNDI2MTEyMjMxWjAZMRcwFQYDVQQDEw5HZW5nYXIgUm9vdCBDQTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBANHMdT3ekYlmYTiHJDit9LSYdGCsU5f0
hHZw2DgJ436Z5vtxnBUu1kkDY+AQutmrj6TLC37TqdPCRPgMo9Wz+IJNVWP1C8Jz
Ov+/x82VhcHDZeelSESY28tFZmta38sqX/wqUtK5ai7agL2PqZCEfwjZpS+fRahJ
TDo1xYWc2/Mi/BWMWIPboDk9+KmB1lKiA5NwmUSulUAwOXm815+bVNcoje79UeEX
YjuVzIMO9B7Y0PwG9mGTPl9Yfr2jabV892v+lfLFpDCikuFO+TsR1eZGCZb6ittc
aaNCZQsGI4Sgklm3LDFWN6A1ftGbjqL/6Uv8QbnHgpkBPINFV4LsT00CAwEAAaNm
MGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE
FESREPC3YKflZwARjMlAr4p24T2RMB8GA1UdIwQYMBaAFESREPC3YKflZwARjMlA
r4p24T2RMA0GCSqGSIb3DQEBCwUAA4IBAQAqYkT0pM9z3VrtCM4IxmVc1oUwTnSo
8GEd3uOr6Png6xWs91hCJp2W2IrV+nKY3mOnP4GrAs4teRJf+pXmAKKVWtcNSQ25
IVk3yw82biKa4jWbfMP05DX7kP/ujBXLu5f9Awg3lU1TtIMPi8czxNjGowLXhLSG
5D4dHwpNaCDj0KXKp66+uoyChfty2BcViu5o0dufHAh886szKGOifEjX2YxRo9+q
OaEQfm79w/NCP+9e5CTx2KsdGHumLwy49wFwJfZp3dmUmTtlfIRCt3ZML1KSeuyy
1VGbLv7MUebKIJYMWpkCnaaJnZrEbQvZZ9/5ztmxLEOODIY8RYciIK6u

Configure HTTP access to certificates

vault write pki_ca/config/urls \
issuing_certificates="https://${VAULT_ADDRESS}/v1/pki_ca/ca" \
crl_distribution_points="https://${VAULT_ADDRESS}/v1/pki_ca/crl"
vault write pki_ca/config/crl expiry="4380h"

Key Value
--- -----
auto_rebuild false
auto_rebuild_grace_period 12h
cross_cluster_revocation false
delta_rebuild_interval 15m
disable false
enable_delta false
expiry 4380h
max_crl_entries 100000
ocsp_disable false
ocsp_expiry 12h
unified_crl false
unified_crl_on_existing_paths false
vault read pki_gnr_ca/crl/rotate
Key Value
--- -----
success true

Create an intermediate root certificate

vault secrets enable -path=pki_int_gnr_ca pki
# Success! Enabled the pki secrets engine at: pki_int_gnr_ca/
vault secrets tune -max-lease-ttl=43800h pki_int_gnr_ca
# Success! Tuned the secrets engine at: pki_int_gnr_ca/
vault write -format=json pki_int_gnr_ca/intermediate/generate/internal common_name="Intermediate Authority" ttl=43800h | jq -r '.data.csr' > ca_int.csr

Generate the signed certificate

vault write -format=json pki_gnr_ca/root/sign-intermediate key_bits=2048 common_name="CA Int Root Issuing CA" csr=@ca_int.csr format=pem_bundle ttl="43800h" | jq -r '.data.certificate' > ca_int.cert.pem
vault write pki_int_gnr_ca/config/urls issuing_certificates="${VAULT_ADDR}/v1/pki_int_gnr_ca/ca" crl_distribution_points="${VAULT_ADDR}/v1/pki_int_gnr_ca/crl"

### Result

Key Value
--- -----
crl_distribution_points [https://address:port/v1/pki_int_gnr_ca/crl]
enable_templating false
issuing_certificates [https://address:port/v1/pki_int_gnr_ca/ca]
ocsp_servers []

Set expiration delay

vault write pki_int_gnr_ca/config/crl expiry="4380h"

Verification

vault read pki_int_gnr_ca/crl/rotate
# Result
Key Value
--- -----
success true
vault write pki_int_gnr_ca/roles/Issuer allow_any_name=True server_flag=False \ 
client_flag=False allow_subdomains=false ou="TO_DEFINE_FOR_NEED"
organization="TO_DEFINE_FOR_NEED" country="GB" key_usage="DigitalSignature,
KeyEncipherment" use_csr_common_name=true ext_key_usage="" ext_key_usage_oids=""
ttl="4380h" max_ttl="4380h" enforce_hostnames=false allow_bare_domains=true
# Result
Key Value
--- -----
allow_any_name true
allow_bare_domains true
allow_glob_domains false
allow_ip_sans true
allow_localhost true
allow_subdomains false
allow_token_displayname false
allow_wildcard_certificates true
allowed_domains []
allowed_domains_template false
allowed_other_sans []
allowed_serial_numbers []
allowed_uri_sans []
allowed_uri_sans_template false
allowed_user_ids []
basic_constraints_valid_for_non_ca false
client_flag false
cn_validations [email hostname]
code_signing_flag false
country []
email_protection_flag false
enforce_hostnames false
ext_key_usage []
ext_key_usage_oids []
generate_lease false
issuer_ref default
key_bits 2048
key_type rsa
key_usage [DigitalSignature KeyEncipherment]
locality []
max_ttl 4380h
no_store false
not_after n/a
not_before_duration 30s
organization []
ou []
policy_identifiers []
postal_code []
province []
require_cn true
serial_number_source json-csr
server_flag false
signature_bits 256
street_address []
ttl 4380h
use_csr_common_name true
use_csr_sans true
use_pss false

Issue a test certificate

vault write -format=json pki_int_gnr_ca/issue/Issuer name="Test Certificate" common_name="Test Certificate"
vault write -format=json pki_int_gnr_ca/issue/Issuer name="Test Certificate" common_name="Test Certificate" | jq -r '.data.certificate' | openssl x509 -noout -text >> cert1
# Result
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
2d:fe:20:ce:88:aa:8e:07:8c:45:86:19:55:5d:3a:30:01:82:f2:e8
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = CA Int Root Issuing CA
Validity
Not Before: Apr 28 15:38:56 2025 GMT
Not After : Oct 28 03:39:17 2025 GMT
Subject: CN = Test Certificate
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:d1:c6:3c:f1:45:09:10:ce:ed:33:d6:6b:a0:88:
ec:82:aa:2b:37:27:4c:8f:23:ea:77:7f:76:f0:25:
ac:8d:0e:df:56:4f:a4:9c:c0:05:d9:7e:57:2b:3a:
bf:1e:5b:f8:c5:c2:9d:79:6f:44:c6:56:67:31:af:
dc:93:00:95:9d:85:6e:9a:0f:52:b4:91:37:c4:ee:
b7:ed:68:d9:4a:8f:19:2b:f6:55:ea:92:29:ab:93:
71:a6:02:97:c9:db:4d:8d:69:97:4a:1d:cf:93:4c:
5a:6a:8b:7f:49:4e:e5:0a:9b:10:f1:27:20:38:20:
42:ad:31:d4:8d:3e:29:00:b3:b3:88:b4:86:35:67:
56:88:06:ae:07:b8:ae:ef:d3:32:7a:16:6f:e9:da:
0a:75:a2:ba:02:72:ad:e8:7b:2c:ba:61:22:04:03:
9d:36:69:f9:b3:fc:8b:0b:0e:d5:6e:2d:ae:d5:c6:
11:75:8b:a3:62:93:3f:0d:96:24:36:ec:97:0e:23:
3c:b9:63:c5:18:65:1b:01:d5:3e:51:d8:39:38:2c:
71:8e:3c:d7:75:2b:de:26:29:b6:dc:f7:7e:79:67:
a9:1f:e5:6a:13:fa:5b:1e:3c:5d:b7:35:d3:c9:26:
e1:88:bc:64:0f:d3:9b:cc:06:74:71:f9:7e:05:e8:
3a:9d
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Subject Key Identifier:
AC:B5:17:C3:E0:F9:C9:7B:8D:83:14:FF:D2:C5:6A:95:2E:2C:42:03
X509v3 Authority Key Identifier:
keyid:1A:42:B8:C4:8A:DD:49:CC:D5:51:93:51:1F:11:A6:A9:18:BF:E7:DE

Authority Information Access:
CA Issuers - URI:https://address:port/v1/pki_int_gnr_ca/ca

X509v3 CRL Distribution Points:

Full Name:
URI:https://address:port/v1/pki_int_gnr_ca/crl

Signature Algorithm: sha256WithRSAEncryption
9e:98:56:b0:7d:0b:8c:85:fa:f7:33:9c:14:e9:cf:b2:fe:a8:
c5:de:88:49:f6:12:c9:0e:7a:4a:d3:ce:f3:2c:d2:29:b8:88:
f2:28:d1:c1:4f:d5:02:01:ce:53:83:ee:91:19:53:a0:53:9e:
33:53:49:53:2c:46:08:09:7a:27:dc:09:eb:56:c9:65:b9:00:
38:29:48:fd:f8:eb:16:fd:2b:bd:9c:7c:08:73:1a:70:13:08:
d8:ae:1f:4a:da:6e:b2:55:e5:35:a2:29:ea:64:d4:d0:ea:4e:
ee:42:46:c8:b1:f4:8a:0f:9e:0d:06:15:ec:c2:d9:b8:79:ca:
0d:2a:8f:3d:78:a3:ed:f6:7e:e9:f3:f2:81:8c:0d:7b:65:ed:
51:a7:f1:a5:76:76:70:ca:d8:e8:a6:5b:8e:e0:73:c4:09:f0:
cb:92:83:23:13:2b:d1:14:b0:c9:da:cc:e4:3b:12:40:8c:d1:
36:bb:85:5f:8b:cf:60:c5:6e:86:a4:d0:46:ac:a8:61:84:11:
b7:03:71:7d:a9:80:b1:eb:f0:f9:5f:13:43:0a:4d:54:18:41:
74:44:d8:7a:00:06:d2:61:65:ac:e7:f7:14:5b:2a:fe:e1:46:
93:9a:17:0e:97:cb:c6:45:68:ab:a3:a4:1d:b2:97:0f:f3:0f:
c6:77:9c:f8