Skip to main content

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:

  1. File encryption - Encrypt entire YAML files containing variables
  2. 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:

bash
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:

bash
ansible-vault create secret_vars.yml

When you run this command:

  1. Ansible will prompt you to enter and confirm a password
  2. Your default text editor will open
  3. You can add your sensitive data in YAML format
  4. Save and close the editor to complete the encryption

Here's an example of what you might put in the file:

yaml
# 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:

yaml
---
- 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:

bash
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:

bash
ansible-vault encrypt_string 'supersecretpassword123' --name 'db_password'

This command will:

  1. Prompt you for a vault password
  2. Encrypt the string 'supersecretpassword123'
  3. Format it with the variable name 'db_password'

The output will look something like:

yaml
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:

yaml
# 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:

  1. Create a password file (make sure to secure this file with proper permissions):
bash
echo "your_vault_password" > ~/.vault_pass.txt
chmod 600 ~/.vault_pass.txt
  1. Use it with Ansible commands:
bash
ansible-playbook playbook.yml --vault-password-file=~/.vault_pass.txt
  1. Or configure it in your ansible.cfg:
ini
[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:

bash
# 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:

bash
ansible-vault create aws_creds.yml

Contents:

yaml
aws_access_key: AKIAIOSFODNN7EXAMPLE
aws_secret_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
aws_region: us-west-2

Use in a playbook:

yaml
---
- 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:

yaml
# 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:

yaml
---
- 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:

  1. Never commit vault passwords to your repository
  2. Consider using a shared password manager for team access to vault passwords
  3. 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:

bash
ansible-vault view secret_vars.yml

To edit an existing encrypted file:

bash
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:

bash
ansible-vault encrypt existing_plaintext.yml

To decrypt an encrypted file (be careful with this!):

bash
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

  1. Create an encrypted file containing database credentials and use it in a playbook that sets up a database.
  2. Create a mixed variable file with both encrypted and plain text variables.
  3. Set up a password file and configure Ansible to use it automatically.
  4. Try using multiple vault IDs to manage different sets of credentials (dev, test, prod).
  5. 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! :)