Chapter 4: Managing Variables and Facts
Protecting secrets with Ansible Vault
Playbooks often need passwords, API keys or private keys. Kept as plain text in a variables file, those secrets are readable by anyone who can see the project, including everyone with access to its Git repository. Ansible Vault encrypts them so the project can be shared safely.
- Create, view, edit, encrypt, decrypt and rekey files with
ansible-vault. - Run a playbook that uses Vault-encrypted variables, with a prompt or a password file.
- Lay out a project so secrets are encrypted and everything else stays readable.
What Vault does
Ansible Vault ships with Ansible. Its command-line tool, ansible-vault, encrypts and decrypts any data file Ansible uses: inventory variables, variable files loaded by a playbook, files passed as extra variables, or variables in roles.
How Ansible Vault protects a secret: The secret is only ever stored encrypted. ansible-navigator decrypts it in memory while the playbook runs, using a password you supply.
The encrypted file starts with a header like $ANSIBLE_VAULT;1.1;AES256, followed by ciphertext. It is safe to commit to version control. When a playbook needs the values, ansible-navigator decrypts them in memory using the Vault password you provide.
The ansible-vault commands
Pick a subcommand to see what it does to the file:
A few details worth knowing:
createopens the file inviby default. Runexport EDITOR=nanofirst to use a different editor.- Instead of typing the password, most subcommands accept
--vault-password-file=FILE, a file containing the password on a single line. Protect that file carefully (for example with mode0600), because it holds the password in plain text.
[student@demo ~]$ ansible-vault create --vault-password-file=vault-pass secret.ymlviewshows the content without changing anything.editalways rewrites the file, so under version control it looks modified even if you changed nothing. Useviewto read.
[student@demo ~]$ ansible-vault view secret1.yml
Vault password: secret
my_secret: "yJJvPqhsiusmmPPZdnjndkdnYNDjdj782meUZcw"Running playbooks that use Vault
If a playbook reads an encrypted file and you give no password, it stops immediately:
[student@demo ~]$ ansible-navigator run -m stdout test-secret.yml
ERROR! Attempting to decrypt but no vault secrets foundThere are three ways to provide the password.
Prompt
[student@demo ~]$ ansible-navigator run -m stdout \
> --playbook-artifact-enable false \
> site.yml --vault-id @prompt
Vault password (default): redhat--vault-id @prompt asks for the password interactively. Playbook artifacts must be disabled, either with --playbook-artifact-enable false as here, or in ansible-navigator.yml:
ansible-navigator:
playbook-artifact:
enable: falsePassword file
[student@demo ~]$ ansible-navigator run -m stdout site.yml \
> --vault-password-file=vault-pw-fileThe file contains the password as a single line of plain text. Restrict its permissions and never commit it to Git.
Environment variable
[student@demo ~]$ export ANSIBLE_VAULT_PASSWORD_FILE=~/vault-pw-file
[student@demo ~]$ ansible-navigator run -m stdout site.ymlANSIBLE_VAULT_PASSWORD_FILE sets the default password file, so you do not need the option on every run.
Several Vault passwords
Larger projects sometimes encrypt different files with different passwords, for example one for development and one for production. Pass several --vault-id (or --vault-password-file) options:
[student@demo ~]$ ansible-navigator run -m stdout \
> --playbook-artifact-enable false site.yml \
> --vault-id one@prompt --vault-id two@prompt
Vault password (one):
Vault password (two):
...output omitted...The labels one and two are Vault IDs. If a file was encrypted with a matching ID (ansible-vault encrypt --vault-id one@prompt …), Ansible tries that password first; otherwise it tries each password until one works. @prompt on its own is shorthand for default@prompt.
Organising secrets in a project
The simplest approach is to keep sensitive variables in their own files and encrypt only those files, leaving everything else readable.
With group_vars and host_vars, you can use a directory named after a group or host instead of a single file. Every file inside the directory applies to that group or host, so you can split plain and secret variables:
The file names vars and vault are only a convention. The directory can hold any number of files with any names, some encrypted and some not.
Playbook variables can be protected the same way: put the secrets in their own file, encrypt it, and load it with vars_files. Because playbook variables beat inventory variables, this is also a handy way to override values.
- name: Create user accounts for all our servers
hosts: devservers
vars_files:
- secret.yml
tasks:
...- You only need to read an encrypted file. Which command should you use?
- `ansible-navigator run -m stdout site.yml --vault-id @prompt` hangs without asking for a password. Why?
- Which command changes the password of an encrypted file?
- What is the safest way to keep one host’s passwords out of plain text while its other variables stay readable?
Takeaway
Create, view, edit, encrypt, decrypt and rekey files with ansible-vault. Use the chapter lab to check this on a real host.