Ansible
Learn how to use Hanzo KMS for secret management in Ansible.
You can find the Hanzo KMS Ansible collection on Ansible Galaxy.
This Ansible Hanzo KMS collection includes a variety of Ansible content to help automate the management of Hanzo KMS services. This collection is maintained by the Hanzo KMS team.
Ansible version compatibility
Tested with the Ansible Core >= 2.12.0 versions, and the current development version of Ansible. Ansible Core versions prior to 2.12.0 have not been tested.
Python version compatibility
This collection depends on the Hanzo KMS SDK for Python.
Requires Python 3.7 or greater.
Installing this collection
You can install the Hanzo KMS collection with the Ansible Galaxy CLI:
ansible-galaxy collection install kms.vaultThe python module dependencies are not installed by ansible-galaxy. They can be manually installed using pip:
pip install kmssdkUsing this collection
You can either call modules by their Fully Qualified Collection Name (FQCN), such as kms.vault.read_secrets, or you can call modules by their short name if you list the kms.vault collection in the playbook's collections keyword.
Authentication
The Hanzo KMS Ansible Collection supports Universal Auth, OIDC Auth, LDAP Auth, and Token Auth for authenticating against Hanzo KMS.
Login Module (Recommended)
The recommended approach is to use the login module to authenticate once and reuse the credentials across multiple tasks. This reduces authentication overhead and makes playbooks cleaner. Alternatively, you can still pass credentials directly to each plugin/module if preferred.
- name: Login to Hanzo KMS
kms.vault.login:
url: "https://app.kms.hanzo.ai"
auth_method: universal_auth
universal_auth_client_id: "{{ client_id }}"
universal_auth_client_secret: "{{ client_secret }}"
register: kms_login
- name: Read secrets using cached login
kms.vault.read_secrets:
login_data: "{{ kms_login.login_data }}"
project_id: "{{ project_id }}"
env_slug: "dev"
path: "/"
as_dict: true
register: secrets
- name: Use the secrets
debug:
msg: "Database URL is {{ secrets.secrets.DATABASE_URL }}"Using Universal Auth for authentication is the most straight-forward way to get started with using the Ansible collection.
To use Universal Auth, you need to provide the Client ID and Client Secret of your Hanzo KMS Machine Identity.
- name: Login with Universal Auth
kms.vault.login:
url: "https://app.kms.hanzo.ai"
auth_method: universal_auth
universal_auth_client_id: "<client-id>"
universal_auth_client_secret: "<client-secret>"
register: kms_loginYou can also provide the auth_method, universal_auth_client_id, and universal_auth_client_secret parameters through environment variables:
| Parameter Name | Environment Variable Name |
|---|---|
auth_method | INFISICAL_AUTH_METHOD |
universal_auth_client_id | INFISICAL_UNIVERSAL_AUTH_CLIENT_ID |
universal_auth_client_secret | INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET |
To use OIDC Auth, you'll need to provide the ID of your machine identity, and the OIDC JWT to be used for authentication.
Please note that in order to use OIDC Auth, you must have 1.0.10 or newer of the kmssdk package installed.
- name: Login with OIDC Auth
kms.vault.login:
url: "https://app.kms.hanzo.ai"
auth_method: oidc_auth
identity_id: "<identity-id>"
jwt: "<oidc-jwt>"
register: kms_loginYou can also provide the auth_method, identity_id, and jwt parameters through environment variables:
| Parameter Name | Environment Variable Name |
|---|---|
| auth_method | INFISICAL_AUTH_METHOD |
| identity_id | INFISICAL_IDENTITY_ID |
| jwt | INFISICAL_JWT |
LDAP Auth allows you to authenticate with Hanzo KMS using a machine identity configured with an LDAP directory. You need to provide the identity ID and your LDAP username and password.
Please note that in order to use LDAP Auth, you must have 1.0.16 or newer of the kmssdk package installed.
- name: Login with LDAP Auth
kms.vault.login:
url: "https://app.kms.hanzo.ai"
auth_method: ldap_auth
identity_id: "<identity-id>"
username: "<ldap-username>"
password: "<ldap-password>"
register: kms_loginYou can also provide the auth_method, identity_id, username, and password parameters through environment variables:
| Parameter Name | Environment Variable Name |
|---|---|
| auth_method | INFISICAL_AUTH_METHOD |
| identity_id | INFISICAL_IDENTITY_ID |
| username | INFISICAL_LDAP_USERNAME |
| password | INFISICAL_LDAP_PASSWORD |
Token Auth is the simplest authentication method that allows you to authenticate directly with an access token. This can be either a Machine Identity Token Auth token or a User JWT token.
Please note that in order to use Token Auth, you must have 1.0.13 or newer of the kmssdk package installed.
- name: Login with Token Auth
kms.vault.login:
url: "https://app.kms.hanzo.ai"
auth_method: token_auth
token: "<your-token>"
register: kms_loginYou can also provide the auth_method and token parameters through environment variables:
| Parameter Name | Environment Variable Name |
|---|---|
| auth_method | INFISICAL_AUTH_METHOD |
| token | INFISICAL_TOKEN |
Available Plugins and Modules
Lookup Plugins
kms.vault.login- Authenticate and return reusable login datakms.vault.read_secrets- Read secrets from Hanzo KMS
Modules
Authentication:
kms.vault.login- Authenticate and return reusable login data
Static Secrets:
kms.vault.read_secrets- Read secrets from Hanzo KMSkms.vault.create_secret- Create a new secretkms.vault.update_secret- Update an existing secretkms.vault.delete_secret- Delete a secret
Dynamic Secrets:
kms.vault.create_dynamic_secret- Create a dynamic secret configurationkms.vault.get_dynamic_secret- Get a dynamic secret by namekms.vault.update_dynamic_secret- Update a dynamic secretkms.vault.delete_dynamic_secret- Delete a dynamic secret
Dynamic Secret Leases:
kms.vault.create_dynamic_secret_lease- Create a lease (generates credentials)kms.vault.get_dynamic_secret_lease- Get lease detailskms.vault.renew_dynamic_secret_lease- Renew an existing leasekms.vault.delete_dynamic_secret_lease- Delete/revoke a lease
Examples
Reading Secrets
---
- name: Read secrets from Hanzo KMS
hosts: localhost
gather_facts: false
tasks:
- name: Login to Hanzo KMS
kms.vault.login:
url: "https://app.kms.hanzo.ai"
auth_method: universal_auth
universal_auth_client_id: "{{ lookup('env', 'INFISICAL_CLIENT_ID') }}"
universal_auth_client_secret: "{{ lookup('env', 'INFISICAL_CLIENT_SECRET') }}"
register: kms_login
- name: Read all secrets as dictionary
kms.vault.read_secrets:
login_data: "{{ kms_login.login_data }}"
project_id: "your-project-id"
env_slug: "dev"
path: "/"
as_dict: true
register: secrets
- name: Use the secrets
debug:
msg: "Database: {{ secrets.secrets.DATABASE_URL }}"Reading secrets with full metadata
Use the raw option to retrieve complete secret metadata including version, creation time, tags, and more:
- name: Read all secrets with full metadata
kms.vault.read_secrets:
login_data: "{{ kms_login.login_data }}"
project_id: "your-project-id"
env_slug: "dev"
path: "/"
raw: true
register: raw_secrets
# Returns: [{"id": "...", "secretKey": "HOST", "secretValue": "google.com", "version": 1, "type": "shared", ...}, ...]
- name: Read all secrets with full metadata as dict
kms.vault.read_secrets:
login_data: "{{ kms_login.login_data }}"
project_id: "your-project-id"
env_slug: "dev"
path: "/"
raw: true
as_dict: true
register: raw_secrets_dict
# Returns: {"HOST": {"id": "...", "secretKey": "HOST", "secretValue": "google.com", "version": 1, ...}, ...}Using the Lookup Plugin
The read_secrets lookup plugin allows for inline secret retrieval. Unlike modules that run on target hosts, lookup plugins run on the Ansible controller during playbook parsing. This is useful for retrieving secrets to use in variable definitions:
vars:
read_all_secrets_within_scope: "{{ lookup('kms.vault.read_secrets', universal_auth_client_id='<>', universal_auth_client_secret='<>', project_id='<>', path='/', env_slug='dev', url='https://app.kms.hanzo.ai') }}"
# [{ "key": "HOST", "value": "google.com" }, { "key": "SMTP", "value": "gmail.smtp.edu" }]
read_all_secrets_as_dict: "{{ lookup('kms.vault.read_secrets', as_dict=True, universal_auth_client_id='<>', universal_auth_client_secret='<>', project_id='<>', path='/', env_slug='dev', url='https://app.kms.hanzo.ai') }}"
# { "SECRET_KEY_1": "secret-value-1", "SECRET_KEY_2": "secret-value-2" } -> Can be accessed as secrets.SECRET_KEY_1
read_secret_by_name_within_scope: "{{ lookup('kms.vault.read_secrets', universal_auth_client_id='<>', universal_auth_client_secret='<>', project_id='<>', path='/', env_slug='dev', secret_name='HOST', url='https://app.kms.hanzo.ai') }}"
# { "key": "HOST", "value": "google.com" }Managing Secrets (CRUD)
Create, update, and delete secrets programmatically:
- name: Create a secret
kms.vault.create_secret:
login_data: "{{ kms_login.login_data }}"
project_id: "{{ project_id }}"
env_slug: "dev"
path: "/"
secret_name: "API_KEY"
secret_value: "my-api-key"
secret_comment: "API key for external service"
register: created_secret
- name: Update a secret
kms.vault.update_secret:
login_data: "{{ kms_login.login_data }}"
project_id: "{{ project_id }}"
env_slug: "dev"
path: "/"
secret_name: "API_KEY"
secret_value: "new-api-key"
register: updated_secret
- name: Rename a secret
kms.vault.update_secret:
login_data: "{{ kms_login.login_data }}"
project_id: "{{ project_id }}"
env_slug: "dev"
path: "/"
secret_name: "OLD_SECRET_NAME"
new_secret_name: "NEW_SECRET_NAME"
register: renamed_secret
- name: Delete a secret
kms.vault.delete_secret:
login_data: "{{ kms_login.login_data }}"
project_id: "{{ project_id }}"
env_slug: "dev"
path: "/"
secret_name: "API_KEY"
register: deleted_secretDynamic Secrets
Dynamic secrets generate credentials on-demand with automatic expiration. They support various providers like SQL databases, AWS, GCP, Azure, and more. For the full list of supported providers and their configuration options, see the Dynamic Secrets documentation.
Creating a Dynamic Secret
# Create a dynamic secret for PostgreSQL
- name: Create a PostgreSQL dynamic secret
kms.vault.create_dynamic_secret:
login_data: "{{ kms_login.login_data }}"
project_slug: "my-project"
env_slug: "dev"
path: "/"
name: "postgres-dev"
provider_type: "sql-database"
inputs:
client: "postgres"
host: "localhost"
port: 5432
database: "mydb"
username: "admin"
password: "admin-password"
creationStatement: "CREATE USER \"{{username}}\" WITH PASSWORD '{{password}}';"
revocationStatement: "DROP USER \"{{username}}\";"
default_ttl: "1h"
max_ttl: "24h"
register: dynamic_secretFor the full list of supported provider types and their input configurations, see the Dynamic Secrets API Documentation.
Getting and Using Dynamic Secret Credentials
To use a dynamic secret, you need to create a lease which generates the actual credentials:
# Create a lease to get database credentials
- name: Get database credentials
kms.vault.create_dynamic_secret_lease:
login_data: "{{ kms_login.login_data }}"
project_slug: "my-project"
env_slug: "dev"
path: "/"
dynamic_secret_name: "postgres-dev"
ttl: "30m"
register: lease
# Use the generated credentials
- name: Connect to database
community.postgresql.postgresql_query:
login_host: localhost
login_user: "{{ lease.data.DB_USERNAME }}"
login_password: "{{ lease.data.DB_PASSWORD }}"
db: mydb
query: "SELECT version();"Managing Leases
# Get lease details
- name: Get lease information
kms.vault.get_dynamic_secret_lease:
login_data: "{{ kms_login.login_data }}"
project_slug: "my-project"
env_slug: "dev"
path: "/"
lease_id: "{{ lease.lease.id }}"
register: lease_details
# Renew a lease before it expires
- name: Renew a lease for 2 more hours
kms.vault.renew_dynamic_secret_lease:
login_data: "{{ kms_login.login_data }}"
project_slug: "my-project"
env_slug: "dev"
path: "/"
lease_id: "{{ lease.lease.id }}"
ttl: "2h"
register: renewed_lease
# Revoke the credentials when done
- name: Delete the lease
kms.vault.delete_dynamic_secret_lease:
login_data: "{{ kms_login.login_data }}"
project_slug: "my-project"
env_slug: "dev"
path: "/"
lease_id: "{{ lease.lease.id }}"Updating and Deleting Dynamic Secrets
# Update a dynamic secret's TTL
- name: Update dynamic secret TTL
kms.vault.update_dynamic_secret:
login_data: "{{ kms_login.login_data }}"
project_slug: "my-project"
env_slug: "dev"
path: "/"
name: "postgres-dev"
default_ttl: "2h"
max_ttl: "48h"
register: updated_secret
# Delete a dynamic secret (also revokes all active leases)
- name: Delete a dynamic secret
kms.vault.delete_dynamic_secret:
login_data: "{{ kms_login.login_data }}"
project_slug: "my-project"
env_slug: "dev"
path: "/"
name: "postgres-dev"
register: deleted_secretTroubleshoot
If you get this Python error when you running the lookup plugin:
objc[72832]: +[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
Fatal Python error: AbortedYou will need to add this to your shell environment or ansible wrapper script:
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YESHow is this guide?
Last updated on