vault icon indicating copy to clipboard operation
vault copied to clipboard

Proxy: Support chroot_namespace on listener block

Open AdrienneCohea opened this issue 3 months ago • 2 comments

Is your feature request related to a problem? Please describe. As a platform engineer, I want to configure Vault Proxy to authenticate to an Enterprise HCP Vault that is namespaced. I don't want to expose clients such as the cert-manager CSI driver, to the detail of having to know the namespace. I would like Vault Proxy to send all requests with a X-Vault-Namespace comprised of the Vault Proxy namespace possibly combined with a child namespace passed in by the client of the proxy.

Describe the solution you'd like chroot_namespace added to the listener block with the same behavior as described in https://developer.hashicorp.com/vault/docs/configuration/listener/tcp#chroot_namespace

Describe alternatives you've considered Using a Kubernetes pod running a Vault proxy sidecar:

# ps aux
PID   USER     TIME  COMMAND
    1 root      0:01 vault proxy -config=/etc/vault/config

Approaches I tried that didn't work:

Namespace in vault stanza.

listener "tcp" {
  address            = "127.0.0.1:8200"
  tls_disable        = true
}

vault {
  address   = "REDACTED"
  ca_cert   = "/etc/vault/ca.crt"
  namespace = "REDACTED"
}

Namespace in listener stanza

listener "tcp" {
  address            = "127.0.0.1:8200"
  tls_disable        = true
  chroot_namespace   = "REDACTED"
}

vault {
  address   = "REDACTED"
  ca_cert   = "/etc/vault/ca.crt"
}

Explain any additional use-cases In a Vault Proxy chrooted to the given namespace, I would like client HTTP requests whether coming from the Vault CLI, SDK, or custom HTTP client to be mutated such that the X-Vault-Namespace header is added automatically if not present and that the value of the header be the chroot_namespace, and if the header is present, that it's assumed to be a child namespace and therefore the value is mutated by prepending the parent namespace, similar to how chroot_namespace functions.

AdrienneCohea avatar May 10 '24 17:05 AdrienneCohea

This is a cool request, but I wonder if you couldn't get the same effect with both:

This has the disadvantage that you couldn't customize it per-listener, but for a single listener it should get the same result. prepend_configured_namespace is intended to do this kind of thing

VioletHynes avatar May 13 '24 18:05 VioletHynes

@AdrienneCohea just to poke this more so that I understand better: does the prepend_configured_namespace option work for you, or would this be something you'd need to configure on a per-listener basis? Hopefully it does and you just didn't spot the config option 🤞

VioletHynes avatar May 15 '24 15:05 VioletHynes

Hi @VioletHynes, thanks so much for sharing this with me! This sounds like exactly the option I want, and I think I will use it for some of our applications. It doesn't appear to work for cert-manager, but I have a workaround.

I'd like to share with you what didn't work and what I think might be causing the problem. I upgraded my Vault agent to version 1.16.2 with a configuration of

listener "tcp" {
  address                = "127.0.0.1:8200"
  tls_disable            = true
  require_request_header = true
}

vault {
  address   = "https://example.com"
  ca_cert   = "/etc/vault/ca.crt"
  namespace = "example_namespace"
}

api_proxy {
  prepend_configured_namespace = true
}

Then I ran (from inside the Vault container) and got a 404 response:

wget -q --header "X-Vault-Request: true" -O - http://127.0.0.1:8200/v1/sys/health
wget: server returned error: HTTP/1.1 404 Not Found

Then I downgraded back to 1.15 (which doesn't include the prepend feature) and tried again getting the expected response:

wget -q --header "X-Vault-Request: true" -O - http://127.0.0.1:8200/v1/sys/health
wget: server returned error: HTTP/1.1 473 status code 473

I tried the same test with other endpoints, such as sys/leader and sys/seal-status, and I got successful responses on Vault 1.15 and Vault 1.16.2 with the prepend_configured_namespace option.

Is it possible that all requests are getting the namespace prepended even if they are for endpoints restricted to the root namespace?

AdrienneCohea avatar May 15 '24 20:05 AdrienneCohea

Thanks for the response, this is super helpful!

Yeah, that's exactly what's happening. I believe that would be the same using chroot_listener. Unfortunately I can't think of a workaround as of right now (since the setting applies to all requests from all listeners). This is super great to know and all of the detail around the use case really helps for understanding the core of the ask.

Since one advantage of this feature is that it can restrict access to Vault's APIs to only a specific namespace, I don't think we can consider it a bug and 'fix' it by letting some API requests ignore the feature. Being unable to access APIs not from that namespace is a feature of the feature. That being said, there's probably some other approach we could take to enable this kind of workflow (perhaps a new option?).

As you mentioned, supporting a chroot_namespace feature on the listener is one option, so that you could have one listener for one namespace and another for another. I can't promise anything as far as new features or timelines, but I'll bring this up internally and see what we can see.

Glad I could help!

VioletHynes avatar May 15 '24 21:05 VioletHynes

Thanks @VioletHynes. I'll go ahead and close this and open a bug against https://github.com/cert-manager/cert-manager instead. The issue is how they verify Vault Issuers and ClusterIssuers. They call health endpoints, but it would be better if they skipped that and simply issued a certificate and then immediately revoked it. That would allow us to then use the prepend_configured_namespace configuration without any issues.

Thank you so much. :tulip:

AdrienneCohea avatar May 16 '24 21:05 AdrienneCohea