terraform-provider-vault
terraform-provider-vault copied to clipboard
RFE/pki: provide a way to generate a self-signed root CA
Hey folks, thanks for the hard work!
We're creating an internal PKI using the Vault's PKI engine and we're trying to terraform it using this provider. In our initial POCs we used the /root/generate/internal
HTTP API endpoint to generate a self-signed certificate that automatically gets configured as the mount's CA.
However, it seems that there is no equivalent operation here. If I'm reading the docs correctly the only way to configure a root CA is via vault_pki_secret_backend_config_ca
, but this resource requires a text pem_bundle
.
We don't want to keep the private key in our version control, so this option doesn't really help us much. We also have no on-premises infrastructure, so no local air-gapped system/hardware where we can store the root CA and potentially read this value from the filesystem.
Given that this is an existing functionality at the Vault API itself, I believe it's reasonable that this provider also exposes that behavior. Perhaps by allowing users to reference a vault_pki_secret_backend_root_cert
in vault_pki_secret_backend_config_ca
or something like that.
Sorry if this functionality already exists and I missed it, thanks!
If I'm reading the docs correctly the only way to configure a root CA is via
vault_pki_secret_backend_config_ca
, but this resource requires a textpem_bundle
.
Hi @LCaparelli–I was taking a hard look at this provider for my own internal ca, and I was wondering if you could point me to anything that explicitly says that it's not possible. I ended up just reading the code, and if I understand it correctly, it doesn't seem like the resource definitions support this workflow. Specifically, I think it's disallowed with how the Read
function is defined for the pki_secret_backend_root_cert resource. Initially, I was confused as to why the cli works in the Build Your Own Certificate Authority (CA) scenario but fails with the equivalent terraform after substep 5 of Step 2: Generate Intermediate CA. Shell and terraform equivalents for this section look something like this:
/*
* ### 2.5
* Once the CSR is signed and the root CA returns a certificate, it can be imported back into Vault.
* ```bash
* vault write pki_int/intermediate/set-signed [email protected]
* ```
*/
resource "vault_pki_secret_backend_intermediate_set_signed" "pki_int" {
backend = vault_mount.pki_int.path
certificate = vault_pki_secret_backend_root_sign_intermediate.pki_int.certificate
}
This resource results in the following terraform error:
Error: error creating intermediate set-signed on PKI secret backend "pki_int": Error making API request.
URL: PUT http://127.0.0.1:8200/v1/pki_int/intermediate/set-signed Code: 400. Errors:
- could not find any existing entry with a private key
I'm assuming that this comes back to storing sensitive values in terraform state, which could make this a bit of a footgun for the general case. I wonder if we couldn't do this safely with some additional controls on the stored tfstate.
n.b. A little frustrating that the provider doesn't (can't?) surface the error on the vault_pki_secret_backend_root_sign_intermediate
resource. For this workflow, it wasn't until I queried the audit log to find that the problem was occurring before reaching vault_pki_secret_backend_intermediate_set_signed
:
$ jq '.[] | select(.error != null) | { time: .time, error: .error, path: .request.path}' audit.json | jq -s .
[
{
"time": "2021-05-02T17:15:42.303571Z",
"error": "1 error occurred:\n\t* error fetching CA certificate: stored CA information not able to be parsed\n\n",
"path": "pki/root/sign-intermediate"
},
{
"time": "2021-05-02T17:15:43.521319Z",
"error": "1 error occurred:\n\t* error fetching CA certificate: stored CA information not able to be parsed\n\n",
"path": "pki/root/sign-intermediate"
}
]
Hi @mjburling, I believe one of the problems is that vault_pki_secret_backend_config_ca
(seemingly the only way to configure the CA for a root CA mount, someone please correct me if I'm wrong) is only able to receive the CA key-pair as a string field. It can't point to a vault_pki_secret_backend_root_cert
as this resource does not expose the private key (rightfully so, IMO).
Even if it did, there would still be the problem of sensitive data on the state. With that in mind, I'd prefer a solution with a resource that represents a root CA with a self-signed cert, where the entire key-pair is stored at the vault (and at the vault alone). In this scenario maybe the state file could contain the public cert itself (or its serial), only regenerating if there is currently no CA in the state or if the cert from state differs from the one in the Vault.
Just spitballing here, of course, I'm not familiar with the codebase and am not sure how viable this is.