Skip to content
CloudOps
All prompts
AI for Infrastructure as Code Difficulty: Advanced ClaudeChatGPT

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

  1. Install collection.
  2. Pick auth method matching environment.
  3. Cache short, not long.
  4. 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

Newsletter

Get weekly AI workflows for DevOps engineers

Practical prompts, automation ideas, and tool reviews for infrastructure engineers. One email per week. No spam.