-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Documentation or implementation bug? KV2 API docs has wrong method for create/update #6195
Comments
Vault doesn't make a distinction between PUT and POST. |
Any ideas on why one fails and the other succeeds? It's been duplicated by another party. The only other difference, besides headers which I'd suspect are inconsequential, are the body - but the body also conforms to the API. |
Yes, the difference is one is writing data formatted for a KVv1 mount and the other is writing data formatted for a KVv2 mount. Note the difference in the data formatting. Closing this as it appears to be an hvac issue. |
But it's a KV2 mount, and the documentation for Create/Update Secret for KV2 states hvac's data formatting, not Vault's.
|
I honestly am not sure, but:
PUT and POST work exactly the same, and they're using data/options format for my KVv2 endpoint. The CLI My sneaking suspicion is that you are not talking to the same Vault server in all cases. Or, that the Vault server you're talking to via the CLI (perhaps due to a VAULT_ADDR setting) is quite old and only supports KVv1 despite version 2 being set in the options map. (To put it another way, you can set the value in the options map even if the current version of Vault doesn't actually support it.) |
Hrm. I'll spin up a fresh instance sometime over the weekend and see if that's the case re: tainted env, but I was pretty careful to perform both against the same server unless I'm somehow running one server on 127.0.0.1:8200 and a totally different one on localhost:8200, as per the headers in the snippets. Vault server and client are both 1.0.1 and I hadn't installed it prior, so I know it's not a version mismatch. Even more confounding is I get a permission denied in hvac but not Vault when writing to the same destination with the same token. ¯_(ツ)_/¯ What happens if Vault can't hit the /v1/sys/internal/ui/mounts preflight? Does it fall back to KV1? (Though I don't think that's it either, because that token also had the default policy enabled and I didn't see a 40x for the path in the packet dump.) |
Apologies for the delay. I've confirmed this with a fresh install of 1.0.1 server and client. The documentation as per here is indeed incorrect. Sorry to be a stick in the mud, but it really is. Below is reproducible (minus exact token strings etc., of course), extensive evidence. SetupServerConfig/var/tmp/testserver.hcl:
Policy/var/tmp/pol.json: {
"path": {
"secret/data/foo/bar/*": {
"capabilities": [
"create",
"read",
"update",
"delete",
"list"
],
"required_parameters": [
"a",
"b"
],
"allowed_parameters": {
"a": [],
"b": [],
"c": []
}
},
"secret/data/foo/baz/*": {
"capabilities": [
"create",
"read",
"update",
"delete",
"list"
],
"required_parameters": [
"a",
"b"
],
"allowed_parameters": {
"a": [],
"b": [],
"c": []
}
}
}
} Invocationexport VAULT_ADDR='http://127.0.0.1:8200' # unnecessary since it's in the config, but what the hey.
vault server -config=/var/tmp/testserver.hcl
(... separate terminal ...)
export VAULT_ADDR='http://127.0.0.1:8200'
vault operator init -key-shares=1 -key-threshold=1 Then yields: Unseal Key 1: UTkBO1/tWiKWnEeMHpKr+lrHpbD1k07bdGyIzXydZGI=
Initial Root Token: s.5r5tmoobrdh1dGAUeQuMy4wa
Vault initialized with 1 key shares and a key threshold of 1. Please securely
distribute the key shares printed above. When the Vault is re-sealed,
restarted, or stopped, you must supply at least 1 of these keys to unseal it
before it can start servicing requests.
Vault does not store the generated master key. Without at least 1 key to
reconstruct the master key, Vault will remain permanently sealed!
It is possible to generate new unseal keys, provided you have a quorum of
existing unseal keys shares. See "vault operator rekey" for more information. Continuing... export VAULT_TOKEN='s.5r5tmoobrdh1dGAUeQuMy4wa'
vault operator unseal
(...)
vault secrets enable -version=2 -path=foo/bar kv
vault secrets enable -version=2 -path=foo/baz kv
vault policy write poc /var/tmp/pol.json Clientvault token create -policy=poc Yields: Key Value
--- -----
token s.1OhMEqUC0f6AxmlVdsKBqR5L
token_accessor 6fIqJ1cQtU6oSaFl75d646pc
token_duration 768h
token_renewable true
token_policies ["default" "poc"]
identity_policies []
policies ["default" "poc"] Continuing... Vaultexport VAULT_TOKEN='s.1OhMEqUC0f6AxmlVdsKBqR5L' hvacimport hvac
client = hvac.Client('http://127.0.0.1:8200', token = 's.1OhMEqUC0f6AxmlVdsKBqR5L') TestingVaultvault kv put secret/data/foo/bar/baz a=1 b=2 c=3 Yields: Success! Data written to: secret/data/foo/bar/baz And per a packet capture:
hvacclient.secrets.kv.v2.create_or_update_secret('foo/bar/baz', secret = {'a': 4, 'b': 5, 'c': 6}) Yields: Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/[REDACTED]/.local/lib/python3.7/site-packages/hvac/api/secrets_engines/kv_v2.py", line 122, in create_or_update_secret
json=params,
File "/home/[REDACTED]/.local/lib/python3.7/site-packages/hvac/adapters.py", line 106, in post
return self.request('post', url, **kwargs)
File "/home/[REDACTED]/.local/lib/python3.7/site-packages/hvac/adapters.py", line 276, in request
utils.raise_for_error(response.status_code, text, errors=errors)
File "/home/[REDACTED]/.local/lib/python3.7/site-packages/hvac/utils.py", line 33, in raise_for_error
raise exceptions.Forbidden(message, errors=errors)
hvac.exceptions.Forbidden: 1 error occurred:
* permission denied And per a packet capture:
Nothing new here. Probably the data format, sure. But please, for goodness' sake, look at what your documentation says for KV2 API data format:
As I stated before, the Vault client's format does not conform to the API and passes. hvac does conform to the API documentation (again, for KV2) and fails with a permission denied. This is even reproducible with curl, replicating the example straight from the docs - the only differences being the actual keys/values and policy: payload.json: {
"options": {
"cas": 0
},
"data": {
"a": "4",
"b": "5",
"c": "6"
}
} curl --header "X-Vault-Token: s.1OhMEqUC0f6AxmlVdsKBqR5L" --request POST --data @payload.json http://127.0.0.1:8200/v1/secret/data/foo/bar/baz Yields:
With a root token, this succeeds:
Which normally would indicate a policy issue except as shown above, the default policy is also applied and the Vault client itself, using the same non-root token (with, obviously, the same policy) succeeds in writing. Of course, the result is not what one would expect: export VAULT_TOKEN='s.5r5tmoobrdh1dGAUeQuMy4wa'
vault kv get -version=2 secret/data/foo/bar/baz Yields:
Again, using the same data format as the KV2 docs. When the format used with the Vault client, which is not the format used in the docs for KV2, it of course succeeds (and even with a non-root token): payload.json: {
"a": "7",
"b": "8",
"c": "9"
} curl -v --header "X-Vault-Token: s.1OhMEqUC0f6AxmlVdsKBqR5L" --request POST --data @payload.json http://127.0.0.1:8200/v1/secret/data/foo/bar/baz
And yields the proper key/value pairs: == Data ==
Key Value
--- -----
a 7
b 8
c 9 Please fix the API documentation for KV2. |
Your packet capture confirms that you are writing to a version 1 mount with the client:
Note this in the output: Note also the mount:
But in HVAC you're accessing secret/data/foo/bar. That's a different, version 1 mount. |
Please review the documentation as per links above. The documentation for KV2 API is giving the KV1 data format. Edit: Are specified
|
No, paths are rooted at That documentation is referencing the API path, not the mount path. |
I see. So the documentation assumes the default -dev server, then. |
Yep, this is on me then. I offer my sincere apologies. I'd like to humbly suggest some clarification of the above in the docs, ideally some sort of clarification via stand-in representations (i.e. |
Describe the bug
(X-REF: hvac/hvac#389)
When using the Vault CLI client, KV2 secrets are correctly written (and read, etc.). However, this does not represent the documentation. When debugging what I thought was an hvac bug, I discovered that hvac conforms to the API docs' request method (
POST
) - but the Vault client does not (PUT
). e.g.hvac:
Vault:
Docs:
As a result, the API-compliant call fails with a permission error (as according to a policy), etc.
To Reproduce
See above (docs fix?).
Expected behavior
The given method in API docs works.
Environment:
The text was updated successfully, but these errors were encountered: