The Ansible scripts I have written so far to update Pingdom IPs and update Palo Alto GPCS IPs have worked fine, certainly as intended, but would fall foul of a PCI auditor. So it is time to hide away the secrets in a vault.
Ansible Vault setup
To set up our secrets file in Ansible vault, I start by making a back up of it (just in case), then we use the ansible-vault command:
cp secrets.yml vault_secrets.yml ansible-vault encrypt vault_secrets.yml
We have to enter a password twice.
As the scripts will probably be run automatically, I don’t want to have to put my password in all the time, so we create a .vault-pass file containing the password, which we then chmod to 600, so it’s only readable by the account being used.
echo "my_password_goes_here" > .vault_pass chmod 600 .vault_pass
Finally, if we are running GIT on the box, we want to exclude this file from being versioned.
echo ‘.vault_pass’ >> .gitignore
Remember to delete the original secrets.yml file!
If we look at the contents of the vault_secrets.yml file, we can see that it is encrypted:
ansible@ansible ~/playbooks$ cat vault_secrets.yml $ANSIBLE_VAULT;1.1;AES256 38383062313566656534353533626137623162613961383430316436343165653137323963376164 6335333531343730346136383538363038363461613264630a663735336663303863336666313166 31643137356539343437316331613638333461626239636331363762636339306633653639306336 6362356535653336630a356466343936303134616664396365633430376463636637336261376336 65303834363939636334623134386532333937643439383431653238333961353131313533613132 62356363666533643964666362633838653536623562356138373831613035653034383832326166 64303536393030353365663261343037336430366238386530303536633934623865363430363262 64356237396133623630383238396661376333313366643635386330656561343032396632303762 6439 ansible@ansible ~/playbooks$
Here is what it looks like, step by step:
To use the vault_pass file, we need to pass it in the playbook command, using the option of “–vault-password-file=”, and specifying the filename:
ansible-playbook test-asa.yml -i hosts --vault-password-file=.vault_pass
In the playbook, we use the “include_vars” command to call up the vault_secrets.yml file.
cat test-asa.yml - hosts: Cisco_ASAs connection: local tasks: - name: GET CREDS include_vars: vault_secrets.yml - name: DEFINE CONNECTION set_fact: connection: authorize: yes host: "{{ inventory_hostname }}" username: "{{ creds['username'] }}" password: "{{ creds['password'] }}" auth_pass: "{{ creds['auth_pass'] }}" timeout: 30 - name: GET VERSION asa_command: provider: "{{ connection }}" commands: - show version register: result - debug: var=result
If we try to run the same playbook, without specifying vault password file, then we get an error:
ansible@ansible ~$ ansible-playbook test-asa.yml -i hosts PLAY [Cisco_ASAs] ***************************************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************ ok: [192.168.3.170] TASK [GET CREDS] ****************************************************************************************************************************************************** fatal: [192.168.3.170]: FAILED! => {"ansible_facts": {}, "ansible_included_var_files": [], "changed": false, "message": "Attempting to decrypt but no vault secrets found"} to retry, use: --limit @/home/ansible/test-asa.retry PLAY RECAP ************************************************************************************************************************************************************ 192.168.3.170 : ok=1 changed=0 unreachable=0 failed=1 ansible@ansible ~$
Now that our passwords are nicely secured away in the vault, the auditors will be happy and the environment much safer!
The cool thing about ansible-vault is that you can cherry-pick what you want to encrypt, so you can have encrypted and non-encrypted string in the same file.
You can do encrypt-string and paste in the | vault string it creates.
Also in ansible 2.5 you should be able to use network_cli as connection type type and use group_vars or host_vars so you dont have to set facts and tasks for authentication in the playbook 9r use provider variables in each task
Cheers Pete! I will give it a go 🙂