Defining Group Variables and Protecting Secrets
Group Variables
Back on Defining the Inventory, you may remember that we broke the inventory up into groups. Groups are a convenient way to break hosts up into units like:
- Operating system
- Region
- Category
Using the operating system grouping system, you could define a group for Windows and a group for Linux. This is especially handy, as Ansible uses different protocols to manage each Windows and Linux.
- Ansible uses WinRM to manage Windows hosts
- Ansible uses SSH to manage Linux hosts
Also, you may have different credentials to manage each set of hosts.
- You might have an SSH key for your Linux hosts
- And, a username and password Windows hosts.
Defining Group Variables
Ansible will search for a group variables file in the following order:
- The directory relative to the playbook
- The directory relative to the inventory file
Say you have an inventory file in: ~/.ansible/inventory/main-inventory.ini
. And, in that inventory, you have a windows
group and a linux
group. You'll want to specify your group variables as such:
- Windows:
-
~/.ansible/inventory/group_vars/windows.yml
- This means that any time a host in your inventory belongs to the
windows
group, it will inherit the variables specified below:
-
---
ansible_user: user
ansible_password: strongpass
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore
- Linux:
-
~/.ansible/inventory/group_vars/linux.yml
- This means that any time a host in your inventory belongs to the
linux
group, it will inherit the variables specified below:
-
---
ansible_ssh_private_key_file: /root/ssh-priv-key.pem
What's the Problem Here?
Your group variables could contain sensitive information -- especially obvious in the case of the windows
group variables. There is a password stored in cleartext.
Fortunately, Ansible has a solutionc called, "Ansible Vault" to encrypt the contents of files.
Protecting Secrets with Ansible Vault
You can encrypt any file with the ansible-vault
command. Its intended use-case is to encrypt files with a password and decrypt them when a playbook is run.
Encrypting Secrets with Ansible Vault
Going back to the windows
group example, this is how you can protect your secrets with Ansible Vault.
- You need to re-arrange your group variables directory a bit:
-
~/.ansible/inventory/group_vars/windows/vars.yml
- This is a cleartext file with Jinja2 templating as placeholders when
vault.yml
is unlocked
- This is a cleartext file with Jinja2 templating as placeholders when
-
~/.ansible/inventory/group_vars/windows/vault.yml
- This file contains the secrets to be encrypted using
ansible-vault
- This file contains the secrets to be encrypted using
-
vault.yml
This file will contain the same contents as the group variables before:
ansible_user: user
ansible_password: strongpass
ansible_connection: winrm
ansible_winrm_transport: ntlm
ansible_winrm_server_cert_validation: ignore
Now, encrypt this file using this command:
ansible-vault encrypt ~/.ansible/inventory/group_vars/windows/vault.yml
You will be prompted to enter a password to encrypt the vault file. Keep this password somewhere safe, as you'll need to remember it in order to decrypt the file later whenever this group variables file is used in a playbook.
vars.yml
---
ansible_user: "{{ vault_ansible_user }}"
ansible_password: "{{ vault_ansible_password }}"
ansible_connection: "{{ vault_ansible_connection }}"
ansible_winrm_transport: "{{ vault_ansible_winrm_transport }}"
ansible_winrm_server_cert_validation: "{{ vault_ansible_winrm_server_cert_validation }}"
Notice the {{ variable_name }}
syntax. This is called Jinja2 templating. When you run a playbook, here's what should happen.
- If your playbook references the
windows
group- Ansible Vault will try to decrypt
~/.ansible/inventory/group_vars/windows/vault.yml
- You will be asked for a password to decrypt the file
- If successful, the
vault.yml
file will decrypt and populate the templates invars.yml
- Then, the playbook will reference the variables in
vars.yml
- Ansible Vault will try to decrypt
Automating with Ansible Vault
What happens if you want to script an Ansible Playbook? You'll need some unattended way to decrypt the vault files when your script runs your playbook.
Ansilbe Vault Password File
IMPORTANT: If you decide to use the Ansible Vault password file, you'll want to make sure you adhere to security best practices, keep your system patched, and monitor for abuse. If an attacker is able to compromise your Ansible server and become root, they could read this file and unlock your encrypted files. (You don't have to use a password file. You'll just have to enter your password every time you run a playbook.)
- Create an empty file as the user who will run the playbooks
- Enter a strong password in it (save the vault pass in a password manager)
- Save the file
-
chmod 600
the file to protect it - Configure your Ansible server to read the file to encrypt/decrypt Vault files
-
Option 1: Environment Variable
- Put this line in the user's
.bashrc
file -
export ANSIBLE_VAULT_PASSWORD_FILE=/path/to/pass_file.txt
- Put this line in the user's
-
Option 2: Ansible Config file
- Edit the user's
.ansible.cfg
- Add this line under
[defaults]
section -
vault_password_file = /path/to/pass_file.txt
- Edit the user's
-
Option 1: Environment Variable
Now, any time you run ansible-vault encrypt
or ansible-vault view
, the password file will be used as your default vault password.