Ansible Vault para Gestión de Secretos
Ansible Vault is a feature for encrypting sensitive data in Ansible playbooks, variable files, and inventories. Using Vault, you can safely store passwords, API keys, certificates, and other secrets in version control without exposing them in plain text. This guide covers encrypting files and strings, vault ID management, password files, CI/CD integration, and security best practices.
Tabla de Contenidos
- Ansible Vault Overview
- Encrypting Files
- Encrypting Strings
- Vault IDs for Multiple Keys
- Password Files
- Using Encrypted Data
- Re-keying and Rotation
- CI/CD Integration
- Best Practices
- Conclusion
Descripción General de Ansible Vault
Ansible Vault encrypts sensitive data using AES256 encryption, enabling secure storage of secrets in version control. Vault-protected data is indistinguishable from regular data during playbook execution, seamlessly integrating encrypted values into automation workflows.
Key features:
- AES256 Encryption: Military-grade encryption for sensitive data
- File Encryption: Encrypt entire variable files or data bags
- String Encryption: Encrypt specific variable values
- Multiple Keys: Use different keys for different environments
- CI/CD Compatible: Provide passwords securely in automated environments
- Transparent Usage: Encrypted data works like plain text in playbooks
Vault workflow:
┌──────────────────────┐
│ Plaintext Secret │
│ (password: secret) │
└──────────┬───────────┘
│ ansible-vault encrypt
▼
┌──────────────────────┐
│ Encrypted File │
│ (AES256) │
└──────────┬───────────┘
│ version control
▼
┌──────────────────────┐
│ Git Repository │
│ (Safe to commit) │
└──────────┬───────────┘
│ ansible-playbook --ask-vault-pass
▼
┌──────────────────────┐
│ Decrypted at Runtime│
│ (In memory only) │
└──────────────────────┘
Cifrando Archivos
Encrypt entire files containing sensitive data.
Create and encrypt file:
# Create plaintext file with secrets
cat > group_vars/databases/vault.yml << 'EOF'
db_password: SuperSecurePassword123!
db_user: admin
api_key: sk-1234567890abcdef
ssl_certificate: |
-----BEGIN CERTIFICATE-----
MIIEpAIBAAKCAQEA1234...
-----END CERTIFICATE-----
EOF
# Encrypt the file
ansible-vault encrypt group_vars/databases/vault.yml
# Verify encryption
cat group_vars/databases/vault.yml
# $ANSIBLE_VAULT;1.1;AES256
# 66386d...
# Enter vault password when prompted
# Vault password: [your secure password]
# Encryption successful
View encrypted file:
# View without decrypting
ansible-vault view group_vars/databases/vault.yml
# Edit encrypted file
ansible-vault edit group_vars/databases/vault.yml
# Re-encrypt with new password
ansible-vault rekey group_vars/databases/vault.yml
# Decrypt file (convert to plaintext)
ansible-vault decrypt group_vars/databases/vault.yml
Encrypt existing variables file:
# Encrypt file in place
ansible-vault encrypt group_vars/prod.yml
# Or create new encrypted file
cat > group_vars/production/secrets.yml << 'EOF'
# Add sensitive data
EOF
ansible-vault encrypt group_vars/production/secrets.yml
Create new encrypted file directly:
# Create and encrypt in one command
ansible-vault create group_vars/webservers/vault.yml
# Editor opens for entering content
# Type sensitive data, save and exit
# File automatically encrypted
Cifrando Cadenas
Encrypt individual string values without encrypting entire files.
Encrypt string:
# Encrypt a single value
ansible-vault encrypt_string
# Enter string: supersecretpassword
# Encryption successful!
# !vault |
# $ANSIBLE_VAULT;1.1;AES256
# 66386d6f6...
# Or encrypt string directly
ansible-vault encrypt_string 'my-api-key' --name 'api_key'
# Output:
# api_key: !vault |
# $ANSIBLE_VAULT;1.1;AES256
# 62373461...
Use encrypted strings in variables:
# group_vars/webservers/vars.yml
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
66386d6f6e6179706f74617469616e0a636f6d6d75746174697665209c6e2f68621f
6e63727076703934613433636161363833653065393162310a6365633964303736
3665366663316361366464623331333539343838643232650a
api_token: !vault |
$ANSIBLE_VAULT;1.1;AES256
31323334353637383930616263646566...
# Plain text values mixed with encrypted ones
server_name: webserver-01
encrypted_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
...
Encrypt string with specific name:
# Encrypt and name variable
ansible-vault encrypt_string 'database_password' \
--name 'db_pass'
# Use in playbook
tasks:
- name: Connect to database
mysql_db:
name: mydb
login_password: "{{ db_pass }}"
IDs de Bóveda para Múltiples Claves
Use different Vault IDs to manage multiple encryption keys for different environments.
Create multiple vault files:
# Create vault ID files
ansible-vault create --vault-id dev@prompt group_vars/dev/vault.yml
ansible-vault create --vault-id prod@prompt group_vars/prod/vault.yml
ansible-vault create --vault-id staging@prompt group_vars/staging/vault.yml
# When prompted, enter different passwords for each environment
# Vault password (dev@prompt): [dev-password]
# Vault password (prod@prompt): [prod-password]
# Vault password (staging@prompt): [staging-password]
Use vault ID in playbooks:
# Encrypt file with specific vault ID
ansible-vault encrypt \
--vault-id dev@prompt \
group_vars/dev/secrets.yml
# Run playbook with multiple vault IDs
ansible-playbook site.yml \
--vault-id dev@prompt \
--vault-id prod@prompt \
-i inventory/all
# Specify hosts for specific environment
ansible-playbook site.yml \
--vault-id dev@prompt \
-i inventory/dev
Password files for vault IDs:
# Create password files
echo "dev-vault-password" > ~/.vault_dev
echo "prod-vault-password" > ~/.vault_prod
chmod 600 ~/.vault_dev ~/.vault_prod
# Use with vault IDs
ansible-vault encrypt \
--vault-id dev@~/.vault_dev \
group_vars/dev/secrets.yml
ansible-playbook site.yml \
--vault-id dev@~/.vault_dev \
--vault-id prod@~/.vault_prod
Archivos de Contraseña
Store vault passwords securely for automation.
Create password file:
# Create password file
echo "my-vault-password" > ~/.ansible/vault_password
# Set restrictive permissions
chmod 600 ~/.ansible/vault_password
# Configure in ansible.cfg
cat >> ansible.cfg << 'EOF'
[defaults]
vault_password_file = ~/.ansible/vault_password
EOF
External password script:
# Create password script
cat > ~/.ansible/vault_pass.sh << 'EOF'
#!/bin/bash
# Retrieve password from secure storage
pass show ansible/vault_password
EOF
chmod +x ~/.ansible/vault_pass.sh
# Configure in ansible.cfg
cat >> ansible.cfg << 'EOF'
[defaults]
vault_password_file = ~/.ansible/vault_pass.sh
EOF
Ansible.cfg configuration:
# ansible.cfg
[defaults]
# Path to vault password file
vault_password_file = ~/.ansible/vault_password
# Or use multiple password files
vault_identity_list = dev@~/.vault_dev, prod@~/.vault_prod
# Encrypt new files with default vault ID
vault_identity = default@~/.vault_password
Usando Datos Cifrados
Use encrypted data transparently in playbooks.
Load encrypted variables:
# playbook.yml
---
- hosts: all
vars_files:
- group_vars/all/vault.yml
- group_vars/{{ inventory_hostname }}/vault.yml
tasks:
- name: Use encrypted variable
debug:
msg: "Database password: {{ db_password }}"
# Vault automatically decrypts at runtime
Run with vault password:
# Prompt for password
ansible-playbook site.yml --ask-vault-pass
# Use password file
ansible-playbook site.yml --vault-password-file ~/.vault_password
# Use vault ID
ansible-playbook site.yml --vault-id dev@prompt
# Specify password directly (not recommended)
ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_password ansible-playbook site.yml
Mixed encrypted and plain text:
# group_vars/webservers.yml
# Plain text
server_name: webserver-01
environment: production
# Encrypted values
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
66386d6f6e...
api_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
31323334...
# Ansible decrypts only encrypted values
Access in templates:
# nginx.conf.j2
upstream backend {
server {{ app_server }}:{{ app_port }};
}
{% if use_auth %}
auth_basic "Restricted";
auth_basic_user_file {{ htpasswd_file }};
# Password variable {{ db_password }} also available
{% endif %}
Re-cifrado y Rotación
Change vault passwords and rotate encryption keys.
Change vault password:
# Rekey file with new password
ansible-vault rekey group_vars/prod/vault.yml
# Old vault password: [enter old password]
# New vault password: [enter new password]
# Confirm new vault password: [confirm]
# Rekey successful
# Rekey with specific vault ID
ansible-vault rekey \
--vault-id prod@prompt \
--new-vault-id prod@prompt \
group_vars/prod/vault.yml
Rotate all vault files:
#!/bin/bash
# rotate-vault-passwords.sh
# Find all encrypted files
for file in $(find . -type f -name '*.yml' -o -name '*.yaml'); do
if head -1 "$file" | grep -q "ANSIBLE_VAULT"; then
echo "Re-keying $file"
ansible-vault rekey --vault-id old@prompt --new-vault-id new@prompt "$file"
fi
done
echo "Password rotation complete"
Decrypt for password rotation:
# Temporarily decrypt, update password, re-encrypt
ansible-vault decrypt group_vars/prod/vault.yml
# Edit file with new values
ansible-vault encrypt group_vars/prod/vault.yml
Integración con CI/CD
Integrate Vault with CI/CD pipelines securely.
GitHub Actions:
# .github/workflows/deploy.yml
name: Deploy with Ansible
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Ansible
run: pip install ansible
- name: Run playbook
env:
VAULT_PASSWORD: ${{ secrets.ANSIBLE_VAULT_PASSWORD }}
run: |
echo "$VAULT_PASSWORD" > /tmp/vault_password
chmod 600 /tmp/vault_password
ansible-playbook site.yml \
--vault-password-file /tmp/vault_password \
--inventory inventory/production
# Clean up
shred -vfz /tmp/vault_password
GitLab CI:
# .gitlab-ci.yml
deploy:
image: ubuntu:20.04
variables:
ANSIBLE_HOST_KEY_CHECKING: "False"
script:
- apt-get update && apt-get install -y ansible
- echo "$VAULT_PASSWORD" > /tmp/vault_pass
- chmod 600 /tmp/vault_pass
- ansible-playbook site.yml
--vault-password-file /tmp/vault_pass
--inventory inventory/production
- shred -vfz /tmp/vault_pass
only:
- main
Jenkins:
// Jenkinsfile
pipeline {
agent any
environment {
VAULT_PASSWORD = credentials('ansible-vault-password')
}
stages {
stage('Deploy') {
steps {
sh '''
echo "$VAULT_PASSWORD" > /tmp/vault_pass
chmod 600 /tmp/vault_pass
ansible-playbook site.yml \
--vault-password-file /tmp/vault_pass \
--inventory inventory/production
shred -vfz /tmp/vault_pass
'''
}
}
}
}
Mejores Prácticas
Password management:
# Strong passwords
# Use 32+ character passwords for production
openssl rand -base64 32 > ~/.vault_password_prod
# Never commit passwords to version control
echo ~/.vault_password >> .gitignore
echo ~/.ansible/vault_pass.sh >> .gitignore
# Rotate passwords regularly
# At least quarterly for production
# Use separate passwords for different environments
# dev, staging, production each have unique passwords
File organization:
project/
├── ansible.cfg # Don't include password file
├── .gitignore # Exclude password files
├── group_vars/
│ ├── all.yml # Public variables
│ ├── all/vault.yml # Encrypted: common secrets
│ ├── dev/
│ │ ├── main.yml # Public dev vars
│ │ └── vault.yml # Encrypted: dev secrets
│ ├── prod/
│ │ ├── main.yml # Public prod vars
│ │ └── vault.yml # Encrypted: prod secrets
├── host_vars/ # Host-specific (keep private)
└── roles/
└── webserver/
├── defaults/
├── vars/vault.yml # Role secrets
Security practices:
# Don't echo passwords in logs
# Use 'no_log: true' for sensitive tasks
- name: Create user
user:
name: appuser
password: "{{ user_password }}"
no_log: true # Don't log password
# Separate encryption key from code
# Use external key management systems (Vault, Secrets Manager)
# Audit vault file access
# Monitor git logs for vault file changes
# Use vault IDs with environment-specific keys
# Never mix environment keys
Conclusión
Ansible Vault provides essential security for infrastructure automation by encrypting sensitive data while maintaining seamless integration with playbooks. By using Vault for passwords, API keys, and certificates, implementing multiple vault IDs for different environments, and securely integrating with CI/CD pipelines, you protect sensitive infrastructure data while enabling safe, auditable automation at scale.


