Ansible Vault Creation
Introduction
When working with Ansible playbooks and roles, you'll often need to handle sensitive information such as passwords, API tokens, or private keys. Storing these values in plain text within your codebase poses a significant security risk. This is where Ansible Vault comes to the rescue.
Ansible Vault is a feature that allows you to encrypt files and strings containing sensitive data, ensuring they remain secure while still being usable within your Ansible automation. In this guide, we'll focus specifically on creating encrypted content with Ansible Vault.
Understanding Ansible Vault
Ansible Vault uses AES256 encryption to protect your sensitive data. It provides two primary methods for encryption:
- File encryption - Encrypt entire YAML files containing variables
- String encryption - Encrypt individual strings that can be used in otherwise unencrypted files
Let's explore both methods.
Prerequisites
Before we begin, ensure you have:
- Ansible installed (version 2.3 or higher)
- Basic familiarity with Ansible playbooks and variables
You can check your Ansible version using:
ansible --version
Creating an Encrypted File
Let's start by creating a completely encrypted file. This is useful for storing multiple sensitive variables together.
Step 1: Create a New Encrypted File
To create a new encrypted file, use the ansible-vault create
command:
ansible-vault create secret_vars.yml
When you run this command:
- Ansible will prompt you to enter and confirm a password
- Your default text editor will open
- You can add your sensitive data in YAML format
- Save and close the editor to complete the encryption
Here's an example of what you might put in the file:
# Database credentials
db_user: admin
db_password: supersecretpassword123
# API tokens
api_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0
# SSH private key passphrase
ssh_passphrase: another_very_secret_password
After saving, the file will be encrypted and look something like this when viewed with cat
:
$ANSIBLE_VAULT;1.1;AES256
32613761383566373164643066303235333866323336663332326335326562643966396364333766
3539623366363434643735626366343038393766653866370a643739623566333332353039323966
35386334666639346563323137363835383038373831343337646562366338366565383933643838
6232383861636661390a323961656430346430313338646461363538316431653561633637666233
30393733633862373563623937316663306661636332653833396362396462343730393237633836
...
Step 2: Using the Encrypted File in a Playbook
To use this encrypted file in a playbook, include it with the vars_files
directive:
---
- name: Database setup
hosts: database_servers
vars_files:
- secret_vars.yml # This file is encrypted
tasks:
- name: Create database user
mysql_user:
name: "{{ db_user }}"
password: "{{ db_password }}"
priv: '*.*:ALL'
state: present
When you run the playbook, Ansible will prompt you for the vault password:
ansible-playbook setup_database.yml
You can also provide the password via a file or command-line option, which we'll discuss later.
Creating Encrypted Strings
Sometimes you only need to encrypt a single value within an otherwise unencrypted file. For this, you can use Ansible's string encryption feature.
Step 1: Encrypt a Single String
To encrypt a string, use the ansible-vault encrypt_string
command:
ansible-vault encrypt_string 'supersecretpassword123' --name 'db_password'
This command will:
- Prompt you for a vault password
- Encrypt the string 'supersecretpassword123'
- Format it with the variable name 'db_password'
The output will look something like:
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
62313365396662343061393464336163383764373764313664313130393665363262623864373739
6566353566623039313463666265333866613862386165310a316338316663666439383138353863
35303631363834643630396338616264383661363733363430303737343930613037306462323439
3863323914360a663361393663383265333165393661343636653064376439333563333462306265
3337
Step 2: Use the Encrypted String in a YAML File
You can now copy this output directly into your variables file:
# vars/main.yml
---
# Plain text variables
db_name: production_db
db_user: admin
db_host: db.example.com
# Encrypted variable
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
62313365396662343061393464336163383764373764313664313130393665363262623864373739
6566353566623039313463666265333866613862386165310a316338316663666439383138353863
35303631363834643630396338616264383661363733363430303737343930613037306462323439
3863323914360a663361393663383265333165393661343636653064376439333563333462306265
3337
This allows you to keep most of your variables in plain text while only encrypting the sensitive ones.
Password Management Options
Using a Password File
Typing the vault password every time can be tedious. You can store the password in a file and reference it with the --vault-password-file
option:
- Create a password file (make sure to secure this file with proper permissions):
echo "your_vault_password" > ~/.vault_pass.txt
chmod 600 ~/.vault_pass.txt
- Use it with Ansible commands:
ansible-playbook playbook.yml --vault-password-file=~/.vault_pass.txt
- Or configure it in your
ansible.cfg
:
[defaults]
vault_password_file = ~/.vault_pass.txt
Using Multiple Vault IDs
If you need to manage different secrets with different passwords, you can use Vault IDs:
# Encrypt with a specific ID
ansible-vault encrypt_string --vault-id dev@prompt 'dev_secret' --name 'api_key'
# Use multiple IDs when running playbooks
ansible-playbook site.yml --vault-id dev@~/.vault_pass_dev.txt --vault-id prod@~/.vault_pass_prod.txt
Practical Examples
Example 1: Managing AWS Credentials
Create an encrypted file for AWS credentials:
ansible-vault create aws_creds.yml
Contents:
aws_access_key: AKIAIOSFODNN7EXAMPLE
aws_secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
aws_region: us-west-2
Use in a playbook:
---
- name: Provision EC2 instances
hosts: localhost
vars_files:
- aws_creds.yml
tasks:
- name: Launch EC2 instance
amazon.aws.ec2_instance:
key_name: my_key
instance_type: t2.micro
image_id: ami-123456
region: "{{ aws_region }}"
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
tags:
Name: web-server
Environment: production
Example 2: Database Configuration with Mixed Variables
Create a variables file with both plain and encrypted values:
# db_config.yml
---
# Non-sensitive information
db_name: customer_database
db_host: 10.0.0.15
db_port: 5432
db_user: app_user
# Sensitive information (encrypted)
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
32613761383566373164643066303235333866323336663332326335326562643966396364333766
3539623366363434643735626366343038393766653866370a643739623566333332353039323966
35386334666639346563323137363835383038373831343337646562366338366565383933643838
6232383861636661390a323961656430346430313338646461363538316431653561633637666233
Use in a template:
---
- name: Configure application database settings
hosts: app_servers
vars_files:
- db_config.yml
tasks:
- name: Generate database configuration file
template:
src: database.conf.j2
dest: /etc/app/database.conf
owner: app
group: app
mode: '0640'
With a template file (database.conf.j2
):
# Database Configuration
DB_NAME={{ db_name }}
DB_HOST={{ db_host }}
DB_PORT={{ db_port }}
DB_USER={{ db_user }}
DB_PASSWORD={{ db_password }}
Working with Ansible Vault in Git Workflows
When working with version control systems like Git, it's safe to commit encrypted files. Here are some best practices:
- Never commit vault passwords to your repository
- Consider using a shared password manager for team access to vault passwords
- For CI/CD systems, securely provide the vault password as an environment variable or CI secret
A common pattern for team environments is to create a .gitignore
entry for a local file containing vault passwords and share those passwords through a separate secure channel.
Viewing and Editing Encrypted Files
To view the contents of an encrypted file:
ansible-vault view secret_vars.yml
To edit an existing encrypted file:
ansible-vault edit secret_vars.yml
Both commands will prompt for the vault password.
Converting Between Encrypted and Decrypted
To encrypt an existing plaintext file:
ansible-vault encrypt existing_plaintext.yml
To decrypt an encrypted file (be careful with this!):
ansible-vault decrypt secret_vars.yml
Visualizing the Ansible Vault Workflow
Here's a diagram showing the typical Ansible Vault workflow:
Summary
Ansible Vault provides a secure way to manage sensitive data within your Ansible automation:
- Use
ansible-vault create
to create fully encrypted files - Use
ansible-vault encrypt_string
for individual encrypted values - Manage passwords with password files or vault IDs
- Integrate encrypted files into your normal Ansible workflows
By incorporating Ansible Vault into your infrastructure management, you can maintain security best practices while still enjoying the benefits of infrastructure as code and version control.
Additional Resources
Practice Exercises
- Create an encrypted file containing database credentials and use it in a playbook that sets up a database.
- Create a mixed variable file with both encrypted and plain text variables.
- Set up a password file and configure Ansible to use it automatically.
- Try using multiple vault IDs to manage different sets of credentials (dev, test, prod).
- Integrate Ansible Vault into a Git workflow with a team member (without sharing the vault password through Git).
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)