Secure Ansible Playbooks using Vault | Beginner Level Guide
This guide covers the fundamentals of securing sensitive data within Ansible playbooks using Ansible Vault. You will learn how to protect passwords, API tokens, and cloud credentials from exposure in version control systems, understand the underlying encryption workflows, and implement production-grade secrets management strategies.
1. The Security Problem: Plaintext Secrets in Version Control
As a DevOps engineer, you write Ansible playbooks to automate infrastructure provisioning, application deployment, and configuration management. Many of these tasks require authentication credentials, such as:
- AWS Access Keys and Secret Keys
- Database passwords
- API tokens for third-party integrations
- SSH private keys
The Naive Approach (Security Risk)
If you hardcode these credentials directly into your playbooks or variable files, they exist in plaintext. When you push your code to a shared Git repository (such as GitHub, GitLab, or an internal Bitbucket server) to collaborate with your team, those secrets are instantly compromised.
Even if the repository is private, storing plaintext secrets in version control violates security compliance standards and exposes the organization to severe insider threats and accidental leaks.
2. The Core Mental Model: The Bank Vault Analogy
To understand how Ansible Vault secures your data, consider the real-world analogy of a physical bank locker or vault.
Real-Life Analogy
- Setting up the Vault: You go to a bank to secure your physical assets (documents, cash, jewelry). To use the vault, you must first establish a secure key or password.
- Locking the Assets: You open the vault with your key, place your sensitive assets inside, and lock it.
- Accessing the Assets: The next time you or an authorized person wants to view, add, or remove items, you must provide the exact same key. If the key is correct, the vault opens; if not, access is denied.
Ansible Vault operates on this exact logical flow. It encrypts your sensitive files or individual variable strings using a password of your choice. Without this password, the contents of the file remain an unreadable, encrypted block of text.
3. Ansible Vault: Out-of-the-Box Secret Management
One of the greatest advantages of Ansible Vault is that it requires no additional installation. It is packaged directly with the core Ansible installation. If you have Ansible installed on your control node, the ansible-vault command-line tool is already available.
To verify its installation, run the following command in your terminal:
ansible-vault --help
How Ansible Vault Secures Files
Ansible Vault uses symmetric encryption (specifically AES-256 by default) to protect files. The same password used to encrypt the file must be supplied to decrypt, edit, or run it during playbook execution.
4. Step-by-Step Evolution: From Plaintext to Encrypted Variables
Let's walk through how to transition from an insecure plaintext configuration to a secure, encrypted Ansible Vault setup.
Step 4.1: The Insecure Plaintext Configuration
In Ansible, variables that apply to all host groups are typically stored in the group_vars/all/ directory. Let's assume we have a file named credentials.yml containing AWS keys:
# group_vars/all/credentials.yml (PLAINTEXT - INSECURE)
ec2_access_key: "AKIAIOSFODNN7EXAMPLE"
ec2_secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
If this file is committed to Git, your AWS account is exposed.
Step 4.2: Creating an Encrypted File with Ansible Vault
To prevent exposure, we will create an encrypted file named aws_credentials.yml inside the group_vars/all/ directory.
You can create this file and prompt Ansible Vault to ask for a password interactively:
ansible-vault create group_vars/all/aws_credentials.yml
Upon executing this command, your terminal will prompt you:
New Vault password:
Confirm New Vault password:
Once you enter and confirm a strong password, Ansible Vault opens your default command-line text editor (e.g., vim or nano). Inside this editor, define your sensitive variables:
ec2_access_key: "AKIAIOSFODNN7EXAMPLE"
ec2_secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
Save and close the file.
Step 4.3: Verifying the Encryption
If you attempt to read the file using the standard cat command, you will only see the encrypted ciphertext:
cat group_vars/all/aws_credentials.yml
Output:
$ANSIBLE_VAULT;1.1;AES256
3836343731373737616265316362633062316335356434653738623630653634336230613165
36353931343734613264356463373231363737633534346433310a6231393664373963336437
6661336630343762613165386231393633633833353631653439626631613032333062393335
...
This encrypted file is completely safe to commit to your Git repository.
5. Deep Dive: Essential Ansible Vault Commands
Ansible Vault provides a suite of subcommands to manage encrypted files throughout their lifecycle.
Command Workflows & Examples
1. Encrypting an Existing Plaintext File
If you already have a plaintext file named secrets.yml and want to encrypt it:
ansible-vault encrypt secrets.yml
2. Editing an Encrypted File
To modify variables inside an encrypted file without manually decrypting and re-encrypting it:
ansible-vault edit group_vars/all/aws_credentials.yml
This decrypts the file into a temporary memory buffer, opens it in your editor, and automatically re-encrypts it using the same password when you save and exit.
3. Viewing Encrypted Content
To read the contents of an encrypted file without modifying it or leaving decrypted traces on your disk:
ansible-vault view group_vars/all/aws_credentials.yml
4. Encrypting a Single String
If you prefer to keep your variable file in plaintext but want to encrypt only a specific sensitive value, use encrypt_string:
ansible-vault encrypt_string 'my_super_secret_api_token' --name 'api_token'
Output:
api_token: !vault |
$ANSIBLE_VAULT;1.1;AES256
363536323635333530393036353335353030303130353035303430313033303030333035
303530363031303930343034303530353036303130393034303430353035303630310a36
You can copy and paste this block directly into any standard plaintext YAML file.
6. Managing Vault Passwords Securely
Typing passwords interactively is fine for local testing, but it fails in automated CI/CD pipelines (e.g., Jenkins, GitHub Actions, GitLab CI) and is tedious for daily development.
6.1. Using a Password File
You can store your vault password in a local file and instruct Ansible to read it automatically using the --vault-password-file flag.
Step 1: Generate a Strong, Random Password
Do not use weak passwords like password123. Use OpenSSL to generate a cryptographically secure, random base64-encoded string:
openssl rand -base64 32 > vault.pass
Step 2: Secure the Password File Permissions
Ensure that only your user account can read this file:
chmod 600 vault.pass
Warning: NEVER commit your
vault.passfile to Git. Addvault.passto your project's.gitignorefile immediately.
Step 3: Execute Vault Commands with the Password File
Now, you can create, edit, or view files without interactive prompts:
ansible-vault view group_vars/all/aws_credentials.yml --vault-password-file vault.pass
7. Architectural Best Practices: Environment-Based Password Segmentation
In an enterprise environment, managing a single Ansible Vault password across the entire organization presents significant security risks:
- If a developer only needs access to the Development environment, giving them the global password grants them access to Production secrets as well.
- If the password is compromised, the entire infrastructure is exposed.
Conversely, having a unique password for every single playbook becomes an operational nightmare.
The Recommended Strategy: Environment-Based Segmentation
Segment your vault passwords by environment boundaries: Development (Dev), Staging, and Production (Prod).
Integrating with Cloud Secret Managers
Instead of storing the production vault.pass file on a virtual machine where unauthorized developers might read it, configure your deployment pipelines to fetch the password dynamically at runtime from a secure store:
- AWS Ecosystem: AWS Systems Manager (SSM) Parameter Store or AWS Secrets Manager.
- Azure Ecosystem: Azure Key Vault.
- Access Control: Use Identity and Access Management (IAM) roles and policies to ensure only authorized production execution nodes have permission to retrieve the production vault password.
8. Complete Integration Workflow: Provisioning AWS EC2 Securely
Let's look at a complete, end-to-end implementation of how an encrypted Ansible Vault file is consumed by an Ansible playbook to securely provision an AWS EC2 instance.
The Execution Flow
Step 8.1: Prerequisites
To interact with AWS APIs, ensure you have installed the required dependencies on your control node:
pip install boto3
ansible-galaxy collection install amazon.aws
Step 8.2: The Encrypted Variable File
Create your encrypted credentials file using your secure password file:
ansible-vault create group_vars/all/aws_credentials.yml --vault-password-file vault.pass
File Contents (Encrypted):
ec2_access_key: "AKIAIOSFODNN7EXAMPLE"
ec2_secret_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
Step 8.3: The Playbook
Write your playbook (provision_ec2.yml). Notice that we do not hardcode any secrets. Instead, we reference the variables defined in our encrypted vault file using Jinja2 templating syntax ({{ ... }}).
---
- name: Provision AWS EC2 Instance Securely
hosts: localhost
connection: local
gather_facts: false
tasks:
- name: Launch a single EC2 Instance
amazon.aws.ec2_instance:
# Pass the decrypted variables securely to the AWS module
aws_access_key: "{{ ec2_access_key }}"
aws_secret_key: "{{ ec2_secret_key }}"
region: "us-east-1"
name: "secure-production-server"
key_name: "prod-ssh-key"
instance_type: "t2.micro"
image_id: "ami-0c7217cdde317cfec" # Example Amazon Linux 2 AMI
wait: true
register: ec2_details
- name: Output Instance Details
ansible.builtin.debug:
var: ec2_details.instances[0].instance_id
Step 8.4: Running the Playbook
To run this playbook, you must provide the vault password so Ansible can decrypt the variables in memory during execution. Pass the password file using the --vault-password-file flag:
ansible-playbook provision_ec2.yml --vault-password-file vault.pass
If you do not want to use a password file and prefer to type the password manually when running the playbook, use the --ask-vault-pass flag instead:
ansible-playbook provision_ec2.yml --ask-vault-pass
Summary and Key Takeaways
- Zero-Trust Version Control: Never commit plaintext passwords, API keys, or cloud credentials to Git. Use Ansible Vault to encrypt sensitive files before pushing them to any repository.
- Zero Extra Dependencies: Ansible Vault is built directly into Ansible; no external installations or third-party agents are required to start encrypting files.
- Symmetric Encryption: Ansible Vault uses strong AES-256 symmetric encryption. The same password is used for both encryption and decryption.
- In-Place Editing: Use the
ansible-vault editcommand to modify encrypted files securely without leaving unencrypted plaintext files on your disk. - Automated Execution: Use
--vault-password-fileto point to a local, git-ignored password file (e.g.,vault.pass) to run playbooks seamlessly in CI/CD pipelines. - Cryptographic Passwords: Generate strong vault passwords using secure tools like OpenSSL (
openssl rand -base64 32) rather than simple, guessable text strings. - Environment Isolation: Segment vault passwords by environment (Dev, Staging, Prod) to enforce the principle of least privilege and limit the blast radius of a compromised password.
- Enterprise Secret Management: For production environments, store your vault passwords in dedicated cloud secret managers (like AWS Secrets Manager or Azure Key Vault) and retrieve them dynamically during deployment.