Vault
Build a certificate authority (CA) in Vault with an offline root
This tutorial builds on the Build Your Own Certificate Authority (CA) tutorial. You will learn how to create a CA chain hierarchy that uses an offline root and online intermediate CAs in Vault.
Prerequisites
To perform the tasks described in this tutorial, you need:
- Vault binary installed.
- Certstrap tool by Square to create a simple offline Root CA.
- Terraform CLI to provision Vault server.
- jq tool to parse JSON output.
- openssl tool which is generally packaged with most OS distributions for inspecting x509 certificates and certificate signing requests that you will create in this tutorial.
- tree tool to view the folder structure.
Scenario introduction
In this tutorial, you will complete the following on your local machine:
- Create an offline Root CA.
- Start Vault server in development mode.
- Create Intermediate Certificate Authority 1 (ICA1) in Vault signed with offline Root CA.
- Create Intermediate Certificate Authority 2 (ICA2) in Vault signed with ICA1.
- Issue a client x509 Certificate rooted in ICA2.

Step 1: Create an offline Root CA
Use the certstrap tool to create the offline Root CA, select a very strong password for protecting the CA key.
$ certstrap init \ --organization "Test" \ --organizational-unit "Test Org" \ --country "US" \ --province "MD" \ --locality "Bethesda" \ --common-name "Testing Root"Output:
Enter passphrase (empty for no passphrase): Enter same passphrase again: Created out/Testing_Root.key (encrypted by passphrase) Created out/Testing_Root.crt Created out/Testing_Root.crlInspect the offline Root CA certificate with openssl to ensure it has the expected
subject.$ openssl x509 -in out/Testing_Root.crt -noout -subject -issuerOutput:
subject= /C=US/ST=DC/L=Bethesda/O=Test/OU=Test Org/CN=Testing Root issuer= /C=US/ST=DC/L=Bethesda/O=Test/OU=Test Org/CN=Testing RootThe
treecommand outputs theoutfolder hierarchy.$ tree outOutput:
out ├── Testing_Root.crl ├── Testing_Root.crt └── Testing_Root.key
Step 2: Start Vault server in dev mode
To proceed with the tutorial, open two terminals on your local machine.
In one terminal, start a Vault dev server with
rootas the root token.$ vault server -dev -dev-root-token-id rootThe Vault dev server defaults to address
127.0.0.1:8200. The server is initialized and unsealed.In a second terminal session, export an environment variable for the
vaultCLI to address the Vault server.$ export VAULT_ADDR=http://127.0.0.1:8200Additionally, export an environment variable for the
vaultCLI to authenticate with the Vault server.$ export VAULT_TOKEN=root
For this tutorial, you can use Vault's root token. However, it is recommended that root tokens are only used for enough initial setup or in emergencies. As a best practice, use an authentication method or token that meets the policy requirements.
The Vault server is ready.
Step 3: Generate ICA1 in vault
Next, use Terraform Vault provider to provision and manage intermediate PKI endpoints in Vault by creating below file hierarchy.
In your second terminal, create the necessary terraform files to manage ICA1 resources in Vault.
Create
main.tffile which definesvaultprovider.$ cat > main.tf << EOF provider "vault" {} locals { default_3y_in_sec = 94608000 default_1y_in_sec = 31536000 default_1hr_in_sec = 3600 } EOFCreate
test_org_ica1.tffile which enables and configures PKI secrets engine.$ cat > test_org_ica1.tf << EOF resource "vault_mount" "test_org_v1_ica1_v1" { path = "test-org/v1/ica1/v1" type = "pki" description = "PKI engine hosting intermediate CA1 v1 for test org" default_lease_ttl_seconds = local.default_1hr_in_sec max_lease_ttl_seconds = local.default_3y_in_sec } resource "vault_pki_secret_backend_intermediate_cert_request" "test_org_v1_ica1_v1" { depends_on = [vault_mount.test_org_v1_ica1_v1] backend = vault_mount.test_org_v1_ica1_v1.path type = "internal" common_name = "Intermediate CA1 v1 " key_type = "rsa" key_bits = "2048" ou = "test org" organization = "test" country = "US" locality = "Bethesda" province = "MD" } EOFTo ensure the file structure is properly configured, use the
treecommand to view the directory.$ tree . ├── main.tf ├── out │ ├── Testing_Root.crl │ ├── Testing_Root.crt │ └── Testing_Root.key └── test_org_ica1.tf 2 directories, 5 fileThe
test_org_ica1.tffile has the necessary code to enable a new PKI endpoint for theICA1in Vault and to generate a Certificate Signing Request (CSR). The CSR will be signed by the offline Root CA next.First, initialize terraform; this downloads the necessary providers and initializes the backend.
$ terraform init Initializing the backend... Initializing provider plugins... ...snip... Terraform has been successfully initialized!Execute the
applycommand to configure Vault.$ terraform applyThis displays the actions to be performed by Terraform.
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # vault_mount.test_org_v1_ica1_v1 will be created + resource "vault_mount" "test_org_v1_ica1_v1" { + accessor = (known after apply) + default_lease_ttl_seconds = 3600 + description = "PKI engine hosting intermediate CA1 v1 for test org" + external_entropy_access = false + id = (known after apply) + max_lease_ttl_seconds = 94608000 + path = "test-org/v1/ica1/v1" + seal_wrap = (known after apply) + type = "pki" } # vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica1_v1 will be created + resource "vault_pki_secret_backend_intermediate_cert_request" "test_org_v1_ica1_v1" { + backend = "test-org/v1/ica1/v1" + common_name = "Intermediate CA1 v1 " + country = "US" + csr = (known after apply) + format = "pem" + id = (known after apply) + key_bits = 2048 + key_type = "rsa" + locality = "Bethesda" + organization = "test" + ou = "test org" + private_key = (sensitive value) + private_key_format = "der" + private_key_type = (known after apply) + province = "MD" + type = "internal" } Plan: 2 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value:When prompted, enter
yesto accept the plan and proceed with Vault configuration.vault_mount.test_org_v1_ica1_v1: Creating... vault_mount.test_org_v1_ica1_v1: Creation complete after 0s [id=test-org/v1/ica1/v1] vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica1_v1: Creating... vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica1_v1: Creation complete after 0s [id=test-org/v1/ica1/v1/intermediate/generate/internal] Apply complete! Resources: 2 added, 0 changed, 0 destroyed.Create a new
csrfolder.$ mkdir csrGet the ICA1 CSR from the Terraform state file and store it under a new
csrfolder.$ terraform show -json | jq '.values["root_module"]["resources"][].values.csr' -r | grep -v null > csr/Test_Org_v1_ICA1_v1.csrSign ICA1 CSR with the offline Root CA.
$ certstrap sign \ --expires "3 year" \ --csr csr/Test_Org_v1_ICA1_v1.csr \ --cert out/Intermediate_CA1_v1.crt \ --intermediate \ --path-length "1" \ --CA "Testing Root" \ "Intermediate CA1 v1"Output:
Enter passphrase for CA key (empty for no passphrase): Building intermediate Created out/Intermediate_CA1_v1.crt from out/Intermediate_CA1_v1.csr signed by out/Testing_Root.keyThe output displays
out/Intermediate_CA1_v1.csrbut it is a tooling print error asIntermediate_CA1_v1.csris passed from under thecsrand notoutfolder.Create the
cacertsfolder to store the CA chain files that will be set on the PKI endpoints in Vault.$ mkdir cacertsAppend offline Root CA at the end of ICA1 cert to create a CA chain under
cacertsfolder. You will use this to set the signed ICA1 in Vault.$ cat out/Intermediate_CA1_v1.crt out/Testing_Root.crt > cacerts/test_org_v1_ica1_v1.crtUpdate the Terraform code to set the signed cert for
ICA1in Vault.$ cat >> test_org_ica1.tf << EOF resource "vault_pki_secret_backend_intermediate_set_signed" "test_org_v1_ica1_v1_signed_cert" { depends_on = [vault_mount.test_org_v1_ica1_v1] backend = vault_mount.test_org_v1_ica1_v1.path certificate = file("\${path.module}/cacerts/test_org_v1_ica1_v1.crt") } EOFApply the Terraform changes to set the signed ICA1 in Vault.
$ terraform applyOutput:
...truncated... Enter a value: yes vault_pki_secret_backend_intermediate_set_signed.test_org_v1_ica1_v1_signed_cert: Creating... vault_pki_secret_backend_intermediate_set_signed.test_org_v1_ica1_v1_signed_cert: Creation complete after 0s [id=test-org/v1/ica1/v1/intermediate/set-signed] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Verify that the Terraform output displays the new ICA1 set
Verify the ICA1 cert in Vault.
$ curl -s $VAULT_ADDR/v1/test-org/v1/ica1/v1/ca/pem | openssl crl2pkcs7 -nocrl -certfile /dev/stdin | openssl pkcs7 -print_certs -nooutOutput:
subject=/C=US/ST=MD/L=Bethesda/O=test/OU=test org/CN=Intermediate CA1 v1 issuer=/C=US/ST=MD/L=Bethesda/O=Test/OU=Test Org/CN=Testing RootVerify the ICA1 CA chain in Vault.
$ curl -s $VAULT_ADDR/v1/test-org/v1/ica1/v1/ca_chain | openssl crl2pkcs7 -nocrl -certfile /dev/stdin | openssl pkcs7 -print_certs -nooutOutput:
subject=/C=US/ST=MD/L=Bethesda/O=test/OU=test org/CN=Intermediate CA1 v1 issuer=/C=US/ST=MD/L=Bethesda/O=Test/OU=Test Org/CN=Testing Root subject=/C=US/ST=MD/L=Bethesda/O=Test/OU=Test Org/CN=Testing Root issuer=/C=US/ST=MD/L=Bethesda/O=Test/OU=Test Org/CN=Testing RootYour directory structure should now resemble the example output.
$ tree . ├── cacerts │ └── test_org_v1_ica1_v1.crt ├── csr │ └── Test_Org_v1_ICA1_v1.csr ├── main.tf ├── out │ ├── Intermediate_CA1_v1.crt │ ├── Testing_Root.crl │ ├── Testing_Root.crt │ └── Testing_Root.key ├── terraform.tfstate ├── terraform.tfstate.backup └── test_org_ica1.tf 4 directories, 10 files
Step 4: Generate ICA2 in vault
Next, generate Terraform code to create and manage ICA2 in Vault.
In your second terminal, create a Terraform file named, "test_org_ica2.tf" to manage ICA2 resources in Vault.
$ cat > test_org_ica2.tf << EOF resource "vault_mount" "test_org_v1_ica2_v1" { path = "test-org/v1/ica2/v1" type = "pki" description = "PKI engine hosting intermediate CA2 v1 for test org" default_lease_ttl_seconds = local.default_1hr_in_sec max_lease_ttl_seconds = local.default_1y_in_sec } resource "vault_pki_secret_backend_intermediate_cert_request" "test_org_v1_ica2_v1" { depends_on = [vault_mount.test_org_v1_ica2_v1] backend = vault_mount.test_org_v1_ica2_v1.path type = "internal" common_name = "Intermediate CA2 v1 " key_type = "rsa" key_bits = "2048" ou = "test org" organization = "test" country = "US" locality = "Bethesda" province = "MD" } resource "vault_pki_secret_backend_root_sign_intermediate" "test_org_v1_sign_ica2_v1_by_ica1_v1" { depends_on = [ vault_mount.test_org_v1_ica1_v1, vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica2_v1, ] backend = vault_mount.test_org_v1_ica1_v1.path csr = vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica2_v1.csr common_name = "Intermediate CA2 v1.1" exclude_cn_from_sans = true ou = "test org" organization = "test" country = "US" locality = "Bethesda" province = "MD" max_path_length = 1 ttl = local.default_1y_in_sec } resource "vault_pki_secret_backend_intermediate_set_signed" "test_org_v1_ica2_v1_signed_cert" { depends_on = [vault_pki_secret_backend_root_sign_intermediate.test_org_v1_sign_ica2_v1_by_ica1_v1] backend = vault_mount.test_org_v1_ica2_v1.path certificate = format("%s\n%s", vault_pki_secret_backend_root_sign_intermediate.test_org_v1_sign_ica2_v1_by_ica1_v1.certificate, file("\${path.module}/cacerts/test_org_v1_ica1_v1.crt")) } EOFApply Terraform changes for ICA2.
$ terraform applyOutput:
vault_mount.test_org_v1_ica1_v1: Refreshing state... [id=test-org/v1/ica1/v1] vault_pki_secret_backend_intermediate_set_signed.test_org_v1_ica1_v1_signed_cert: Refreshing state... [id=test-org/v1/ica1/v1/intermediate/set-signed] vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica1_v1: Refreshing state... [id=test-org/v1/ica1/v1/intermediate/generate/internal] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # vault_mount.test_org_v1_ica2_v1 will be created + resource "vault_mount" "test_org_v1_ica2_v1" { + accessor = (known after apply) + default_lease_ttl_seconds = 3600 + description = "PKI engine hosting intermediate CA2 v1 for test org" + external_entropy_access = false + id = (known after apply) + max_lease_ttl_seconds = 31536000 + path = "test-org/v1/ica2/v1" + seal_wrap = (known after apply) + type = "pki" } # vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica2_v1 will be created + resource "vault_pki_secret_backend_intermediate_cert_request" "test_org_v1_ica2_v1" { + backend = "test-org/v1/ica2/v1" + common_name = "Intermediate CA2 v1 " + country = "US" + csr = (known after apply) + format = "pem" + id = (known after apply) + key_bits = 2048 + key_type = "rsa" + locality = "Bethesda" + organization = "test" + ou = "test org" + private_key = (sensitive value) + private_key_format = "der" + private_key_type = (known after apply) + province = "MD" + type = "internal" } # vault_pki_secret_backend_intermediate_set_signed.test_org_v1_ica2_v1_signed_cert will be created + resource "vault_pki_secret_backend_intermediate_set_signed" "test_org_v1_ica2_v1_signed_cert" { + backend = "test-org/v1/ica2/v1" + certificate = (known after apply) + id = (known after apply) } # vault_pki_secret_backend_root_sign_intermediate.test_org_v1_sign_ica2_v1_by_ica1_v1 will be created + resource "vault_pki_secret_backend_root_sign_intermediate" "test_org_v1_sign_ica2_v1_by_ica1_v1" { + backend = "test-org/v1/ica1/v1" + ca_chain = (known after apply) + certificate = (known after apply) + common_name = "Intermediate CA2 v1.1" + country = "US" + csr = (known after apply) + exclude_cn_from_sans = true + format = "pem" + id = (known after apply) + issuing_ca = (known after apply) + locality = "Bethesda" + max_path_length = 1 + organization = "test" + ou = "test org" + province = "MD" + serial = (known after apply) + ttl = "31536000" + use_csr_values = false } Plan: 4 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value:When prompted, enter
yesto accept the plan and proceed with Vault configuration.vault_mount.test_org_v1_ica2_v1: Creating... vault_mount.test_org_v1_ica2_v1: Creation complete after 0s [id=test-org/v1/ica2/v1] vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica2_v1: Creating... vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica2_v1: Creation complete after 0s [id=test-org/v1/ica2/v1/intermediate/generate/internal] vault_pki_secret_backend_root_sign_intermediate.test_org_v1_sign_ica2_v1_by_ica1_v1: Creating... vault_pki_secret_backend_root_sign_intermediate.test_org_v1_sign_ica2_v1_by_ica1_v1: Creation complete after 0s [id=test-org/v1/ica1/v1/Intermediate CA2 v1.1] vault_pki_secret_backend_intermediate_set_signed.test_org_v1_ica2_v1_signed_cert: Creating... vault_pki_secret_backend_intermediate_set_signed.test_org_v1_ica2_v1_signed_cert: Creation complete after 0s [id=test-org/v1/ica2/v1/intermediate/set-signed] Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Verify that the Terraform output displays the new ICA2 set
Verify the ICA2 cert in Vault.
$ curl -s $VAULT_ADDR/v1/test-org/v1/ica2/v1/ca/pem | openssl crl2pkcs7 -nocrl -certfile /dev/stdin | openssl pkcs7 -print_certs -nooutOutput:
subject=/C=US/ST=MD/L=Bethesda/O=test/OU=test org/CN=Intermediate CA2 v1.1 issuer=/C=US/ST=MD/L=Bethesda/O=test/OU=test org/CN=Intermediate CA1 v1Verify the ICA2 CA chain in Vault.
$ curl -s $VAULT_ADDR/v1/test-org/v1/ica2/v1/ca_chain | openssl crl2pkcs7 -nocrl -certfile /dev/stdin | openssl pkcs7 -print_certs -nooutOutput:
subject=/C=US/ST=MD/L=Bethesda/O=test/OU=test org/CN=Intermediate CA2 v1.1 issuer=/C=US/ST=MD/L=Bethesda/O=test/OU=test org/CN=Intermediate CA1 v1 subject=/C=US/ST=MD/L=Bethesda/O=test/OU=test org/CN=Intermediate CA1 v1 issuer=/C=US/ST=MD/L=Bethesda/O=Test/OU=Test Org/CN=Testing Root subject=/C=US/ST=MD/L=Bethesda/O=Test/OU=Test Org/CN=Testing Root issuer=/C=US/ST=MD/L=Bethesda/O=Test/OU=Test Org/CN=Testing RootRun ICA2 x509 certificate constraint check.
$ curl -s $VAULT_ADDR/v1/test-org/v1/ica2/v1/ca/pem | openssl x509 -in /dev/stdin -noout -text | grep "X509v3 extensions" -A 13Output example:
X509v3 extensions: X509v3 Key Usage: critical Certificate Sign, CRL Sign X509v3 Basic Constraints: critical CA:TRUE, pathlen:1 X509v3 Subject Key Identifier: AE:88:D1:D6:3D:3D:AD:BD:AF:6F:D0:9D:CB:5A:E6:A6:B3:71:94:CB X509v3 Authority Key Identifier: keyid:11:12:F5:E4:85:6C:E4:ED:75:37:FB:C3:CD:14:D6:B8:81:14:F6:44 X509v3 Name Constraints: critical Permitted: DNS:test.comNotice that the
X509v3 Basic Constraintsvaluepathlen:1, ensures that ICA2 can only sign CSR requests, but not create more intermediate certificate authorities.
Congratulations, you successfully established your intermediate CAs in Vault with an offline Root.
Step 5: Issue a client x509 cert rooted in ICA2
Create a new PKI role rooted in ICA2 to issue client x509 certificates for
test.comsubdomains.$ cat > test_org_ica2_role_test_dot_com.tf << EOF resource "vault_pki_secret_backend_role" "role" { backend = vault_mount.test_org_v1_ica2_v1.path name = "test-dot-com-subdomain" ttl = local.default_1hr_in_sec allow_ip_sans = true key_type = "rsa" key_bits = 2048 key_usage = [ "DigitalSignature"] allow_any_name = false allow_localhost = false allowed_domains = ["test.com"] allow_bare_domains = false allow_subdomains = true server_flag = false client_flag = true no_store = true country = ["US"] locality = ["Bethesda"] province = ["MD"] } EOFApply Terraform changes for ICA2.
$ terraform applyOutput:
vault_mount.test_org_v1_ica2_v1: Refreshing state... [id=test-org/v1/ica2/v1] vault_mount.test_org_v1_ica1_v1: Refreshing state... [id=test-org/v1/ica1/v1] vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica1_v1: Refreshing state... [id=test-org/v1/ica1/v1/intermediate/generate/internal] vault_pki_secret_backend_intermediate_set_signed.test_org_v1_ica1_v1_signed_cert: Refreshing state... [id=test-org/v1/ica1/v1/intermediate/set-signed] vault_pki_secret_backend_intermediate_cert_request.test_org_v1_ica2_v1: Refreshing state... [id=test-org/v1/ica2/v1/intermediate/generate/internal] vault_pki_secret_backend_root_sign_intermediate.test_org_v1_sign_ica2_v1_by_ica1_v1: Refreshing state... [id=test-org/v1/ica1/v1/Intermediate CA2 v1.1] vault_pki_secret_backend_intermediate_set_signed.test_org_v1_ica2_v1_signed_cert: Refreshing state... [id=test-org/v1/ica2/v1/intermediate/set-signed] Note: Objects have changed outside of Terraform Terraform detected the following changes made outside of Terraform since the last "terraform apply": # vault_mount.test_org_v1_ica2_v1 has been changed ~ resource "vault_mount" "test_org_v1_ica2_v1" { id = "test-org/v1/ica2/v1" + options = {} # (9 unchanged attributes hidden) } Unless you have made equivalent changes to your configuration, or ignored the relevant attributes using ignore_changes, the following plan may include actions to undo or respond to these changes. ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # vault_pki_secret_backend_role.role will be created + resource "vault_pki_secret_backend_role" "role" { + allow_any_name = false + allow_bare_domains = false + allow_glob_domains = false + allow_ip_sans = true + allow_localhost = false + allow_subdomains = true + allowed_domains = [ + "test.com", ] + allowed_domains_template = false + backend = "test-org/v1/ica2/v1" + basic_constraints_valid_for_non_ca = false + client_flag = true + code_signing_flag = false + country = [ + "US", ] + email_protection_flag = false + enforce_hostnames = true + generate_lease = false + id = (known after apply) + key_bits = 2048 + key_type = "rsa" + key_usage = [ + "DigitalSignature", ] + locality = [ + "Bethesda", ] + name = "test-dot-com-subdomain" + no_store = true + not_before_duration = (known after apply) + province = [ + "MD", ] + require_cn = true + server_flag = false + ttl = "3600" + use_csr_common_name = true + use_csr_sans = true } Plan: 1 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value:When prompted, enter
yesto accept the plan and proceed with Vault configuration.vault_pki_secret_backend_role.role: Creating... vault_pki_secret_backend_role.role: Creation complete after 0s [id=test-org/v1/ica2/v1/roles/test-dot-com-subdomain] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.Next, create a certificate rooted in ICA2 using Vault CLI.
$ vault write -format=json test-org/v1/ica2/v1/issue/test-dot-com-subdomain \ common_name=1.test.com | jq .data.certificate -r | openssl x509 -in /dev/stdin -text -nooutOutput example:
Certificate: Data: Version: 3 (0x2) Serial Number: 7f:79:7f:87:92:26:81:37:1c:64:de:40:14:44:19:5d:b3:e6:64:16 Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, ST=MD, L=Bethesda, O=test, OU=test org, CN=Intermediate CA2 v1.1 Validity Not Before: Sep 25 23:26:16 2021 GMT Not After : Sep 26 00:26:45 2021 GMT Subject: C=US, ST=MD, L=Bethesda, CN=1.test.com Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:c2:9b:7c:91:55:da:70:5e:72:5e:3c:aa:20:9f: 2d:c7:3c:ed:4f:5e:a7:cf:50:3b:0b:e4:4f:df:69: 34:1a:40:0d:bf:1a:6c:53:1f:f2:0d:3a:4a:83:3f: 47:16:8e:88:4c:a9:bc:be:20:22:04:c0:9b:76:52: b1:96:a8:8e:0f:4e:36:b8:aa:4f:da:3b:1b:3b:64: 34:c6:c8:e5:c2:2a:da:a1:e4:3c:0d:13:f3:e5:8c: a4:b1:d5:37:11:d0:99:70:b0:37:5a:f1:4a:e9:5a: e3:09:ba:db:d9:ee:59:a3:94:ee:b4:97:85:3b:a4: 0a:0d:31:c9:91:09:7e:66:de:01:10:fd:1e:dd:89: b9:65:e9:9d:c6:aa:c6:11:b8:c4:eb:06:e6:c3:ac: 6c:b4:1b:65:e9:29:bb:c7:26:84:fb:52:0e:07:bd: da:c2:37:5d:d2:21:4c:a9:7f:51:c4:61:03:bc:06: a8:9e:18:0c:2b:8b:7b:9a:0d:30:d0:7e:2e:14:72: 6b:0b:55:c3:68:51:6c:3b:9d:87:46:0a:3d:7b:77: a9:48:06:96:ed:af:2d:25:f4:28:eb:5b:13:ac:61: 22:8a:c8:a7:99:eb:d1:1c:41:3d:4b:e6:2e:16:f3: 56:7e:b6:38:ac:07:b1:66:4c:5f:f2:65:2c:36:1b: 91:1d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Key Usage: critical Digital Signature X509v3 Extended Key Usage: TLS Web Client Authentication X509v3 Subject Key Identifier: 1B:A5:58:99:2E:0E:42:48:B3:8F:C4:D4:6D:E5:91:C2:5B:48:13:57 X509v3 Authority Key Identifier: keyid:7A:AF:49:89:C6:BC:F1:5D:F4:A9:3A:79:66:CD:CA:E4:36:7E:78:64 X509v3 Subject Alternative Name: DNS:1.test.com Signature Algorithm: sha256WithRSAEncryption 7a:c2:1d:47:8e:5b:92:c6:6b:5b:28:8e:a6:29:64:1a:ea:bd: c3:0f:4b:c1:37:8c:61:78:b8:1c:d9:2a:9c:aa:33:00:40:f2: 14:3a:ae:b6:ec:9e:d3:aa:ea:9f:50:15:9b:03:0c:30:9b:6d: f1:79:47:77:d2:1c:ff:bf:ee:8c:70:b1:c6:15:65:4c:e4:76: d1:b8:cd:27:68:ec:e8:dd:41:b1:50:bd:0a:1a:16:ab:8e:aa: 6b:1f:8e:15:28:e6:51:ee:5d:c6:62:b0:cd:d7:87:cb:9b:18: 6c:c3:82:44:4a:71:f8:bb:fa:c2:88:39:d4:7b:08:e5:7e:8a: 47:ad:7b:d4:06:d7:e6:f3:d8:c9:79:83:22:b6:0a:db:10:44: 9d:1b:5c:19:73:90:f4:cf:0f:72:52:14:1d:e6:10:ef:29:91: 55:10:2d:17:f5:4a:d2:ed:85:be:37:6c:f1:75:b2:61:70:cd: b2:ed:43:ec:bc:69:60:87:99:57:ca:69:2c:76:b8:8e:26:46: c2:a2:ad:ff:a7:99:04:8a:d4:58:dd:99:53:6f:3f:10:1f:52: 24:6d:af:e0:a8:a8:eb:62:10:f8:1c:5c:99:13:43:55:d9:a1: 53:34:62:60:e6:fd:aa:49:30:58:18:5e:aa:c4:51:50:50:ac: d6:df:4f:b1Congratulations, you have successfully created intermediate CAs (ICA1/ICA2) in Vault rooted in an offline Root CA and have issued a client certificate rooted in intermediate CA(ICA2).
Use the
treecommand on your current folder to display the folder hierarchy.$ tree . ├── cacerts │ └── test_org_v1_ica1_v1.crt ├── csr │ └── Test_Org_v1_ICA1_v1.csr ├── main.tf ├── out │ ├── Intermediate_CA1_v1.crt │ ├── Testing_Root.crl │ ├── Testing_Root.crt │ └── Testing_Root.key ├── terraform.tfstate ├── terraform.tfstate.backup ├── test_org_ica1.tf ├── test_org_ica2.tf └── test_org_ica2_role_test_dot_com.tf 4 directories, 12 files
For production workflow, you can decide to not check in the csr folder as the information under it can be obtained from the Terraform state file.
Clean up
If you wish to clean up your environment after completing the tutorial, follow the steps in this section.
Run Terraform to undo all the changes.
$ terraform apply -destroy -auto-approve ...snip... Apply complete! Resources: 0 added, 0 changed, 8 destroyed.Remove the terraform state files and
.tffiles.$ rm *tfstate* *.tfRemove the
csr,cacerts, andoutdirectories.$ rm -rf csr cacerts outUnset the
VAULT_TOKENenvironment variable.$ unset VAULT_TOKENUnset the
VAULT_ADDRenvironment variable.$ unset VAULT_ADDRYou can stop the Vault dev server by pressing Ctrl+C where the server is running. Or, execute the following command.
$ pgrep -f vault | xargs kill