- Use a separate secret management service, such as Vault by HashiCorp, Keywhiz by Square, or a hosted service like AWS’s Key Management Service or Microsoft Azure’s Key Vault.
- Use Ansible Vault, which is built into Ansible and stores encrypted passwords and other sensitive data alongside the rest of your playbook.
Ansible Vault works much like a real-world vault:
- You take any YAML file you would normally have in your playbook (e.g. a variables file, host vars, group vars, role default vars, or even task includes!), and store it in the vault.
- Ansible encrypts the vault (‘closes the door’), using a key (a password you set).
- You store the key (your vault’s password) separately from the playbook in a location only you control or can access.
- You use the key to let Ansible decrypt the encrypted vault whenever you run your playbook.
Let’s see how it works in practice. Here’s a playbook in a file named main.yml that demonstrates the use of an API key:
---- hosts: localhostconnection: localgather_facts: novars_files:- vars/api_key.ymltasks:- name: Echo the API key which was injected into the env.shell: echo $API_KEYenvironment:API_KEY: "{{ myapp_api_key }}"register: echo_result- name: Show the result.debug: var=echo_result.stdout
vars/api_key.yml:
---
myapp_api_key: "l9bTqfBlbXTQiDaJMqgPJ1VdeFLfId98"
This is convenient, but it’s not safe to store the API key in plain text. Even when running the playbook locally on an access-restricted computer, secrets should be encrypted.
To encrypt the file with Vault, run:
~/Downloads/tmp took 2s
❯ ansible-vault encrypt vars/api_key.yml
New Vault password:
Confirm New Vault password:
Encryption successful
Enter a secure password for the file, and Ansible will encrypt it. If you open the file now, you should see something like:
~/Downloads/tmp took 8s
❯ cat vars/api_key.yml
$ANSIBLE_VAULT;1.1;AES256
36656634633630653262663338373235306137613534653431383835333662303162633536623066
3736653466633939633639313565373734313930323436340a626533396534653266656162356538
39326635303861343533306637663338623061663062663138623538386134656536303465656162
3335343436396538660a663933353161616538363930646664626639653632353065303636376362
31313931306332663862623463616135313838653632353763623761303739666266323663336235
36663763313165356232373636633439326264306266303461373561383837333866626238373862
626636653833396335373362633233313434
Next time you run the playbook, you will need to provide the password. If you don’t specify the password, you’ll receive an error:
~/Downloads/tmp
❯ ansible-playbook main.yml
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to
see details
ERROR! Attempting to decrypt but no vault secrets found
There are a number of ways you can provide the password, depending on how you run playbooks. Providing the password at playbook runtime works well when running a playbook interactively:
# Use --ask-vault-pass to supply the vault password at runtime.
~/Downloads/tmp
❯ ansible-playbook main.yml --ask-vault-pass
Vault password:
For convenience, or for automated playbook runs (e.g. on a continuous integration server), you can supply vault passwords via a password file. Just like secure keys in your ∼/.ssh folder, you should treat these files carefully: never check them into source control, and set strict permissions (e.g. 600) so only you can read or write this file. Create the file ∼/.ansible/vault_pass.txt with your password in it, set permissions to 600, and tell Ansible the location of the file when you run the playbook:
# Use --vault-password-file to supply the password via file/script.
~/Downloads/tmp took 4s
❯ ansible-playbook main.yml --vault-password-file=~/.ansible/vault_pass.txt
More options and examples are available in the official documentation for Ansible Vault.
