September 17, 2017 · network automation ansible ansible-vault

Networking with Ansible 108.1

The Ansible Vault 101

Uncencrypted clear text passwords all over our yaml files is not really optimal in terms of security, there are many ways to work with this and since we are working a lot with ansible right now we already have a tool at our disposal to help us mitigate this problem. Ansible Vault can help us out easily, and is quite easy to start using.

Ansible Vault - Documentation

Ansible Vault CLI Reference

ansible-vault encrypt credentials.yml So, you're all done but you realised you were either too lazy or had no idea securing credentials was considered a VERY GOOD idea? This is how you go about encrypting a file with sensitive information after creating it.

ansible-vault edit credentials.yml Sometimes things change, and this command will enable us to easily change an already encrypted file.

ansible-vault decrypt credentials.yml If we for some reason would need to later decrypt our file, this command is how we would go about doing it.

ansible-vault create credentials.yml Creates the file encrypted (no need to manually encrypt it)

ansible-vault view credentials.yml Sometimes we just want to look at things, sometimes these things happen to be encrypted by us. This command let's us sneak a peak at whatever variable declaration spree we were having.

ansible-playbook vaulted_playbook.yml --vault-password-file .vault_pass.txt We use this to provide a a password file instead of interacting with the running of our playbooks. Let's say for a play that is scheduled to run and where we cannot/will not manually interact with the running of the play.

ansible-playbook vaulted_playbook.yml --ask-vault-pass On runtime a prompt requesting the vault password will be displayed, and the play will be paused until a password is entered.

Ansible Vault Best Practice

Encrypting variables makes them really hard to work with if you use CLI tools since they now are obscured from your mighty commandline skills. A recommended best practise from Ansible to handle this is to create a mapping of variables to "vaulted" variables.

For general maintenance, it is often easier to use grep, or similar tools, to find variables in your Ansible setup. Since vaults obscure these variables, it is best to work with a layer of indirection. When running a playbook, Ansible finds the variables in the unencrypted file and all sensitive variables come from the encrypted file.

A best practice approach for this is to start with a group_vars/ subdirectory named after the group. Inside of this subdirectory, create two files named vars and vault. Inside of the vars file, define all of the variables needed, including any sensitive ones. Next, copy all of the sensitive variables over to the vault file and prefix these variables with vault_. You should adjust the variables in the vars file to point to the matching vault_ variables and ensure that the vault file is vault encrypted.

Ansible Vault - Basic Example

We are going to have our username and password variable encrypted by using ansible-vault. But first we will look at the playbook and how the variables have been declared.

Playbook: Ansible NTC Show ASA Interfaces

---
- name: Cisco ASA - Show Interfaces
  hosts: asavaultz
  gather_facts: False
  tasks:
    - name: NTC TEMPLATE show interfaces
      ntc_show_command:
        host: "{{ ansible_host }}"
        connection: "{{ connection }}"
        platform: "{{ platform }}"
        username: "{{ username }}"
        password: "{{ password }}"
        command: "show version"
      register: interfaces

    - name: debug 'show interfaces' output
      debug:
        var: interfaces.response

Group_vars Directory Structure

group_vars/  
└── asavaultz
    ├── credentials.yml       # Our unencrypted file, with variables referencing the encrypted variables.
    └── vault_credentials.yml # Our Ansible-Vault encrypted file, needs vault password to be used, viewed or edited.

group_vars\asavaultz\credentials.yml

---
hostname: "{{ ansible_host }}"  
username: "{{ vault_username }}"  
password: "{{ vault_password }}"  

This is our group_vars credentials file, notice how the variables username and password has been declared as variables prefixed with vault_. To comply with the best practice bit from the Ansible documentation snippet above.

group_vars\asavaultz\vault_credentials.yml
This is the file we actually encrypt with ansible-vault encrypt vault_credentials.yml. We then get to specify a password which can be passed to our ansible-playbook with the --ask-vault-pass argument when running it.

---
vault_username: "dodgy_username"  
vault_password: "dodgy_password"  

The variable lookup game

Let follow this variable game starting from our first username reference in our playbook.

  1. username: "{{ username }}"
    The variable username references another variable called username which comes from group_vars\asavaultz\credentials.yml
  2. username: "{{ vault_username }}"
    Which has yet another another reference, but this time to the value it has in group_vars\asavaultz\vault_credentials.yml
  3. In our play it is this final value of type str dodgy_username that is used when running our playbook.

And the same sequence of references and lookups goes for our str dodgy_password to be passed as the value for password when running our playbook.