Skip to main content

Ansible Variable Encryption

Introduction

When working with Ansible, you'll often need to manage sensitive information like passwords, API keys, and other credentials. Storing these values as plaintext in your playbooks or variable files creates a security risk, especially when your code is version-controlled or shared with a team.

Ansible provides a built-in solution called Ansible Vault that allows you to encrypt sensitive variables and files, ensuring your secrets remain secure while still being usable in your automation tasks.

Understanding Ansible Vault

Ansible Vault is a feature that encrypts and decrypts variable files, enabling you to securely store sensitive information in your Ansible projects. The encrypted files can be safely committed to version control systems without exposing the secret values.

Getting Started with Ansible Vault

Creating an Encrypted File

To create an encrypted file from scratch, use the ansible-vault create command:

bash
ansible-vault create secret_vars.yml

This command will:

  1. Prompt you to create and confirm a vault password
  2. Open an editor where you can add your variables
  3. Save the file in encrypted format

The content inside might look like:

yaml
db_password: super_secret_password
api_key: abcd1234efgh5678
ssl_private_key: |
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDRFLSrKLJQa5d0
...
-----END PRIVATE KEY-----

Encrypting an Existing File

If you already have an unencrypted variable file, you can encrypt it with:

bash
ansible-vault encrypt existing_vars.yml

Viewing Encrypted Files

To view the contents of an encrypted file without decrypting it permanently:

bash
ansible-vault view secret_vars.yml

Editing Encrypted Files

To edit an encrypted file:

bash
ansible-vault edit secret_vars.yml

Decrypting Files

If you need to permanently decrypt a file:

bash
ansible-vault decrypt secret_vars.yml

Using Encrypted Variables in Playbooks

Running Playbooks with Vault-Encrypted Files

When running a playbook that uses encrypted variables, you need to provide the vault password:

bash
ansible-playbook site.yml --ask-vault-pass

This will prompt you for the vault password before running the playbook.

Using a Password File

For automation purposes, you can store the password in a file (which should be properly secured and not committed to version control):

bash
ansible-playbook site.yml --vault-password-file ~/.vault_pass.txt

You can also set the environment variable ANSIBLE_VAULT_PASSWORD_FILE to point to your password file:

bash
export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_pass.txt
ansible-playbook site.yml

Example Playbook Using Encrypted Variables

Here's a simple example of a playbook that uses encrypted variables:

yaml
---
- name: Configure database
hosts: database_servers
vars_files:
- secret_vars.yml

tasks:
- name: Create database user
mysql_user:
name: app_user
password: "{{ db_password }}"
priv: "app_db.*:ALL"
state: present

- name: Configure API access
template:
src: api_config.j2
dest: /etc/app/api_config.json

Encrypting Individual Variables

Sometimes you may want to encrypt just a single variable rather than an entire file. Ansible allows this through the !vault tag.

Creating an Encrypted String

To create an encrypted string:

bash
ansible-vault encrypt_string 'secret_value' --name 'secret_variable'

This outputs something like:

yaml
secret_variable: !vault |
$ANSIBLE_VAULT;1.1;AES256
66386439653236336462626566653063336164663966303231363934653561363132333163393765
3630643034346262376566643863323435613733666132380a636530393639316233313130333433
63383063383033303830363033363732303762336666363863613061393362323563373363336638
6633376235386266630a623236353964636265353234333435373262373331366366623263613138
3161

Using Encrypted Strings in YAML Files

You can paste the encrypted string directly into your variable files:

yaml
# group_vars/all.yml
---
regular_variable: normal_value
secret_variable: !vault |
$ANSIBLE_VAULT;1.1;AES256
66386439653236336462626566653063336164663966303231363934653561363132333163393765
3630643034346262376566643863323435613733666132380a636530393639316233313130333433
63383063383033303830363033363732303762336666363863613061393362323563373363336638
6633376235386266630a623236353964636265353234333435373262373331366366623263613138
3161

Multiple Vault Passwords

For complex setups with different teams or environments, you may need multiple vault passwords.

Creating Files with Different Vault IDs

bash
ansible-vault create --vault-id dev@prompt dev_secrets.yml
ansible-vault create --vault-id prod@prompt prod_secrets.yml

Using Multiple Vault Passwords in Playbooks

bash
ansible-playbook site.yml --vault-id dev@~/.dev_vault_pass.txt --vault-id prod@~/.prod_vault_pass.txt

Real-World Example: Deploying a Web Application

Let's consider a practical example of deploying a web application with encrypted database credentials and API keys.

Directory Structure

project/
├── inventory/
│ └── hosts
├── group_vars/
│ ├── all.yml
│ └── webservers/
│ ├── vars.yml
│ └── vault.yml # Encrypted file
├── playbooks/
│ └── deploy_webapp.yml
└── ansible.cfg

Encrypted Variable File (vault.yml)

bash
ansible-vault create group_vars/webservers/vault.yml

Content:

yaml
db_user: webapp_user
db_password: super_secure_password123
api_key: 89a7sd6f76asd6f7as6df7
jwt_secret: very_secret_jwt_key

Regular Variable File (vars.yml)

yaml
# group_vars/webservers/vars.yml
app_name: awesome_webapp
app_version: 1.2.3
app_port: 8080
db_host: db.example.com
db_name: webapp_db

Deployment Playbook

yaml
---
# playbooks/deploy_webapp.yml
- name: Deploy Web Application
hosts: webservers
vars_files:
- ../group_vars/webservers/vars.yml
- ../group_vars/webservers/vault.yml

tasks:
- name: Install application packages
package:
name: "{{ app_name }}-{{ app_version }}"
state: present

- name: Generate application config
template:
src: templates/app_config.j2
dest: "/etc/{{ app_name }}/config.json"
owner: app
group: app
mode: '0600'
notify: restart application

- name: Ensure application service is running
service:
name: "{{ app_name }}"
state: started
enabled: yes

handlers:
- name: restart application
service:
name: "{{ app_name }}"
state: restarted

Config Template (app_config.j2)

json
{
"app": {
"name": "{{ app_name }}",
"port": {{ app_port }}
},
"database": {
"host": "{{ db_host }}",
"name": "{{ db_name }}",
"user": "{{ db_user }}",
"password": "{{ db_password }}"
},
"api": {
"key": "{{ api_key }}",
"jwt_secret": "{{ jwt_secret }}"
}
}

Best Practices for Ansible Vault

  1. Never commit vault passwords to version control: Store vault passwords securely outside your repository.

  2. Use different vault passwords for different environments: Maintain separate vault passwords for development, staging, and production.

  3. Rotate vault passwords regularly: Change your vault passwords periodically for enhanced security.

  4. Restrict access to vault passwords: Only team members who absolutely need access should have it.

  5. Only encrypt sensitive data: Keep non-sensitive variables unencrypted for easier debugging and version control diffs.

  6. Separate variables into encrypted and unencrypted files: This approach keeps most of your variables easily readable.

  7. Use CI/CD integration: For automated deployments, store vault passwords securely in your CI/CD system's secure variables or secrets management.

Troubleshooting Common Issues

Error: "Decryption failed"

This usually means the wrong password was provided. Double-check your password or password file.

Error: "Vault password file not found"

Ensure the path to your vault password file is correct and the file exists.

Error: "Could not parse vault content"

This typically indicates that the encrypted file was modified manually or corrupted. Restore from a backup or re-encrypt your variables.

Summary

Ansible Vault provides a robust solution for encrypting sensitive data within your Ansible infrastructure code. By following the practices outlined in this guide, you can safely manage credentials, API keys, and other secrets while maintaining the security of your infrastructure.

With Ansible Vault, you can:

  • Create and edit encrypted files
  • Encrypt individual variables
  • Use encrypted variables in playbooks
  • Manage multiple vault passwords for different environments
  • Integrate secure practices into your CI/CD pipeline

Additional Resources

Exercises

  1. Create an encrypted variable file containing database credentials and use it in a playbook that configures a database server.

  2. Set up a project structure with separate vault files for development and production environments.

  3. Create a script that rotates vault passwords for your Ansible project.

  4. Configure a CI/CD pipeline that uses Ansible Vault for deploying an application securely.

  5. Practice encrypting individual variables and using them alongside unencrypted variables in the same file.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)