jopenlibs / vault-java-driver

Zero-dependency Java client for HashiCorp's Vault
https://jopenlibs.github.io/vault-java-driver
26 stars 18 forks source link

[BUG] The sys lease renew endpoint is incorrect resulting in 403 responses #53

Closed andrewflbarnes closed 11 months ago

andrewflbarnes commented 11 months ago

Describe the bug

Given some lease ID, the current implementation of this driver generates a request for the endpoint /v1/sys/leases/renew/<lease ID> and includes only the increment in the body. See Leases.java.

Per Hashicorp's documentation the lease renew API endpoint is v1/sys/leases/renew and the lease ID should be included in the payload under the field lease_id in a JSON object. e.g.

You can similarly confirm this with the CLI e.g.

vault lease renew -output-curl-string <lease ID>

curl \
  -X PUT \
  -H "X-Vault-Request: true" \
  -H "X-Vault-Token: $(vault print token)" \
  -d '{"increment":0,"lease_id":"<lease ID>"}' \
  https://vault:8200/v1/sys/leases/renew

Note: Hashicorp vault uses, and generates, PUTs which appear to work as well as the POSTs described in their own docs.

Looking at hashicorps own vault leases interactions I don't see a point at which the lease ID was expected in the URL:

To Reproduce

Get a renewable lease secret, e.g. something like database/... and attempt to renew the lease ID by calling something equivalent to below.

vault.sys().leases().renew(leaseId, 3600);
Exception in thread "main" io.github.jopenlibs.vault.VaultException: Expecting HTTP status 200, but instead receiving 403
    at io.github.jopenlibs.vault.api.sys.Leases.lambda$renew$3(Leases.java:203)
    at io.github.jopenlibs.vault.api.OperationsBase.retry(OperationsBase.java:31)
    at io.github.jopenlibs.vault.api.OperationsBase.retry(OperationsBase.java:19)
    at io.github.jopenlibs.vault.api.sys.Leases.renew(Leases.java:186)

Corresponding curl commands behave similarly (work with the documented endpoint + payload, 403 with jopenlibs endpoint + payload):

$ curl -X POST -H "X-Vault-Token: $(vault print token)" -H "X-Vault-Request: true" -d '{"increment":0,"lease_id":"<lease ID>"}' https://vault:8200/v1/sys/leases/renew -v | jq
...
< HTTP/2 200
...
{
  "request_id": "...",
  "lease_id": "<lease ID>",
  "renewable": true,
  "lease_duration": 3600,
  ...
}

$ curl -X POST -H "X-Vault-Token: $(vault print token)" -H "X-Vault-Request: true" -d '{"increment":3600}' "https://vault:8200/v1/sys/leases/renew/<lease ID>" -v | jq
...
< HTTP/2 403
...
{
  "errors": [
    "1 error occurred:\n\t* permission denied\n\n"
  ]
}
andrewflbarnes commented 11 months ago

Mistake on my part - this was a limitation of the role policy which allows the use of the deprecated endpoint /sys/renew/... but not the current endpoint /sys/leases/renew/...