Ansible External Secrets (HashiCorp Vault) Prompt
Integrate Ansible with HashiCorp Vault — secret lookup at runtime, AppRole auth, KV v2, dynamic secrets, caching.
- Target user
- Ansible engineers using external secret managers
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT
The prompt
You are a senior security engineer who has integrated Ansible with HashiCorp Vault — AppRole auth from CI, dynamic database credentials, secret rotation. I will provide: - The secret type (static, dynamic, certificate) - Vault server config - Symptom (lookup fails, auth expired, slow) Your job: 1. **HashiCorp Vault basics** (distinct from Ansible Vault): - Centralized secrets management - REST API - Dynamic / static secrets 2. **Ansible integration via `community.hashi_vault`**: - Collection installed - Lookup at task time - Multiple auth methods 3. **For auth methods**: - **Token** — simple, dev/test - **AppRole** — CI/CD pattern; role_id + secret_id - **JWT/OIDC** — modern; GitLab CI provides JWT - **AWS IAM** — for EC2 instances 4. **For KV v2**: - Versioned key-value - Path: `secret/data/<path>` - Different from v1 5. **For dynamic secrets**: - Database credentials generated on demand - Short TTL - Auto-rotation 6. **For PKI**: - Generate certificates on demand - For internal CA 7. **For caching**: - Lookups happen per task; can repeat - `set_fact` to cache for play 8. **For CI/CD integration**: - GitLab JWT → Vault auth - AppRole secret_id from CI variable Mark DESTRUCTIVE: caching dynamic credentials past TTL (expired), exposing Vault token in logs, auth method too permissive. --- Secret type: [DESCRIBE] Vault config: [DESCRIBE] Symptom: [DESCRIBE]
Why this prompt works
External secrets are modern best practice. This prompt walks Vault integration.
How to use it
- Install collection.
- Pick auth method matching environment.
- Cache short, not long.
- Audit Vault logs.
Useful commands
# Install collection
ansible-galaxy collection install community.hashi_vault
# Test lookup
ansible localhost -m debug -a "msg={{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/data/myapp:password url=https://vault.example.com token=$VAULT_TOKEN') }}"
# Set token env
export VAULT_ADDR=https://vault.example.com
export VAULT_TOKEN=$(vault login -method=approle role_id=$ROLE_ID secret_id=$SECRET_ID -format=json | jq -r .auth.client_token)
Patterns
Static secret lookup (token auth)
- hosts: web
vars:
db_password: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/data/db:password url=https://vault.example.com token=' + lookup('env', 'VAULT_TOKEN')) }}"
tasks:
- name: Use secret
template:
src: db.conf.j2
dest: /etc/db.conf
AppRole authentication (CI/CD)
- name: Authenticate to Vault via AppRole
community.hashi_vault.vault_login:
url: https://vault.example.com
auth_method: approle
role_id: "{{ vault_role_id }}"
secret_id: "{{ vault_secret_id }}"
register: vault_auth
- name: Fetch DB password
set_fact:
db_password: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/data/db:password url=https://vault.example.com token=' + vault_auth.login.auth.client_token) }}"
Dynamic DB credentials
- name: Get dynamic DB credentials (15min TTL)
community.hashi_vault.vault_read:
url: https://vault.example.com
token: "{{ vault_token }}"
path: database/creds/readonly-role
register: dynamic_creds
- name: Use credentials
template:
src: db.conf.j2
dest: /etc/db.conf
vars:
db_user: "{{ dynamic_creds.data.data.username }}"
db_password: "{{ dynamic_creds.data.data.password }}"
GitLab CI + Vault (JWT auth)
# .gitlab-ci.yml
ansible-deploy:
variables:
VAULT_ADDR: https://vault.example.com
script:
# GitLab provides $CI_JOB_JWT
- |
VAULT_TOKEN=$(curl -X POST \
-d "{\"jwt\":\"$CI_JOB_JWT\",\"role\":\"ci-deploy\"}" \
$VAULT_ADDR/v1/auth/jwt/login | jq -r .auth.client_token)
export VAULT_TOKEN
- ansible-playbook site.yml
# In playbook
- hosts: all
vars:
db_password: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/data/db:password url=' + lookup('env', 'VAULT_ADDR') + ' token=' + lookup('env', 'VAULT_TOKEN')) }}"
Cache for play
- hosts: web
vars:
db_password: "{{ lookup('community.hashi_vault.hashi_vault', 'secret=secret/data/db:password ...') }}"
pre_tasks:
- name: Cache secret for play
set_fact:
cached_db_password: "{{ db_password }}"
tasks:
# Use cached_db_password in tasks; avoids re-lookup
Common findings this catches
- Lookup slow → cache for play.
- Token expired → refresh; AppRole pattern.
- Wrong path → KV v1 vs v2 (
data/prefix for v2). - Auth method failures → check Vault policies.
- Logs expose secret → use
no_log: true. - Multiple lookups in loop → cache.
- CI JWT issues → audience configuration.
When to escalate
- Vault server scaling — engineering.
- Auth strategy design — security.
- PKI integration — strategic.
Related prompts
-
Ansible CI/CD Lint & Test Pipeline Prompt
Build Ansible CI/CD pipelines — lint, syntax check, Molecule tests, vault validation, deploy stages.
-
Ansible Vault Secrets Management Prompt
Use Ansible Vault — encrypt secrets, vault IDs, multi-vault setups, integration with external secret managers.
-
GitLab CI/CD Pipeline & Access Tokens Security Prompt
Manage and secure GitLab tokens — trigger tokens, project access tokens, group access tokens, $CI_JOB_TOKEN scope, leak detection and rotation.