Rotate your CA seamlessly using a Vault PKI

Stéphane Este-Gracias
20 min readSep 28, 2022

Automate your Certificates Lifecycle with Vault — Part 3

Photo by Daniel Chen on Unsplash

This article is a part of a series about how to
Automate your Certificates Lifecycle with Vault.

  1. Build an Internal PKI with Vault
  2. Issue, Deploy and Renew your Private Certificates with Vault and Consul-Template
  3. Rotate your CA seamlessly using a Vault PKI (this article)
  4. Securely store Public Certificates in Vault, generated by acme.sh
  5. Codify Vault Internal PKI using Terraform

Introduction

This article contains a walkthrough to rotate the Issuing, Intermediate and Root CA from Vault PKI built in the first article of this series.

Pre-Requisites

Multi-Issuer Feature

Since 1.11.0, Vault allows a single PKI secret engine mount to have multiple CA certificates (known as ‘issuer’ in Vault PKI configuration) for the purpose of facilitating rotation.

Default issuer

In the following diagrams, an issuer is represented by a squared box at the bottom of the CA. For instance, in the next diagram, the issuer is named v1.

default issuer in CA and issuer_ref in role

By default, thedefault issuer refers to the first CA certificate created on the PKI secret engines (v1 in the previous diagram).

By default, when creating a role, the default issuer is set as the default issuer_ref if not set. The issuer_ref is the reference to an existing issuer in the CA for issuing the leaf certificates.

As a result, the leaf certificates (generated by role X) are issued by the v1 issuer (as issuer_ref = default = v1).

CA Rotation

In the following diagrams, the default issuer has a red border. For instance, in the next diagram, the default issuer is v1.

Before rotation

In the ‘Before rotation’ diagram, a new issuer named v2 has been created in addition to v1. The leaf certificates (generated by role X) are still issued by the v1 issuer. Moreover, two new roles have been created as well:

  • role Y for issuing leaf certificates with the v1 issuer because issuer_ref is equal to v1
  • role Z for issuing leaf certificates with the v2 issuer because issuer_ref is equal to v2
After rotation

By updating the default issuer to the v2 issuer in the CA configuration, the leaf certificates (generated by role X) are now issued by the v2 issuer, and roles Y and Z are still issuing leaf certificates using, respectively, v1 and v2 issuers.

Thanks to this technique, you can manage the CA rotation seamlessly.

In the next three sections, the CA rotation is managed on the Vault PKI.

Launch consul-template with Renew Certificate configuration from the previous article and keep it running while following the next procedures in another terminal.

$ consul-template -config=consul-template.hcl
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFEM5nkiEm2i/eEEP1XV3n7k9I8IZapKtNMc9EQLUu9NoAoGCCqGSM49
AwEHoUQDQgAEk7G6GdS1lcn16trtzA5eIUyXG28BTg8+Q5c5Z3LltBlSW/prcvgT
fzvHC7+/3eNFCKl0P2J8NJMRIvHA/TcUPg==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.1.1
subject=O = Example, CN = test.example.com
notBefore=Sep 20 13:17:19 2022 GMT
notAfter=Sep 20 13:18:19 2022 GMT
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOqeSC1afjMvPCuCMKoVsataoyIvu/DeF/B7PeZEVWx8oAoGCCqGSM49
AwEHoUQDQgAEwLQlUF99S0b9E4x3nSm8RuyaKv6kG5qbSIA5lu5K061B2SaGeNHN
lKhOmLuGf0aURfqpoU/iLjJt0K9jnznQvw==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.1.1
subject=O = Example, CN = test.example.com
notBefore=Sep 20 13:17:46 2022 GMT
notAfter=Sep 20 13:18:46 2022 GMT
...

Rotate Issuing CA

First, let’s update the Issuing CA.

Rename issuers

To ease the next steps, let’s rename the issuers pointed by the default issuer of each CA.

$ vault list -detailed pki_int/issuers
Keys is_default issuer_name
---- ---------- -----------
17438773-df12-5bab-a7ee-83a7305037fb true n/a
$ vault write -format=json \
pki_int/issuer/default \
issuer_name=v1.1 \
> pki_int_v1.1.rename.json
$ cat pki_int_v1.1.rename.json

{
"request_id": "9e8ca209-b6ef-835c-cc32-0b7ea97f1c23",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"ca_chain": [
"-----BEGIN CERTIFICATE-----\nMIIB2DCCAX2gAwIBAgIRAMlAuLmxYK0hqR4uaheiDMowCgYIKoZIzj0EAwIwNDEQ\nMA4GA1UEChMHRXhhbXBsZTEgMB4GA1UEAxMXRXhhbXBsZSBMYWJzIFJvb3QgQ0Eg\ndjEwHhcNMjIwOTE5MTQ1NTA4WhcNMjcwOTE5MTUwNTA4WjA+MRAwDgYDVQQKEwdF\neGFtcGxlMSowKAYDVQQDEyFFeGFtcGxlIExhYnMgSW50ZXJtZWRpYXRlIENBIHYx\nLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATBv71in6dt4FYoFIUWPEl8/PTk\nN7vIryxD2sff7PY421erP9ZlWjG3dG5+1kFvHUrp26PGBYid304oVPIYWPHIo2Yw\nZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQU\n1v5Vz/G4Ai+KsgSqLatba/3vJMIwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDIlZxg\n7z5RvXYwCgYIKoZIzj0EAwIDSQAwRgIhAIgYXf1QhKLiAZxp08viP0jU57qRkNMP\nxYSDwURq/rvoAiEAuq3Wytby/RsaMUvPhjOT0CR7fim9Pwaw1W5HdZ1WWg0=\n-----END CERTIFICATE-----\n"
],
"certificate": "-----BEGIN CERTIFICATE-----\nMIIB2DCCAX2gAwIBAgIRAMlAuLmxYK0hqR4uaheiDMowCgYIKoZIzj0EAwIwNDEQ\nMA4GA1UEChMHRXhhbXBsZTEgMB4GA1UEAxMXRXhhbXBsZSBMYWJzIFJvb3QgQ0Eg\ndjEwHhcNMjIwOTE5MTQ1NTA4WhcNMjcwOTE5MTUwNTA4WjA+MRAwDgYDVQQKEwdF\neGFtcGxlMSowKAYDVQQDEyFFeGFtcGxlIExhYnMgSW50ZXJtZWRpYXRlIENBIHYx\nLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATBv71in6dt4FYoFIUWPEl8/PTk\nN7vIryxD2sff7PY421erP9ZlWjG3dG5+1kFvHUrp26PGBYid304oVPIYWPHIo2Yw\nZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQU\n1v5Vz/G4Ai+KsgSqLatba/3vJMIwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDIlZxg\n7z5RvXYwCgYIKoZIzj0EAwIDSQAwRgIhAIgYXf1QhKLiAZxp08viP0jU57qRkNMP\nxYSDwURq/rvoAiEAuq3Wytby/RsaMUvPhjOT0CR7fim9Pwaw1W5HdZ1WWg0=\n-----END CERTIFICATE-----\n",
"issuer_id": "17438773-df12-5bab-a7ee-83a7305037fb",
"issuer_name": "v1.1",
"key_id": "abd74d58-4e4c-05a3-2b30-6ad9a8f66038",
"leaf_not_after_behavior": "err",
"manual_chain": null,
"usage": "read-only,issuing-certificates,crl-signing"
},
"warnings": null
}
$ vault list -detailed pki_iss/issuers
Keys is_default issuer_name
---- ---------- -----------
42149e44-785e-3dec-a7e1-ba9e1c4804a0 false n/a
8b135654-2301-3efd-fd20-575e5d56e050 false n/a
957c0c19-a66b-f2fa-b868-05f01bc142e5 true n/a
$ vault write -format=json \
pki_iss/issuer/default \
issuer_name=v1.1.1 \
> pki_iss_v1.1.1.rename.json

$ cat pki_iss_v1.1.1.rename.json
{
"request_id": "0f4ce3f2-1d83-a05e-07ec-beef3b319902",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"ca_chain": [
"-----BEGIN CERTIFICATE-----\nMIICWzCCAgGgAwIBAgIUTknVQDg1TmMqIYU/H4Z0j9q6q2IwCgYIKoZIzj0EAwIw\nPjEQMA4GA1UEChMHRXhhbXBsZTEqMCgGA1UEAxMhRXhhbXBsZSBMYWJzIEludGVy\nbWVkaWF0ZSBDQSB2MS4xMB4XDTIyMDkxOTE1MDQzOFoXDTIzMDkxOTE1MDUwOFow\nOzEQMA4GA1UEChMHRXhhbXBsZTEnMCUGA1UEAxMeRXhhbXBsZSBMYWJzIElzc3Vp\nbmcgQ0EgdjEuMS4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWlU5PUeiItWC\nYyltWZaS4W8fNANZkSjmd2oShXp2nSVDwN4+Dvf2ixFdzUWbklo5cBRLZxweL59c\nhbYsbVgL9qOB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIB\nADAdBgNVHQ4EFgQUqUDW46qmyyNELSER3ILqIXbmgOIwHwYDVR0jBBgwFoAU1v5V\nz/G4Ai+KsgSqLatba/3vJMIwPwYIKwYBBQUHAQEEMzAxMC8GCCsGAQUFBzAChiNo\ndHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNVHR8ELjAsMCqg\nKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jcmwwCgYIKoZI\nzj0EAwIDSAAwRQIhALbt1mZx0pLyGMO8hyUDHfQpRAah0c3dZn5vusIW+vcCAiAz\n/WTjjxMm5QeaEh9KBLQrcXXN2jXV7PI886sLBE/xCQ==\n-----END CERTIFICATE-----\n",
"-----BEGIN CERTIFICATE-----\nMIIB2DCCAX2gAwIBAgIRAMlAuLmxYK0hqR4uaheiDMowCgYIKoZIzj0EAwIwNDEQ\nMA4GA1UEChMHRXhhbXBsZTEgMB4GA1UEAxMXRXhhbXBsZSBMYWJzIFJvb3QgQ0Eg\ndjEwHhcNMjIwOTE5MTQ1NTA4WhcNMjcwOTE5MTUwNTA4WjA+MRAwDgYDVQQKEwdF\neGFtcGxlMSowKAYDVQQDEyFFeGFtcGxlIExhYnMgSW50ZXJtZWRpYXRlIENBIHYx\nLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATBv71in6dt4FYoFIUWPEl8/PTk\nN7vIryxD2sff7PY421erP9ZlWjG3dG5+1kFvHUrp26PGBYid304oVPIYWPHIo2Yw\nZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQU\n1v5Vz/G4Ai+KsgSqLatba/3vJMIwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDIlZxg\n7z5RvXYwCgYIKoZIzj0EAwIDSQAwRgIhAIgYXf1QhKLiAZxp08viP0jU57qRkNMP\nxYSDwURq/rvoAiEAuq3Wytby/RsaMUvPhjOT0CR7fim9Pwaw1W5HdZ1WWg0=\n-----END CERTIFICATE-----\n"
],
"certificate": "-----BEGIN CERTIFICATE-----\nMIICWzCCAgGgAwIBAgIUTknVQDg1TmMqIYU/H4Z0j9q6q2IwCgYIKoZIzj0EAwIw\nPjEQMA4GA1UEChMHRXhhbXBsZTEqMCgGA1UEAxMhRXhhbXBsZSBMYWJzIEludGVy\nbWVkaWF0ZSBDQSB2MS4xMB4XDTIyMDkxOTE1MDQzOFoXDTIzMDkxOTE1MDUwOFow\nOzEQMA4GA1UEChMHRXhhbXBsZTEnMCUGA1UEAxMeRXhhbXBsZSBMYWJzIElzc3Vp\nbmcgQ0EgdjEuMS4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWlU5PUeiItWC\nYyltWZaS4W8fNANZkSjmd2oShXp2nSVDwN4+Dvf2ixFdzUWbklo5cBRLZxweL59c\nhbYsbVgL9qOB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIB\nADAdBgNVHQ4EFgQUqUDW46qmyyNELSER3ILqIXbmgOIwHwYDVR0jBBgwFoAU1v5V\nz/G4Ai+KsgSqLatba/3vJMIwPwYIKwYBBQUHAQEEMzAxMC8GCCsGAQUFBzAChiNo\ndHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNVHR8ELjAsMCqg\nKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jcmwwCgYIKoZI\nzj0EAwIDSAAwRQIhALbt1mZx0pLyGMO8hyUDHfQpRAah0c3dZn5vusIW+vcCAiAz\n/WTjjxMm5QeaEh9KBLQrcXXN2jXV7PI886sLBE/xCQ==\n-----END CERTIFICATE-----\n",
"issuer_id": "957c0c19-a66b-f2fa-b868-05f01bc142e5",
"issuer_name": "v1.1.1",
"key_id": "a9461b57-5fe0-7ba8-6abd-8b6766526f65",
"leaf_not_after_behavior": "err",
"manual_chain": null,
"usage": "read-only,issuing-certificates,crl-signing"
},
"warnings": null
}
Generate v1.1.2 issuer for Issuing CA

Now, let’s generate a new issuer for Issuing CA.

$ vault write -format=json \
pki_iss/intermediate/generate/internal \
organization="Example" \
common_name="Example Labs Issuing CA v1.1.2" \
key_type=ec \
key_bits=256 \
> pki_iss_v1.1.2.csr.json
$ cat pki_iss_v1.1.2.csr.json

{
"request_id": "e81eed25-bf87-9a0e-8f77-42b77eb79674",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIH7MIGiAgEAMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhh\nbXBsZSBMYWJzIElzc3VpbmcgQ0EgdjEuMS4yMFkwEwYHKoZIzj0CAQYIKoZIzj0D\nAQcDQgAE3W9Ss1pVeWWZMKKZoSZq+k5HEesw7hyteyuswzHVxAgJ61ppHW0mOb3y\nJubTrYLDXqLaF77V6we6HYHVB8ElvKAAMAoGCCqGSM49BAMCA0gAMEUCIBbP6vvI\n0/+9GkW2agFpyj4LFaxczI8c8oi9aIsA5UhnAiEAkR0uqgpODwYMBgWy0c2Ro1py\ndXhbxna8mY+Pkh6Edbo=\n-----END CERTIFICATE REQUEST-----",
"key_id": "70aef752-39ae-6af7-cdc7-38cf6bb3e029"
},
"warnings": null
}
  • Extract the CSR from the response and verify it
$ cat pki_iss_v1.1.2.csr.json | jq -r '.data.csr' \
> pki_iss_v1.1.2.csr
$ openssl req -text -noout -verify -in pki_iss_v1.1.2.csr
verify OK
Certificate Request:
Data:
Version: 1 (0x0)
Subject: O = Example, CN = Example Labs Issuing CA v1.1.2
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:dd:6f:52:b3:5a:55:79:65:99:30:a2:99:a1:26:
6a:fa:4e:47:11:eb:30:ee:1c:ad:7b:2b:ac:c3:31:
d5:c4:08:09:eb:5a:69:1d:6d:26:39:bd:f2:26:e6:
d3:ad:82:c3:5e:a2:da:17:be:d5:eb:07:ba:1d:81:
d5:07:c1:25:bc
ASN1 OID: prime256v1
NIST CURVE: P-256
Attributes:
a0:00
Signature Algorithm: ecdsa-with-SHA256
30:45:02:20:16:cf:ea:fb:c8:d3:ff:bd:1a:45:b6:6a:01:69:
ca:3e:0b:15:ac:5c:cc:8f:1c:f2:88:bd:68:8b:00:e5:48:67:
02:21:00:91:1d:2e:aa:0a:4e:0f:06:0c:06:05:b2:d1:cd:91:
a3:5a:72:75:78:5b:c6:76:bc:99:8f:8f:92:1e:84:75:ba
$ vault write -format=json \
pki_int/root/sign-intermediate \
organization="Example" \
csr=@pki_iss_v1.1.2.csr \
ttl=8760h \
format=pem \
> pki_iss_v1.1.2.crt.json
$ cat pki_iss_v1.1.2.crt.json
{
"request_id": "dee3e028-816e-1d38-eab6-eed0a133b8f1",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"ca_chain": [
"-----BEGIN CERTIFICATE-----\nMIICXzCCAgagAwIBAgIUTlImmt7P5VGyZ0yInSv0dZfBOiwwCgYIKoZIzj0EAwIw\nPjEQMA4GA1UEChMHRXhhbXBsZTEqMCgGA1UEAxMhRXhhbXBsZSBMYWJzIEludGVy\nbWVkaWF0ZSBDQSB2MS4xMB4XDTIyMDkyMDEyNTYyN1oXDTIzMDkyMDEyNTY1N1ow\nQDEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMScwJQYDVQQDEx5FeGFtcGxlIExhYnMg\nSXNzdWluZyBDQSB2MS4xLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATdb1Kz\nWlV5ZZkwopmhJmr6TkcR6zDuHK17K6zDMdXECAnrWmkdbSY5vfIm5tOtgsNeotoX\nvtXrB7odgdUHwSW8o4HfMIHcMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEAMB0GA1UdDgQWBBQ3Q5fp1oVoSM8dVztrwzQXVU8aIDAfBgNVHSMEGDAW\ngBTW/lXP8bgCL4qyBKotq1tr/e8kwjA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH\nMAKGI2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfaW50L2NhMDUGA1UdHwQu\nMCwwKqAooCaGJGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfaW50L2NybDAK\nBggqhkjOPQQDAgNHADBEAiBwvCW87AC6E9dIeiqalklwLNQD18YJ2q6hOLxIwiVD\nKQIgYlUYXzkHNuPcvQXIbXY88g+EiMf8leGo3iOCQQ/MDRA=\n-----END CERTIFICATE-----",
"-----BEGIN CERTIFICATE-----\nMIIB2DCCAX2gAwIBAgIRAMlAuLmxYK0hqR4uaheiDMowCgYIKoZIzj0EAwIwNDEQ\nMA4GA1UEChMHRXhhbXBsZTEgMB4GA1UEAxMXRXhhbXBsZSBMYWJzIFJvb3QgQ0Eg\ndjEwHhcNMjIwOTE5MTQ1NTA4WhcNMjcwOTE5MTUwNTA4WjA+MRAwDgYDVQQKEwdF\neGFtcGxlMSowKAYDVQQDEyFFeGFtcGxlIExhYnMgSW50ZXJtZWRpYXRlIENBIHYx\nLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATBv71in6dt4FYoFIUWPEl8/PTk\nN7vIryxD2sff7PY421erP9ZlWjG3dG5+1kFvHUrp26PGBYid304oVPIYWPHIo2Yw\nZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQU\n1v5Vz/G4Ai+KsgSqLatba/3vJMIwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDIlZxg\n7z5RvXYwCgYIKoZIzj0EAwIDSQAwRgIhAIgYXf1QhKLiAZxp08viP0jU57qRkNMP\nxYSDwURq/rvoAiEAuq3Wytby/RsaMUvPhjOT0CR7fim9Pwaw1W5HdZ1WWg0=\n-----END CERTIFICATE-----"
],
"certificate": "-----BEGIN CERTIFICATE-----\nMIICXzCCAgagAwIBAgIUTlImmt7P5VGyZ0yInSv0dZfBOiwwCgYIKoZIzj0EAwIw\nPjEQMA4GA1UEChMHRXhhbXBsZTEqMCgGA1UEAxMhRXhhbXBsZSBMYWJzIEludGVy\nbWVkaWF0ZSBDQSB2MS4xMB4XDTIyMDkyMDEyNTYyN1oXDTIzMDkyMDEyNTY1N1ow\nQDEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMScwJQYDVQQDEx5FeGFtcGxlIExhYnMg\nSXNzdWluZyBDQSB2MS4xLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATdb1Kz\nWlV5ZZkwopmhJmr6TkcR6zDuHK17K6zDMdXECAnrWmkdbSY5vfIm5tOtgsNeotoX\nvtXrB7odgdUHwSW8o4HfMIHcMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEAMB0GA1UdDgQWBBQ3Q5fp1oVoSM8dVztrwzQXVU8aIDAfBgNVHSMEGDAW\ngBTW/lXP8bgCL4qyBKotq1tr/e8kwjA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH\nMAKGI2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfaW50L2NhMDUGA1UdHwQu\nMCwwKqAooCaGJGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfaW50L2NybDAK\nBggqhkjOPQQDAgNHADBEAiBwvCW87AC6E9dIeiqalklwLNQD18YJ2q6hOLxIwiVD\nKQIgYlUYXzkHNuPcvQXIbXY88g+EiMf8leGo3iOCQQ/MDRA=\n-----END CERTIFICATE-----",
"expiration": 1695214617,
"issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIB2DCCAX2gAwIBAgIRAMlAuLmxYK0hqR4uaheiDMowCgYIKoZIzj0EAwIwNDEQ\nMA4GA1UEChMHRXhhbXBsZTEgMB4GA1UEAxMXRXhhbXBsZSBMYWJzIFJvb3QgQ0Eg\ndjEwHhcNMjIwOTE5MTQ1NTA4WhcNMjcwOTE5MTUwNTA4WjA+MRAwDgYDVQQKEwdF\neGFtcGxlMSowKAYDVQQDEyFFeGFtcGxlIExhYnMgSW50ZXJtZWRpYXRlIENBIHYx\nLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATBv71in6dt4FYoFIUWPEl8/PTk\nN7vIryxD2sff7PY421erP9ZlWjG3dG5+1kFvHUrp26PGBYid304oVPIYWPHIo2Yw\nZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQU\n1v5Vz/G4Ai+KsgSqLatba/3vJMIwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDIlZxg\n7z5RvXYwCgYIKoZIzj0EAwIDSQAwRgIhAIgYXf1QhKLiAZxp08viP0jU57qRkNMP\nxYSDwURq/rvoAiEAuq3Wytby/RsaMUvPhjOT0CR7fim9Pwaw1W5HdZ1WWg0=\n-----END CERTIFICATE-----",
"serial_number": "4e:52:26:9a:de:cf:e5:51:b2:67:4c:88:9d:2b:f4:75:97:c1:3a:2c"
},
"warnings": [
"Max path length of the signed certificate is zero. This certificate cannot be used to issue intermediate CA certificates."
]
}
$ cat pki_iss_v1.1.2.crt.json | jq -r '.data.certificate' \
> pki_iss_v1.1.2.crt
$ openssl x509 -in pki_iss_v1.1.2.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
4e:52:26:9a:de:cf:e5:51:b2:67:4c:88:9d:2b:f4:75:97:...
Signature Algorithm: ecdsa-with-SHA256
Issuer: O = Example, CN = Example Labs Intermediate CA v1.1
Validity
Not Before: Sep 20 12:56:27 2022 GMT
Not After : Sep 20 12:56:57 2023 GMT
Subject: O = Example, CN = Example Labs Issuing CA v1.1.2
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:dd:6f:52:b3:5a:55:79:65:99:30:a2:99:a1:26:
6a:fa:4e:47:11:eb:30:ee:1c:ad:7b:2b:ac:c3:31:
d5:c4:08:09:eb:5a:69:1d:6d:26:39:bd:f2:26:e6:
d3:ad:82:c3:5e:a2:da:17:be:d5:eb:07:ba:1d:81:
d5:07:c1:25:bc
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 Subject Key Identifier:
37:43:97:E9:D6:85:68:48:CF:1D:57:3B:6B:C3:34:17:...
X509v3 Authority Key Identifier:
keyid:D6:FE:55:CF:F1:B8:02:2F:8A:B2:04:AA:2D:AB:...
Authority Information Access:
CA Issuers - URI:http://127.0.0.1:8200/v1/pki_int/ca
X509v3 CRL Distribution Points: Full Name:
URI:http://127.0.0.1:8200/v1/pki_int/crl
Signature Algorithm: ecdsa-with-SHA256
30:44:02:20:70:bc:25:bc:ec:00:ba:13:d7:48:7a:2a:9a:96:
49:70:2c:d4:03:d7:c6:09:da:ae:a1:38:bc:48:c2:25:43:29:
02:20:62:55:18:5f:39:07:36:e3:dc:bd:05:c8:6d:76:3c:f2:
0f:84:88:c7:fc:95:e1:a8:de:23:82:41:0f:cc:0d:10
$ cat pki_iss_v1.1.2.crt pki_int_v1.1.crt > pki_iss_v1.1.2.chain.crt
$ vault write -format=json \
pki_iss/intermediate/set-signed \
certificate=@pki_iss_v1.1.2.chain.crt \
> pki_iss_v1.1.2.set-signed.json
$ cat pki_iss_v1.1.2.set-signed.json
{
"request_id": "6d6e0da8-ee81-1492-465f-c1ea35eff46d",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"imported_issuers": [
"42149e44-785e-3dec-a7e1-ba9e1c4804a0"
],
"imported_keys": null,
"mapping": {
"42149e44-785e-3dec-a7e1-ba9e1c4804a0": "70aef752-39ae-6af7-cdc7-38cf6bb3e029",
"8b135654-2301-3efd-fd20-575e5d56e050": ""
}
},
"warnings": null
}
  • Extract the issuer_id from the previous response (here 42149e44-785e-3dec-a7e1-ba9e1c4804a0), then rename the new issuer to v1.1.2 using the pki_iss/issuer/:issuer_ref endpoint.
$ cat pki_iss_v1.1.2.set-signed.json \
| jq -r '.data.imported_issuers[0]' \
> pki_iss_v1.1.2.issuer_id
$ vault write -format=json \
pki_iss/issuer/`cat pki_iss_v1.1.2.issuer_id` \
issuer_name=v1.1.2 \
> pki_iss_v1.1.2.rename.json

$ cat pki_iss_v1.1.2.rename.json
{
"request_id": "867c84cc-31f8-6b80-75ec-d5c0b696d42b",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"ca_chain": [
"-----BEGIN CERTIFICATE-----\nMIICXzCCAgagAwIBAgIUTlImmt7P5VGyZ0yInSv0dZfBOiwwCgYIKoZIzj0EAwIw\nPjEQMA4GA1UEChMHRXhhbXBsZTEqMCgGA1UEAxMhRXhhbXBsZSBMYWJzIEludGVy\nbWVkaWF0ZSBDQSB2MS4xMB4XDTIyMDkyMDEyNTYyN1oXDTIzMDkyMDEyNTY1N1ow\nQDEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMScwJQYDVQQDEx5FeGFtcGxlIExhYnMg\nSXNzdWluZyBDQSB2MS4xLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATdb1Kz\nWlV5ZZkwopmhJmr6TkcR6zDuHK17K6zDMdXECAnrWmkdbSY5vfIm5tOtgsNeotoX\nvtXrB7odgdUHwSW8o4HfMIHcMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEAMB0GA1UdDgQWBBQ3Q5fp1oVoSM8dVztrwzQXVU8aIDAfBgNVHSMEGDAW\ngBTW/lXP8bgCL4qyBKotq1tr/e8kwjA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH\nMAKGI2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfaW50L2NhMDUGA1UdHwQu\nMCwwKqAooCaGJGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfaW50L2NybDAK\nBggqhkjOPQQDAgNHADBEAiBwvCW87AC6E9dIeiqalklwLNQD18YJ2q6hOLxIwiVD\nKQIgYlUYXzkHNuPcvQXIbXY88g+EiMf8leGo3iOCQQ/MDRA=\n-----END CERTIFICATE-----\n",
"-----BEGIN CERTIFICATE-----\nMIIB2DCCAX2gAwIBAgIRAMlAuLmxYK0hqR4uaheiDMowCgYIKoZIzj0EAwIwNDEQ\nMA4GA1UEChMHRXhhbXBsZTEgMB4GA1UEAxMXRXhhbXBsZSBMYWJzIFJvb3QgQ0Eg\ndjEwHhcNMjIwOTE5MTQ1NTA4WhcNMjcwOTE5MTUwNTA4WjA+MRAwDgYDVQQKEwdF\neGFtcGxlMSowKAYDVQQDEyFFeGFtcGxlIExhYnMgSW50ZXJtZWRpYXRlIENBIHYx\nLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATBv71in6dt4FYoFIUWPEl8/PTk\nN7vIryxD2sff7PY421erP9ZlWjG3dG5+1kFvHUrp26PGBYid304oVPIYWPHIo2Yw\nZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQU\n1v5Vz/G4Ai+KsgSqLatba/3vJMIwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDIlZxg\n7z5RvXYwCgYIKoZIzj0EAwIDSQAwRgIhAIgYXf1QhKLiAZxp08viP0jU57qRkNMP\nxYSDwURq/rvoAiEAuq3Wytby/RsaMUvPhjOT0CR7fim9Pwaw1W5HdZ1WWg0=\n-----END CERTIFICATE-----\n"
],
"certificate": "-----BEGIN CERTIFICATE-----\nMIICXzCCAgagAwIBAgIUTlImmt7P5VGyZ0yInSv0dZfBOiwwCgYIKoZIzj0EAwIw\nPjEQMA4GA1UEChMHRXhhbXBsZTEqMCgGA1UEAxMhRXhhbXBsZSBMYWJzIEludGVy\nbWVkaWF0ZSBDQSB2MS4xMB4XDTIyMDkyMDEyNTYyN1oXDTIzMDkyMDEyNTY1N1ow\nQDEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMScwJQYDVQQDEx5FeGFtcGxlIExhYnMg\nSXNzdWluZyBDQSB2MS4xLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATdb1Kz\nWlV5ZZkwopmhJmr6TkcR6zDuHK17K6zDMdXECAnrWmkdbSY5vfIm5tOtgsNeotoX\nvtXrB7odgdUHwSW8o4HfMIHcMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEAMB0GA1UdDgQWBBQ3Q5fp1oVoSM8dVztrwzQXVU8aIDAfBgNVHSMEGDAW\ngBTW/lXP8bgCL4qyBKotq1tr/e8kwjA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH\nMAKGI2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfaW50L2NhMDUGA1UdHwQu\nMCwwKqAooCaGJGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfaW50L2NybDAK\nBggqhkjOPQQDAgNHADBEAiBwvCW87AC6E9dIeiqalklwLNQD18YJ2q6hOLxIwiVD\nKQIgYlUYXzkHNuPcvQXIbXY88g+EiMf8leGo3iOCQQ/MDRA=\n-----END CERTIFICATE-----\n",
"issuer_id": "42149e44-785e-3dec-a7e1-ba9e1c4804a0",
"issuer_name": "v1.1.2",
"key_id": "70aef752-39ae-6af7-cdc7-38cf6bb3e029",
"leaf_not_after_behavior": "err",
"manual_chain": null,
"usage": "read-only,issuing-certificates,crl-signing"
},
"warnings": null
}
Default issuer is still v1.1.1

At this stage, the v1.1.2 issuer has been generated.

Let’s check the terminal where consul-template is running. As the default issuer is still v1.1.1, the issued leaf certificates are still with v1.1.1 issuer.

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFEM5nkiEm2i/eEEP1XV3n7k9I8IZapKtNMc9EQLUu9NoAoGCCqGSM49
AwEHoUQDQgAEk7G6GdS1lcn16trtzA5eIUyXG28BTg8+Q5c5Z3LltBlSW/prcvgT
fzvHC7+/3eNFCKl0P2J8NJMRIvHA/TcUPg==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.1.1
subject=O = Example, CN = test.example.com
notBefore=Sep 20 13:17:19 2022 GMT
notAfter=Sep 20 13:18:19 2022 GMT
Set default issuer to v1.1.2
  • Now, rotate the Issuing CA by setting the default issuer to v1.1.2 using the pki_iss/root/replaceendpoint.
$ vault write -format=json \
pki_iss/root/replace \
default=v1.1.2 \
> pki_iss_v1.1.2.replace.json
$ cat pki_iss_v1.1.2.replace.json
{
"request_id": "78be6c7a-3dd4-2825-df32-d3fe04d12f70",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"default": "42149e44-785e-3dec-a7e1-ba9e1c4804a0"
},
"warnings": null
}
$ vault list -detailed pki_iss/issuers | grep -v "n/a"
Keys is_default issuer_name
---- ---------- -----------
42149e44-785e-3dec-a7e1-ba9e1c4804a0 true v1.1.2
957c0c19-a66b-f2fa-b868-05f01bc142e5 false v1.1.1

Let’s check the terminal where consul-template is running. As the default issuer has been replace by the v1.1.2 issuer, the issued leaf certificates are now with v1.1.2 issuer. The CA chain is updated as well because the Issuing CA certificate is now the one from v1.1.2 issuer.

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIO8Mm3OX65AcxR/dehWyJ/tmwTbL6gG9tBj7isagnUZZoAoGCCqGSM49
AwEHoUQDQgAEYV3hVaLrMtFbMo072ZH7VPaazecX5VmdHqjsGDImawXdVeMAgvrw
ut+5O7CPriBhxTiCrV71YABVBsg9FD7mfw==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.1.1
subject=O = Example, CN = test.example.com
notBefore=Sep 20 13:23:33 2022 GMT
notAfter=Sep 20 13:24:33 2022 GMT
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIHfHYbilbIiWgT1UI8gIZW7BK8TDBf6wgkZfMrDCvUavoAoGCCqGSM49
AwEHoUQDQgAEvEn3LC16OyC43Z/HJRAmcQZov4hICgjcr/X1edKF4LliKq5ADkn1
2feYOMDJ6JJXg1LoJADRRxLZng71X9A1qw==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.1.2
subject=O = Example, CN = test.example.com
notBefore=Sep 20 13:23:58 2022 GMT
notAfter=Sep 20 13:24:58 2022 GMT
-----BEGIN CERTIFICATE-----
MIICXzCCAgagAwIBAgIUTlImmt7P5VGyZ0yInSv0dZfBOiwwCgYIKoZIzj0EAwIw
PjEQMA4GA1UEChMHRXhhbXBsZTEqMCgGA1UEAxMhRXhhbXBsZSBMYWJzIEludGVy
bWVkaWF0ZSBDQSB2MS4xMB4XDTIyMDkyMDEyNTYyN1oXDTIzMDkyMDEyNTY1N1ow
QDEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMScwJQYDVQQDEx5FeGFtcGxlIExhYnMg
SXNzdWluZyBDQSB2MS4xLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATdb1Kz
WlV5ZZkwopmhJmr6TkcR6zDuHK17K6zDMdXECAnrWmkdbSY5vfIm5tOtgsNeotoX
vtXrB7odgdUHwSW8o4HfMIHcMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG
AQH/AgEAMB0GA1UdDgQWBBQ3Q5fp1oVoSM8dVztrwzQXVU8aIDAfBgNVHSMEGDAW
gBTW/lXP8bgCL4qyBKotq1tr/e8kwjA/BggrBgEFBQcBAQQzMDEwLwYIKwYBBQUH
MAKGI2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfaW50L2NhMDUGA1UdHwQu
MCwwKqAooCaGJGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2lfaW50L2NybDAK
BggqhkjOPQQDAgNHADBEAiBwvCW87AC6E9dIeiqalklwLNQD18YJ2q6hOLxIwiVD
KQIgYlUYXzkHNuPcvQXIbXY88g+EiMf8leGo3iOCQQ/MDRA=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB2DCCAX2gAwIBAgIRAMlAuLmxYK0hqR4uaheiDMowCgYIKoZIzj0EAwIwNDEQ
MA4GA1UEChMHRXhhbXBsZTEgMB4GA1UEAxMXRXhhbXBsZSBMYWJzIFJvb3QgQ0Eg
djEwHhcNMjIwOTE5MTQ1NTA4WhcNMjcwOTE5MTUwNTA4WjA+MRAwDgYDVQQKEwdF
eGFtcGxlMSowKAYDVQQDEyFFeGFtcGxlIExhYnMgSW50ZXJtZWRpYXRlIENBIHYx
LjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATBv71in6dt4FYoFIUWPEl8/PTk
N7vIryxD2sff7PY421erP9ZlWjG3dG5+1kFvHUrp26PGBYid304oVPIYWPHIo2Yw
ZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQU
1v5Vz/G4Ai+KsgSqLatba/3vJMIwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDIlZxg
7z5RvXYwCgYIKoZIzj0EAwIDSQAwRgIhAIgYXf1QhKLiAZxp08viP0jU57qRkNMP
xYSDwURq/rvoAiEAuq3Wytby/RsaMUvPhjOT0CR7fim9Pwaw1W5HdZ1WWg0=
-----END CERTIFICATE-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJLESZuhH7B4FbrlolGQBwiMf5jQNbmJvN7u0fhzv8esoAoGCCqGSM49
AwEHoUQDQgAEf3/pMWH4OGy5a4nw/KHIWovCKOEJjwNKQiwtVQbHU6XQnWVk1vGL
pDPLPMQ44FmHP+8RibCtwTkgMtge/Gmnow==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.1.2
subject=O = Example, CN = test.example.com
notBefore=Sep 20 13:24:24 2022 GMT
notAfter=Sep 20 13:25:24 2022 GMT

As a result, the issuing CA has been rotated, and the automatic generation of leaf certificates is passed on seamlessly to the new issuer.

In the next section, the Intermediate CA is rotated.

Rotate Intermediate CA

Now, let’s update the Intermediate CA.

Generate v1.2 issuer for Intermediate CA

Let’s generate a new issuer for the Intermediate CA.

$ vault write -format=json \
pki_int/intermediate/generate/internal \
organization="Example" \
common_name="Example Labs Intermediae CA v1.2" \
key_type=ec \
key_bits=256 \
| jq -r '.data.csr' > pki_int_v1.2.csr
  • Sign and generate a certificate using the CSR with Root CA v1
$ certstrap --depot-path root sign \
--CA "Example Labs Root CA v1" \
--passphrase "secret" \
--intermediate \
--csr pki_int_v1.2.csr \
--expires "5 years" \
--path-length 1 \
--cert pki_int_v1.2.crt \
"Example Labs Intermediate CA v1.2"

Building intermediate
$ openssl x509 -in pki_int_v1.2.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
1b:ca:05:50:05:fc:3e:55:7e:91:d2:d6:a0:22:f3:17
Signature Algorithm: ecdsa-with-SHA256
Issuer: O = Example, CN = Example Labs Root CA v1
Validity
Not Before: Sep 20 13:48:18 2022 GMT
Not After : Sep 20 13:58:18 2027 GMT
Subject: O = Example, CN = Example Labs Intermediae CA v1.2
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:a3:12:fe:9c:ca:bb:63:ce:77:ad:f2:e5:31:8e:
e9:8f:89:fd:dc:0f:49:be:51:1b:2c:e8:a5:ed:a0:
3d:af:3f:a9:c3:5a:ba:b7:0f:12:22:cd:4e:f8:e9:
61:3e:b4:5f:6e:18:1e:b1:f9:1b:1b:ee:50:db:0f:
3e:de:8e:b1:bb
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:1
X509v3 Subject Key Identifier:
89:14:DC:23:34:8B:23:4B:21:EE:44:67:29:66:1C:18:...
X509v3 Authority Key Identifier:
keyid:C2:49:FB:2B:5C:B3:31:12:FB:14:B0:C8:95:9C:...
Signature Algorithm: ecdsa-with-SHA256
30:44:02:20:58:91:c1:82:d1:ce:ed:85:74:e1:5f:55:5e:c2:
58:e2:0b:c1:e5:59:45:fe:de:23:d0:46:4e:53:42:d8:0c:1e:
02:20:6c:ff:8f:91:8b:a7:9e:c4:f9:e9:8f:10:b9:1c:a1:32:
35:d5:8a:3b:5f:da:b4:39:d6:29:e2:7c:a3:06:b2:b2
$ vault write -format=json \
pki_int/intermediate/set-signed \
certificate=@pki_int_v1.2.crt \
> pki_int_v1.2.set-signed.json
$ cat pki_int_v1.2.set-signed.json
{
"request_id": "ce5b613e-0f3e-5efa-0855-d1ff2a8ca772",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"imported_issuers": [
"08ca0f1e-abad-4a6a-f632-6199adc0a9d4"
],
"imported_keys": null,
"mapping": {
"08ca0f1e-abad-4a6a-f632-6199adc0a9d4": "7bafaabe-a63b-2731-9bd1-ad6ca515cbe6"
}
},
"warnings": null
}
  • Extract the issuer_id from the previous response (here 09ca0f1e-abad-4a6a-f632-6199adv0a9d4), then rename the new issuer to v1.2 using the pki_int/issuer/:issuer_ref endpoint.
$ cat pki_int_v1.2.set-signed.json \
| jq -r '.data.imported_issuers[0]' \
> pki_int_v1.2.issuer_ref
$ vault write -format=json \
pki_int/issuer/`cat pki_int_v1.2.issuer_ref` \
issuer_name=v1.2 \
> pki_int_v1.2.rename.json
{
"request_id": "e7cb577f-1b2e-6aac-ac6f-b1df867f378a",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"ca_chain": [
"-----BEGIN CERTIFICATE-----\nMIIB2TCCAYCgAwIBAgIQG8oFUAX8PlV+kdLWoCLzFzAKBggqhkjOPQQDAjA0MRAw\nDgYDVQQKEwdFeGFtcGxlMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9vdCBDQSB2\nMTAeFw0yMjA5MjAxMzQ4MThaFw0yNzA5MjAxMzU4MThaMEIxFTATBgNVBAoTDEV4\nYW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVkaWFlIENB\nIHYxLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjEv6cyrtjznet8uUxjumP\nif3cD0m+URss6KXtoD2vP6nDWrq3DxIizU746WE+tF9uGB6x+Rsb7lDbDz7ejrG7\no2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E\nFgQUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDI\nlZxg7z5RvXYwCgYIKoZIzj0EAwIDRwAwRAIgWJHBgtHO7YV04V9VXsJY4gvB5VlF\n/t4j0EZOU0LYDB4CIGz/j5GLp57E+emPELkcoTI11Yo7X9q0OdYp4nyjBrKy\n-----END CERTIFICATE-----\n"
],
"certificate": "-----BEGIN CERTIFICATE-----\nMIIB2TCCAYCgAwIBAgIQG8oFUAX8PlV+kdLWoCLzFzAKBggqhkjOPQQDAjA0MRAw\nDgYDVQQKEwdFeGFtcGxlMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9vdCBDQSB2\nMTAeFw0yMjA5MjAxMzQ4MThaFw0yNzA5MjAxMzU4MThaMEIxFTATBgNVBAoTDEV4\nYW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVkaWFlIENB\nIHYxLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjEv6cyrtjznet8uUxjumP\nif3cD0m+URss6KXtoD2vP6nDWrq3DxIizU746WE+tF9uGB6x+Rsb7lDbDz7ejrG7\no2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E\nFgQUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDI\nlZxg7z5RvXYwCgYIKoZIzj0EAwIDRwAwRAIgWJHBgtHO7YV04V9VXsJY4gvB5VlF\n/t4j0EZOU0LYDB4CIGz/j5GLp57E+emPELkcoTI11Yo7X9q0OdYp4nyjBrKy\n-----END CERTIFICATE-----\n",
"issuer_id": "08ca0f1e-abad-4a6a-f632-6199adc0a9d4",
"issuer_name": "v1.2",
"key_id": "7bafaabe-a63b-2731-9bd1-ad6ca515cbe6",
"leaf_not_after_behavior": "err",
"manual_chain": null,
"usage": "read-only,issuing-certificates,crl-signing"
},
"warnings": null
}
Generate v1.2.1 issuer for Issuing CA

Now, let’s generate a new issuer for the Issuing CA.

$ vault write -format=json \
pki_iss/intermediate/generate/internal \
organization="Example" \
common_name="Example Labs Issuing CA v1.2.1" \
key_type=ec \
key_bits=256 \
| jq -r '.data.csr' > pki_iss_v1.2.1.csr

The pki_int/root/sign-intermediate endpoint uses the default issuer. So, it can’t be used because the default issuer for Intermediate CA isn’t set to v1.2.

$ vault write -format=json \
pki_int/issuer/v1.2/sign-intermediate \
organization="Example" \
csr=@pki_iss_v1.2.1.csr \
ttl=8760h \
format=pem \
> pki_iss_v1.2.1.crt.json

$ cat pki_iss_v1.2.1.crt.json
{
"request_id": "ed5b2b2b-1d7c-35d3-e1cb-c54273fa4912",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"ca_chain": [
"-----BEGIN CERTIFICATE-----\nMIICZDCCAgqgAwIBAgIUMEo78R2WbVUklZKtRK29YZyWj6IwCgYIKoZIzj0EAwIw\nQjEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMSkwJwYDVQQDEyBFeGFtcGxlIExhYnMg\nSW50ZXJtZWRpYWUgQ0EgdjEuMjAeFw0yMjA5MjAxNDIxNThaFw0yMzA5MjAxNDIy\nMjhaMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhhbXBsZSBM\nYWJzIElzc3VpbmcgQ0EgdjEuMi4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\nb25UxYE/Wk3cmJGmgq7H0RA5gBJNTuHfG+nszNlmjvr0hlbl2eb6c2nHPUDnVm06\n8xiX+YEp5o4k5WKbpAWLB6OB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/\nBAgwBgEB/wIBADAdBgNVHQ4EFgQUGj9YO8B8HiPIinLrhn+m5t0q3J4wHwYDVR0j\nBBgwFoAUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwPwYIKwYBBQUHAQEEMzAxMC8GCCsG\nAQUFBzAChiNodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNV\nHR8ELjAsMCqgKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9j\ncmwwCgYIKoZIzj0EAwIDSAAwRQIhAP9R8GYDrQ+dbalPeHAUc72RazDvVFOFt5zR\nF2XoLB3gAiABK9YOSpdV/UCyjs+plIHmkIg27+tfABZ/WduS0cplUg==\n-----END CERTIFICATE-----",
"-----BEGIN CERTIFICATE-----\nMIIB2TCCAYCgAwIBAgIQG8oFUAX8PlV+kdLWoCLzFzAKBggqhkjOPQQDAjA0MRAw\nDgYDVQQKEwdFeGFtcGxlMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9vdCBDQSB2\nMTAeFw0yMjA5MjAxMzQ4MThaFw0yNzA5MjAxMzU4MThaMEIxFTATBgNVBAoTDEV4\nYW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVkaWFlIENB\nIHYxLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjEv6cyrtjznet8uUxjumP\nif3cD0m+URss6KXtoD2vP6nDWrq3DxIizU746WE+tF9uGB6x+Rsb7lDbDz7ejrG7\no2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E\nFgQUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDI\nlZxg7z5RvXYwCgYIKoZIzj0EAwIDRwAwRAIgWJHBgtHO7YV04V9VXsJY4gvB5VlF\n/t4j0EZOU0LYDB4CIGz/j5GLp57E+emPELkcoTI11Yo7X9q0OdYp4nyjBrKy\n-----END CERTIFICATE-----"
],
"certificate": "-----BEGIN CERTIFICATE-----\nMIICZDCCAgqgAwIBAgIUMEo78R2WbVUklZKtRK29YZyWj6IwCgYIKoZIzj0EAwIw\nQjEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMSkwJwYDVQQDEyBFeGFtcGxlIExhYnMg\nSW50ZXJtZWRpYWUgQ0EgdjEuMjAeFw0yMjA5MjAxNDIxNThaFw0yMzA5MjAxNDIy\nMjhaMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhhbXBsZSBM\nYWJzIElzc3VpbmcgQ0EgdjEuMi4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\nb25UxYE/Wk3cmJGmgq7H0RA5gBJNTuHfG+nszNlmjvr0hlbl2eb6c2nHPUDnVm06\n8xiX+YEp5o4k5WKbpAWLB6OB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/\nBAgwBgEB/wIBADAdBgNVHQ4EFgQUGj9YO8B8HiPIinLrhn+m5t0q3J4wHwYDVR0j\nBBgwFoAUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwPwYIKwYBBQUHAQEEMzAxMC8GCCsG\nAQUFBzAChiNodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNV\nHR8ELjAsMCqgKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9j\ncmwwCgYIKoZIzj0EAwIDSAAwRQIhAP9R8GYDrQ+dbalPeHAUc72RazDvVFOFt5zR\nF2XoLB3gAiABK9YOSpdV/UCyjs+plIHmkIg27+tfABZ/WduS0cplUg==\n-----END CERTIFICATE-----",
"expiration": 1695219748,
"issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIB2TCCAYCgAwIBAgIQG8oFUAX8PlV+kdLWoCLzFzAKBggqhkjOPQQDAjA0MRAw\nDgYDVQQKEwdFeGFtcGxlMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9vdCBDQSB2\nMTAeFw0yMjA5MjAxMzQ4MThaFw0yNzA5MjAxMzU4MThaMEIxFTATBgNVBAoTDEV4\nYW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVkaWFlIENB\nIHYxLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjEv6cyrtjznet8uUxjumP\nif3cD0m+URss6KXtoD2vP6nDWrq3DxIizU746WE+tF9uGB6x+Rsb7lDbDz7ejrG7\no2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E\nFgQUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDI\nlZxg7z5RvXYwCgYIKoZIzj0EAwIDRwAwRAIgWJHBgtHO7YV04V9VXsJY4gvB5VlF\n/t4j0EZOU0LYDB4CIGz/j5GLp57E+emPELkcoTI11Yo7X9q0OdYp4nyjBrKy\n-----END CERTIFICATE-----",
"serial_number": "30:4a:3b:f1:1d:96:6d:55:24:95:92:ad:44:ad:bd:61:9c:96:8f:a2"
},
"warnings": [
"Max path length of the signed certificate is zero. This certificate cannot be used to issue intermediate CA certificates."
]
}
$ cat pki_iss_v1.2.1.crt.json \
| jq -r '.data.certificate' \
> pki_iss_v1.2.1.crt
$ openssl x509 -in pki_iss_v1.2.1.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
30:4a:3b:f1:1d:96:6d:55:24:95:92:ad:44:ad:bd:61:9c:...
Signature Algorithm: ecdsa-with-SHA256
Issuer: O = Example, CN = Example Labs Intermediae CA v1.2
Validity
Not Before: Sep 20 14:21:58 2022 GMT
Not After : Sep 20 14:22:28 2023 GMT
Subject: O = Example, CN = Example Labs Issuing CA v1.2.1
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:6f:6e:54:c5:81:3f:5a:4d:dc:98:91:a6:82:ae:
c7:d1:10:39:80:12:4d:4e:e1:df:1b:e9:ec:cc:d9:
66:8e:fa:f4:86:56:e5:d9:e6:fa:73:69:c7:3d:40:
e7:56:6d:3a:f3:18:97:f9:81:29:e6:8e:24:e5:62:
9b:a4:05:8b:07
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 Subject Key Identifier:
1A:3F:58:3B:C0:7C:1E:23:C8:8A:72:EB:86:7F:A6:E6:...
X509v3 Authority Key Identifier:
keyid:89:14:DC:23:34:8B:23:4B:21:EE:44:67:29:66:...
Authority Information Access:
CA Issuers - URI:http://127.0.0.1:8200/v1/pki_int/ca
X509v3 CRL Distribution Points: Full Name:
URI:http://127.0.0.1:8200/v1/pki_int/crl
Signature Algorithm: ecdsa-with-SHA256
30:45:02:21:00:ff:51:f0:66:03:ad:0f:9d:6d:a9:4f:78:70:
14:73:bd:91:6b:30:ef:54:53:85:b7:9c:d1:17:65:e8:2c:1d:
e0:02:20:01:2b:d6:0e:4a:97:55:fd:40:b2:8e:cf:a9:94:81:
e6:90:88:36:ef:eb:5f:00:16:7f:59:db:92:d1:ca:65:52
$ cat pki_iss_v1.2.1.crt pki_int_v1.2.crt > pki_iss_v1.2.1.chain.crt
$ vault write -format=json \
pki_iss/intermediate/set-signed \
certificate=@pki_iss_v1.2.1.chain.crt \
> pki_iss_v1.2.1.set-signed.json
$ cat pki_iss_v1.2.1.set-signed.json

{
"request_id": "07efbab3-cd52-cb48-8d8d-c77d98619464",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"imported_issuers": [
"b0074a43-589b-b59e-5683-f4c6f8b3348a",
"0531724f-5b62-fc93-03f1-d7c3bef99f1b"
],
"imported_keys": null,
"mapping": {
"0531724f-5b62-fc93-03f1-d7c3bef99f1b": "",
"b0074a43-589b-b59e-5683-f4c6f8b3348a": "b25aae5e-21f9-a18a-6dbe-e9c0ec1d9c25"
}
},
"warnings": null
}
  • Extract the issuer_id from the previous response, then rename the new issuer to v1.2.1 using the pki_iss/issuer/:issuer_refendpoint.
$ cat pki_iss_v1.2.1.set-signed.json \
| jq -r '.data.imported_issuers[0]' \
> pki_iss_v1.2.1.issuer_ref
$ vault write -format=json \
pki_iss/issuer/`cat pki_iss_v1.2.1.issuer_ref` \
issuer_name=v1.2.1 \
> pki_iss_v1.2.1.rename.json
$ cat pki_iss_v1.2.1.rename.json

{
"request_id": "bb29f6ac-7bd7-5585-6d13-284d38f8a871",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"ca_chain": [
"-----BEGIN CERTIFICATE-----\nMIICZDCCAgqgAwIBAgIUMEo78R2WbVUklZKtRK29YZyWj6IwCgYIKoZIzj0EAwIw\nQjEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMSkwJwYDVQQDEyBFeGFtcGxlIExhYnMg\nSW50ZXJtZWRpYWUgQ0EgdjEuMjAeFw0yMjA5MjAxNDIxNThaFw0yMzA5MjAxNDIy\nMjhaMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhhbXBsZSBM\nYWJzIElzc3VpbmcgQ0EgdjEuMi4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\nb25UxYE/Wk3cmJGmgq7H0RA5gBJNTuHfG+nszNlmjvr0hlbl2eb6c2nHPUDnVm06\n8xiX+YEp5o4k5WKbpAWLB6OB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/\nBAgwBgEB/wIBADAdBgNVHQ4EFgQUGj9YO8B8HiPIinLrhn+m5t0q3J4wHwYDVR0j\nBBgwFoAUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwPwYIKwYBBQUHAQEEMzAxMC8GCCsG\nAQUFBzAChiNodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNV\nHR8ELjAsMCqgKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9j\ncmwwCgYIKoZIzj0EAwIDSAAwRQIhAP9R8GYDrQ+dbalPeHAUc72RazDvVFOFt5zR\nF2XoLB3gAiABK9YOSpdV/UCyjs+plIHmkIg27+tfABZ/WduS0cplUg==\n-----END CERTIFICATE-----\n",
"-----BEGIN CERTIFICATE-----\nMIIB2TCCAYCgAwIBAgIQG8oFUAX8PlV+kdLWoCLzFzAKBggqhkjOPQQDAjA0MRAw\nDgYDVQQKEwdFeGFtcGxlMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9vdCBDQSB2\nMTAeFw0yMjA5MjAxMzQ4MThaFw0yNzA5MjAxMzU4MThaMEIxFTATBgNVBAoTDEV4\nYW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVkaWFlIENB\nIHYxLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjEv6cyrtjznet8uUxjumP\nif3cD0m+URss6KXtoD2vP6nDWrq3DxIizU746WE+tF9uGB6x+Rsb7lDbDz7ejrG7\no2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E\nFgQUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDI\nlZxg7z5RvXYwCgYIKoZIzj0EAwIDRwAwRAIgWJHBgtHO7YV04V9VXsJY4gvB5VlF\n/t4j0EZOU0LYDB4CIGz/j5GLp57E+emPELkcoTI11Yo7X9q0OdYp4nyjBrKy\n-----END CERTIFICATE-----\n"
],
"certificate": "-----BEGIN CERTIFICATE-----\nMIICZDCCAgqgAwIBAgIUMEo78R2WbVUklZKtRK29YZyWj6IwCgYIKoZIzj0EAwIw\nQjEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMSkwJwYDVQQDEyBFeGFtcGxlIExhYnMg\nSW50ZXJtZWRpYWUgQ0EgdjEuMjAeFw0yMjA5MjAxNDIxNThaFw0yMzA5MjAxNDIy\nMjhaMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhhbXBsZSBM\nYWJzIElzc3VpbmcgQ0EgdjEuMi4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\nb25UxYE/Wk3cmJGmgq7H0RA5gBJNTuHfG+nszNlmjvr0hlbl2eb6c2nHPUDnVm06\n8xiX+YEp5o4k5WKbpAWLB6OB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/\nBAgwBgEB/wIBADAdBgNVHQ4EFgQUGj9YO8B8HiPIinLrhn+m5t0q3J4wHwYDVR0j\nBBgwFoAUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwPwYIKwYBBQUHAQEEMzAxMC8GCCsG\nAQUFBzAChiNodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNV\nHR8ELjAsMCqgKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9j\ncmwwCgYIKoZIzj0EAwIDSAAwRQIhAP9R8GYDrQ+dbalPeHAUc72RazDvVFOFt5zR\nF2XoLB3gAiABK9YOSpdV/UCyjs+plIHmkIg27+tfABZ/WduS0cplUg==\n-----END CERTIFICATE-----\n",
"issuer_id": "b0074a43-589b-b59e-5683-f4c6f8b3348a",
"issuer_name": "v1.2.1",
"key_id": "b25aae5e-21f9-a18a-6dbe-e9c0ec1d9c25",
"leaf_not_after_behavior": "err",
"manual_chain": null,
"usage": "read-only,issuing-certificates,crl-signing"
},
"warnings": null
}

At this stage, the v1.2 and v1.2.1 issuers have been generated.

Let’s check the terminal where consul-template is running. As the default issuer is still v1.1.2, the issued leaf certificates are still with v1.1.2 issuer.

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEILirPGC01CN6f74ALnRVT+Ro24TBk6VIROOGkjkJEAgNoAoGCCqGSM49
AwEHoUQDQgAEYJFAFWFoB1FBx1kUKXBwzBlMrtv4iA4wpogAXpNPLJnSWMQx6l70
K2JJtaOXm3AUaUNYEU6I0XlumYNhZ9rg/Q==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.1.2
subject=O = Example, CN = test.example.com
notBefore=Sep 20 14:34:25 2022 GMT
notAfter=Sep 20 14:35:25 2022 GMT
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIBqV1hRGpfLYz/3e5B7MH3U9ysdvwFoKrWuGbyqHw2XioAoGCCqGSM49
AwEHoUQDQgAEBbgqffirdifrmnzRFKe3JQfv0Msi+djaSSQlc4QXF0xpwsFZ3mpX
cXNUEEMuHeVumEJY8MrXnTmnfn/bc2D3uA==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.1.2
subject=O = Example, CN = test.example.com
notBefore=Sep 20 14:34:53 2022 GMT
notAfter=Sep 20 14:35:53 2022 GMT
Set default issuer to v1.2
  • Now, rotate the Intermediate CA by setting the default issuer to v1.2 using the pki_int/root/replaceendpoint.
$ vault write -format=json \
pki_int/root/replace \
default=v1.2 \
> pki_int_v1.2.replace.json
$ cat pki_int_v1.2.replace.json
{
"request_id": "4e469221-c1e8-5eb0-2815-58b031b2e276",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"default": "08ca0f1e-abad-4a6a-f632-6199adc0a9d4"
},
"warnings": null
}
$ vault list -detailed pki_int/issuers
Keys is_default issuer_name
---- ---------- -----------
08ca0f1e-abad-4a6a-f632-6199adc0a9d4 true v1.2
17438773-df12-5bab-a7ee-83a7305037fb false v1.1
Set default issuer to v1.2.1
  • Now, rotate the Issuing CA by setting the default issuer to v1.2.1 using the pki_iss/root/replaceendpoint.
$ vault write -format=json \
pki_iss/root/replace \
default=v1.2.1 \
> pki_iss_v1.2.1.replace.json
$ cat pki_iss_v1.2.1.replace.json
{
"request_id": "053a5a0d-96cc-bf9b-5e9a-d037581d6443",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"default": "b0074a43-589b-b59e-5683-f4c6f8b3348a"
},
"warnings": null
}
$ vault list -detailed pki_iss/issuers | grep -v "n/a"
Keys is_default issuer_name
---- ---------- -----------
42149e44-785e-3dec-a7e1-ba9e1c4804a0 false v1.1.2
957c0c19-a66b-f2fa-b868-05f01bc142e5 false v1.1.1
b0074a43-589b-b59e-5683-f4c6f8b3348a true v1.2.1

Let’s check the terminal where consul-template is running. As the default issuer has been replace by the v1.2.1 issuer, the issued leaf certificates are now with v1.2.1 issuer. The CA chain is updated as well because the Intermediate CA and the Issuing CA certificates are now respectively from the v1.2 and the v1.1.2 issuers.

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIGJG0DeO+g0Bm45IAZiXSyTtmEaVfsl3fyq3yUYoPf4poAoGCCqGSM49
AwEHoUQDQgAEdOjXpuQmByDMhwReZSiz6LWQ/IlW3m3ywykQgeC9afsNlqKoB1y1
Szfek5wcfLwB/5Afs/pG1TTkF0tcKa+oAQ==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.1.2
subject=O = Example, CN = test.example.com
notBefore=Sep 20 14:38:23 2022 GMT
notAfter=Sep 20 14:39:23 2022 GMT
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIORzgwnBQLRiXg0VlKw2rvlmVyw1zBfUSmege4MZ35ykoAoGCCqGSM49
AwEHoUQDQgAEvaDezFf31ErSxJw3vniiAWylYXYcnL5/SaTOg7Fh2fGFE4BVkUxF
5wMWU7H+OYoj5nGBxjwXyLcn1jT9v4IuyQ==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.2.1
subject=O = Example, CN = test.example.com
notBefore=Sep 20 14:38:51 2022 GMT
notAfter=Sep 20 14:39:51 2022 GMT
-----BEGIN CERTIFICATE-----
MIICZDCCAgqgAwIBAgIUMEo78R2WbVUklZKtRK29YZyWj6IwCgYIKoZIzj0EAwIw
QjEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMSkwJwYDVQQDEyBFeGFtcGxlIExhYnMg
SW50ZXJtZWRpYWUgQ0EgdjEuMjAeFw0yMjA5MjAxNDIxNThaFw0yMzA5MjAxNDIy
MjhaMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhhbXBsZSBM
YWJzIElzc3VpbmcgQ0EgdjEuMi4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
b25UxYE/Wk3cmJGmgq7H0RA5gBJNTuHfG+nszNlmjvr0hlbl2eb6c2nHPUDnVm06
8xiX+YEp5o4k5WKbpAWLB6OB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/
BAgwBgEB/wIBADAdBgNVHQ4EFgQUGj9YO8B8HiPIinLrhn+m5t0q3J4wHwYDVR0j
BBgwFoAUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwPwYIKwYBBQUHAQEEMzAxMC8GCCsG
AQUFBzAChiNodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNV
HR8ELjAsMCqgKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9j
cmwwCgYIKoZIzj0EAwIDSAAwRQIhAP9R8GYDrQ+dbalPeHAUc72RazDvVFOFt5zR
F2XoLB3gAiABK9YOSpdV/UCyjs+plIHmkIg27+tfABZ/WduS0cplUg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB2TCCAYCgAwIBAgIQG8oFUAX8PlV+kdLWoCLzFzAKBggqhkjOPQQDAjA0MRAw
DgYDVQQKEwdFeGFtcGxlMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9vdCBDQSB2
MTAeFw0yMjA5MjAxMzQ4MThaFw0yNzA5MjAxMzU4MThaMEIxFTATBgNVBAoTDEV4
YW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVkaWFlIENB
IHYxLjIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjEv6cyrtjznet8uUxjumP
if3cD0m+URss6KXtoD2vP6nDWrq3DxIizU746WE+tF9uGB6x+Rsb7lDbDz7ejrG7
o2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4E
FgQUiRTcIzSLI0sh7kRnKWYcGJ9zOIkwHwYDVR0jBBgwFoAUwkn7K1yzMRL7FLDI
lZxg7z5RvXYwCgYIKoZIzj0EAwIDRwAwRAIgWJHBgtHO7YV04V9VXsJY4gvB5VlF
/t4j0EZOU0LYDB4CIGz/j5GLp57E+emPELkcoTI11Yo7X9q0OdYp4nyjBrKy
-----END CERTIFICATE-----

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJJeN5J3GzrOw0xosA30ZLv9nA87c0kkcp95/lGVG0CooAoGCCqGSM49
AwEHoUQDQgAEhr2YsJN2Ss0eR9TGhKIDpo777Dk5G6/PfU+r7LbSFqZwx5DcCwMf
c/iZC41alZ75ycYA7ZJSwh93xzqOJIE6dw==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.2.1
subject=O = Example, CN = test.example.com
notBefore=Sep 20 14:39:17 2022 GMT
notAfter=Sep 20 14:40:17 2022 GMT

As a result, the Intermediate CA and the Issuing CA have been rotated, and the automatic generation of leaf certificates is passed on seamlessly to the new issuer.

In the next section, the Root CA is rotated.

Rotate Root CA

Now, let’s update the Root CA.

Generate Root CA v2

First, generate a self-signed Root CA v2 using certstrap

$ certstrap --depot-path root \
init \
--organization "Example" \
--common-name "Example Labs Root CA v2" \
--expires "10 years" \
--curve P-256 \
--path-length 2 \
--passphrase "secret"

Created root/Example_Labs_Root_CA_v2.key (encrypted by passphrase)
Created root/Example_Labs_Root_CA_v2.crt
Created root/Example_Labs_Root_CA_v2.crl
Generate v2.1 issuer for Intermediate CA

Let’s generate a new issuer for the Intermediate CA.

$ vault write -format=json \
pki_int/intermediate/generate/internal \
organization="Example" \
common_name="Example Labs Intermediae CA v2.1" \
key_type=ec \
key_bits=256 \
| jq -r '.data.csr' > pki_int_v2.1.csr
  • Sign and generate a certificate using the CSR with Root CA v2
$ certstrap --depot-path root \
sign \
--CA "Example Labs Root CA v2" \
--passphrase "secret" \
--intermediate \
--csr pki_int_v2.1.csr \
--expires "5 years" \
--path-length 1 \
--cert pki_int_v2.1.crt \
"Example Labs Intermediate CA v2.1"

Building intermediate
$ openssl x509 -in pki_int_v2.1.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
c2:60:be:af:06:ab:b2:c0:cd:09:46:89:e6:29:01:35
Signature Algorithm: ecdsa-with-SHA256
Issuer: O = Example, CN = Example Labs Root CA v2
Validity
Not Before: Sep 20 14:44:54 2022 GMT
Not After : Sep 20 14:54:54 2027 GMT
Subject: O = Example, CN = Example Labs Intermediae CA v2.1
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:97:68:be:e1:f5:b9:60:8c:df:b3:93:b0:df:32:
da:db:d1:2f:d9:d2:c3:dc:23:f4:65:06:b7:93:34:
ab:20:fe:ab:5f:a4:cf:7c:5b:f2:98:9a:a7:56:9a:
9b:ee:68:60:f7:4d:b0:ac:3a:2d:6f:83:5b:f9:bb:
d5:05:03:14:9b
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:1
X509v3 Subject Key Identifier:
F5:4C:47:59:A7:46:E5:98:A7:F4:6D:DB:55:F6:58:5E:...
X509v3 Authority Key Identifier:
keyid:51:49:EE:AF:2A:CD:6B:7C:EE:96:03:60:F2:0C:...
Signature Algorithm: ecdsa-with-SHA256
30:46:02:21:00:a5:cc:ec:ad:36:6e:9b:b7:76:75:2f:68:3d:
c4:88:03:55:4c:72:70:89:88:1b:80:8e:e2:4e:59:74:cc:c5:
38:02:21:00:8f:a9:1f:c4:36:fb:bb:20:01:39:3d:5a:e2:65:
b6:4d:4b:43:bc:18:8d:0d:f9:25:c3:5d:e4:2d:87:8b:cb:88
$ vault write -format=json \
pki_int/intermediate/set-signed \
certificate=@pki_int_v2.1.crt \
> pki_int_v2.1.set-signed.json
$ cat pki_int_v2.1.set-signed.json
{
"request_id": "de4c817e-3cd7-f6a1-1baf-d201a2435a3b",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"imported_issuers": [
"b2549f1f-3304-3e76-1e72-f02510a4659d"
],
"imported_keys": null,
"mapping": {
"b2549f1f-3304-3e76-1e72-f02510a4659d": "85c8cf07-047a-e44b-7a73-0b3a0261af7a"
}
},
"warnings": null
}
  • Extract the issuer_id from the previous response, then rename the new issuer to v2.1 using the pki_int/issuer/:issuer_ref endpoint.
$ cat pki_int_v2.1.set-signed.json \
| jq -r '.data.imported_issuers[0]' \
> pki_int_v2.1.issuer_ref
$ vault write -format=json \
pki_int/issuer/`cat pki_int_v2.1.issuer_ref` \
issuer_name=v2.1 \
> pki_int_v2.1.rename.json
$ cat pki_int_v2.1.rename.json
{
"request_id": "f617c3ba-8eb9-8885-0690-3a94a628f38e",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"ca_chain": [
"-----BEGIN CERTIFICATE-----\nMIIB4TCCAYagAwIBAgIRAMJgvq8Gq7LAzQlGieYpATUwCgYIKoZIzj0EAwIwOTEV\nMBMGA1UEChMMRXhhbXBsZSBMYWJzMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9v\ndCBDQSB2MjAeFw0yMjA5MjAxNDQ0NTRaFw0yNzA5MjAxNDU0NTRaMEIxFTATBgNV\nBAoTDEV4YW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVk\naWFlIENBIHYyLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASXaL7h9blgjN+z\nk7DfMtrb0S/Z0sPcI/RlBreTNKsg/qtfpM98W/KYmqdWmpvuaGD3TbCsOi1vg1v5\nu9UFAxSbo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQU9UxHWadG5Zin9G3bVfZYXp0XZb8wHwYDVR0jBBgwFoAUUUnuryrN\na3zulgNg8gyXQ59isjowCgYIKoZIzj0EAwIDSQAwRgIhAKXM7K02bpu3dnUvaD3E\niANVTHJwiYgbgI7iTll0zMU4AiEAj6kfxDb7uyABOT1a4mW2TUtDvBiNDfklw13k\nLYeLy4g=\n-----END CERTIFICATE-----\n"
],
"certificate": "-----BEGIN CERTIFICATE-----\nMIIB4TCCAYagAwIBAgIRAMJgvq8Gq7LAzQlGieYpATUwCgYIKoZIzj0EAwIwOTEV\nMBMGA1UEChMMRXhhbXBsZSBMYWJzMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9v\ndCBDQSB2MjAeFw0yMjA5MjAxNDQ0NTRaFw0yNzA5MjAxNDU0NTRaMEIxFTATBgNV\nBAoTDEV4YW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVk\naWFlIENBIHYyLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASXaL7h9blgjN+z\nk7DfMtrb0S/Z0sPcI/RlBreTNKsg/qtfpM98W/KYmqdWmpvuaGD3TbCsOi1vg1v5\nu9UFAxSbo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQU9UxHWadG5Zin9G3bVfZYXp0XZb8wHwYDVR0jBBgwFoAUUUnuryrN\na3zulgNg8gyXQ59isjowCgYIKoZIzj0EAwIDSQAwRgIhAKXM7K02bpu3dnUvaD3E\niANVTHJwiYgbgI7iTll0zMU4AiEAj6kfxDb7uyABOT1a4mW2TUtDvBiNDfklw13k\nLYeLy4g=\n-----END CERTIFICATE-----\n",
"issuer_id": "b2549f1f-3304-3e76-1e72-f02510a4659d",
"issuer_name": "v2.1",
"key_id": "85c8cf07-047a-e44b-7a73-0b3a0261af7a",
"leaf_not_after_behavior": "err",
"manual_chain": null,
"usage": "read-only,issuing-certificates,crl-signing"
},
"warnings": null
}
Generate v2.1.1 issuer for Issuing CA

Now, let’s generate a new issuer for Issuing CA.

$ vault write -format=json \
pki_iss/intermediate/generate/internal \
organization="Example" \
common_name="Example Labs Issuing CA v2.1.1" \
key_type=ec \
key_bits=256 \
| jq -r '.data.csr' > pki_iss_v2.1.1.csr

The pki_int/root/sign-intermediate endpoint uses the default issuer. So, it can’t be used because the default issuer for Intermediate CA isn’t set to v2.1.

$ vault write -format=json \
pki_int/issuer/v2.1/sign-intermediate \
organization="Example" \
csr=@pki_iss_v2.1.1.csr \
ttl=8760h \
format=pem \
> pki_iss_v2.1.1.crt.json
$ cat pki_iss_v2.1.1.crt.json

{
"request_id": "fad0a282-b007-668f-1a9c-fcadfdaa174f",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"ca_chain": [
"-----BEGIN CERTIFICATE-----\nMIICZDCCAgqgAwIBAgIUPie9Pf1M0IH7dBNvrkYx4BSIlxUwCgYIKoZIzj0EAwIw\nQjEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMSkwJwYDVQQDEyBFeGFtcGxlIExhYnMg\nSW50ZXJtZWRpYWUgQ0EgdjIuMTAeFw0yMjA5MjAxNjI1NTNaFw0yMzA5MjAxNjI2\nMjNaMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhhbXBsZSBM\nYWJzIElzc3VpbmcgQ0EgdjIuMS4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\nEexLHdGKeYFlBhMwjSlgLxvLNPrWSBgbzfhpUX4gaWSk9A/VeYFy1sxqblPImXZT\npMSAMeGmT120NnAqMDvHhaOB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/\nBAgwBgEB/wIBADAdBgNVHQ4EFgQUh0VbbLaqHCDv2IwgZxsN3alDPXYwHwYDVR0j\nBBgwFoAU9UxHWadG5Zin9G3bVfZYXp0XZb8wPwYIKwYBBQUHAQEEMzAxMC8GCCsG\nAQUFBzAChiNodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNV\nHR8ELjAsMCqgKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9j\ncmwwCgYIKoZIzj0EAwIDSAAwRQIhAPHuWMYBr9ivWAjLLWxVrQynpxl3pdd7v/i/\nXfpvl5jOAiAePmQMgmaNRMZ81mttNm7L2nmuA8Gr7ep6SmwWLVnVkA==\n-----END CERTIFICATE-----",
"-----BEGIN CERTIFICATE-----\nMIIB4TCCAYagAwIBAgIRAMJgvq8Gq7LAzQlGieYpATUwCgYIKoZIzj0EAwIwOTEV\nMBMGA1UEChMMRXhhbXBsZSBMYWJzMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9v\ndCBDQSB2MjAeFw0yMjA5MjAxNDQ0NTRaFw0yNzA5MjAxNDU0NTRaMEIxFTATBgNV\nBAoTDEV4YW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVk\naWFlIENBIHYyLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASXaL7h9blgjN+z\nk7DfMtrb0S/Z0sPcI/RlBreTNKsg/qtfpM98W/KYmqdWmpvuaGD3TbCsOi1vg1v5\nu9UFAxSbo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQU9UxHWadG5Zin9G3bVfZYXp0XZb8wHwYDVR0jBBgwFoAUUUnuryrN\na3zulgNg8gyXQ59isjowCgYIKoZIzj0EAwIDSQAwRgIhAKXM7K02bpu3dnUvaD3E\niANVTHJwiYgbgI7iTll0zMU4AiEAj6kfxDb7uyABOT1a4mW2TUtDvBiNDfklw13k\nLYeLy4g=\n-----END CERTIFICATE-----"
],
"certificate": "-----BEGIN CERTIFICATE-----\nMIICZDCCAgqgAwIBAgIUPie9Pf1M0IH7dBNvrkYx4BSIlxUwCgYIKoZIzj0EAwIw\nQjEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMSkwJwYDVQQDEyBFeGFtcGxlIExhYnMg\nSW50ZXJtZWRpYWUgQ0EgdjIuMTAeFw0yMjA5MjAxNjI1NTNaFw0yMzA5MjAxNjI2\nMjNaMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhhbXBsZSBM\nYWJzIElzc3VpbmcgQ0EgdjIuMS4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\nEexLHdGKeYFlBhMwjSlgLxvLNPrWSBgbzfhpUX4gaWSk9A/VeYFy1sxqblPImXZT\npMSAMeGmT120NnAqMDvHhaOB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/\nBAgwBgEB/wIBADAdBgNVHQ4EFgQUh0VbbLaqHCDv2IwgZxsN3alDPXYwHwYDVR0j\nBBgwFoAU9UxHWadG5Zin9G3bVfZYXp0XZb8wPwYIKwYBBQUHAQEEMzAxMC8GCCsG\nAQUFBzAChiNodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNV\nHR8ELjAsMCqgKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9j\ncmwwCgYIKoZIzj0EAwIDSAAwRQIhAPHuWMYBr9ivWAjLLWxVrQynpxl3pdd7v/i/\nXfpvl5jOAiAePmQMgmaNRMZ81mttNm7L2nmuA8Gr7ep6SmwWLVnVkA==\n-----END CERTIFICATE-----",
"expiration": 1695227183,
"issuing_ca": "-----BEGIN CERTIFICATE-----\nMIIB4TCCAYagAwIBAgIRAMJgvq8Gq7LAzQlGieYpATUwCgYIKoZIzj0EAwIwOTEV\nMBMGA1UEChMMRXhhbXBsZSBMYWJzMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9v\ndCBDQSB2MjAeFw0yMjA5MjAxNDQ0NTRaFw0yNzA5MjAxNDU0NTRaMEIxFTATBgNV\nBAoTDEV4YW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVk\naWFlIENBIHYyLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASXaL7h9blgjN+z\nk7DfMtrb0S/Z0sPcI/RlBreTNKsg/qtfpM98W/KYmqdWmpvuaGD3TbCsOi1vg1v5\nu9UFAxSbo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQU9UxHWadG5Zin9G3bVfZYXp0XZb8wHwYDVR0jBBgwFoAUUUnuryrN\na3zulgNg8gyXQ59isjowCgYIKoZIzj0EAwIDSQAwRgIhAKXM7K02bpu3dnUvaD3E\niANVTHJwiYgbgI7iTll0zMU4AiEAj6kfxDb7uyABOT1a4mW2TUtDvBiNDfklw13k\nLYeLy4g=\n-----END CERTIFICATE-----",
"serial_number": "3e:27:bd:3d:fd:4c:d0:81:fb:74:13:6f:ae:46:31:e0:14:88:97:15"
},
"warnings": [
"Max path length of the signed certificate is zero. This certificate cannot be used to issue intermediate CA certificates."
]
}
$ cat pki_iss_v2.1.1.crt.json \
| jq -r '.data.certificate' \
> pki_iss_v2.1.1.crt
$ openssl x509 -in pki_iss_v2.1.1.crt -text -noout

Certificate:
Data:
Version: 3 (0x2)
Serial Number:
3e:27:bd:3d:fd:4c:d0:81:fb:74:13:6f:ae:46:31:e0:...
Signature Algorithm: ecdsa-with-SHA256
Issuer: O = Example, CN = Example Labs Intermediae CA v2.1
Validity
Not Before: Sep 20 16:25:53 2022 GMT
Not After : Sep 20 16:26:23 2023 GMT
Subject: O = Example, CN = Example Labs Issuing CA v2.1.1
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:11:ec:4b:1d:d1:8a:79:81:65:06:13:30:8d:29:
60:2f:1b:cb:34:fa:d6:48:18:1b:cd:f8:69:51:7e:
20:69:64:a4:f4:0f:d5:79:81:72:d6:cc:6a:6e:53:
c8:99:76:53:a4:c4:80:31:e1:a6:4f:5d:b4:36:70:
2a:30:3b:c7:85
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 Subject Key Identifier:
87:45:5B:6C:B6:AA:1C:20:EF:D8:8C:20:67:1B:0D:...
X509v3 Authority Key Identifier:
keyid:F5:4C:47:59:A7:46:E5:98:A7:F4:6D:DB:55:F6:...
Authority Information Access:
CA Issuers - URI:http://127.0.0.1:8200/v1/pki_int/ca
X509v3 CRL Distribution Points: Full Name:
URI:http://127.0.0.1:8200/v1/pki_int/crl
Signature Algorithm: ecdsa-with-SHA256
30:45:02:21:00:f1:ee:58:c6:01:af:d8:af:58:08:cb:2d:6c:
55:ad:0c:a7:a7:19:77:a5:d7:7b:bf:f8:bf:5d:fa:6f:97:98:
ce:02:20:1e:3e:64:0c:82:66:8d:44:c6:7c:d6:6b:6d:36:6e:
cb:da:79:ae:03:c1:ab:ed:ea:7a:4a:6c:16:2d:59:d5:90
$ cat pki_iss_v2.1.1.crt pki_int_v2.1.crt > pki_iss_v2.1.1.chain.crt
$ vault write -format=json \
pki_iss/intermediate/set-signed \
certificate=@pki_iss_v2.1.1.chain.crt \
> pki_iss_v2.1.1.set-signed.json
$ cat pki_iss_v2.1.1.set-signed.json
{
"request_id": "51eb024e-c4fa-1ac7-bf61-bbb5a1b535e4",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"imported_issuers": [
"68c43ef3-f6f8-5ac6-ee21-e320d96f68f0",
"396e8878-26e0-74d0-9b2b-d02943c65902"
],
"imported_keys": null,
"mapping": {
"396e8878-26e0-74d0-9b2b-d02943c65902": "",
"68c43ef3-f6f8-5ac6-ee21-e320d96f68f0": "ec038893-b95b-e19f-179f-5cbda0cdab2f"
}
},
"warnings": null
}
  • Extract the issuer_id from the previous response, then rename the new issuer to v2.1.1 using the pki_iss/issuer/:issuer_ref endpoint.
$ cat pki_iss_v2.1.1.set-signed.json \
| jq -r '.data.imported_issuers[0]' \
> pki_iss_v2.1.1.issuer_ref
$ vault write -format=json \
pki_iss/issuer/`cat pki_iss_v2.1.1.issuer_ref` \
issuer_name=v2.1.1 \
> pki_iss_v2.1.1.rename.json
$ cat pki_iss_v2.1.1.rename.json

{
"request_id": "ab5e3d2a-d33c-c462-cbfe-7a5f180d2909",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"ca_chain": [
"-----BEGIN CERTIFICATE-----\nMIICZDCCAgqgAwIBAgIUPie9Pf1M0IH7dBNvrkYx4BSIlxUwCgYIKoZIzj0EAwIw\nQjEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMSkwJwYDVQQDEyBFeGFtcGxlIExhYnMg\nSW50ZXJtZWRpYWUgQ0EgdjIuMTAeFw0yMjA5MjAxNjI1NTNaFw0yMzA5MjAxNjI2\nMjNaMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhhbXBsZSBM\nYWJzIElzc3VpbmcgQ0EgdjIuMS4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\nEexLHdGKeYFlBhMwjSlgLxvLNPrWSBgbzfhpUX4gaWSk9A/VeYFy1sxqblPImXZT\npMSAMeGmT120NnAqMDvHhaOB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/\nBAgwBgEB/wIBADAdBgNVHQ4EFgQUh0VbbLaqHCDv2IwgZxsN3alDPXYwHwYDVR0j\nBBgwFoAU9UxHWadG5Zin9G3bVfZYXp0XZb8wPwYIKwYBBQUHAQEEMzAxMC8GCCsG\nAQUFBzAChiNodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNV\nHR8ELjAsMCqgKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9j\ncmwwCgYIKoZIzj0EAwIDSAAwRQIhAPHuWMYBr9ivWAjLLWxVrQynpxl3pdd7v/i/\nXfpvl5jOAiAePmQMgmaNRMZ81mttNm7L2nmuA8Gr7ep6SmwWLVnVkA==\n-----END CERTIFICATE-----\n",
"-----BEGIN CERTIFICATE-----\nMIIB4TCCAYagAwIBAgIRAMJgvq8Gq7LAzQlGieYpATUwCgYIKoZIzj0EAwIwOTEV\nMBMGA1UEChMMRXhhbXBsZSBMYWJzMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9v\ndCBDQSB2MjAeFw0yMjA5MjAxNDQ0NTRaFw0yNzA5MjAxNDU0NTRaMEIxFTATBgNV\nBAoTDEV4YW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVk\naWFlIENBIHYyLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASXaL7h9blgjN+z\nk7DfMtrb0S/Z0sPcI/RlBreTNKsg/qtfpM98W/KYmqdWmpvuaGD3TbCsOi1vg1v5\nu9UFAxSbo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQU9UxHWadG5Zin9G3bVfZYXp0XZb8wHwYDVR0jBBgwFoAUUUnuryrN\na3zulgNg8gyXQ59isjowCgYIKoZIzj0EAwIDSQAwRgIhAKXM7K02bpu3dnUvaD3E\niANVTHJwiYgbgI7iTll0zMU4AiEAj6kfxDb7uyABOT1a4mW2TUtDvBiNDfklw13k\nLYeLy4g=\n-----END CERTIFICATE-----\n"
],
"certificate": "-----BEGIN CERTIFICATE-----\nMIICZDCCAgqgAwIBAgIUPie9Pf1M0IH7dBNvrkYx4BSIlxUwCgYIKoZIzj0EAwIw\nQjEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMSkwJwYDVQQDEyBFeGFtcGxlIExhYnMg\nSW50ZXJtZWRpYWUgQ0EgdjIuMTAeFw0yMjA5MjAxNjI1NTNaFw0yMzA5MjAxNjI2\nMjNaMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhhbXBsZSBM\nYWJzIElzc3VpbmcgQ0EgdjIuMS4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\nEexLHdGKeYFlBhMwjSlgLxvLNPrWSBgbzfhpUX4gaWSk9A/VeYFy1sxqblPImXZT\npMSAMeGmT120NnAqMDvHhaOB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/\nBAgwBgEB/wIBADAdBgNVHQ4EFgQUh0VbbLaqHCDv2IwgZxsN3alDPXYwHwYDVR0j\nBBgwFoAU9UxHWadG5Zin9G3bVfZYXp0XZb8wPwYIKwYBBQUHAQEEMzAxMC8GCCsG\nAQUFBzAChiNodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNV\nHR8ELjAsMCqgKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9j\ncmwwCgYIKoZIzj0EAwIDSAAwRQIhAPHuWMYBr9ivWAjLLWxVrQynpxl3pdd7v/i/\nXfpvl5jOAiAePmQMgmaNRMZ81mttNm7L2nmuA8Gr7ep6SmwWLVnVkA==\n-----END CERTIFICATE-----\n",
"issuer_id": "68c43ef3-f6f8-5ac6-ee21-e320d96f68f0",
"issuer_name": "v2.1.1",
"key_id": "ec038893-b95b-e19f-179f-5cbda0cdab2f",
"leaf_not_after_behavior": "err",
"manual_chain": null,
"usage": "issuing-certificates,crl-signing,read-only"
},
"warnings": null
}
Set default issuer to v2.1
  • Now, rotate the Intermediate CA by setting the default issuer to v2.1 using the pki_int/root/replaceendpoint.
$ vault write -format=json \
pki_int/root/replace \
default=v2.1 \
> pki_int_v2.1.replace.json
$ cat pki_int_v2.1.replace.json

{
"request_id": "f30cde61-31bc-582f-818c-bfeaf60f9edd",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"default": "b2549f1f-3304-3e76-1e72-f02510a4659d"
},
"warnings": null
}
$ vault list -detailed pki_int/issuers
Keys is_default issuer_name
---- ---------- -----------
08ca0f1e-abad-4a6a-f632-6199adc0a9d4 false v1.2
17438773-df12-5bab-a7ee-83a7305037fb false v1.1
b2549f1f-3304-3e76-1e72-f02510a4659d true v2.1
Set default issuer to v2.1.1
  • Now, rotate the Issuing CA by setting the default issuer to v2.1.1 using the pki_iss/root/replaceendpoint.
$ vault write -format=json \
pki_iss/root/replace \
default=v2.1.1 \
> pki_iss_v2.1.1.replace.json

$ cat pki_iss_v2.1.1.replace.json
{
"request_id": "dc969f74-3a99-1497-0ea0-1c3506fde036",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": {
"default": "68c43ef3-f6f8-5ac6-ee21-e320d96f68f0"
},
"warnings": null
}
$ vault list -detailed pki_iss/issuers | grep -v "n/a"
Keys is_default issuer_name
---- ---------- -----------
42149e44-785e-3dec-a7e1-ba9e1c4804a0 false v1.1.2
68c43ef3-f6f8-5ac6-ee21-e320d96f68f0 true v2.1.1
957c0c19-a66b-f2fa-b868-05f01bc142e5 false v1.1.1
b0074a43-589b-b59e-5683-f4c6f8b3348a false v1.2.1

Let’s check the terminal where consul-template is running. As the default issuer has been replace by the v2.1.1 issuer, the issued leaf certificates are now with v2.1.1 issuer. The CA chain is updated as well because the Intermediate CA and the Issuing CA certificates are now respectively from the v2.1 and the v2.1.1 issuers.

----BEGIN EC PRIVATE KEY-----
MHcCAQEEIK9Gxr0XfGYxjt1CVZ7F8wRkdxZf4Qz/Bkl5Ar9K5LpNoAoGCCqGSM49
AwEHoUQDQgAEGlLdQQurLXgTETFEExH+WQVDLWtBO/gLc9HAvHpPtvJGgi32mA44
6lD0j+SsYmnWclodPbMWt1CgQItI/aoydQ==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v1.2.1
subject=O = Example, CN = test.example.com
notBefore=Sep 20 16:36:56 2022 GMT
notAfter=Sep 20 16:37:56 2022 GMT
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICcqlkR22J+f+BWuATUkbbtkQ9+NvJV64HdCNoxaFjj1oAoGCCqGSM49
AwEHoUQDQgAEzV2HpXpZYP14HmKD2IEi9Tl0xYIF9Vll6LivJX76oK0hWuvitPkt
GGVEnzCmWliPpdoSN2ZFZIB158GSlKN1iA==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v2.1.1
subject=O = Example, CN = test.example.com
notBefore=Sep 20 16:37:22 2022 GMT
notAfter=Sep 20 16:38:22 2022 GMT
-----BEGIN CERTIFICATE-----
MIICZDCCAgqgAwIBAgIUPie9Pf1M0IH7dBNvrkYx4BSIlxUwCgYIKoZIzj0EAwIw
QjEVMBMGA1UEChMMRXhhbXBsZSBMYWJzMSkwJwYDVQQDEyBFeGFtcGxlIExhYnMg
SW50ZXJtZWRpYWUgQ0EgdjIuMTAeFw0yMjA5MjAxNjI1NTNaFw0yMzA5MjAxNjI2
MjNaMEAxFTATBgNVBAoTDEV4YW1wbGUgTGFiczEnMCUGA1UEAxMeRXhhbXBsZSBM
YWJzIElzc3VpbmcgQ0EgdjIuMS4xMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
EexLHdGKeYFlBhMwjSlgLxvLNPrWSBgbzfhpUX4gaWSk9A/VeYFy1sxqblPImXZT
pMSAMeGmT120NnAqMDvHhaOB3zCB3DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/
BAgwBgEB/wIBADAdBgNVHQ4EFgQUh0VbbLaqHCDv2IwgZxsN3alDPXYwHwYDVR0j
BBgwFoAU9UxHWadG5Zin9G3bVfZYXp0XZb8wPwYIKwYBBQUHAQEEMzAxMC8GCCsG
AQUFBzAChiNodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9jYTA1BgNV
HR8ELjAsMCqgKKAmhiRodHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpX2ludC9j
cmwwCgYIKoZIzj0EAwIDSAAwRQIhAPHuWMYBr9ivWAjLLWxVrQynpxl3pdd7v/i/
Xfpvl5jOAiAePmQMgmaNRMZ81mttNm7L2nmuA8Gr7ep6SmwWLVnVkA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB4TCCAYagAwIBAgIRAMJgvq8Gq7LAzQlGieYpATUwCgYIKoZIzj0EAwIwOTEV
MBMGA1UEChMMRXhhbXBsZSBMYWJzMSAwHgYDVQQDExdFeGFtcGxlIExhYnMgUm9v
dCBDQSB2MjAeFw0yMjA5MjAxNDQ0NTRaFw0yNzA5MjAxNDU0NTRaMEIxFTATBgNV
BAoTDEV4YW1wbGUgTGFiczEpMCcGA1UEAxMgRXhhbXBsZSBMYWJzIEludGVybWVk
aWFlIENBIHYyLjEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASXaL7h9blgjN+z
k7DfMtrb0S/Z0sPcI/RlBreTNKsg/qtfpM98W/KYmqdWmpvuaGD3TbCsOi1vg1v5
u9UFAxSbo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd
BgNVHQ4EFgQU9UxHWadG5Zin9G3bVfZYXp0XZb8wHwYDVR0jBBgwFoAUUUnuryrN
a3zulgNg8gyXQ59isjowCgYIKoZIzj0EAwIDSQAwRgIhAKXM7K02bpu3dnUvaD3E
iANVTHJwiYgbgI7iTll0zMU4AiEAj6kfxDb7uyABOT1a4mW2TUtDvBiNDfklw13k
LYeLy4g=
-----END CERTIFICATE-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIBQk/EcAdTT/H3rOndgshCZ4kpd0H5SqPur56gnWbFIGoAoGCCqGSM49
AwEHoUQDQgAEYCpMUaAIX025yCm/8obgOCiibPSsh0jGhIr8kXG9jXpt3H0Di3x/
LCQ1MAC9ZpPkRa5G35w/mt8iCLCH4hmyjg==
-----END EC PRIVATE KEY-----
issuer=O = Example, CN = Example Labs Issuing CA v2.1.1
subject=O = Example, CN = test.example.com
notBefore=Sep 20 16:37:49 2022 GMT
notAfter=Sep 20 16:38:49 2022 GMT

As a result, the Root CA, the Intermediate CA and the Issuing CA have been rotated, and the automatic generation of leaf certificates is passed on seamlessly to the new issuer.

Conclusion

By introducing Multi-Issuer Feature on Vault 1.11.0, the certificates lifecycle is now easier than previous version where a PKI secret engine and a new role had to be created to manage the change of each CA which involved changing the consul-template configuration.

Thus, after rotating the Issuing, Intermediate and Root CA from a Vault PKI, the automatic generation of leaf certificates is passed on seamlessly: no more change is required on roles or on consul-template configuration.

This configuration can be codified using the Terraform Vault provider to do this, read the Codify Vault Internal PKI using Terraform article.

Next Steps

The next article (Part 4) presents a solution to manage your public certificates and securely store Public Certificates in Vault, generated by acme.sh.

References

--

--