In this post, like the previous one (Ansible – Secrets in Ansible Vault), I want to show how to use Ansible Vault encryption, but this time, for an entire file.
Encrypting an entire file is as useful as encrypting variables, for example, to apply SSL key files or certificates, they should be encrypted, especially if they are in some type of versioner, such as GitLab or GitHub.

Following the same principle, I will create a file with the passwords on the Ansible host, see the post mentioned above, they are exactly the same keys and processes.

All sources for this post are on GitHub: https://github.com/faustobranco/devops-db/tree/master/knowledge-base/ansible/crypt_file

Password file

Another way to encrypt and decrypt is to use a file with the password. I personally find it much more practical, and with some care in a protected environment, it remains safe.

For this lab, I created a Docker to serve as a specific Ansible server, as most of the scripts, in the case of this Lab, will be run by Jenkins and the Ansible sources in GitLab.
In this container, docker, I will then create the file with the password, simple, in plain text.

An interesting point is that this file can contain several passwords identified by a tag, which can be used according to your criteria, environment, systems, etc.
In this example, I will use two tags: dev and prod.

This file should be protected mode: ‘0644’, owner: root, group: root

/root/.vault_password.sec

dev:SnxvwDsh365DAnId1gfojBSKzfHc8x1vmvyNiaC1dkrlcE5NNe
prod:nBODrPRuespQUOmpEUHFGtynIjoBvjfrA1zl8YF7hVTU9fOIrr

Encrypt files.

To encrypt a file, there are a few ways, one of them is to assign a text editor to Ansible Vault, create an encrypted file with an Ansible command and work on it with Ansible by calling the text editor, so it decrypts, you work on the file and when you save it automatically encrypts again, there are several examples of this process on the net.

But I will only encrypt ready-made files, as in the following example, a certificate that I use in the LDAP of this project.

The file is already in the Playbook folders to make it easier, but encryption can occur in any folder that ansible has access to.

$ ansible-vault encrypt /work/crypt_file/roles/ldap/files/certs/ldapcacert.crt --vault-id prod@/root/.vault_password.sec 


Encryption successful

To validate the encrypted file, see its status now:

$ cat /work/crypt_file/roles/ldap/files/certs/ldapcacert.crt

$ANSIBLE_VAULT;1.2;AES256;prod
39383365323234653035313936646237343737316430343634356137626164616332393739353665
6232343461336231396136326438376434363462316237300a646561663432323538663162643839
38616465343038356438623363643236396530633734343231313731353463306439613266623363
[...]

To view decrypted content:

ansible-vault view /work/crypt_file/roles/ldap/files/certs/ldapcacert.crt --vault-id prod@/root/.vault_password.sec 

Playbook

The playbook is very simple, just to show the values ​​in the terminal, to demonstrate that the values ​​were successfully decrypted, and finally, a cat in the file created on the host.

- crypt_file
|-- hosts
|-- roles
|   `-- ldap
|       |-- files
|       |   `-- certs
|       |       `-- ldapcacert.crt
|       |-- tasks
|       |   `-- main.yaml
|       |-- templates
|       `-- vars
|-- crypt_file.yaml
`-- vars
    `-- global_vars.yaml

(playbook) crypt_file.yaml

- hosts: "tests_Hosts"
  become: true
  roles:
   - ldap
  vars_files:
    - vars/global_vars.yaml
  gather_facts: True

(role/task) roles/ldap/tasks/main.yaml

- name: Copy certificates
  copy:
    src: "{{ role_path }}/files/certs/"
    dest: /etc/ssl/certs/

Let’s run the playbook. To do this we have to pass, in addition to the standard parameters, also the file with the passwords.

But if the file has more than one password, which one will Ansible choose? Note that in files encryptions, this information already has this information, the tags are in the instructions, example: $ANSIBLE_VAULT;1.2;AES256;prod

ansible-playbook -i /work/crypt_file/hosts /work/crypt_file/crypt_file.yaml --vault-id prod@/root/.vault_password.sec

The return, as Ansible standard:

PLAY [tests_Hosts] ***********************************************************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01]

TASK [ldap : Copy certificates] **********************************************************************************************************************************************************************************************************************************************************************************************
ok: [srv-infrastructure-test-master-01]

PLAY RECAP *******************************************************************************************************************************************************************************************************************************************************************************************************************
srv-infrastructure-test-master-01 : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Now, on the target host, check the created file:

root@srv-infrastructure-test-master-01:/home/fbranco# cat /etc/ssl/certs/ldapcacert.crt
-----BEGIN CERTIFICATE-----
MIIFwjCCA6qgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgYQxCzAJBgNVBAYTAlBU
MQ4wDAYDVQQIDAVQb3J0bzEOMAwGA1UEBwwFUG9ydG8xEjAQBgNVBAoMCURldm9w
cy1EQjEcMBoGA1UEAwwTbGRhcC5kZXZvcHMtZGIuaW5mbzEjMCEGCSqGSIb3DQEJ
ARYUYWRtaW5AZGV2b3BzLWRiLmluZm8wHhcNMjQwNDA4MTEzMzE0WhcNMjUwNDA4
MTEzMzE0WjB0MQswCQYDVQQGEwJQVDEOMAwGA1UECAwFUG9ydG8xEjAQBgNVBAoM
[...]

Just as it should be!