Ansible Vault Usage

Ansible Vault is a feature of ansible that allows you to keep sensitive data such as passwords in encrypted files, rather then as plaintext in playbooks.
A command line tool, ansible-vault, allows you to edit files. With command line flags you can pass in the ansible vault password or the password file. You can specify the location of the password file in the ansible.cfg file.

Ansbile Vault can encrypt andy structured data file used by Ansible. This includes group_vars or host_vars inventory variables. Any variables loaded by include_vars, vars_files or files passed in by the ansible-playbook command line (-e @myfile.yml).

Best practice is to start with the groups_vars subdirectory named after the group. Inside the subdirectory, create two files named vars and vault.  Inside vars file, define all variables needed, including the sensitive ones.  Copy all the sensitive variables over to the vault file and prefix these variables with vault_.  Adjust the variables in the vars file to point to the matching vault_ variables using jinja2 syntax, and enure the vault file is encrypted.

Directory setup

Notice the vars.yml and the vault.yml are under the directory of the web group.

.
└── install
├── ansible.cfg
├── ansible.log
├── group_vars
│   └── web
│       ├── vars.yml
│       └── vault.yml
├── host_vars
├── inventory
├── VAULT_PASSWORD_FILE
└── users.yml

Inventory file – install/inventory

[all]
controller.example.local
node1.example.local

[web]
node1.example.local

Vars file – install/group_vars/web/vars.yml

The passwords are  stored in jinja2 format from the key variable  in the vault.yml file.

---
users:
  - name: jdoe 
    password: '{{ vault_jdoe_password }}' 
  - name: jsmith
    password: '{{ vault_jsmith_password }}' 
  - name: ssmith
    password: '{{ vault_jsmith_password }}'

The playbook adds users and passwords to the server – install/users.yml

This will add the user and password to the servers in the web group. Only node1 will add the users.

---
- name: All software need by all servers
  hosts: all 
    tasks:
    - name: Users creation
      user:
        home: "/home/{{ item.name }}"
        name: '{{ item.name }}'
        password: "{{ item.password | password_hash('sha512') }}"
        state: present
      with_items: "{{ users }}"
      when: "'web' in group_names"

The Vault  file needs to be encrypted. To do this, I first make a vault password file that  will keep the  vault encryption password.  Make sure you protect the vault password file.  Set the permission on the file to 600 so only the ansible user can use it.

Vault yaml  file – install/group_vars/web/vault.yml

vault_jdoe_password: temp123 
vault_jsmith_password: temp456 
vault_ssmith_password: temp789

VAULT_PASSWD_FILE – install/VAULT_PASSWD_FILE

$ cat VAULT_PASSWD_FILE 
mysecretpassword

To encrypt the file

$ ansible-vault encrypt --vault-password-file=../../VAULT_PASSWD_FILE vault.yml
Encryption successful

$ cat vault.yml 
$ANSIBLE_VAULT;1.1;AES256
33363365306138313766356135636136376566626433633533336533643135316630373164626230
6639343664373338613735623333383736333161376136620a663935303031313761313637633938
65383036313361306364633432383833343132346637386237373862313435653761626531643631
3132663134313435350a363038386639363439303865326437623464356438323961386336313466
63623632626233653330663535306433393230636531386134383336616537306433643462303363
39623163646238663137643339336232643438636362303264643463353131623734643232396162
66313963366430346233656137653064613266306330333566363334373565376435356136663832
62633630616138646361

Now the vault.yml file  is encrypted.

We can now proceed with running the playbook to install the users on node1.  I use the ” –vault-password-file ” argument to pass in the vault file with the password.

$ ansible-playbook -i inventory --vault-password-file=VAULT_PASSWD_FILE users.yml

PLAY [All software need by all servers] ****************************************************

TASK [Gathering Facts] *********************************************************************
ok: [controller.example.local]
ok: [node1.example.local]

TASK [Users creation] **********************************************************************
skipping: [controller.example.local]
changed: [node1.example.local] => (item={u'password': u'temp123', u'name': u'jdoe'})
changed: [node1.example.local] => (item={u'password': u'temp456', u'name': u'jsmith'})
changed: [node1.example.local] => (item={u'password': u'temp456', u'name': u'ssmith'})

PLAY RECAP *********************************************************************************
controller.example.local : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 
node1.example.local : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Notice the users are only placed into the node1 server and not the controller. Also notice the plain text passwords are shown in the output.  This is because we stored them as plain passwords in the vault.yml file and  let the users.yml file encrypt them on the fly.  To prevent this, you can put the encrypted  password in the vault.yml file and  remove the ” | password_hash(‘sha512’) ” from the users.yml file.  The encrypted password will still be seen but not the plain text since it was never  stored.