A Deep Dive into Ansible Vault: Safeguarding Your Sensitive Data

Ansible Vault is a feature of Ansible that allows you to encrypt sensitive data such as passwords or keys in encrypted files, rather than as plaintext in playbooks or roles. This provides the ability to secure any sensitive data that is necessary to successfully run Ansible projects. Ansible Vault uses the AES 256 algorithm to provide symmetric encryption, which means that it uses the same password for encrypting and decrypting files. The ansible-vault command is the main interface for managing encrypted content within Ansible, and it is used to initially encrypt files and subsequently used to view, edit, or decrypt the data. Ansible Vault is especially useful if you have confidential data that you want to secure and prevent from being publicly exposed.

Don’t forget to join my Discord: https://discord.gg/YbSYGsQYES

Ansible Vault can encrypt any structured data file used by Ansible, including group variables files from inventory, host variables files from inventory, variables files passed to ansible-playbook with -e @file.yml or -e @file.json, variables files loaded by include_vars or vars_files, variables files in roles defaults files in roles, tasks files, handlers files, binary files, or other arbitrary files.

To encrypt files with Ansible Vault, you can use the command line tool to edit files.

Alternatively, you may specify the location of a password file or command Ansible to always prompt for the password in your ansible.cfg file. These options require no command line flag usage.

Ansible 2.4 and later support the concept of multiple vault strings that are encrypted with different passwords.

Different vaults can be given a label to distinguish them (generally values like dev, prod etc.).

When you pass a vault ID as an option to the ansible-vault command, you add a label (a hint or nickname) to the encrypted content.

--vault-id label@source

When the playbook uses multiple encrypted variables encrypted with different passwords, you must pass the vault IDs when you run that playbook.

Encrypt Files With Ansible Vault

Variables in Ansible can come from many different locations. The Variable Precedence document describes it in detail. Though Ansible is very flexible with using variables, I suggest to keep it simple and well maintainable.

The ansible-vault tool can create, edit, encrypt and decrypt files. Create and edit will open the default editor.

Encrypted files get decrypted when they are used or referenced.

The following command will create an encrypted file in host_vars/ansible/vault.yml.

ansible-vault create host_vars/ansible/vault.yml

You will be asked for a Vault password.

The variable file will be opened in the default editor and you can add you content.

---
var1: This is a var from an encrypted file!

When you close the file it will be encrypted on the disk.

# cat host_vars/ansible/vault.yml 
$ANSIBLE_VAULT;1.1;AES256
65316664313737636231643034326135643030373761306566366530313164643064653932336563
3130366361623262353834326165323362633237316664360a383631623132303839323236323136
66366238626234336139313838303461313538343833363135626535333037306530623031656362
6131386638313261370a306639393661653732343966623137333861663563363664656232663336
62643038376563373666663931343238373833616638303937393662323930666531343839393037
62393332353239626464633164373933376638643661366634663930353866333437353235353334
383261376561646662636261333032343562

When a playbook is executed Ansible finds the variables in the encrypted file. The --ask-vault-pass command line option can be used to prompt for a password that decrypts the file during the playbook run.

ansible-playbook -i inventory check-vars.yml --ask-vault-pass
Vault password: 
(...)

After providing the password the playbook will run and the variables will be used.

Encrypt Files With Ansible Vault: Using Multiple Vault Passwords

In a dynamically growing infrastructure it is unavoidable to use different environments. Separate teams should have distinct access rights. There can be many reasons for separating secret data logically and protect them with different passwords.

Labeling and the Vault ID comes very handy here.

You can also use the --vault-id option to pass a single password with its vault label.

ansible-vault create --vault-id=prod@secrets/prod.txt host_vars/ansible/vault_prod_secrets.yml

The above command creates an encrypted file labelled as prod in the host_vars/ansible directory. The password for the encryption and decryption is being read from the secrets/prod.txt file.

You can add the variables to this file as in the previous section.

To run a playbook using the Vault ID use the --vault-id option again.

ansible-playbook -i inventory playbook.yml --vault-id=prod@secrets/prod.txt

The variables labelled as prod will be decrypted by the password from the secrets/prod.txt file.

If you don’t want to provide the password file on the command line or if you use one vault password file more frequently than any other, you can set the DEFAULT_VAULT_PASSWORD_FILE configuration option.

To add the data of an other team to the playbook with different password just create another variable file with a different password file and label.

ansible-vault create --vault-id=dbteam@secrets/password.txt host_vars/ansible/vault_dbteam_secrets.yml

The Database Team can add their own data into the secret file and the playbook can be run with multiple Vault IDs.

ansible-playbook -i inventory playbook.yml --vault-id=dbteam@secrets/password.txt --vault-id=prod@secrets/prod.txt

Ansible will find the password for the labels and decrypt the files.

Encrypt Strings in Variable Files

The ansible-vault encrypt_string command encrypts and formats any string into a format that can be included in a playbook, role, variables, or files. The encrypted string is stored as a key-value pair, where the key is the name of the variable and the value is the encrypted string. The encrypted content always includes the !vault tag, which tells Ansible and YAML that the content needs to be decrypted, and a | character, which allows multi-line strings. The encrypted string is created by encrypting the plain text string with a password, which can be provided interactively or through a file. The resulting encrypted string is then formatted in a way that can be included in a playbook or other Ansible file.

Encrypted strings get decrypted on demand, run time.

To create an encrypted string use the ansible-vault command with the encrypt_string option.

ansible-vault encrypt_string "This is an encrypted string in a variable"

!vault |
          $ANSIBLE_VAULT;1.1;AES256
          35653335636139643661626261623235646330366433613164373535333133393130386538343161
          3737323663373662613266346539386263333662323566390a326438363461346363346262653035
          63326232613938636235303663656534333433663530366562666265396564316436313531323863
          6330346361336364350a623364393732333762613865323037386661316363613531633561383632
          65653038663166333563393732373937383464353162663432313261376664646563366536356232
          3065383939666538636338393935633432653636623163633262

The command will prompt for a password. Then the generated string can be used in any vars file as a value.

The drawback of this technique is that the command will get in the shell history, so the secret data can be seen by others. To avoid leaking secret data use the standard input to read it. We can give a name to the variable that will be the key in a file with the --stdin-name option.

ansible-vault encrypt_string --vault-id=test@secrets/password.txt --stdin-name my_secret
Reading plaintext input from stdin. (ctrl-d to end input, twice if your content does not already have a newline)
This is a secret I write in the stdin and it won't be seen in the history file.
Encryption successful
my_secret: !vault |
          $ANSIBLE_VAULT;1.2;AES256;test
(...)

After typing the secret and hitting the Ctrl+d two times, you get the encrypted string that can be used in the variable files as usual.

Encrypt Strings in Variable Files: Using Multiple Vault Passwords

You can use multiple Vault Passwords in the same variable file with encrypted strings.

ansible-vault encrypt_string --vault-id=webteam@secrets/password.txt --stdin-name my_web_secret
(...)

ansible-vault encrypt_string --vault-id=dbteam@secrets/prod.txt --stdin-name my_db_secret
(...)

ansible-playbook -i inventory playbook.yml --vault-id=webteam@secrets/password.txt --vault-id=dbteam@secrets/prod.txt

It is also possible to prompt for a password using @prompt.

ansible-playbook -i inventory playbook.yml --vault-id=webteam@secrets/password.txt --vault-id=dbteam@prompt

With using the above command Ansible will prompt for the DB Team password instead of reading it from a file.

Conclusion

In conclusion, harnessing the power of Ansible Vault in conjunction with Vault IDs is a game-changer in the realm of infrastructure management and security. By seamlessly integrating Ansible’s robust automation capabilities with the encryption and access control features offered by Vault IDs, organizations can fortify their systems against unauthorized access while maintaining the efficiency and agility necessary in today’s fast-paced IT landscape. This powerful combination empowers administrators to confidently handle sensitive data and secrets, ensuring compliance with security best practices and regulatory requirements. As technology evolves and security threats persist, Ansible Vault with Vault IDs stands as an indispensable tool for safeguarding sensitive information and preserving the integrity of infrastructure automation processes.

If you enjoyed the article, don’t forget to join my Discord Server: https://discord.gg/YbSYGsQYES

Leave a comment