Trouble adding signed certificates to CA

ENV:
hashicorp/vault - v2.23.0 & 2.24.0
hashicorp/tls - v3.1.0
Vault - 1.8.2
terraform - 1.0.7-1.
Server - Linux (Amazon)

Hi One for the brains trust.

I have written a number of Terraform scripts that install and configure a root & intermediate CA server in Vault.
Everything is going well in the configuration, with the exception of writing the certificates back to the CA server.
My code is based on the instructions at

I have exactly what I would like in a dev instance of vault, this was created using the vault CLI.
But I would like a repeatable process in order to be able to do this in multiple environments.
With the Terraform instance of the configuration, I can perform all tasks, including writing the keypairs out to files. The keypairs are matched as confirmed using openssl modulus/md5.

Occasionally, my code works as required, but then as part of my testing I hose the vault instance, reinitialize and rerun, and is not repeatable. The 2 CA’s are created with all roles/groups/policies, but when you go into secrets/CA/Configuration/Configure I am presented with 2 buttons for ‘Configure CA’ and ‘Set signed Intermediate’.
This should instead present me with the options to download CA Certificates in either Pem or Der format and ‘download ca certificate chain’

Unless there is something wrong, it appears that the 2 code blocks for ‘vault_pki_secret_backend_config_ca’ are not working as advertised.

For the CA I create the private key using tls_private_key and sign the ca cert with it.

resource "vault_mount" "root" {
   type = "pki"
   path = "pki-root-ca"
   default_lease_ttl_seconds = 31556952 # 1 years
   max_lease_ttl_seconds = 157680000 # 5 years
   description = "Root Certificate Authority"
 }

 resource "vault_pki_secret_backend_role" "pki_root_r" {
   backend = vault_mount.root.path
   name = "pki_root_r"
   ttl = 3600
   allow_ip_sans = false
   key_type = "rsa"
   key_bits = 4096
   allowed_domains = ["<REDACTED>"]
   allow_subdomains = false
   allow_localhost = false
   allow_bare_domains = false
   allow_any_name = false
   allow_glob_domains = false
   enforce_hostnames = true
   ou = ["${tls_self_signed_cert.ca_cert.subject[0].organizational_unit}"]
   organization = ["${tls_self_signed_cert.ca_cert.subject[0].organization}"]
   country = ["${tls_self_signed_cert.ca_cert.subject[0].country}"]
 }

 resource "vault_mount" "pki_int" {
   path = "pki-intermediate"
   type = "pki"
   description = "This is the intermediate CA"
   default_lease_ttl_seconds = 3600
   max_lease_ttl_seconds = 86400
 }

 # Modify the mount point and set URLs for the issuer and crl.
 resource "vault_pki_secret_backend_config_urls" "config_urls" {
   depends_on = [ vault_mount.root ]  
   backend              = vault_mount.root.path
   issuing_certificates = ["https://<REDACTED>:8300/v1/pki/ca"]
   crl_distribution_points= ["http://<REDACTED>:8300/v1/pki/crl"]
 }
 resource "tls_private_key" "ca_key" {
   algorithm = "RSA"
   rsa_bits = 4096
 }

 resource "tls_self_signed_cert" "ca_cert" {
   private_key_pem = tls_private_key.ca_key.private_key_pem
   key_algorithm = "RSA"
   subject {
     common_name = "<REDACTED> Root CA"
     organization = "<REDACTED>"
     organizational_unit = "<REDACTED>" 
     country = "<REDACTED>"
   }
   # 175200 = 20 years
   validity_period_hours = 175200
   allowed_uses = [
     "cert_signing",
     "crl_signing"
   ]
   is_ca_certificate = true 
 }

I then try to write the keypairs to the root ca

resource "vault_pki_secret_backend_config_ca" "root_ca_config" {
   depends_on = [ vault_mount.root, tls_private_key.ca_key ]  
   backend  = vault_mount.root.path
   pem_bundle = local_file.root_ca_pem_bundle.sensitive_content
 }

I have tried creating the CSR with both internal/exported types no difference.

resource "vault_pki_secret_backend_intermediate_cert_request" "intermediate" {
  depends_on = [ vault_mount.pki_int ] 
  backend = vault_mount.pki_int.path
  type = "internal" #'exported/internal'
  # This appears to be overwritten when the CA signs this cert, I'm not sure 
  # the importance of common_name here.
  common_name = "<REDACTED> Intermediate Certificate"
  format = "pem"
  private_key_format = "der"
  key_type = "rsa"
  key_bits = "4096"
}

resource "vault_pki_secret_backend_root_sign_intermediate" "intermediate" {
  depends_on = [ 
    vault_pki_secret_backend_intermediate_cert_request.intermediate
  ]
  backend = vault_mount.root.path

  csr = vault_pki_secret_backend_intermediate_cert_request.intermediate.csr
  common_name = "<REDACTED> Intermediate Certificate"
  exclude_cn_from_sans = true
  ou = "<REDACTED>"
  organization = "<REDACTED>"
  country = "<REDACTED>"
  # Note that I am asking for 8 years here, since the vault_mount.root has a max_lease_ttl of 5 years
  # this 8 year request is shortened to 5.
  ttl = 252288000 #8 years
}

resource "vault_pki_secret_backend_intermediate_set_signed" "intermediate" { 
backend = vault_mount.pki_int.path
certificate = "${vault_pki_secret_backend_root_sign_intermediate.intermediate.certificate}\n${tls_self_signed_cert.ca_cert.cert_pem}"
}

resource "vault_pki_secret_backend_config_ca" "int_ca_config" {
  depends_on = [ 
    vault_mount.pki_int
  ]  
  backend  = vault_mount.pki_int.path
  #pem_bundle = local_file.ca_int_pem_bundle.sensitive_content
  pem_bundle = "${path.root}/output/int_ca/int_ca_pem_bundle.pem"
}

resource "local_file" "ca_int_pem_bundle" {
  sensitive_content = vault_pki_secret_backend_root_sign_intermediate.intermediate.certificate
  filename = "${path.root}/output/int_ca/int_ca_pem_bundle.pem"
  file_permission = "0777"
}

resource "vault_pki_secret_backend_role" "role-server-cer" {
 backend = vault_mount.pki_int.path
 name = "pki_int_r"
 allowed_domains = [ "<REDACTED>" ]
 allow_subdomains = true
 allow_glob_domains = false
 allow_any_name = false
 enforce_hostnames = true
 allow_ip_sans = true
 server_flag = true
 client_flag = false 
 ou = ["<REDACTED>"]
 organization = ["<REDACTED>"]
 country = ["<REDACTED>"]
 # 2 years
 max_ttl = 63113904 
 # 30 days
 ttl = 2592000
 no_store = true
}

When I upgrade the vault provider to the latest version I get the following error

URL: PUT http://127.0.0.1:8200/v1/pki-root-ca/root/sign-intermediate
│ Code: 500. Errors:
│ 
│ * 1 error occurred:
│       * could not fetch the CA certificate (was one set?): backend must be configured with a CA certificate/key
│ 
│ 
│ 
│   with vault_pki_secret_backend_root_sign_intermediate.intermediate,
│   on ca.tf line 152, in resource "vault_pki_secret_backend_root_sign_intermediate" "intermediate":
│  152:   resource "vault_pki_secret_backend_root_sign_intermediate" "intermediate" {
│

The logs, in debug, don’t show anything in relation to the CA keypairs being added to the vault instance.
There are no firewalls, Selinux is disabled.

1 Like