hvac¶

Header image

HashiCorp Vault API client for Python 2.7/3.x

Travis CI codecov Documentation Status PyPI version Twitter - @python_hvac Gitter chat

Tested against the latest release, HEAD ref, and 3 previous major versions (counting back from the latest release) of Vault. Currently supports Vault v0.10.4 or later.

Installation¶

pip install hvac

If you would like to be able to return parsed HCL data as a Python dict for methods that support it:

pip install "hvac[parser]"

Getting Started¶

Initialize the Client¶

Using TLS:

>>> client = hvac.Client(url='https://localhost:8200')
>>> client.is_authenticated()
True

Using TLS with client-side certificate authentication:

>>> client = hvac.Client(
...     url='https://localhost:8200',
...     token=os.environ['VAULT_TOKEN'],
...     cert=(client_cert_path, client_key_path),
...     verify=server_cert_path,
... )
>>> client.is_authenticated()
True

Using Vault Enterprise namespace:

>>> client = hvac.Client(
...     url='https://localhost:8200',
...     namespace=os.getenv('VAULT_NAMESPACE'),
... )

Using plaintext / HTTP (not recommended for anything other than development work):

>>> client = hvac.Client(url='http://localhost:8200')

Vault Cluster - Initialize and Seal/Unseal¶

>>> client.sys.is_initialized()
False

>>> shares = 5
>>> threshold = 3
>>> result = client.sys.initialize(shares, threshold)
>>> root_token = result['root_token']
>>> keys = result['keys']
>>> client.sys.is_initialized()
True

>>> client.token = root_token

>>> client.sys.is_sealed()
True
>>> # Unseal a Vault cluster with individual keys
>>> unseal_response1 = client.sys.submit_unseal_key(keys[0])
>>> unseal_response2 = client.sys.submit_unseal_key(keys[1])
>>> unseal_response3 = client.sys.submit_unseal_key(keys[2])
>>> client.sys.is_sealed()
False
>>> # Seal a previously unsealed Vault cluster.
>>> client.sys.seal()
<Response [204]>
>>> client.sys.is_sealed()
True

>>> # Unseal with multiple keys until threshold met
>>> unseal_response = client.sys.submit_unseal_keys(keys)

>>> client.sys.is_sealed()
False

Read and write to secrets engines¶

Note

Vault currently defaults the secret/ path to the KV secrets engine version 2 automatically when the Vault server is started in “dev” mode.

Note

Starting with Vault v1.1.0, _no_ KV secrets engine is mounted by default. I.e., outside of dev mode, a KV engine mounted under path secret/ much be explicitly enabled before use.

KV Secrets Engine - Version 2¶

 >>> # Retrieve an authenticated hvac.Client() instance
 >>> client = test_utils.create_client()
 >>>
 >>> # Write a k/v pair under path: secret/foo
 >>> create_response = client.secrets.kv.v2.create_or_update_secret(
 ...     path='foo',
 ...     secret=dict(baz='bar'),
 ... )
 >>>
 >>> # Read the data written under path: secret/foo
 >>> read_response = client.secrets.kv.read_secret_version(path='foo')
 >>> print('Value under path "secret/foo" / key "baz": {val}'.format(
 ...     val=read_response['data']['data']['baz'],
 ... ))
 Value under path "secret/foo" / key "baz": bar
 >>>
 >>> # Delete all metadata/versions for path: secret/foo
 >>> client.secrets.kv.delete_metadata_and_all_versions('foo')
 <Response [204]>

KV Secrets Engine - Version 1¶

Preferred usage:

 >>> create_response = client.secrets.kv.v1.create_or_update_secret('foo', secret=dict(baz='bar'))
 >>> read_response = client.secrets.kv.v1.read_secret('foo')
 >>> print('Value under path "secret/foo" / key "baz": {val}'.format(
 ...     val=read_response['data']['baz'],
 ... ))
 Value under path "secret/foo" / key "baz": bar
 >>> delete_response = client.secrets.kv.v1.delete_secret('foo')

Authentication¶

Basic Token Authentication¶

# Token
>>> client.token = os.environ['VAULT_TOKEN']
>>> client.is_authenticated()
True

LDAP Authentication Example¶

>>> client = hvac.Client(url='https://localhost:8200')
>>> # LDAP, getpass -> user/password, bring in LDAP3 here for teststup?
>>> login_response = client.auth.ldap.login(
...     username=os.environ['LDAP_USERNAME'],
...     password=os.environ['LDAP_PASSWORD'],
... )
>>> client.is_authenticated()
True
>>> print('The client token returned from the LDAP auth method is: {token}'.format(
...     token=login_response['auth']['client_token']
... ))
The client token returned from the LDAP auth method is: ...