CHAPTER 12
In this chapter, we will describe how Ansible can protect sensitive data.
Whenever we want to automate something, sooner or later there is a moment where we encounter a password, API keys, certificates, or some other sensitive content.
As with any other code, we would use a versioning system such as Git or Subversion to keep our code versioned. This automatically means that we would expose sensitive information to people who are not intended to see it.
Rather than leaving this content (playbooks, variable files, etc.) visible in plaintext, Ansible offers a tool called Ansible Vault that allows data encryption and decryption. Only after encrypting the sensitive content should we feel safe about putting it into a source control.
To use Ansible Vault, we need to encrypt the data by providing a password, and the same for decrypting the content. This password of passwords obviously should be kept in some (other) safe place.
Ansible offers a command line tool called ansible-vault, which will enable us to encrypt the content.
The encrypt command encrypts the existing file. We can also pass the --output argument to specify the name of the newly encrypted file. If the --output is not provided, the file will simply be overwritten by the encrypted content.
Code Listing 76: Encrypt a file
$ ansible-vault encrypt <filename> --output=<new_filename> |
Ansible offers the ability to encrypt multiple files with different passwords; each file would have its own. This can be done by supplying the --vault-id parameter to the encrypt command. In our case, we have given an identifier called secret@prompt. Prompt, in this case, means that the password will be supplied in the command line.
Code Listing 77: Specify value-id
$ ansible-vault encrypt --value-id secret@prompt <file> |
The decrypt command decrypts the existing file.
Code Listing 78: Decrypt a file
$ ansible-vault decrypt <filename> |
If the file has been given a –vault-id during the encryption, as we have seen in the previous example, we could provide the --vault-id in the command line with the same name as we provided during the encryption.
Code Listing 79: Decrypt a file supplying the vault-id
$ ansible-vault decrypt --vault-id secret@prompt <filename> |
The view command enables us to see the content.
Code Listing 80: View encrypted file
$ ansible-vault view <filename> |
The edit command allows us to edit the file. When we use the edit command, an editor will open the file ready to be edited in the command line.
Code Listing 81: Edit encrypted file
$ ansible-vault edit <filename> |
Changing a password for an already encrypted file is rather simple using the rekey command. This command is useful, as otherwise we would need to do two operations—decrypt and encrypt—to achieve the same thing. We can provide multiple files to the command.
Code Listing 82: Changing the encryption password
$ ansible-vault rekey <filename> <filename2> |
When referencing an encrypted file within an Ansible playbook, we need to provide a password for the content to be decrypted during the execution. The ansible-playbook command offers an option to supply the password through the --vault-id option.
The @prompt option will prompt the user to provide the password in the command line.
Code Listing 83: Execute playbook by providing the password
$ ansible-playbook –-vault-id @prompt playbook.yml |
There are situations where the secret might be displayed during the execution of the playbook. We can suppress the output by using the no_log: true directive within the task.
Code Listing 84: Suppressing the output
… tasks: - name: print variable debug: msg: {{ secret_variable }} no_log: true |
Let’s create a file called secret_file.yml with the following content.
Code Listing 85: content of secret_file.yml
password: some_very_secret_password |
And let’s encrypt this file with the encrypt command.
Code Listing 86: Encrypting the file
(avenv) [vagrant@amgr vault]$ ansible-vault encrypt secret_file.yml |
You will be asked for a password, which will be used to encrypt the file. After supplying the password (in my case, the password is 1234) and reopening the file, we will see that the file has been encrypted, and that it is unreadable by a human.
Code Listing 87: Secret_file.yml after encryption
$ANSIBLE_VAULT;1.1;AES256 66626463316264313732366638323532653130363232383131643434643235393763343039383362 3363356465383565613938623666306161663463396361370a366362623965663437353934636165 32373964313433343130343634663061393166656333373466663631383631643063623336313830 3234386136663232650a343862336163616264666565326630353934343635643663376536373464 35343664626635626263383764663139653165363835323332336632316462656262663839633833 3762343138656233333531326139336633393431323438663233 |
Let’s now create a playbook where we will use this secret information.
Code Listing 88: Playbook that references encrypted file
--- - name: Handling secret information hosts: lb become: yes gather_facts: false tasks: - name: Load encrypted variable include_vars: file: secret_file.yml
- name: Retrieve information from the secret_file debug: msg: "{{ password }}" - name: Retrieve information from the secret_file but not show output debug: msg: "{{ password }}" no_log: true |
We are already familiar with the tasks section. We can see a new module called include_vars, which is responsible for loading files with variables so that those are available to other tasks. This is very handy, as we can reference our encrypted file (secret_file.yml).
Additionally, we would like to display the password value in the subsequent two tasks; one, however, should suppress the output as we have previously seen, by using the no_log: true argument.
We can now execute the playbook and see that providing the --vault-id parameter with @prompt will actually prompt for a password. I will supply the password used for encrypting the file.
Code Listing 89: Run playbook with secret data
(avenv) [vagrant@amgr Code_Listing_88]$ ansible-playbook --vault-id @prompt playbook.yml |
The result looks like the following figure.

Figure 43: Result when executing the playbook
We can clearly see that in the first task, the output gets properly shown, while in the second, that’s not the case.