Consul
Build your own certificate authority (CA)
Vault's PKI secrets engine can dynamically generate X.509 certificates on demand. Services can request certificates without going through a manual process of generating a private key and Certificate Signing Request (CSR), submitting to a Certificate Authority (CA), and then waiting for the verification and signing process to complete.
Personas
The steps described in this tutorial are typically performed by a security engineer.
Challenge
Organizations should protect their website, but the traditional PKI process workflow takes a long time, which motivates organizations to create certificates which do not expire for a year or more.
Solution
Use Vault to create X.509 certificates for usage in Mutual Transport Layer Security (MTLS) or other arbitrary PKI encryption. You can use this solution to create web server certificates, but if users do not import the CA chains, browsers do complain about the self-signed certificates.
Creating PKI certificates is generally a cumbersome process using traditional
tools like openssl
or even more advanced frameworks like Cloudflare's PKI and TLS toolkit
(CFSSL). These tools also require human effort to verify certificate distribution meets
organizational security policies.
Vault's PKI secrets engine makes this a lot simpler. The PKI secrets engine can be an intermediate-only certificate authority, which potentially allows for higher levels of security.
- Store CA outside of Vault (air-gapped).
- Create CSRs for the intermediate CA.
- Sign CSR outside Vault and import intermediate CA.
- Issue leaf certificates from the Intermediate CA.
Refer to Build Certificate Authority (CA) in Vault with an offline Root for an example of using a root CA external to Vault.
Prerequisites
To perform the tasks described in this tutorial, you need:
A Vault environment. Refer to the Getting Started tutorial to install Vault.
The API and CLI versions of the example scenario use the
jq
tool to parse JSON output. Installjq
in your Vault environment to follow the examples which use this tool.The web UI OpenSSL tool is used for some parts of the Web UI version of this tutorial.
Launch Terminal
This tutorial includes a free interactive command-line lab that lets you follow along on actual cloud infrastructure.
Policy requirements
Note
For the purposes of this tutorial, you can use a root
token to
work with Vault. However, it is recommended that root tokens are used just for initial setup or in emergencies. As a best practice, use tokens
with appropriate set of policies based on your role in the organization.
To perform all tasks demonstrated in this tutorial, your policy must include the following capabilities:
# Enable secrets engine
path "sys/mounts/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# List enabled secrets engine
path "sys/mounts" {
capabilities = [ "read", "list" ]
}
# Work with pki secrets engine
path "pki*" {
capabilities = [ "create", "read", "update", "delete", "list", "sudo", "patch" ]
}
If you are not familiar with policies, complete the policies tutorial.
Scenario introduction
In this tutorial, you are going to first generate a self-signed root certificate.
Then you are going to generate an intermediate certificate that is signed by
the root. You can then create a role and generate a certificate for the test.example.com
domain.
You can choose to complete this tutorial at this point or you can continue with the advanced section on multiple issuer functionality beginning with step 7.
There, you'll learn how enable a second root CA in the same secrets engine mount. You also learn how to rotate the older root CA, and begin issuing certificates from the existing role with the new root CA. Finally, you learn how to sunset the older CA.
In this tutorial, you perform the following operations:
- Generate Root CA
- Generate Intermediate CA
- Create a Role
- Request Certificates
- Revoke Certificates
- Remove Expired Certificates
- Enable new Root CA (optional)
- Create a Root Bridge CA (optional)
- Create a cross-signed intermediate (optional)
- Set default issuer and issue certificate (optional)
- Sunset older Root CA (optional)
Notice about multi-issuer functionality
Vault version 1.11.0 and greater allows a single PKI mount to have many Certificate Authority (CA) certificates ("issuers") in a single mount. All issuers within a single mount get treated as a single Authority, meaning that:
- Certificate Revocation List (CRL) configuration is common to all issuers/
- All authority access URLs are common to all issuers.
- Issued certificates' serial numbers are unique across all issuers.
However, since each issuer may have a distinct subject and keys, different issuers may have different CRLs.
It is strongly encouraged to limit the scope of CAs within a mount and not to mix different types of CAs (roots and intermediates).
Note
Some functionality does not work if a default issuer is not configured. Vault automatically selects the default issuer from the current issuing certificate on migration from an older Vault version (Vault < 1.11.0).
Lab setup
In another terminal, start a Vault dev server with
root
as the root token.$ vault server -dev -dev-root-token-id root
The Vault dev server defaults to running at
127.0.0.1:8200
. The server is also initialized and unsealed.Insecure operation
Do not run a Vault dev server in production. This approach is used here to simplify the unsealing process just for this demonstration.
Export an environment variable for the
vault
CLI to address the Vault server.$ export VAULT_ADDR=http://127.0.0.1:8200
Export an environment variable for the
vault
CLI to authenticate with the Vault server.$ export VAULT_TOKEN=root
The Vault server is ready.
Step 1: generate root CA
In this step, you are going to generate a self-signed root certificate using PKI secrets engine.
Enable the
pki
secrets engine at thepki
path.$ vault secrets enable pki
Example output:
Success! Enabled the pki secrets engine at: pki/
Tune the
pki
secrets engine to issue certificates with a maximum time-to-live (TTL) of 87600 hours.$ vault secrets tune -max-lease-ttl=87600h pki
Example output:
Success! Tuned the secrets engine at: pki/
Generate the example.com root CA, give it an issuer name, and save its certificate in the file
root_2023_ca.crt
.$ vault write -field=certificate pki/root/generate/internal \ common_name="example.com" \ issuer_name="root-2023" \ ttl=87600h > root_2023_ca.crt
This command is not expected to produce any output.
This generates a new self-signed CA certificate and private key. Vault automatically revokes the generated root at the end of its lease period (TTL). The CA certificate signs its own Certificate Revocation List (CRL).
List the issuer information for the root CA.
$ vault list pki/issuers/ Keys ---- 09c2c9a0-a874-36d2-de85-d79a7a51e373
Copy this key, you'll use this key in the next step.
You can read the issuer with its ID to get the certificates and other metadata about the issuer. Let's skip the certificate output, but list the issuer metadata and usage information.
$ vault read pki/issuer/$(vault list -format=json pki/issuers/ | jq -r '.[]') \ | tail -n 6
Example output:
leaf_not_after_behavior err manual_chain <nil> ocsp_servers [] revocation_signature_algorithm SHA256WithRSA revoked false usage crl-signing,issuing-certificates,ocsp-signing,read-only
Create a role for the root CA. Creating this role allows for specifying an issuer when necessary for the purposes of this scenario. This also provides a simple way to transition from one issuer to another by referring to it by name.
$ vault write pki/roles/2023-servers allow_any_name=true Success! Data written to: pki/roles/2023-servers
Example output:
Key Value --- ----- allow_any_name true allow_bare_domains false 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 true cn_validations [email hostname] code_signing_flag false country [] email_protection_flag false enforce_hostnames true ext_key_usage [] ext_key_usage_oids [] generate_lease false issuer_ref default key_bits 2048 key_type rsa key_usage [DigitalSignature KeyAgreement KeyEncipherment] locality [] max_ttl 0s no_store false not_after n/a not_before_duration 30s organization [] ou [] policy_identifiers [] postal_code [] province [] require_cn true server_flag true signature_bits 256 street_address [] ttl 0s use_csr_common_name true use_csr_sans true use_pss false
Note
This role is overly permissive in the names that it allows just for the purposes of simplification in this tutorial.
Configure the CA and CRL URLs.
$ vault write pki/config/urls \ issuing_certificates="$VAULT_ADDR/v1/pki/ca" \ crl_distribution_points="$VAULT_ADDR/v1/pki/crl"
Example output:
Key Value --- ----- crl_distribution_points [http://127.0.0.1:8200/v1/pki/crl] enable_templating false issuing_certificates [http://127.0.0.1:8200/v1/pki/ca] ocsp_servers []
Note
When using multiple issuers in the same mount, it is suggested to use the per-issuer AIA fields rather than the global (
/config/urls
) variant. This is for correctness: these fields are used for chain building and automatic CRL detection in certain applications. If they point to the wrong issuer's information, these applications may break.
Step 2: generate intermediate CA
Now, you are going to create an intermediate CA using the root CA you regenerated in the first step.
Tip
If you have Vault version 1.13.0 or later, you can use the new CLI helper pki issue
to generate your intermediate CA. Follow the steps in the pki issue command tab to use the helper instead of the standard CLI workflow.
First, enable the
pki
secrets engine at thepki_int
path.$ vault secrets enable -path=pki_int pki
Successful output example:
Success! Enabled the pki secrets engine at: pki_int/
Tune the
pki_int
secrets engine to issue certificates with a maximum time-to-live (TTL) of 43800 hours.$ vault secrets tune -max-lease-ttl=43800h pki_int
Successful output example:
Success! Tuned the secrets engine at: pki_int/
Execute the following command to generate an intermediate and save the CSR as
pki_intermediate.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
This command is expected to produce no output.
Sign the intermediate certificate with the root CA private key, and save the generated certificate as
intermediate.cert.pem
.$ 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
This command is expected to produce no output.
Once the CSR is signed and the root CA returns a certificate, it can be imported back into Vault.
$ vault write pki_int/intermediate/set-signed certificate=@intermediate.cert.pem
Successful output example:
Key Value --- ----- imported_issuers [ffefa5b2-ae7c-b765-1672-c275fec29dc7 276a666f-c8da-20c5-c5a4-e01dff8ff2ea] imported_keys <nil> mapping map[276a666f-c8da-20c5-c5a4-e01dff8ff2ea: ffefa5b2-ae7c-b765-1672-c275fec29dc7:0f021093-a446-5b8e-70e8-a6bbda6f1a99]
Step 3: create a role
A role is a logical name that maps to a policy used to generate those credentials. It allows configuration parameters to control certificate common names, alternate names, the key uses that they are valid for, and more.
Here are a few noteworthy parameters:
Param | Description |
---|---|
allowed_domains | Specifies the domains of the role (used with allow_bare_domains and allow-subdomains options) |
allow_bare_domains | Specifies if clients can request certificates matching the value of the actual domains themselves |
allow_subdomains | Specifies if clients can request certificates with CNs that are subdomains of the CNs allowed by the other role options (NOTE: This includes wildcard subdomains.) |
allow_glob_domains | Allows names specified in allowed_domains to contain glob patterns (e.g. ftp*.example.com) |
In this step, you are going to create a role named example-dot-com
.
Create a role named example-dot-com
which allows subdomains, and specify the default issuer ref ID as the value of issuer_ref
.
$ 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"
Example output:
Key Value
--- -----
allow_any_name false
allow_bare_domains false
allow_glob_domains false
allow_ip_sans true
allow_localhost true
allow_subdomains true
allow_token_displayname false
allow_wildcard_certificates true
allowed_domains [example.com]
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 true
cn_validations [email hostname]
code_signing_flag false
country []
email_protection_flag false
enforce_hostnames true
ext_key_usage []
ext_key_usage_oids []
generate_lease false
issuer_ref b96a564f-6031-83e2-4d43-fd2b4bede424
key_bits 2048
key_type rsa
key_usage [DigitalSignature KeyAgreement KeyEncipherment]
locality []
max_ttl 720h
no_store false
not_after n/a
not_before_duration 30s
organization []
ou []
policy_identifiers []
postal_code []
province []
require_cn true
server_flag true
signature_bits 256
street_address []
ttl 0s
use_csr_common_name true
use_csr_sans true
use_pss false
Step 4: request certificates
Keep certificate lifetimes short to align with Vault's philosophy of short-lived secrets.
Execute the following command to request a new certificate for the
test.example.com
domain based on the example-dot-com
role.
$ vault write pki_int/issue/example-dot-com common_name="test.example.com" ttl="24h"
Example output:
Key Value
--- -----
certificate -----BEGIN CERTIFICATE-----
MIIDwzCCAqugAwIBAgIUTQABMCAsXjG6ExFTX8201xKVH4IwDQYJKoZIhvcNAQEL
BQAwGjEYMBYGA1UEAxMPd3d3LmV4YW1wbGUuY29tMB4XDTE4MDcyNDIxMTMxOVoX
...
-----END CERTIFICATE-----
issuing_ca -----BEGIN CERTIFICATE-----
MIIDQTCCAimgAwIBAgIUbMYp39mdj7dKX033ZjK18rx05x8wDQYJKoZIhvcNAQEL
...
-----END CERTIFICATE-----
private_key -----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAte1fqy2Ekj+EFqKV6N5QJlBgMo/U4IIxwLZI6a87yAC/rDhm
W58liadXrwjzRgWeqVOoCRr/B5JnRLbyIKBVp6MMFwZVkynEPzDmy0ynuomSfJkM
...
-----END RSA PRIVATE KEY-----
private_key_type rsa
serial_number 4d:00:01:30:20:2c:5e:31:ba:13:11:53:5f:cd:b4:d7:12:95:1f:82
The response has the PEM-encoded private key, key type and certificate serial number.
Tip
A certificate can be renewed at any time by issuing a new certificate with the same CN. The prior certificate remains valid through its time-to-live value unless explicitly revoked.
Step 5: revoke certificates
If a certificate must be revoked, you can perform the revocation action that causes the CRL to be regenerated. When you regenerate the CRL, Vault removes any expired certificates from it.
Note
As of Vault version 1.12.0, the PKI Secret Engine's Bring-Your-Own-Cert (BYOC) capability allows revocation of certificates not stored before (e.g., issued via a role with no_store=true
). This means that setting no_store=true
is now safe to be used globally, regardless of importance of issued certificates, and their likelihood for revocation.
In certain circumstances, you may wish to revoke an issued certificate.
To revoke a certificate, execute the following command, replacing the <serial_number>
placeholder with the actual serial number of the certificate you want to revoke.
$ vault write pki_int/revoke serial_number=<serial_number>
Example:
$ vault write pki_int/revoke \
serial_number="3f:03:a9:10:e0:28:df:dc:d8:a8:f9:50:7b:cd:d4:8c:01:f5:47:5e"
Key Value
--- -----
revocation_time 1692733613
revocation_time_rfc3339 2023-08-22T19:46:53.117254Z
state revoked
Step 6: remove expired certificates
Keep the storage backend and CRL by periodically removing certificates that have expired and are past a certain buffer period beyond their expiration time.
To remove revoked certificate and clean the CRL.
$ vault write pki_int/tidy tidy_cert_store=true tidy_revoked_certs=true
WARNING! The following warnings were returned from Vault:
* Tidy operation successfully started. Any information from the operation
will be printed to Vault's server logs.
Note
You can expect the warning message on every invocation of the tidy command. It serves to alert the operator that they can observe progress from the tidy operation in the Vault operational log.
You are now finished with the steps in the main scenario, and can move to the Cleanup section from here.
The following steps 7-10 are optional and for learning about Root CA rotation. These steps also require that you are using Vault version 1.11.0 or greater.
Step 7: rotate root CA
Before version 1.11.0, you could not enable more than one root CA in the same PKI secrets engine mount. This makes rotating the root CA challenging when coordinating a number of PKI secrets engine mounts, and manually managing two root CAs while simultaneously deploying the new root CA to clients.
Vault version 1.11.0 introduces a set of new features in the PKI secrets engine, including multi-issuer capabilities, which include more than one root CA in the same secrets engine mount. This enables less burdensome root CA rotation. You can also use CA migration helpers to ease the operational burden of migrating a root CA controlled by Vault.
To begin learning about this capability, enable another root CA in the existing PKI secrets engine mount using the new rotate feature.
$ vault write pki/root/rotate/internal \ common_name="example.com" \ issuer_name="root-2024"
Key Value --- ----- certificate -----BEGIN CERTIFICATE----- MIIDpzCCAo+gAwIBAgIUT2afmPzCe/DQFO4c/Re0H7nC0jMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTQzMTA0WhcNMjIw NzIyMTQzMTM0WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd 9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/ nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280 FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL3 9WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB 8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAO BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7d oyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAUoWSv9g7doyvm9Xqspi9jH6kfhq8w OwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgy MDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgw JqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3 DQEBCwUAA4IBAQByO9DyRVJYjK9xrnfNnD1pbG0WXWRmsk7dxtXY336ollMl0eqO uEEHNGy0a4c1UKOjFg0LSg3c/DzUoPluUB4Kk9gs4ifn+1cm2k6G9gjT/6Wi0xIW 0t7+a7XX8ttPO7T4ZFDJT2KDINz42Oeht5u82TuKgBfdQsXm9XnJLqckQbaCZLPs uvyAT8MrgBABOvCVF1yurHNrmu+js6fZxu4wAO7ANMBDzNPYYx0IphYRGCnBte1N j4vSiTtlFOdf8+gdM8lSlv4XV56e10MepNSvvFDd1De6l+ErLciZJQydDklX2e3R 1GlQmm3d5Sxn5Wob3FA4nkyqLq21RlH2RRgo -----END CERTIFICATE----- expiration 1658500294 issuer_id f4baa074-10d7-7fc3-1623-f6f906ceed98 issuer_name root-2024 issuing_ca -----BEGIN CERTIFICATE----- MIIDpzCCAo+gAwIBAgIUT2afmPzCe/DQFO4c/Re0H7nC0jMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTQzMTA0WhcNMjIw NzIyMTQzMTM0WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd 9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/ nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280 FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL3 9WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB 8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAO BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7d oyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAUoWSv9g7doyvm9Xqspi9jH6kfhq8w OwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgy MDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgw JqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3 DQEBCwUAA4IBAQByO9DyRVJYjK9xrnfNnD1pbG0WXWRmsk7dxtXY336ollMl0eqO uEEHNGy0a4c1UKOjFg0LSg3c/DzUoPluUB4Kk9gs4ifn+1cm2k6G9gjT/6Wi0xIW 0t7+a7XX8ttPO7T4ZFDJT2KDINz42Oeht5u82TuKgBfdQsXm9XnJLqckQbaCZLPs uvyAT8MrgBABOvCVF1yurHNrmu+js6fZxu4wAO7ANMBDzNPYYx0IphYRGCnBte1N j4vSiTtlFOdf8+gdM8lSlv4XV56e10MepNSvvFDd1De6l+ErLciZJQydDklX2e3R 1GlQmm3d5Sxn5Wob3FA4nkyqLq21RlH2RRgo -----END CERTIFICATE----- key_id 775fb40a-4568-f613-2c6d-0f6802e859e1 key_name n/a serial_number 4f:66:9f:98:fc:c2:7b:f0:d0:14:ee:1c:fd:17:b4:1f:b9:c2:d2:33
Note that the certificate information has multi-issuer information, such as the
issuer_ref
andissuer_name
values.You can also list the issuers to confirm the addition of the new Root CA.
$ vault list pki/issuers Keys ---- 09c2c9a0-a874-36d2-de85-d79a7a51e373 f4baa074-10d7-7fc3-1623-f6f906ceed98
Both root CA issuers are now enabled in the same PKI secrets engine mount. While the new root CA is enabled, it's not yet actively used, and all later issuance from the mount uses the original root CA issuer,
root-2023
.Tip
At this point, the new root CA certificate can be deployed to all devices which require it as part of rotating out the old root CA.
Create a role for the new example.com root CA; creating this role allows for specifying an issuer when necessary. This also provides a simple way to transition from one issuer to another by referring to it by name.
$ vault write pki/roles/2024-servers allow_any_name=true Success! Data written to: pki/roles/2024-servers
Key Value --- ----- allow_any_name true allow_bare_domains false 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 true cn_validations [email hostname] code_signing_flag false country [] email_protection_flag false enforce_hostnames true ext_key_usage [] ext_key_usage_oids [] generate_lease false issuer_ref default key_bits 2048 key_type rsa key_usage [DigitalSignature KeyAgreement KeyEncipherment] locality [] max_ttl 0s no_store false not_after n/a not_before_duration 30s organization [] ou [] policy_identifiers [] postal_code [] province [] require_cn true server_flag true signature_bits 256 street_address [] ttl 0s use_csr_common_name true use_csr_sans true use_pss false
Note
This role is overly permissive in the names that it allows just for the purposes of simplification in this tutorial.
Step 8: create a root bridge CA
A significant step in rotating an older root CA involves handling devices which might be offline for long periods of time, but which need to eventually come online and fetch the new root certificate.
If you want to effectively handle this situation, you can do so with the use of a root bridge CA between the older root to the new root. This helps clients of the older root trust certificates which the new root signs, and provides a predictable way to rotate the root with a clear time-frame (the pki/intermediate TTL).
The new cross-sign command provides this capability to the Vault operator in a familiar way, resembling the command syntax for creating a new intermediate CA with an existing key.
Two approaches to root CA rotation
You should choose to either create a root bridge CA as described in this section or create a cross-signed intermediate as described in the following section for your migration strategy, but do not perform the tasks for both steps.
Create the cross-signed Intermediate CSR.
$ vault write -format=json pki/intermediate/cross-sign \ common_name="example.com" \ key_ref="$(vault read pki/issuer/root-2024 \ | grep -i key_id | awk '{print $2}')" \ | jq -r '.data.csr' \ | tee cross-signed-intermediate.csr
Example output:
-----BEGIN CERTIFICATE REQUEST----- MIIChDCCAWwCAQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQDAE9mbxAD9IcyZZFWO2TWNrG4hqaK/QgMy9lGq nfT7Zi++tV826EBxc4sA5331nVCrbWeRnXOiixUjxvAaZedD4CscLFKq/9rJC5tT v51T1ZaHa9wFJG0GeEHOvxbP5YRmz4JRRTF5ezVXZHjp8hVGbaLly6tdQN/K3Otv NBc8TMNehRJsLC1P7VjsIAGne0P16fZeR65Sjf//i1J2g3BZmF5jSCtglU5aFDqi 9/VjzEfgnl6hkdUZMU7idKMtBnS6NiTIfZ3c+yUJDHFPFYoCe6Kob4cXM6DPy8dI QfGPsFDMp5/1b21DtLgURNUaTqZOWX8W2/E4mMrDfT6c4VWDAgMBAAGgKTAnBgkq hkiG9w0BCQ4xGjAYMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMA0GCSqGSIb3DQEB CwUAA4IBAQAeUqJ4t+IXNgGCMl2xCZ0a9Fypj873Ork+OgVz2zoASH14zia2MY3g GQe7NR9MFgebZMNG2hR3hcU22bmoUrsB+RITsgiQa1hYqZk5/MB059QvEUBYrBsn dSN6bFkembWYBLqae7I8JDW4UY+06LSI4eGeV2n5VyMJ1WwxerbYOCvFpRK+7qYf O4r6roMAuM5uTpKJMMqMipwG0dLJEXC/9E/j3V0qiN9yIy74PdNWJahg6X5biytL WGNfsVafnjH5zkJfb0iEDECJz8tuayEW98JLzEGfeH6dz0S1hAMhoWiqiL1ZQeOe 7zSKnUooThRs1904nojr6If74Pj058p4 -----END CERTIFICATE REQUEST-----
Sign the resulting CSR with the older root CA.
$ vault write -format=json pki/issuer/root-2023/sign-intermediate \ common_name="example.com" \ csr=@cross-signed-intermediate.csr \ | jq -r '.data.certificate' | tee cross-signed-intermediate.crt
Example output:
-----BEGIN CERTIFICATE----- MIIDpzCCAo+gAwIBAgIUOjMm1b+ICXC682TSMH7wsFRdYMkwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTUwODA3WhcNMjIw NzIyMTUwODM3WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd 9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/ nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280 FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL3 9WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB 8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAO BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7d oyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAU+RF2dgdU6BZrOKHck1QpEmqPemUw OwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgy MDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgw JqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3 DQEBCwUAA4IBAQARw49qG9j/N46En+ME8u3uK0DmVxo/Fuj/RCNOBQ3EnIJ8zU+V hujyckHcQNQ0f8nfrdE1JHnn+bnhOIzO1qaaooSlmhWg1HuEolOn/g1Aq1xJvmOd nWKr4G1iwo3xmID6AYAI80LaVAeRcrk+S6dmhDuo1KT4CZmGNo+sz0rguute7aTh N568OGJF7qHoLFSn3/pe9zvpjuBiH9jiB1HmWbL/JqntTherr5JWK6W7EukGFNOd HEn/n/QfBuKX32QU8SjVb0ZRWd7CbJwL7nsNY6jnqlwLnCOyncL8hhnW6U8QbHqd dm1l9PpE7BssfVTk/exS/Icemf6XFzDeIrqT -----END CERTIFICATE-----
The result is a cross-signed certificate, but no issuer gets created yet. Import the signed certificate to create the new issuer.
Import the cross-signed certificate.
$ vault write pki/intermediate/set-signed \ certificate=@cross-signed-intermediate.crt
Example output:
Key Value --- ----- imported_issuers [3f5a71f1-6558-0c82-2f8c-c3feb27eee8a] imported_keys <nil> mapping map[3f5a71f1-6558-0c82-2f8c-c3feb27eee8a:775fb40a-4568-f613-2c6d-0f6802e859e1]
You now have 2 root CAs with a cross-signed intermediate CA providing a trust chain between them. You are ready to handle migration of devices which were not initially possible to migrate to the new root CA.
Read the issuer for the new root CA. You'll notice that there are now more certificates in the
ca_chain
field.$ vault read pki/issuer/root-2024
Key Value --- ----- ca_chain [-----BEGIN CERTIFICATE----- MIIDpzCCAo+gAwIBAgIUT2afmPzCe/DQFO4c/Re0H7nC0jMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTQzMTA0WhcNMjIw NzIyMTQzMTM0WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd 9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/ nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280 FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL3 9WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB 8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAO BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7d oyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAUoWSv9g7doyvm9Xqspi9jH6kfhq8w OwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgy MDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgw JqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3 DQEBCwUAA4IBAQByO9DyRVJYjK9xrnfNnD1pbG0WXWRmsk7dxtXY336ollMl0eqO uEEHNGy0a4c1UKOjFg0LSg3c/DzUoPluUB4Kk9gs4ifn+1cm2k6G9gjT/6Wi0xIW 0t7+a7XX8ttPO7T4ZFDJT2KDINz42Oeht5u82TuKgBfdQsXm9XnJLqckQbaCZLPs uvyAT8MrgBABOvCVF1yurHNrmu+js6fZxu4wAO7ANMBDzNPYYx0IphYRGCnBte1N j4vSiTtlFOdf8+gdM8lSlv4XV56e10MepNSvvFDd1De6l+ErLciZJQydDklX2e3R 1GlQmm3d5Sxn5Wob3FA4nkyqLq21RlH2RRgo -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDpzCCAo+gAwIBAgIUOjMm1b+ICXC682TSMH7wsFRdYMkwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTUwODA3WhcNMjIw NzIyMTUwODM3WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd 9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/ nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280 FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL3 9WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB 8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAO BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7d oyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAU+RF2dgdU6BZrOKHck1QpEmqPemUw OwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgy MDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgw JqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3 DQEBCwUAA4IBAQARw49qG9j/N46En+ME8u3uK0DmVxo/Fuj/RCNOBQ3EnIJ8zU+V hujyckHcQNQ0f8nfrdE1JHnn+bnhOIzO1qaaooSlmhWg1HuEolOn/g1Aq1xJvmOd nWKr4G1iwo3xmID6AYAI80LaVAeRcrk+S6dmhDuo1KT4CZmGNo+sz0rguute7aTh N568OGJF7qHoLFSn3/pe9zvpjuBiH9jiB1HmWbL/JqntTherr5JWK6W7EukGFNOd HEn/n/QfBuKX32QU8SjVb0ZRWd7CbJwL7nsNY6jnqlwLnCOyncL8hhnW6U8QbHqd dm1l9PpE7BssfVTk/exS/Icemf6XFzDeIrqT -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDNTCCAh2gAwIBAgIUfDvqkDZG/fr7np0RZ50wHl2VO+QwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTQyMjU1WhcNMzIw NjE3MTQyMzI1WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAJkM2EYB3+5S70a+aZpJeyvN8wY1wNnRIStPnJCq uIlgMGu3u+c/fVUwpsxh+KSGMfLnA8vdVmZhkjd+Si97RlqV4yxA6OfJYlSyrOBH ODA3E+J302gekWPGd851EpbAx+1MDekWoGprCEaiJCVIulNAgDWSHQHqfHNKJMox GMxvCKhse+NcVMZoRUxBPG9pgKeb7gXIXlnPVOKeZAZYzzUCrU0x/OHCD6xKOVNN t8mmncKmUlQach8D1r0LA1IvNCYjhNF4+RGIYBAuuym2nKXI4aj3mtYrlDSnnBwZ T3/8CdMwf0qy10KCExDHc+Yyge6EcbJBLnfYkIjOj/PzT8UCAwEAAaN7MHkwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPkRdnYHVOgW azih3JNUKRJqj3plMB8GA1UdIwQYMBaAFPkRdnYHVOgWazih3JNUKRJqj3plMBYG A1UdEQQPMA2CC2V4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQA+fKtmp+8j J6KcS9aeiNgyVc2RuZQBVMkn0l9z6c6+zZwn7LbQ9LmoTfcbE8aXj3gKJlYGD+p6 6fCClmQjq8epWdT/HuO/5efFiiRsCan1eaKoK7dah9z39kfYxaXrOmG6nXjFDn0m u+ZxBtuW3kkib0MYnVvJDe/xJ8pg2J8Mt1tAqcbDbJZWW+yEH4XFJdjDt9LxeNm7 0y2BzDfr1Ckzh/rHowHEBDX/1a2rGgdU7n5j5mgMYKCcP5G+dlWhm3kztFo2aRni RE939WmlzLob9vgKBEkO7hfcs4kMO6TwDJx0/BZ3OpM54mgHf/DXkiY/AIsRYBp9 8iJESkjzeDAA -----END CERTIFICATE----- ] certificate -----BEGIN CERTIFICATE----- MIIDpzCCAo+gAwIBAgIUT2afmPzCe/DQFO4c/Re0H7nC0jMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTQzMTA0WhcNMjIw NzIyMTQzMTM0WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd 9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/ nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280 FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL3 9WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB 8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAO BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7d oyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAUoWSv9g7doyvm9Xqspi9jH6kfhq8w OwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgy MDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgw JqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3 DQEBCwUAA4IBAQByO9DyRVJYjK9xrnfNnD1pbG0WXWRmsk7dxtXY336ollMl0eqO uEEHNGy0a4c1UKOjFg0LSg3c/DzUoPluUB4Kk9gs4ifn+1cm2k6G9gjT/6Wi0xIW 0t7+a7XX8ttPO7T4ZFDJT2KDINz42Oeht5u82TuKgBfdQsXm9XnJLqckQbaCZLPs uvyAT8MrgBABOvCVF1yurHNrmu+js6fZxu4wAO7ANMBDzNPYYx0IphYRGCnBte1N j4vSiTtlFOdf8+gdM8lSlv4XV56e10MepNSvvFDd1De6l+ErLciZJQydDklX2e3R 1GlQmm3d5Sxn5Wob3FA4nkyqLq21RlH2RRgo -----END CERTIFICATE----- issuer_id f4baa074-10d7-7fc3-1623-f6f906ceed98 issuer_name root-2024 key_id 775fb40a-4568-f613-2c6d-0f6802e859e1 leaf_not_after_behavior err manual_chain <nil> usage read-only,issuing-certificates,crl-signing
Specifically, you'll notice 3 certificates in ca_chain
, as follows:
The new root CA certificate (root-2024).
The new cross-signed intermediate CA certificate.
The older root CA certificate (root-2023).
If you do not want the chain composed in this way, you can specify a custom chain with the manual_chain
parameter when creating the intermediate CA. More information is available in the
API documentation.
Step 9: create a cross-signed intermediate
The previous section describes creating a root bridge certificate that is useful for bridging between two separate roots of trust. In other words, if you have devices with root-2023 hard-coded and not replaceable, the root bridge CA allows you to validate against it.
You can also create a cross-signed intermediate CA to achieve this in an alternative way.
Two approaches to root CA rotation
You should choose to either create a cross-signed intermediate as described in this section, or create a root bridge CA as described in the previous section for your migration strategy, but do not perform the tasks for both steps.
Follow these steps to create the cross-signed intermediate CA.
Get a CSR to cross-sign the intermediate.
$ vault write -format=json pki_int/intermediate/cross-sign \ common_name="example.com Intermediate Authority" \ key_ref="$(vault read pki_int/issuer/$(vault read -field=default pki_int/config/issuers) \ | grep -i key_id | awk '{print $2}')" \ | jq -r '.data.csr' \ | tee cross-signed-intermediate.csr
Example output:
-----BEGIN CERTIFICATE REQUEST----- MIICcjCCAVoCAQAwLTErMCkGA1UEAxMiZXhhbXBsZS5jb20gSW50ZXJtZWRpYXRl IEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALRWH4ag H8Lh4eRTS9qVN4zsuovY+aHxmAf5Yt9Atwbd7obx/OdpiAmeHjH03hZlo0/GV6UZ 43QuR/WqYZgIHvcDMNZaqYMy4Bp6PYDDDHTEm43oOkDvA/ZslWI/nt/f1o6D/O4R 6JvQaE5GrzANyUhmq3BrvYpof8abvZpchCeCtAKyD7vmLrtsVAH2fGpYboTV02zL 5+HZY3CKxoELhrVab7hArnq6VLQvHY6nvC5y7XV6D/ze+BuVNfKRDhapZzDPr2CQ Y0RWlOGGopJ1QBUp2AMlY/0PwJhO7WKpPudZw9YZd7sncLuJiX5sVOUzBafEww9B kz/1pDsAesr89GkCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQA17CFuLX3MDfkb e4E+O1saZHnYgJ4lRurwg+E/CMPNHve8wkrtk/zv5cPJ6GSNusuEW/QPtSSpRsjn Qj32qtEYqzNQhGpMGHh0VEEgjXYNtHp1dnlUodZQe2+1+u/aPeniblpEM4e/joER 5AlxqlOZXUEz6rM8ExdMkPhN4pN3kNU/aaBVhEC8pxTig2kWR3uVMmF3DWSgkVNP SjJjbPFSEnKuIIHMfkwjv4QFnWhkgiNzwlKjmjK9WQD7JDkX9davkcr4AUAi23Js NxfOqlTNDke66lP1+GlUnStNy7XlcaMFuOSBQr30vtyn9G190XhA1m3dHtBqwehP zaC6UpJT -----END CERTIFICATE REQUEST-----
Sign the CSR under the new root.
$ vault write -format=json pki/issuer/root-2024/sign-intermediate \ common_name="example.com Intermediate Authority" \ csr=@cross-signed-intermediate.csr \ | jq -r '.data.certificate' | tee cross-signed-intermediate.crt
Example output:
-----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUV4yUTVdgE/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMw OTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkl y61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq 0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJ il952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmc dxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV +bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E= -----END CERTIFICATE-----
Import the cross-signed certificate into the new mount.
$ vault write pki_int/intermediate/set-signed \ certificate=@cross-signed-intermediate.crt
Example abbreviated output:
...snip... Key Value --- ----- existing_issuers <nil> existing_keys <nil> imported_issuers [58dabd1a-73ee-c483-5371-add26cb1c48b] imported_keys <nil> mapping map[58dabd1a-73ee-c483-5371-add26cb1c48b:80375808-3015-91fc-ab36-b88e5b91d645] ...snip...
Set the issuer name.
$ vault write pki_int/issuer/58dabd1a-73ee-c483-5371-add26cb1c48b \ issuer_name=xc-example-dot-com-intermediate
Be sure to use the correct
imported_issuers
UUID for the value of issuer instead of the example value.Key Value --- ----- ca_chain [-----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUV4yUTVdgE/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMw OTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkl y61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq 0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJ il952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmc dxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV +bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E= -----END CERTIFICATE----- ] certificate -----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUV4yUTVdgE/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMw OTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkl y61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq 0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJ il952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmc dxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV +bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E= -----END CERTIFICATE----- crl_distribution_points [] issuer_id 58dabd1a-73ee-c483-5371-add26cb1c48b issuer_name xc-example-dot-com-intermediate issuing_certificates [] key_id 80375808-3015-91fc-ab36-b88e5b91d645 leaf_not_after_behavior err manual_chain <nil> ocsp_servers [] revocation_signature_algorithm n/a revoked false usage crl-signing,issuing-certificates,ocsp-signing,read-only
When reading issuers, the CA chain does not change. Try reading the intermediate CA:
$ vault read -field=ca_chain pki_int/issuer/"$(vault read -field=default pki_int/config/issuers)"
Example output:
[-----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUP/K4tDfqvxdDokLmfVQ0SCcjBS8wDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk0MzQzWhcNMjgw ODIwMTk0NDEzWjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBTS5JNOBLW/rwXBFO2Ol5zpfO9wnzA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAGQUfS3m41bC0lpEq7/KpVxGeIFutct21jWQX1AmORXFiu1yK+cA JJnDd1bRUE8MhhGH1lmFPZ8dpVvC/wm4Q1TvQGo1K82z4sUh1IDFqTMJOhwYYsQk rKqLCPcdcWxtgRnYldUp1AHnObFvQvJlJndZVpMfxRamTaLQjDEon7ItldOR4ZLo SCg18ZvUlqQk/bzosPq7pvmmShGpnX5ln02J1+6BYMZTbxn/FBjWIb466Bquc1+l CWHuOkHvnzAQ00oFKWTvEXr0EobWWANLuFnWiite8ZTwZjpkYPoXpOnK9dmk61rV +AlTy7qovM4Y5Yjg2uOA6FZbg3SW11RLEUA= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDNTCCAh2gAwIBAgIUezeBwAzYGi0DTibs/fKPq0zpBS8wDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk0MjU3WhcNMzMw ODE5MTk0MzI3WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAL9LxaXPq/iBmifhy9GEQaHpdmPrvGvH2oCS3Ejd eE5Zjb2Fm8R1HTYcWQ4HtLygG4rKdzKv8cXaMSOAXCcyyIgMsQxIkYsXbq+agJhB /AiGiH0lhx1vy6YmHUGqo8oGmWLMp4pGaFruz/Ij2V3K1a4WMAXW3+/NjQu871bI HVe+RfoIK3ZxM8vNGSq8SJ/7gh3XxZ4Cq+x3uMlKknSNpZc/AWQIEuzp78gYGKtt Tm4XAlY63Vb972d4m2KMY3Ux2NJDP9otSKwDRRFBAyY0ktTJkrEFgioA6F5qo3wz NwW55x8iTI12m2OSdUGg7PoMZBuOWm9KF/NTgdpHlkL9pRUCAwEAAaN7MHkwDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNLkk04Etb+v BcEU7Y6XnOl873CfMB8GA1UdIwQYMBaAFNLkk04Etb+vBcEU7Y6XnOl873CfMBYG A1UdEQQPMA2CC2V4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAVy+u6KEO1 6pEetpLFDrZPVQi2+DC76lkcHf3KnevUzKtbzRW4VipiI88Uj/9B7YXQFQXmHs3Q HibrTNUZbhqF3S25PnVGaJutlqC4qWmxwAWthOEFhrZRyRuIiEQrjriSNj4liCnt TmAT+GCEdqdKoQ/MclSEfThLPpk9Gm4REv2EX1savDLOxt3AkQTpLkwqK79+H1Jj rcyR9Dsq5db7oxZdMCk47wxcwJvwv5TLub+/MVfiFFLEkpucTf0A/i0bY30IXUAI IUoULskw4l2rAWC88sxA/ve3bXsESTXKbafLWKfp7WmnW3kBiRlCBLSt4JnRb3u+ ZeJPV8vHwlyi -----END CERTIFICATE----- ]
Read the cross-signed intermediate CA.
$ vault read -field=ca_chain pki_int/issuer/xc-example-dot-com-intermediate
Example output:
[-----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUV4yUTVdgE/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMw OTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkl y61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq 0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJ il952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmc dxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV +bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E= -----END CERTIFICATE----- ]
(optional) If you prefer to update them to refer to each other on sign requests, you can use
manual_chain
since they are sibling CAs, not in a hierarchy, and automated chain building does not detect them.Set a
manual_chain
value on the intermediate CA.$ vault patch pki_int/issuer/"$(vault read -field=default pki_int/config/issuers)" \ manual_chain=self,xc-example-dot-com-intermediate
Key Value --- ----- ca_chain [-----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUP/K4tDfqvxdDokLmfVQ0SCcjBS8wDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk0MzQzWhcNMjgw ODIwMTk0NDEzWjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBTS5JNOBLW/rwXBFO2Ol5zpfO9wnzA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAGQUfS3m41bC0lpEq7/KpVxGeIFutct21jWQX1AmORXFiu1yK+cA JJnDd1bRUE8MhhGH1lmFPZ8dpVvC/wm4Q1TvQGo1K82z4sUh1IDFqTMJOhwYYsQk rKqLCPcdcWxtgRnYldUp1AHnObFvQvJlJndZVpMfxRamTaLQjDEon7ItldOR4ZLo SCg18ZvUlqQk/bzosPq7pvmmShGpnX5ln02J1+6BYMZTbxn/FBjWIb466Bquc1+l CWHuOkHvnzAQ00oFKWTvEXr0EobWWANLuFnWiite8ZTwZjpkYPoXpOnK9dmk61rV +AlTy7qovM4Y5Yjg2uOA6FZbg3SW11RLEUA= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUV4yUTVdgE/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMw OTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkl y61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq 0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJ il952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmc dxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV +bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E= -----END CERTIFICATE----- ] certificate -----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUP/K4tDfqvxdDokLmfVQ0SCcjBS8wDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk0MzQzWhcNMjgw ODIwMTk0NDEzWjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBTS5JNOBLW/rwXBFO2Ol5zpfO9wnzA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAGQUfS3m41bC0lpEq7/KpVxGeIFutct21jWQX1AmORXFiu1yK+cA JJnDd1bRUE8MhhGH1lmFPZ8dpVvC/wm4Q1TvQGo1K82z4sUh1IDFqTMJOhwYYsQk rKqLCPcdcWxtgRnYldUp1AHnObFvQvJlJndZVpMfxRamTaLQjDEon7ItldOR4ZLo SCg18ZvUlqQk/bzosPq7pvmmShGpnX5ln02J1+6BYMZTbxn/FBjWIb466Bquc1+l CWHuOkHvnzAQ00oFKWTvEXr0EobWWANLuFnWiite8ZTwZjpkYPoXpOnK9dmk61rV +AlTy7qovM4Y5Yjg2uOA6FZbg3SW11RLEUA= -----END CERTIFICATE----- crl_distribution_points [] issuer_id 4e2e04ff-de9b-10ff-59e1-ccaa8247e1ae issuer_name n/a issuing_certificates [] key_id 80375808-3015-91fc-ab36-b88e5b91d645 leaf_not_after_behavior err manual_chain [4e2e04ff-de9b-10ff-59e1-ccaa8247e1ae 58dabd1a-73ee-c483-5371-add26cb1c48b] ocsp_servers [] revocation_signature_algorithm n/a revoked false usage crl-signing,issuing-certificates,ocsp-signing,read-only
Set a
manual_chain
value on the cross-signed intermediate CA.$ vault patch pki_int/issuer/xc-example-dot-com-intermediate \ manual_chain=self,"$(vault read -field=default pki_int/config/issuers)"
--- ----- ca_chain [-----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUV4yUTVdgE/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMw OTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkl y61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq 0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJ il952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmc dxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV +bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUP/K4tDfqvxdDokLmfVQ0SCcjBS8wDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk0MzQzWhcNMjgw ODIwMTk0NDEzWjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBTS5JNOBLW/rwXBFO2Ol5zpfO9wnzA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAGQUfS3m41bC0lpEq7/KpVxGeIFutct21jWQX1AmORXFiu1yK+cA JJnDd1bRUE8MhhGH1lmFPZ8dpVvC/wm4Q1TvQGo1K82z4sUh1IDFqTMJOhwYYsQk rKqLCPcdcWxtgRnYldUp1AHnObFvQvJlJndZVpMfxRamTaLQjDEon7ItldOR4ZLo SCg18ZvUlqQk/bzosPq7pvmmShGpnX5ln02J1+6BYMZTbxn/FBjWIb466Bquc1+l CWHuOkHvnzAQ00oFKWTvEXr0EobWWANLuFnWiite8ZTwZjpkYPoXpOnK9dmk61rV +AlTy7qovM4Y5Yjg2uOA6FZbg3SW11RLEUA= -----END CERTIFICATE----- ] certificate -----BEGIN CERTIFICATE----- MIIDpjCCAo6gAwIBAgIUV4yUTVdgE/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMw OTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAf wuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnj dC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHo m9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn 4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBj RFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GT P/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAW gBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH MAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAm oCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcN AQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkl y61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq 0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJ il952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmc dxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV +bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E= -----END CERTIFICATE----- crl_distribution_points [] issuer_id 58dabd1a-73ee-c483-5371-add26cb1c48b issuer_name xc-example-dot-com-intermediate issuing_certificates [] key_id 80375808-3015-91fc-ab36-b88e5b91d645 leaf_not_after_behavior err manual_chain [58dabd1a-73ee-c483-5371-add26cb1c48b 4e2e04ff-de9b-10ff-59e1-ccaa8247e1ae] ocsp_servers [] revocation_signature_algorithm n/a revoked false usage crl-signing,issuing-certificates,ocsp-signing,read-only
Step 10: set default issuer
After your defined cutoff point for the older root CA, and after you have distributed the new root CA to all devices, you can switch the default issuer to the new root CA.
Use the root replace command to do this, and specify the issuer name of the new root CA as the value to the default
parameter.
$ vault write pki/root/replace default=root-2024
Key Value
--- -----
default f4baa074-10d7-7fc3-1623-f6f906ceed98
From this point forward, Vault issues new certificates based on the new root CA (root-2024).
Step 11: sunset defunct root CA
The last step is to sunset the older root CA.
You can effectively sunset the older root CA by removing its ability to issue certificates, while preserving the ability to sign CRLs and revoke certificates.
Remove issuing-certificates
from the Root CA capabilities.
$ vault write pki/issuer/root-2023 \
issuer_name="root-2023" \
usage=read-only,crl-signing | tail -n 5
Example output:
issuer_name root-2023
key_id b785654a-6ab6-0904-be34-3f5b1c1e8d53
leaf_not_after_behavior err
manual_chain <nil>
usage crl-signing,read-only
You'll notice "issuing-certificates" removed from usage
, and now just "crl-signing", and "read-only" are available on the older root CA. This means it can't issue any further certificates going forward.
You can confirm this by attempting to issue a certificate directly from the older root CA.
$ vault write pki/issuer/root-2023/issue/2023-servers \
common_name="super.secret.internal.dev" \
ttl=10m
The request fails.
Error writing data to pki/issuer/root-2023/issue/2023-servers: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/pki/issuer/root-2023/issue/2023-servers
Code: 500. Errors:
* 1 error occurred:
* error fetching CA certificate: error while attempting to use issuer 09c2c9a0-a874-36d2-de85-d79a7a51e373: requested usage issuing-certificates for issuer [id:09c2c9a0-a874-36d2-de85-d79a7a51e373 / name:root-2023] but only had usage read-only,crl-signing
CRLs and OCSP
Both Certificate revocation lists (CRL) and online certificate status protocol (OCSP) allow interrogating revocation status of certificates.
These methods include internal security and authenticity (both CRLs and OCSP responses get signed by the issuing CA within Vault). This means both are fine to distribute over non-secure and non-authenticated channels, such as HTTP.
Vault version 1.12.0 and greater supports automated CRL rebuilding (including optional Delta CRLs which it can rebuild more often than complete CRLs) via the /config/crl API endpoint.
You can also configure automatic tidying of revoked and expired certificates with the /config/auto-tidy endpoint.
Tip
It is suggested that these features be enabled when possible to ensure compatibility with the wider PKIX ecosystem, and to enhance performance of the cluster.
Cleanup
You can unset the two environment variables, VAULT_ADDR
and VAULT_TOKEN
, that you set in the beginning of this tutorial and remove the files you created to clean up.
Unset the environment variables.
$ unset VAULT_ADDR VAULT_TOKEN
Remove the files.
$ rm -f \
root_2023_ca.crt \
intermediate.cert.pem \
pki_intermediate.csr \
payload.json \
payload-url.json \
payload-int.json \
payload-int-cert.json \
payload-signed.json \
payload-role.json
If you also followed the advanced steps, you'll need to remove some additional files.
$ rm -f \
root_2023_ca.crt \
cross-signed-intermediate.csr \
cross-signed-intermediate.crt
If you were doing the terraform version of this tutorial, go back to where the learn-vault-pki-engine
repository was cloned.
$ cd ../..
Delete the learn-vault-pki-engine
directory.
$ rm -rf learn-vault-pki-engine
Stop the Vault server process.
$ pgrep -f vault | xargs kill
Next steps
Check out the Streamline Certificate Management with HashiCorp Vault webinar recording.
Also, refer to the Vault PKI Secrets Engine Integration tutorial for an example of Nomad using the PKI secrets engine to generate and renew the X.509 certificates it uses. To automate the process, this tutorial leverages the Consul Template tool.