Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vault_pki_secret_backend_root_cert resource does not support multiple issuers #1968

Closed
lukestephenson opened this issue Aug 7, 2023 · 4 comments
Assignees
Labels

Comments

@lukestephenson
Copy link

Terraform Version

Using vault terraform provider version 3.18.0. (Docker image is hashicorp/terraform:0.12.31, but this isn't particularly relevant).

Affected Resource(s)

  • vault_pki_secret_backend_root_cert

Terraform Configuration Files

Here is a minimal terraform example which reproduces the issue for us:

resource "vault_mount" "pki" {
  path = local.path
  type = "pki"
}

resource "vault_pki_secret_backend_root_cert" "root-current" {
  depends_on   = [vault_mount.pki]
  backend      = vault_mount.pki.path
  type         = "internal"
  common_name  = "current.root"
  key_bits     = local.pki_ca_key_bits
  ttl          = local.root_cert_ttl
  organization = "root_cert_for_${vault_mount.pki.accessor}"
  issuer_name  = "current"
}

resource "vault_pki_secret_backend_config_urls" "config_urls" {
  backend                 = vault_mount.pki.path
  issuing_certificates    = ["${local.vault_addr}/v1/${vault_mount.pki.path}/ca"]
  crl_distribution_points = ["${local.vault_addr}/v1/${vault_mount.pki.path}/crl"]
}

resource "vault_pki_secret_backend_root_cert" "root-next" {
  depends_on   = [vault_mount.pki]
  backend      = vault_mount.pki.path
  type         = "internal"
  common_name  = "next.root"
  key_bits     = local.pki_ca_key_bits
  ttl          = local.root_cert_ttl
  organization = "root_cert_for_${vault_mount.pki.accessor}"
  issuer_name  = "next"
}

Debug Output

Note that two different issuers are assigned the same ID.

vault_pki_secret_backend_root_cert.root-current: Refreshing state... [id=pki/root/root/generate/internal]
vault_pki_secret_backend_root_cert.root-next: Refreshing state... [id=pki/root/root/generate/internal]

Panic Output

Expected Behavior

Issuers should not only be identified by the path, but also by other fields to guarantee uniqueness. In this case it is possible to have multiple issuers under one path.

Actual Behavior

We are trying to follow the root CA rotation guide, but using terraform rather than the vault commands.

What we have observed is that terraform will initially allow a second issuer to be created, but on subsequent runs of terraform apply, one of the issuers is deleted. Each subsequent run alternates between the two different issuers being created / destroyed.

Relevant code

Looking at the vault terraform implementation, it doesn’t look like this is supported.

For example, the ID of the resource is set using only the path.

Additionally, when deleting the resource, only the path is used.

if _, err := client.Logical().Delete(path); err != nil {

Steps to Reproduce

Please list the steps required to reproduce the issue, for example:

  1. terraform apply * 3

Important Factoids

N/A

References

This issue was first discussed on the forums:

@vinay-gopalan
Copy link
Contributor

Hi @lukestephenson, thanks for raising this issue! Since the Root Cert resource was existent prior to multi-issuer support being added to the TFVP, it was tricky to change the ID behavior and tracking of multiple issuers within the legacy code, which needed to continue supporting the legacy behavior (non-multi-issuer) as well. In order to mitigate this, we decided to add dedicated support for a new PKI Issuer resource. This resource is needed in TF land to accurately keep track of multiple issuers and make updates to them. The idea is that we give TF the appropriate info it needs to now keep track of the issuer created by the Generate Root Cert endpoint.

The individual issuer resources will keep track of extra issuer info, such as the ID. We can track a new issuer within the TF state by using the issuer resource as follows:

resource "vault_pki_secret_backend_root_cert" "root" {
  backend     = vault_mount.pki.path
  type        = "internal"
  common_name = "test"
  ttl         = "86400"
}

resource "vault_pki_secret_backend_issuer" "example" {
  backend     = vault_pki_secret_backend_root_cert.root.backend
  issuer_ref  = vault_pki_secret_backend_root_cert.root.issuer_id
}

Here, the issuer created by the Generate Root Cert endpoint is being tracked by the Issuer resource. Issuer metadata is encoded into the resource ID as well (mount info and issuer ID). We can also update issuer parameters using this resource.

Could you let us know if using this flow to track multiple issuers works for your use-case? If not, we'll be happy to investigate further and open up a bug. Thanks!

@lukestephenson
Copy link
Author

Hi @vinay-gopalan . We tried this approach but didn't have any luck. To be honest, the approach to achieving this with terraform is not very well documented so we may have been trying the wrong thing.

It would be nice if the terraform had more validations to prevent setting up things which are not intended / supported. Here is one of our attempts (we tried a lot of different ways / succeeded with none of them):

locals {
  vault_addr                   = "http://vault:8212"
  path = "pki/root"
  pki_ca_key_bits = 2048
  root_cert_ttl =  "17520h" # 2 years
}

provider "vault" {
  version = "3.18.0"
  token   = "zdi_token"
  address = "http://vault:8212"
}

resource "vault_mount" "pki" {
  path = local.path
  type = "pki"
}

resource "vault_pki_secret_backend_config_urls" "config_urls" {
  backend                 = vault_mount.pki.path
  issuing_certificates    = ["${local.vault_addr}/v1/${vault_mount.pki.path}/ca"]
  crl_distribution_points = ["${local.vault_addr}/v1/${vault_mount.pki.path}/crl"]
}

resource "vault_pki_secret_backend_root_cert" "root-current" {
  depends_on   = [vault_mount.pki]
  backend      = vault_mount.pki.path
  type         = "internal"
  common_name  = "current.root"
  key_bits     = local.pki_ca_key_bits
  ttl          = local.root_cert_ttl
  organization = "root_cert_for_${vault_mount.pki.accessor}"
  issuer_name = "root-current"
}

resource "vault_pki_secret_backend_issuer" "root-current" {
  backend     = vault_pki_secret_backend_root_cert.root-current.backend
  issuer_ref  = vault_pki_secret_backend_root_cert.root-current.issuer_id
  issuer_name = "root-current"
}

resource "vault_pki_secret_backend_root_cert" "root-next" {
  depends_on   = [vault_mount.pki]
  backend      = vault_mount.pki.path
  type         = "internal"
  common_name  = "next.root"
  key_bits     = local.pki_ca_key_bits
  ttl          = local.root_cert_ttl
  organization = "root_cert_for_${vault_mount.pki.accessor}"
  issuer_name = "root-next"
}

resource "vault_pki_secret_backend_issuer" "root-next" {
  backend     = vault_pki_secret_backend_root_cert.root-next.backend
  issuer_ref  = vault_pki_secret_backend_root_cert.root-next.issuer_id
  issuer_name = "root-next"
}

But that had exactly the same problem with the multiple resources ending up in a create / destroy cycle. As it is, we haven't been able to solve this.

@vinay-gopalan
Copy link
Contributor

Hi @lukestephenson, my apologies. You are definitely correct in identifying this as a bug! 🙏🏼 I was able to resolve the issue and have a fix up for it in PR #1973. Along with adding unique IDs for when the multi-issuer API is supported, we also ensured that the CustomizeDiff function that was causing the diff in the TF state was working as expected.

The fix is slated for the upcoming 3.20.0 release. Will keep you posted!

@vinay-gopalan
Copy link
Contributor

Hi, a fix for this issue was released as part of v3.20.0. Going to close this, but please let us know if you face any other problems! 🙏🏼

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants