In this post, I will show simple python code snippets to read and write KV secrets in Vault. I’ll use the structure and Vault we created in other posts here.

https://devops-db.com/vault-installation/

https://devops-db.com/jenkins-vault-integration/

For the reading example, the approle we created in the Jenkins integration post would work, but I’m also going to create another approle, with write rights. I will continue using the secret/infrastructure/jenkins structure for the example.

To do this, you need to install the HVAC module: https://pypi.org/project/hvac/

https://github.com/faustobranco/devops-db/blob/master/knowledge-base/python/vault/read_secrets.py

import hvac

VAULT_URL = 'http://vault.devops-db.internal:8200/'
VAULT_ROLE_ID = '2a89c925-62fc-44b7-fed5-d2de5e31cb69'
VAULT_SECRET_ID = 'f01e3323-ff2f-849d-e7a1-49805d2300e0'

client = hvac.Client(url=VAULT_URL)
ret_auth = client.auth.approle.login(VAULT_ROLE_ID, VAULT_SECRET_ID)
return_read_kv_1 = client.read('secret/data/infrastructure/jenkins/test-secret01')
print(return_read_kv_1)
print(return_read_kv_1['data']['data']['username'])
# usr-test01

print(return_read_kv_1['data']['data']['pwd'])
# 1234qwer

mount_point = 'secret'
secret_path = 'infrastructure/jenkins/test-secret01'
return_read_kv_2 = client.secrets.kv.v2.read_secret(path=secret_path, mount_point=mount_point)
print(return_read_kv_2['data']['data']['username'])
# usr-test01

print(return_read_kv_2['data']['data']['pwd'])
# 1234qwer

For the second example, I will create a new approle, with slightly higher permissions, as I don’t want to mix it with the Jenkins approle.

$ vault write auth/approle/role/approle-python-rw token_num_uses=0 secret_id_num_uses=0 policies=python-rw

Success! Data written to: auth/approle/role/approle-python-rw



$ vault read auth/approle/role/approle-python-rw/role-id

Key        Value
---        -----
role_id    20745553-59b8-1499-4698-17489ffa1b18


$ vault write -f auth/approle/role/approle-python-rw/secret-id

Key                   Value
---                   -----
secret_id             ec5de6f2-9c30-ca12-2147-c27103758089
secret_id_accessor    439f124d-7e84-2649-5f2a-68fcc7d19ec3
secret_id_num_uses    0
secret_id_ttl         0s


$ vault policy write python-rw -<<EOF
path "secret/data/infrastructure/jenkins/*" {
  capabilities = ["create", "list", "read", "update"]
}
EOF

Success! Uploaded policy: python-rw

https://github.com/faustobranco/devops-db/blob/master/knowledge-base/python/vault/write_secrets.py

# pip install hvac
# https://pypi.org/project/hvac/


import hvac

VAULT_URL = 'http://vault.devops-db.internal:8200/'
VAULT_ROLE_ID = '20745553-59b8-1499-4698-17489ffa1b18'
VAULT_SECRET_ID = 'ec5de6f2-9c30-ca12-2147-c27103758089'

client = hvac.Client(url=VAULT_URL)
ret_auth = client.auth.approle.login(VAULT_ROLE_ID, VAULT_SECRET_ID)

client.secrets.kv.v2.create_or_update_secret(
    mount_point='secret',
    path='infrastructure/jenkins/test-secret02',
    secret=dict(url='http://devops-db.internal/', token='1234567890qwertyuio'),
)

# {'request_id': '652ec9aa-06b1-734f-4574-0177ef2f8e8b', 'lease_id': '', 'renewable': False, 'lease_duration': 0, 'data': {'created_time': '2025-02-04T13:00:09.900091139Z', 'custom_metadata': None, 'deletion_time': '', 'destroyed': False, 'version': 1}, 'wrap_info': None, 'warnings': None, 'auth': None, 'mount_type': 'kv'}


return_read_kv_1 = client.read('secret/data/infrastructure/jenkins/test-secret02')
print(return_read_kv_1)
print(return_read_kv_1['data']['data']['url'])
# http://devops-db.internal/
 
print(return_read_kv_1['data']['data']['token'])
# 1234567890qwertyuio