Ansible OIDC Integration with HashiCorp Vault: Zero Trust Credential Management (Complete Guide)
By Luca Berton · Published 2024-01-01 · Category: installation
Learn how to configure Ansible Automation Platform 2.7 as an OIDC provider for HashiCorp Vault for zero trust security.
Ansible Automation Platform 2.7 introduces native OIDC (OpenID Connect) provider integration with HashiCorp Vault, enabling zero-trust credential management for automation workloads. This Technology Preview feature replaces static service accounts with short-lived, job-specific tokens.
The Problem: Static Credentials
Traditional automation credential management has significant risks:
❌ Static Approach:
┌──────────┐ Static Token ┌──────────────┐
│ Ansible │ ──────────────────► │ HashiCorp │
│ Job │ (never expires) │ Vault │
└──────────┘ └──────────────┘
Problems:
- Token shared across all jobs
- No expiration → leaked tokens work forever
- No job-level audit trail
- Credential sprawl across environments
See also: Ansible AAP as OIDC Authentication Provider for HashiCorp Vault: Zero Trust Workflow
The Solution: OIDC Integration
✅ OIDC Approach (AAP 2.7):
┌──────────┐ 1. Request Token ┌──────────────┐
│ Ansible │ ──────────────────► │ AAP OIDC │
│ Job │ │ Provider │
└────┬─────┘ └──────┬───────┘
│ │
│ 3. Use token │ 2. Short-lived JWT
│ (auto-expires) │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ HashiCorp │ ◄──────────── │ Verify JWT │
│ Vault │ │ │
└──────────────┘ └──────────────┘
How It Works
Ansible job starts → AAP generates a short-lived JWT token unique to this job Token contains claims: job ID, template name, organization, user Vault validates the JWT against AAP's OIDC discovery endpoint Vault issues scoped credentials based on the JWT claims Token expires when the job completes — cannot be reusedSee also: Ansible Automation Platform and HashiCorp Vault: End-to-End Trusted Automation (Integration Guide)
Configuration
Step 1: Configure Vault JWT Auth
# Enable JWT auth method in Vault
vault auth enable jwt
# Configure AAP as the OIDC provider
vault write auth/jwt/config \
oidc_discovery_url="https://aap.example.com/.well-known/openid-configuration" \
bound_issuer="https://aap.example.com"
Step 2: Create Vault Role
# Create a role that maps JWT claims to Vault policies
vault write auth/jwt/role/ansible-automation \
role_type="jwt" \
bound_audiences="vault" \
user_claim="sub" \
policies="ansible-secrets" \
ttl="1h" \
bound_claims_type="glob" \
bound_claims='{"organization":"*","job_template":"*"}'
Step 3: Create Vault Policy
# ansible-secrets.hcl
path "secret/data/ansible/*" {
capabilities = ["read"]
}
path "database/creds/ansible-role" {
capabilities = ["read"]
}
Step 4: Use in Playbook
---
- name: Retrieve secrets with OIDC token
hosts: all
become: true
tasks:
- name: Get database credentials from Vault
community.hashi_vault.vault_read:
url: https://vault.example.com
path: secret/data/ansible/database
auth_method: jwt
jwt: "{{ ansible_oidc_token }}"
role: ansible-automation
register: db_secret
delegate_to: localhost
no_log: true
- name: Configure application
ansible.builtin.template:
src: app-config.j2
dest: /etc/myapp/config.yml
owner: appuser
mode: '0600'
vars:
db_host: "{{ db_secret.data.data.hostname }}"
db_user: "{{ db_secret.data.data.username }}"
db_pass: "{{ db_secret.data.data.password }}"
Security Benefits
| Feature | Static Credentials | OIDC Integration | |---|---|---| | Token lifetime | Permanent | Job-scoped (minutes/hours) | | Credential scope | Broad access | Per-job, per-template | | Audit trail | "service account used" | "job #1234 by user X accessed path Y" | | Rotation needed | Manual/periodic | Automatic (new token per job) | | Leaked credential risk | High (permanent access) | Low (expired token is useless) | | Compliance | Difficult to prove | Built-in zero-trust evidence |
See also: AAP 2.6 Credential Management: Vaults, External Secrets, and Machine Credentials
Advanced: Scoped Access by Job Template
# Vault role for production-only templates
vault write auth/jwt/role/prod-deploy \
bound_claims='{"job_template":"Production*"}' \
policies="production-secrets" \
ttl="30m"
# Vault role for staging
vault write auth/jwt/role/staging-deploy \
bound_claims='{"job_template":"Staging*"}' \
policies="staging-secrets" \
ttl="1h"
FAQ
Do I need to change existing playbooks?
Minimal changes. Replace static Vault token references with {{ ansible_oidc_token }} and set auth_method: jwt in Vault lookups.
What happens if the token expires mid-job?
Set the Vault role TTL longer than your longest job. AAP tokens are scoped to job lifetime — they remain valid until the job completes.
Can I use this with Vault's dynamic secrets?
Yes. This is the ideal use case. Combine OIDC authentication with Vault's dynamic database credentials, AWS STS tokens, or PKI certificates for fully ephemeral access.
Is this compatible with Vault Enterprise and HCP Vault?
Yes. The OIDC/JWT auth method is available in Vault Community, Enterprise, and HCP Vault.
What about non-Vault secret managers?
The OIDC provider is a general-purpose feature. While the initial integration targets HashiCorp Vault, the OIDC tokens can potentially authenticate with any service that supports JWT/OIDC authentication.
Related Articles
• Red Hat Ansible Automation Platform 2.7: What's New • Ansible Vault Complete Guide • Install Ansible Automation Controller on a Single HostCategory: installation