Bootstrap FreeKB - Hashicorp Vault - Restore prior version of a secret using Python hvac
Hashicorp Vault - Restore prior version of a secret using Python hvac

Updated:   |  Hashicorp Vault articles

This assumes you are familiar with the Python hvac client. If not, check out my article Hashicorp Vault - Getting Started with Python hvac.

This assumes the following has already been done.

Let's say the secrets engine has been enabled with -path=secret/

~]# vault secrets enable -path=secret/ kv
Success! Enabled the kv secrets engine at: secret/

 

And let's say approle has been enabled and there is a role named "my-role" and contains a policy named "my-policy".

~]$ vault read auth/approle/role/my-role
Key                        Value
---                        -----
policies                   [my-policy]

 

In this example, since the secrets engine has been enabled with -path=secret/ the policy path will need to begin with secret/

Let's say "my-policy" permits the following capabilities to "secret/my_path/*".

~]$ vault policy read my-policy
path "secret/my_path/*" {
  capabilities = ["create", "delete", "list", "patch", "read", "update"]
}

 

In this scenario, you would first use approle login with the role ID and secret ID for my-role.

  • mount_path='my_path' is used here since my-policy has secret/my_path/*
  • path='' is used to list all of the secrets in secret/my_path/

Check out my article Hashicorp Vault - Error Handling using Python hvac for details on how to include Error Handling

Let's say you want to be able to restore a prior version of a secret. So first and foremost, it's important to understand the different requests that will create a new version of a secret.

  • When you create a new secret, current_version will be 1
  • When you update a secret, current_version will be incremented by 1

This can be seen with the read_secret_metadata.

#!/usr/bin/python3
import hvac

client = hvac.Client(url='http://vault.example.com:8200')

client.auth.approle.login(
  role_id="b4a68549-1464-7aac-b0cd-d22954985aa8",
  secret_id="6039e2e2-6017-8db9-2e1b-dd6bd449f901"
)

response = client.secrets.kv.v2.read_secret_metadata(
  mount_point='my_path',
  path=''
)

print(f"response = {response}")

client.logout()

 

Something like this should be returned. Notice in this example version 2 is the current_version.

{
  'request_id': '34f2cb66-853e-d69a-6232-b2019b139c38',
  'lease_id': '',
  'renewable': False,
  'lease_duration': 0,
  'data': {
    'cas_required': False,
    'created_time': '2024-03-21T08:31:48.115790111Z',
    'current_version': 2,
    'custom_metadata': None,
    'delete_version_after': '0s',
    'max_versions': 0,
    'oldest_version': 0,
    'updated_time': '2024-06-04T04:58:20.451509858Z',
    'versions': {
      '1': {
        'created_time': '2024-01-21T08:31:48.115790111Z',
        'deletion_time': '2024-02-21T08:34:32.936446412Z',
        'destroyed': True},
      '2': {
        'created_time': '2024-03-21T08:31:48.115790111Z',
        'deletion_time': '',
        'destroyed': False}
      }
    },
   'wrap_info': None,
   'warnings': None,
   'auth': None,
   'mount_type': 'kv'
}

 

Best I can tell, there is no way to modify or update or change current_version, which presents a challenge. Let's say you have two versions of a secret.

  • version 1
  • version 2 (current_version)

And you want to go back to version 1. Unfortunately, since you cannot modify current_version, there is no way to set current_version to 1. So, what to do?

Notice in this example that version 1 has a deletion_time whereas version 2 does not. So a workaround I came up with is to use deletion_time as my way of identifying the "current" secret.

  • The version that does NOT have a deletion_time is the "current" version
  • All other versions must be deleted so that they have a deletion_time

It's important to then recognize that 

 

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter fe378c in the box below so that we can be sure you are a human.