Sometimes you need to rotate or renew intermediate CA certificate if the current intermediate CA is expired, expiring or you get error when trying to generate leaf certificate. You cannot generate a certificate that has an expiration time greater than the expiry time of the intermediate CA certificate. If you try to generate a certificate which has expiry date beyond the expiration of the CA certificate then you will get an error such as this:
$ vault write pki_int/issue/example-dot-com common_name="test.example.com" ttl="28m"
Error writing data to pki_int/issue/example-dot-com: Error making API request.
URL: PUT http://localhost:8200/v1/pki_int/issue/example-dot-com
Code: 400. Errors:
* cannot satisfy request, as TTL would result in notAfter 2023-09-12T06:37:56.299291355Z that is beyond the expiration of the CA certificate at 2023-09-12T06:37:10Z
Rotation of intermediate certificates: Rotation of intermediate certificates is a fairly simple process. Assuming a decent operational setup (wherein during end-entity issuance, the full certificate chain is updated in the service's configuration), this should be as easy as creating a new intermediate CA, signing it against the root CA, and then beginning issuance against the new intermediate certificate.
In other words, to renew intermediate certs for the PKI engine, you could create a new intermediate and run both (old expiring one and new) CAs in parallel. The original (old) intermediate would continue to service CRL and read requests only until it expires. The new intermediate CA signed by the root CA issues certificates.
The tentative steps to renew intermediate CA cert for the PKI engine are as follows:
Generate an intermediate and save the CSR
$ vault write -format=json pki_int/intermediate/generate/internal \ common_name="example.com Intermediate Authority" \ issuer_name="example-dot-com-intermediate" \ | jq -r '.data.csr' > pki_intermediate.csr
Sign the intermediate certificate with the root CA private key, and save the generated certificate
vault write -format=json pki/root/sign-intermediate \ issuer_ref="root-2023" \ csr=@pki_intermediate.csr \ format=pem_bundle ttl="43800h" \ | jq -r '.data.certificate' > intermediate.cert.pem
- If you use an external root CA, you would sign the CSR outside of vault and save the generated certificate
Once the CSR is signed and the root CA (can be external) returns a certificate, it can be imported back into Vault.
vault write pki_int/intermediate/set-signed email@example.com
- Create a role which can be used to generate leaf certificates
vault write pki_int/roles/example-dot-com \ issuer_ref="$(vault read -field=default pki_int/config/issuers)" \ allowed_domains="example.com" \ allow_subdomains=true \ max_ttl="720h"
Things to consider
Use a different issuer_name and common_name while generating CSR: Creating a new CSR with same common name and issuer_name should not cause any issue because every time you create a new CSR, a new serial number and issuer_ref are generated which are unique. As long as you use the correct
issuer_ref, while generating certificates using that CA, it should be fine. But for the sake of avoiding confusion, you can create a new intermediate CA with new
Correct use of issuer_ref when creating a role: Depending on your use case, you could do the following while setting up new role:
- Use specific
issuer_ref="..."when creating the new role instead of
issuer_ref="$(vault read -field=default pki_int/config/issuers)"
- If you want to change the default issuer, you can do that in two ways:
- Use specific
- Build your own certificate authority (CA)
- Build certificate authority (CA) in Vault with an offline root
- X.509 rotation primitives
- PKI secrets engine