Hello!
Might be a dumb question but is it expected that a destroyed version of a secret is still tagged as the current
version? I would have expected current
to be the non-deleted / non-destroyed latest version of the secret.
Thanks!
Hello!
Might be a dumb question but is it expected that a destroyed version of a secret is still tagged as the current
version? I would have expected current
to be the non-deleted / non-destroyed latest version of the secret.
Thanks!
I noticed this as well, while wrapping the API in an app.
After destroying the latest version of a secret using DELETE /v1/secrets/ the very next GET (and all subsequent) returns the deleted secret version.
The documentation (KV - Secrets Engines - HTTP API | Vault | HashiCorp Developer) states:
This marks the version as deleted and will stop it from being returned from reads, but the underlying data will not be removed
This means when retrieving the latest ‘undeleted’ secret, I first have to call the secret metadata and decrement through the versions listed until I find one that is not deleted, then issue a second API call to retrieve that version.
It seems like a bug.
Here’s the metadata for a secret after creating some versions, then deleting the latest version, showing version 3 as destroyed, but still current.
{
"request_id": "be066955-7793-a45d-992f-c78332194906",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": {
"cas_required": false,
"created_time": "2021-01-04T17:40:17.619668519Z",
"current_version": 3,
"delete_version_after": "0s",
"max_versions": 0,
"oldest_version": 0,
"updated_time": "2021-01-04T17:46:03.003753606Z",
"versions": {
"1": {
"created_time": "2021-01-04T17:40:17.619668519Z",
"deletion_time": "2021-01-04T17:42:03.619784047Z",
"destroyed": false
},
"2": {
"created_time": "2021-01-04T17:45:57.026095923Z",
"deletion_time": "2022-02-03T17:45:57.026095923Z",
"destroyed": false
},
"3": {
"created_time": "2021-01-04T17:46:03.003753606Z",
"deletion_time": "2022-02-03T17:46:03.003753606Z",
"destroyed": true
}
}
},
"wrap_info": null,
"warnings": null,
"auth": null
}
Ever happen to come across a solution to this? Only thing I can think of is to wipe the secret entirely (all versions) and re-create it, or “create new version” of the most recent non-deleted version - effectively make a copy it so that the current version in the metadata pointer will change.
It doesn’t seem to make much sense to me that current version stays pointed at an object that no longer exists.
Hi
can this help you ?
vault kv metadata get -format=json secret/mysecret | jq '.data.versions|to_entries|map(select(.value.destroyed==false).key)|max'
Update: My command gives you the last not destroyed version.
If you need not destroyed and not deleted, add a condition with 'deletion_time==“”
Ended up revisiting this problem. Came up with a solution for Ruby based on the vault gem.
client = Vault::Client.new(address: endpoint.to_s)
kv = client.kv(kv_mount_path)
# Vault is dumb and says the current version is the highest version number,
# regardless of deleted or destroyed status. We will redefine that here to make
# current_version reflect the most recent active version.
#
# @return [Symbol, nil] the most recent version
def current_version(path)
metadata = kv.read_metadata(path)
return nil if metadata.nil?
active_versions = metadata[:versions].select { |_, v| !v[:destroyed] && v[:deletion_time].empty? }
return nil if active_versions.empty?
active_versions.keys.last
end