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 Vault install guide 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 enginepath "sys/mounts/*" { capabilities = [ "create", "read", "update", "delete", "list" ]} # List enabled secrets enginepath "sys/mounts" { capabilities = [ "read", "list" ]} # Work with pki secrets enginepath "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 errmanual_chain <nil>ocsp_servers []revocation_signature_algorithm SHA256WithRSArevoked falseusage 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=trueSuccess! Data written to: pki/roles/2023-servers
Example output:
Key Value--- -----allow_any_name trueallow_bare_domains falseallow_glob_domains falseallow_ip_sans trueallow_localhost trueallow_subdomains falseallow_token_displayname falseallow_wildcard_certificates trueallowed_domains []allowed_domains_template falseallowed_other_sans []allowed_serial_numbers []allowed_uri_sans []allowed_uri_sans_template falseallowed_user_ids []basic_constraints_valid_for_non_ca falseclient_flag truecn_validations [email hostname]code_signing_flag falsecountry []email_protection_flag falseenforce_hostnames trueext_key_usage []ext_key_usage_oids []generate_lease falseissuer_ref defaultkey_bits 2048key_type rsakey_usage [DigitalSignature KeyAgreement KeyEncipherment]locality []max_ttl 0sno_store falsenot_after n/anot_before_duration 30sorganization []ou []policy_identifiers []postal_code []province []require_cn trueserver_flag truesignature_bits 256street_address []ttl 0suse_csr_common_name trueuse_csr_sans trueuse_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 falseissuing_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 falseallow_bare_domains falseallow_glob_domains falseallow_ip_sans trueallow_localhost trueallow_subdomains trueallow_token_displayname falseallow_wildcard_certificates trueallowed_domains [example.com]allowed_domains_template falseallowed_other_sans []allowed_serial_numbers []allowed_uri_sans []allowed_uri_sans_template falseallowed_user_ids []basic_constraints_valid_for_non_ca falseclient_flag truecn_validations [email hostname]code_signing_flag falsecountry []email_protection_flag falseenforce_hostnames trueext_key_usage []ext_key_usage_oids []generate_lease falseissuer_ref b96a564f-6031-83e2-4d43-fd2b4bede424key_bits 2048key_type rsakey_usage [DigitalSignature KeyAgreement KeyEncipherment]locality []max_ttl 720hno_store falsenot_after n/anot_before_duration 30sorganization []ou []policy_identifiers []postal_code []province []require_cn trueserver_flag truesignature_bits 256street_address []ttl 0suse_csr_common_name trueuse_csr_sans trueuse_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-----MIIDwzCCAqugAwIBAgIUTQABMCAsXjG6ExFTX8201xKVH4IwDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UEAxMPd3d3LmV4YW1wbGUuY29tMB4XDTE4MDcyNDIxMTMxOVoX ...-----END CERTIFICATE-----issuing_ca -----BEGIN CERTIFICATE-----MIIDQTCCAimgAwIBAgIUbMYp39mdj7dKX033ZjK18rx05x8wDQYJKoZIhvcNAQEL ...-----END CERTIFICATE-----private_key -----BEGIN RSA PRIVATE KEY-----MIIEowIBAAKCAQEAte1fqy2Ekj+EFqKV6N5QJlBgMo/U4IIxwLZI6a87yAC/rDhmW58liadXrwjzRgWeqVOoCRr/B5JnRLbyIKBVp6MMFwZVkynEPzDmy0ynuomSfJkM ...-----END RSA PRIVATE KEY-----private_key_type rsaserial_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 1692733613revocation_time_rfc3339 2023-08-22T19:46:53.117254Zstate 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=trueWARNING! 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/Re0H7nC0jMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTQzMTA0WhcNMjIwNzIyMTQzMTM0WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL39WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7doyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAUoWSv9g7doyvm9Xqspi9jH6kfhq8wOwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQByO9DyRVJYjK9xrnfNnD1pbG0WXWRmsk7dxtXY336ollMl0eqOuEEHNGy0a4c1UKOjFg0LSg3c/DzUoPluUB4Kk9gs4ifn+1cm2k6G9gjT/6Wi0xIW0t7+a7XX8ttPO7T4ZFDJT2KDINz42Oeht5u82TuKgBfdQsXm9XnJLqckQbaCZLPsuvyAT8MrgBABOvCVF1yurHNrmu+js6fZxu4wAO7ANMBDzNPYYx0IphYRGCnBte1Nj4vSiTtlFOdf8+gdM8lSlv4XV56e10MepNSvvFDd1De6l+ErLciZJQydDklX2e3R1GlQmm3d5Sxn5Wob3FA4nkyqLq21RlH2RRgo-----END CERTIFICATE-----expiration 1658500294issuer_id f4baa074-10d7-7fc3-1623-f6f906ceed98issuer_name root-2024issuing_ca -----BEGIN CERTIFICATE-----MIIDpzCCAo+gAwIBAgIUT2afmPzCe/DQFO4c/Re0H7nC0jMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTQzMTA0WhcNMjIwNzIyMTQzMTM0WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL39WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7doyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAUoWSv9g7doyvm9Xqspi9jH6kfhq8wOwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQByO9DyRVJYjK9xrnfNnD1pbG0WXWRmsk7dxtXY336ollMl0eqOuEEHNGy0a4c1UKOjFg0LSg3c/DzUoPluUB4Kk9gs4ifn+1cm2k6G9gjT/6Wi0xIW0t7+a7XX8ttPO7T4ZFDJT2KDINz42Oeht5u82TuKgBfdQsXm9XnJLqckQbaCZLPsuvyAT8MrgBABOvCVF1yurHNrmu+js6fZxu4wAO7ANMBDzNPYYx0IphYRGCnBte1Nj4vSiTtlFOdf8+gdM8lSlv4XV56e10MepNSvvFDd1De6l+ErLciZJQydDklX2e3R1GlQmm3d5Sxn5Wob3FA4nkyqLq21RlH2RRgo-----END CERTIFICATE-----key_id 775fb40a-4568-f613-2c6d-0f6802e859e1key_name n/aserial_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-d79a7a51e373f4baa074-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=trueSuccess! Data written to: pki/roles/2024-servers
Key Value--- -----allow_any_name trueallow_bare_domains falseallow_glob_domains falseallow_ip_sans trueallow_localhost trueallow_subdomains falseallow_token_displayname falseallow_wildcard_certificates trueallowed_domains []allowed_domains_template falseallowed_other_sans []allowed_serial_numbers []allowed_uri_sans []allowed_uri_sans_template falseallowed_user_ids []basic_constraints_valid_for_non_ca falseclient_flag truecn_validations [email hostname]code_signing_flag falsecountry []email_protection_flag falseenforce_hostnames trueext_key_usage []ext_key_usage_oids []generate_lease falseissuer_ref defaultkey_bits 2048key_type rsakey_usage [DigitalSignature KeyAgreement KeyEncipherment]locality []max_ttl 0sno_store falsenot_after n/anot_before_duration 30sorganization []ou []policy_identifiers []postal_code []province []require_cn trueserver_flag truesignature_bits 256street_address []ttl 0suse_csr_common_name trueuse_csr_sans trueuse_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-----MIIChDCCAWwCAQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAE9mbxAD9IcyZZFWO2TWNrG4hqaK/QgMy9lGqnfT7Zi++tV826EBxc4sA5331nVCrbWeRnXOiixUjxvAaZedD4CscLFKq/9rJC5tTv51T1ZaHa9wFJG0GeEHOvxbP5YRmz4JRRTF5ezVXZHjp8hVGbaLly6tdQN/K3OtvNBc8TMNehRJsLC1P7VjsIAGne0P16fZeR65Sjf//i1J2g3BZmF5jSCtglU5aFDqi9/VjzEfgnl6hkdUZMU7idKMtBnS6NiTIfZ3c+yUJDHFPFYoCe6Kob4cXM6DPy8dIQfGPsFDMp5/1b21DtLgURNUaTqZOWX8W2/E4mMrDfT6c4VWDAgMBAAGgKTAnBgkqhkiG9w0BCQ4xGjAYMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAeUqJ4t+IXNgGCMl2xCZ0a9Fypj873Ork+OgVz2zoASH14zia2MY3gGQe7NR9MFgebZMNG2hR3hcU22bmoUrsB+RITsgiQa1hYqZk5/MB059QvEUBYrBsndSN6bFkembWYBLqae7I8JDW4UY+06LSI4eGeV2n5VyMJ1WwxerbYOCvFpRK+7qYfO4r6roMAuM5uTpKJMMqMipwG0dLJEXC/9E/j3V0qiN9yIy74PdNWJahg6X5biytLWGNfsVafnjH5zkJfb0iEDECJz8tuayEW98JLzEGfeH6dz0S1hAMhoWiqiL1ZQeOe7zSKnUooThRs1904nojr6If74Pj058p4-----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+ICXC682TSMH7wsFRdYMkwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTUwODA3WhcNMjIwNzIyMTUwODM3WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL39WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7doyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAU+RF2dgdU6BZrOKHck1QpEmqPemUwOwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQARw49qG9j/N46En+ME8u3uK0DmVxo/Fuj/RCNOBQ3EnIJ8zU+VhujyckHcQNQ0f8nfrdE1JHnn+bnhOIzO1qaaooSlmhWg1HuEolOn/g1Aq1xJvmOdnWKr4G1iwo3xmID6AYAI80LaVAeRcrk+S6dmhDuo1KT4CZmGNo+sz0rguute7aThN568OGJF7qHoLFSn3/pe9zvpjuBiH9jiB1HmWbL/JqntTherr5JWK6W7EukGFNOdHEn/n/QfBuKX32QU8SjVb0ZRWd7CbJwL7nsNY6jnqlwLnCOyncL8hhnW6U8QbHqddm1l9PpE7BssfVTk/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/Re0H7nC0jMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTQzMTA0WhcNMjIwNzIyMTQzMTM0WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL39WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7doyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAUoWSv9g7doyvm9Xqspi9jH6kfhq8wOwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQByO9DyRVJYjK9xrnfNnD1pbG0WXWRmsk7dxtXY336ollMl0eqOuEEHNGy0a4c1UKOjFg0LSg3c/DzUoPluUB4Kk9gs4ifn+1cm2k6G9gjT/6Wi0xIW0t7+a7XX8ttPO7T4ZFDJT2KDINz42Oeht5u82TuKgBfdQsXm9XnJLqckQbaCZLPsuvyAT8MrgBABOvCVF1yurHNrmu+js6fZxu4wAO7ANMBDzNPYYx0IphYRGCnBte1Nj4vSiTtlFOdf8+gdM8lSlv4XV56e10MepNSvvFDd1De6l+ErLciZJQydDklX2e3R1GlQmm3d5Sxn5Wob3FA4nkyqLq21RlH2RRgo-----END CERTIFICATE----- -----BEGIN CERTIFICATE-----MIIDpzCCAo+gAwIBAgIUOjMm1b+ICXC682TSMH7wsFRdYMkwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTUwODA3WhcNMjIwNzIyMTUwODM3WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL39WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7doyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAU+RF2dgdU6BZrOKHck1QpEmqPemUwOwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQARw49qG9j/N46En+ME8u3uK0DmVxo/Fuj/RCNOBQ3EnIJ8zU+VhujyckHcQNQ0f8nfrdE1JHnn+bnhOIzO1qaaooSlmhWg1HuEolOn/g1Aq1xJvmOdnWKr4G1iwo3xmID6AYAI80LaVAeRcrk+S6dmhDuo1KT4CZmGNo+sz0rguute7aThN568OGJF7qHoLFSn3/pe9zvpjuBiH9jiB1HmWbL/JqntTherr5JWK6W7EukGFNOdHEn/n/QfBuKX32QU8SjVb0ZRWd7CbJwL7nsNY6jnqlwLnCOyncL8hhnW6U8QbHqddm1l9PpE7BssfVTk/exS/Icemf6XFzDeIrqT-----END CERTIFICATE----- -----BEGIN CERTIFICATE-----MIIDNTCCAh2gAwIBAgIUfDvqkDZG/fr7np0RZ50wHl2VO+QwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTQyMjU1WhcNMzIwNjE3MTQyMzI1WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJkM2EYB3+5S70a+aZpJeyvN8wY1wNnRIStPnJCquIlgMGu3u+c/fVUwpsxh+KSGMfLnA8vdVmZhkjd+Si97RlqV4yxA6OfJYlSyrOBHODA3E+J302gekWPGd851EpbAx+1MDekWoGprCEaiJCVIulNAgDWSHQHqfHNKJMoxGMxvCKhse+NcVMZoRUxBPG9pgKeb7gXIXlnPVOKeZAZYzzUCrU0x/OHCD6xKOVNNt8mmncKmUlQach8D1r0LA1IvNCYjhNF4+RGIYBAuuym2nKXI4aj3mtYrlDSnnBwZT3/8CdMwf0qy10KCExDHc+Yyge6EcbJBLnfYkIjOj/PzT8UCAwEAAaN7MHkwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFPkRdnYHVOgWazih3JNUKRJqj3plMB8GA1UdIwQYMBaAFPkRdnYHVOgWazih3JNUKRJqj3plMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQA+fKtmp+8jJ6KcS9aeiNgyVc2RuZQBVMkn0l9z6c6+zZwn7LbQ9LmoTfcbE8aXj3gKJlYGD+p66fCClmQjq8epWdT/HuO/5efFiiRsCan1eaKoK7dah9z39kfYxaXrOmG6nXjFDn0mu+ZxBtuW3kkib0MYnVvJDe/xJ8pg2J8Mt1tAqcbDbJZWW+yEH4XFJdjDt9LxeNm70y2BzDfr1Ckzh/rHowHEBDX/1a2rGgdU7n5j5mgMYKCcP5G+dlWhm3kztFo2aRniRE939WmlzLob9vgKBEkO7hfcs4kMO6TwDJx0/BZ3OpM54mgHf/DXkiY/AIsRYBp98iJESkjzeDAA-----END CERTIFICATE-----]certificate -----BEGIN CERTIFICATE-----MIIDpzCCAo+gAwIBAgIUT2afmPzCe/DQFO4c/Re0H7nC0jMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjIwNjIwMTQzMTA0WhcNMjIwNzIyMTQzMTM0WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMAT2ZvEAP0hzJlkVY7ZNY2sbiGpor9CAzL2Uaqd9PtmL761XzboQHFziwDnffWdUKttZ5Gdc6KLFSPG8Bpl50PgKxwsUqr/2skLm1O/nVPVlodr3AUkbQZ4Qc6/Fs/lhGbPglFFMXl7NVdkeOnyFUZtouXLq11A38rc6280FzxMw16FEmwsLU/tWOwgAad7Q/Xp9l5HrlKN//+LUnaDcFmYXmNIK2CVTloUOqL39WPMR+CeXqGR1RkxTuJ0oy0GdLo2JMh9ndz7JQkMcU8VigJ7oqhvhxczoM/Lx0hB8Y+wUMynn/VvbUO0uBRE1RpOpk5Zfxbb8TiYysN9PpzhVYMCAwEAAaOB7DCB6TAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoWSv9g7doyvm9Xqspi9jH6kfhq8wHwYDVR0jBBgwFoAUoWSv9g7doyvm9Xqspi9jH6kfhq8wOwYIKwYBBQUHAQEELzAtMCsGCCsGAQUFBzAChh9odHRwOi8vMTI3LjAuMC4xOjgyMDAvdjEvcGtpL2NhMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMDEGA1UdHwQqMCgwJqAkoCKGIGh0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQByO9DyRVJYjK9xrnfNnD1pbG0WXWRmsk7dxtXY336ollMl0eqOuEEHNGy0a4c1UKOjFg0LSg3c/DzUoPluUB4Kk9gs4ifn+1cm2k6G9gjT/6Wi0xIW0t7+a7XX8ttPO7T4ZFDJT2KDINz42Oeht5u82TuKgBfdQsXm9XnJLqckQbaCZLPsuvyAT8MrgBABOvCVF1yurHNrmu+js6fZxu4wAO7ANMBDzNPYYx0IphYRGCnBte1Nj4vSiTtlFOdf8+gdM8lSlv4XV56e10MepNSvvFDd1De6l+ErLciZJQydDklX2e3R1GlQmm3d5Sxn5Wob3FA4nkyqLq21RlH2RRgo-----END CERTIFICATE-----issuer_id f4baa074-10d7-7fc3-1623-f6f906ceed98issuer_name root-2024key_id 775fb40a-4568-f613-2c6d-0f6802e859e1leaf_not_after_behavior errmanual_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-----MIICcjCCAVoCAQAwLTErMCkGA1UEAxMiZXhhbXBsZS5jb20gSW50ZXJtZWRpYXRlIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALRWH4agH8Lh4eRTS9qVN4zsuovY+aHxmAf5Yt9Atwbd7obx/OdpiAmeHjH03hZlo0/GV6UZ43QuR/WqYZgIHvcDMNZaqYMy4Bp6PYDDDHTEm43oOkDvA/ZslWI/nt/f1o6D/O4R6JvQaE5GrzANyUhmq3BrvYpof8abvZpchCeCtAKyD7vmLrtsVAH2fGpYboTV02zL5+HZY3CKxoELhrVab7hArnq6VLQvHY6nvC5y7XV6D/ze+BuVNfKRDhapZzDPr2CQY0RWlOGGopJ1QBUp2AMlY/0PwJhO7WKpPudZw9YZd7sncLuJiX5sVOUzBafEww9Bkz/1pDsAesr89GkCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQA17CFuLX3MDfkbe4E+O1saZHnYgJ4lRurwg+E/CMPNHve8wkrtk/zv5cPJ6GSNusuEW/QPtSSpRsjnQj32qtEYqzNQhGpMGHh0VEEgjXYNtHp1dnlUodZQe2+1+u/aPeniblpEM4e/joER5AlxqlOZXUEz6rM8ExdMkPhN4pN3kNU/aaBVhEC8pxTig2kWR3uVMmF3DWSgkVNPSjJjbPFSEnKuIIHMfkwjv4QFnWhkgiNzwlKjmjK9WQD7JDkX9davkcr4AUAi23JsNxfOqlTNDke66lP1+GlUnStNy7XlcaMFuOSBQr30vtyn9G190XhA1m3dHtBqwehPzaC6UpJT-----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/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMwOTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkly61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJil952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmcdxbfFjojiyfKVpgayA54rkB/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/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMwOTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkly61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJil952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmcdxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV+bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E=-----END CERTIFICATE-----]certificate -----BEGIN CERTIFICATE-----MIIDpjCCAo6gAwIBAgIUV4yUTVdgE/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMwOTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkly61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJil952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmcdxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV+bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E=-----END CERTIFICATE-----crl_distribution_points []issuer_id 58dabd1a-73ee-c483-5371-add26cb1c48bissuer_name xc-example-dot-com-intermediateissuing_certificates []key_id 80375808-3015-91fc-ab36-b88e5b91d645leaf_not_after_behavior errmanual_chain <nil>ocsp_servers []revocation_signature_algorithm n/arevoked falseusage 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/K4tDfqvxdDokLmfVQ0SCcjBS8wDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk0MzQzWhcNMjgwODIwMTk0NDEzWjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBTS5JNOBLW/rwXBFO2Ol5zpfO9wnzA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAGQUfS3m41bC0lpEq7/KpVxGeIFutct21jWQX1AmORXFiu1yK+cAJJnDd1bRUE8MhhGH1lmFPZ8dpVvC/wm4Q1TvQGo1K82z4sUh1IDFqTMJOhwYYsQkrKqLCPcdcWxtgRnYldUp1AHnObFvQvJlJndZVpMfxRamTaLQjDEon7ItldOR4ZLoSCg18ZvUlqQk/bzosPq7pvmmShGpnX5ln02J1+6BYMZTbxn/FBjWIb466Bquc1+lCWHuOkHvnzAQ00oFKWTvEXr0EobWWANLuFnWiite8ZTwZjpkYPoXpOnK9dmk61rV+AlTy7qovM4Y5Yjg2uOA6FZbg3SW11RLEUA=-----END CERTIFICATE----- -----BEGIN CERTIFICATE-----MIIDNTCCAh2gAwIBAgIUezeBwAzYGi0DTibs/fKPq0zpBS8wDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk0MjU3WhcNMzMwODE5MTk0MzI3WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9LxaXPq/iBmifhy9GEQaHpdmPrvGvH2oCS3EjdeE5Zjb2Fm8R1HTYcWQ4HtLygG4rKdzKv8cXaMSOAXCcyyIgMsQxIkYsXbq+agJhB/AiGiH0lhx1vy6YmHUGqo8oGmWLMp4pGaFruz/Ij2V3K1a4WMAXW3+/NjQu871bIHVe+RfoIK3ZxM8vNGSq8SJ/7gh3XxZ4Cq+x3uMlKknSNpZc/AWQIEuzp78gYGKttTm4XAlY63Vb972d4m2KMY3Ux2NJDP9otSKwDRRFBAyY0ktTJkrEFgioA6F5qo3wzNwW55x8iTI12m2OSdUGg7PoMZBuOWm9KF/NTgdpHlkL9pRUCAwEAAaN7MHkwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNLkk04Etb+vBcEU7Y6XnOl873CfMB8GA1UdIwQYMBaAFNLkk04Etb+vBcEU7Y6XnOl873CfMBYGA1UdEQQPMA2CC2V4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAVy+u6KEO16pEetpLFDrZPVQi2+DC76lkcHf3KnevUzKtbzRW4VipiI88Uj/9B7YXQFQXmHs3QHibrTNUZbhqF3S25PnVGaJutlqC4qWmxwAWthOEFhrZRyRuIiEQrjriSNj4liCntTmAT+GCEdqdKoQ/MclSEfThLPpk9Gm4REv2EX1savDLOxt3AkQTpLkwqK79+H1JjrcyR9Dsq5db7oxZdMCk47wxcwJvwv5TLub+/MVfiFFLEkpucTf0A/i0bY30IXUAIIUoULskw4l2rAWC88sxA/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/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMwOTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkly61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJil952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmcdxbfFjojiyfKVpgayA54rkB/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/K4tDfqvxdDokLmfVQ0SCcjBS8wDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk0MzQzWhcNMjgwODIwMTk0NDEzWjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBTS5JNOBLW/rwXBFO2Ol5zpfO9wnzA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAGQUfS3m41bC0lpEq7/KpVxGeIFutct21jWQX1AmORXFiu1yK+cAJJnDd1bRUE8MhhGH1lmFPZ8dpVvC/wm4Q1TvQGo1K82z4sUh1IDFqTMJOhwYYsQkrKqLCPcdcWxtgRnYldUp1AHnObFvQvJlJndZVpMfxRamTaLQjDEon7ItldOR4ZLoSCg18ZvUlqQk/bzosPq7pvmmShGpnX5ln02J1+6BYMZTbxn/FBjWIb466Bquc1+lCWHuOkHvnzAQ00oFKWTvEXr0EobWWANLuFnWiite8ZTwZjpkYPoXpOnK9dmk61rV+AlTy7qovM4Y5Yjg2uOA6FZbg3SW11RLEUA=-----END CERTIFICATE----- -----BEGIN CERTIFICATE-----MIIDpjCCAo6gAwIBAgIUV4yUTVdgE/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMwOTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkly61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJil952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmcdxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV+bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E=-----END CERTIFICATE-----]certificate -----BEGIN CERTIFICATE-----MIIDpjCCAo6gAwIBAgIUP/K4tDfqvxdDokLmfVQ0SCcjBS8wDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk0MzQzWhcNMjgwODIwMTk0NDEzWjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBTS5JNOBLW/rwXBFO2Ol5zpfO9wnzA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAGQUfS3m41bC0lpEq7/KpVxGeIFutct21jWQX1AmORXFiu1yK+cAJJnDd1bRUE8MhhGH1lmFPZ8dpVvC/wm4Q1TvQGo1K82z4sUh1IDFqTMJOhwYYsQkrKqLCPcdcWxtgRnYldUp1AHnObFvQvJlJndZVpMfxRamTaLQjDEon7ItldOR4ZLoSCg18ZvUlqQk/bzosPq7pvmmShGpnX5ln02J1+6BYMZTbxn/FBjWIb466Bquc1+lCWHuOkHvnzAQ00oFKWTvEXr0EobWWANLuFnWiite8ZTwZjpkYPoXpOnK9dmk61rV+AlTy7qovM4Y5Yjg2uOA6FZbg3SW11RLEUA=-----END CERTIFICATE-----crl_distribution_points []issuer_id 4e2e04ff-de9b-10ff-59e1-ccaa8247e1aeissuer_name n/aissuing_certificates []key_id 80375808-3015-91fc-ab36-b88e5b91d645leaf_not_after_behavior errmanual_chain [4e2e04ff-de9b-10ff-59e1-ccaa8247e1ae 58dabd1a-73ee-c483-5371-add26cb1c48b]ocsp_servers []revocation_signature_algorithm n/arevoked falseusage 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/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMwOTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkly61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJil952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmcdxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV+bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E=-----END CERTIFICATE----- -----BEGIN CERTIFICATE-----MIIDpjCCAo6gAwIBAgIUP/K4tDfqvxdDokLmfVQ0SCcjBS8wDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk0MzQzWhcNMjgwODIwMTk0NDEzWjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBTS5JNOBLW/rwXBFO2Ol5zpfO9wnzA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAGQUfS3m41bC0lpEq7/KpVxGeIFutct21jWQX1AmORXFiu1yK+cAJJnDd1bRUE8MhhGH1lmFPZ8dpVvC/wm4Q1TvQGo1K82z4sUh1IDFqTMJOhwYYsQkrKqLCPcdcWxtgRnYldUp1AHnObFvQvJlJndZVpMfxRamTaLQjDEon7ItldOR4ZLoSCg18ZvUlqQk/bzosPq7pvmmShGpnX5ln02J1+6BYMZTbxn/FBjWIb466Bquc1+lCWHuOkHvnzAQ00oFKWTvEXr0EobWWANLuFnWiite8ZTwZjpkYPoXpOnK9dmk61rV+AlTy7qovM4Y5Yjg2uOA6FZbg3SW11RLEUA=-----END CERTIFICATE-----]certificate -----BEGIN CERTIFICATE-----MIIDpjCCAo6gAwIBAgIUV4yUTVdgE/E50pbw0u1eDOicToMwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwODIyMTk1MjI2WhcNMjMwOTIzMTk1MjU2WjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtFYfhqAfwuHh5FNL2pU3jOy6i9j5ofGYB/li30C3Bt3uhvH852mICZ4eMfTeFmWjT8ZXpRnjdC5H9aphmAge9wMw1lqpgzLgGno9gMMMdMSbjeg6QO8D9myVYj+e39/WjoP87hHom9BoTkavMA3JSGarcGu9imh/xpu9mlyEJ4K0ArIPu+Yuu2xUAfZ8alhuhNXTbMvn4dljcIrGgQuGtVpvuECuerpUtC8djqe8LnLtdXoP/N74G5U18pEOFqlnMM+vYJBjRFaU4YaiknVAFSnYAyVj/Q/AmE7tYqk+51nD1hl3uydwu4mJfmxU5TMFp8TDD0GTP/WkOwB6yvz0aQIDAQABo4HUMIHRMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSnjahgWrDluYwFlvSie5k5MaHzRDAfBgNVHSMEGDAWgBR2Mdo2xl0gsSOc0mOwpx9Tx8AaeDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAKGH2h0dHA6Ly8xMjcuMC4wLjE6ODIwMC92MS9wa2kvY2EwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDovLzEyNy4wLjAuMTo4MjAwL3YxL3BraS9jcmwwDQYJKoZIhvcNAQELBQADggEBAAuJDED9c4gNf0eOJZbglDKUID1CdVSdwXqLKX4JycFxWvraLJkly61ulx7bdEURhvMP4Df38sxYDkjNel+Ma5Pk5IGXzKezRdxHTf3uMQOUfLaH6AUq0gJiAqNjBBR+iJiP6/dEkv2DUnevXd0CcMTwDGS1Hu0M82DQ8k52+b9qRuAks6hJil952LYSe+rvcXlWsw1isppEMDIYlwsfzRv/enaIXOlTAfNF+n4RJLHlrNjdFsmcdxbfFjojiyfKVpgayA54rkB/iCrqVxNM4hGRpjfk6EGtZ0gAbisr9TDNbvynrUaV+bgMuk68oTgOwVgkZw+By5G8pVY1AJVKA6E=-----END CERTIFICATE-----crl_distribution_points []issuer_id 58dabd1a-73ee-c483-5371-add26cb1c48bissuer_name xc-example-dot-com-intermediateissuing_certificates []key_id 80375808-3015-91fc-ab36-b88e5b91d645leaf_not_after_behavior errmanual_chain [58dabd1a-73ee-c483-5371-add26cb1c48b 4e2e04ff-de9b-10ff-59e1-ccaa8247e1ae]ocsp_servers []revocation_signature_algorithm n/arevoked falseusage 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-2024Key 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-2023key_id b785654a-6ab6-0904-be34-3f5b1c1e8d53leaf_not_after_behavior errmanual_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-serversCode: 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.