I am working on a Python sample code for the first time. This is about how to retrieve secrets from Hashicorp Vault secrets manager API; hvac.client.secrets.kv.v2
, my code is as follows:
# 1. Setup client by the url of the custom vault instance.
# if null defualts points to a localhost instance (host='localhost', port=port)
client = Client(url = vault_url)
# Note: The instance is being managed by Hasicorp, and python hvac implementation by default builds the URL appending and prepending the following '/v1/auth/' +CUSTOM_AUTH_PATH+ '/login' to the given url, so
# for the login I used custom login with application credentials
# 2. Preparing json params
params = {
'client_id': vault_user_id,
'client_secret': vault_token_id,
'grant_type' : vault_login_type,
'audience': vault_audience
}
# 3. Login to retrieve the token
result = client.login(url=vault_path,use_token=False,json=params)
As next step I am trying to retrieve the secrets
client.secrets.kv.v2.read_secret_version(path=vault_secret_name, version="1",mount_point='secret'))
This is a very simple step, but it raises an error code I can't find on the web:
InvalidPath: {"code":5,"message":"Not Found","details":[]}, on get
It seems like the URL I am giving is not the right one, because the secret path I am requesting is not available, then after reviewing it, it seems correct:
https://api.cloud.hashicorp.com/secrets/.../v1/secret/data/vault_secret_name
I also reviewed the client object properties, and corrected them as follows
client.token = result ['access_token']
client.url = vault_secret_engine_url
Then I tried curl - it and it works, without raising any error. I think it is an easy implementation, that must be working fine, but it doesn't. I hope my explanation is understandable, letting you know the required details to find a solution.
This works for me, at least.
To retrieve the secrets, hvac provides a client object composed of an adapter object containing the current session. The request method is then present as a public method on any of the given objects. However, the first two objects, Client and Adapter, raise an error. Client raises it by default, and Adapter raises it because it is formatting the URL and adding some extra data to the path.
To avoid this error, I implemented the session object directly from inside hvac.Client.Adapter, providing the custom format required for my case, as shown below:
# 1. Fill the empty objects in the adapter to execute the request with a custom URL.
client.adapter.ignore_exceptions=False # turn it to false to skip throwing the exception
client.adapter.token=result ['access_token'] # filling the token retrieved previuosly
client.adapter.base_uri= vault_secret_engine_url # filling the url
# 2.Format the header as required.
request_header_token={"Authorization": "Bearer {token}".format(token=client.adapter.token)}
# 3. Implementing the request by the session object.
secret_response1=client.adapter.session.request(method="GET",
url=client.adapter.base_uri,
headers=request_header_token,
allow_redirects=client.adapter.allow_redirects)
# 4. Retrieving the secret
print (secret_response1.json().get("secrets")[0]["static_version"]["value"])