This blog post will explore Ansible Vault as a mechanism for keeping your sensitive values and secrets secure in your playbooks and other Ansible files. We will investigate different options for working with encrypted content and password management options.
If you are new to Ansible or interested in other Ansible concepts, these Ansible tutorials on Spacelift’s blog might be helpful.
What we will cover:
Ansible Vault is an Ansible feature that provides a native way to handle sensitive information. It allows users to encrypt secrets and other sensitive data, such as API keys, passwords, and other credentials, to protect them at rest. Ansible Vault is designed to work with YAML files, but it can encrypt any type of text-based file.
Instead of storing secrets in plaintext, Ansible Vault provides a secure, native, and low-effort option for managing sensitive information by leveraging encryption. Encrypted content can be stored in playbooks, variable files, and roles, persisted under source control, and shared without exposure risks.
Ansible Vault protects sensitive content only at rest. Users are responsible for not exposing decrypted content in the console or in any other way. If necessary, check out the no_log
option for tasks to hide their output.
Passwords are required to encrypt and decrypt sensitive data with Ansible Vault. They are used to create encrypted variables or files, decrypt, and view or edit the encrypted content.
To supply the password for these operations, you can either leverage the ansible-vault
command and get prompted for it, set up a location of a password file in your main configuration definition, ansible.cfg
, or integrate with an external secret store solution that holds your passwords. There is a password management process for each of these cases.
Password management for simple cases
For simple cases, small teams, and a few encrypted values, you might leverage the same password for all your encrypted content. This approach simplifies your password management process because you only have to deal with a single password. You should store and handle this password and other sensitive data in your secret management system.
Password management for more complex systems
You might have to create and manage more vault passwords for complex systems and different access levels for different teams and people. For example, you might use a different password per team, per environment, per ansible role, application, directory, or any other pattern that fits your needs.
In such cases, you can specify a dedicated vault ID for every password. Whenever you generate newly encrypted content, you can pass the dedicated ID with the flag --vault-id
. Store this ID along with the password and pass it with the password during decryption.
We will explore more examples of leveraging vault IDs in the section on how to encrypt sensitive values.
Where to store your Ansible Vault passwords?
As discussed previously, storing passwords in a local file is a simple but not very secure option. If you decide to use this option, make sure the file has the correct permissions, store the password as a string in a single line, and don’t persist it in any code repositories.
A more secure and scalable way is to use an external secret store for storing passwords and fetch them dynamically with the help of a vault password client script. A vault password client script is responsible for connecting to the remote secret store, fetching the secret, and printing the password to standard output.
Check out the official documentation’s section on storing passwords in third-party tools with Vault password client scripts for details on how to create and use such scripts.
Ansible Vault can help users encrypt mainly two types of data — variables and files. This means we can encrypt either whole files or only specific values stored in encrypted variables.
Encrypting specific variables means content will be decrypted on demand only when needed. This option allows us to mix encrypted and plaintext content as required inside playbooks and roles. One drawback of this approach is that it works only with variables and that changing or rotating the password might be cumbersome because there is no command to support this.
On the other hand, encrypting whole files allows us to encrypt other content (tasks, for example) apart from variables, with decryption happening when the file is referenced. We can easily use the rekey
command to change or rotate the password used for file encryption. In general, file-level encryption is easier to use and manage.
A disadvantage of this approach is that encrypting the whole content of the files reduces readability and accessibility because it’s difficult to read the file and understand its contents.
One way to bypass this issue is to keep the names or references of your encrypted content in a separate, non-encrypted file. For more information on the topic, see Keep vaulted variables safely visible.
Let’s look at some examples. We will start by encrypting a variable.
1. Encrypting Ansible variables
To encrypt a string to use in an Ansible variable, you can leverage the ansible-vault encrypt_string
command. The syntax is:
ansible-vault encrypt_string 'your_secret_value' --name 'your_variable_name'
Let’s encrypt the string encrypt_this_string_please
named encrypted_string
and provide the password via the command line:
Notice that the encrypted content produced starts with the !vault
tag, which indicates to Ansible that this value is encrypted and needs decryption to use. After this tag, Ansible adds a header before the encrypted content that includes the format ID, the vault format version, and the cipher algorithm used for encryption.
If you create the encrypted variable with a vault ID, this is also included in the generated content. If you are interested in more information, check out the format of files created with Ansible Vault section of the official docs.
You can also select the password source. For example, let’s use a file named password_file
as our password source.
To avoid persisting the secret value in your shell history, don’t pass directly with the command, but opt to be prompted for a string to encrypt like this:
ansible-vault encrypt_string --vault-id dev@password_file --stdin-name 'encrypted_string'
You can find more command options by using the --help
flag.
ansible-vault encrypt_string --help
2. Encrypting Ansible files
To encrypt whole files that include structured data, you can leverage the ansible-vault create
or the ansible-vault encrypt
commands. Different encryptable files include group, host, defaults, roles, and other custom variable files, tasks files, handlers files, binary, or other arbitrary files.
Creating a new encrypted file
To create a new encrypted file with Ansible Vault, use:
ansible-vault create <file_name>
Enter a password when prompted, add your content in the editor, save, and exit. The file will be encrypted automatically.
For example, let’s create a new encrypted file, encrypted_file.yml
, with vault ID dev, and get prompted for the password, use this command:
ansible-vault create --vault-id dev@prompt encrypted_file.yml
This will open your configured editor (by default, vi) to provide the content to be encrypted. The considerations for storing and using Ansible Vault passwords discussed earlier also apply here.
After you provide your plain text content to the file and save and exit from it, you will only see the encrypted version when you try to view the content. You will need to decrypt it to view it in plain text again.
Encrypting an existing file
To encrypt an existing file with Ansible Vault, use:
ansible-vault encrypt <file_name>
This will prompt you to set a password for encryption. Once completed, the file will be encrypted and its contents secured.
Before encrypting this example existing file, let’s take a look at its content:
cat file_to_be_encrypted.yml
---
- name: Install htop
hosts: all
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
- name: Install htop
apt:
name: htop
state: present
Next, let’s encrypt it. This operation is as simple as running this command:
ansible-vault encrypt file_to_be_encrypted.yml
New Vault password:
Confirm New Vault password:
Encryption successful
You will be prompted for a password, which is required for the decrypt operation.
Now if we want to check the content of the file, this is what we will see:
cat file_to_be_encrypted.yml
$ANSIBLE_VAULT;1.1;AES256
35303362626338626165386633633863326432346539306162393065636236353238636435623033
6466383631393263373538343533346165316462643431660a373437393463616539303830386162
65653831663562333439663235373732383830323761383935643330316637616433396531626632
3137313134333263350a313965313832383533396135623761616234366134316530313964313361
39346433346462383130393163646465346534616661373766316163333161636331393436313435
62623736623539613831353838383961316566393530323837363138616232626565633063653163
64646464663663643362623234356332376465326631373934383133613839633138623939343832
31636261633237303462666231626166386435656266333865666130656562366336636232623164
34663565303634613837303738633135653739386465303530636534343337616166373836633461
64396236393838336266623635323031336465626262383031356362346232636166323365376661
38393931363964663462656537306231633561373038363963616631366165626432646364343431
62353935323338303632323934643831633534386365613163646630333436616438623436366365
36366632383265323833336638356436393537313066616466386666356239633365363137353335
6337313962336661643238363535633263333364326136343365
In the previous section, we explained the process and reviewed several options for encrypting different content with Ansible Vault. Now, let’s look at how we can utilize and work with encrypted content.
One of the most common user operations is to view the encrypted content if necessary. You can leverage the debug module to view the plaintext value of encrypted content.
Let’s create a simple encrypted variable and pass the password via the prompt:
Next, we store this variable in a file named file_with_stored_encrypted_variable.yml
.
To view the encrypted value, use the debug
module and pass the location of the password as we have seen earlier:
ansible localhost -m ansible.builtin.debug -a var="encrypted_variable" -e "@file_with_stored_encrypted_variable.yml" --vault-password-file password_file
localhost | SUCCESS => {
"changed": false,
"encrypted_variable": "encrypt_this"
}
1. Viewing encrypted files
Viewing the contents of encrypted files without decrypting them permanently is quite simple with the ansible-vault view
command:
ansible-vault view encrypted_file.yml
2. Editing encrypted files
Another handy option when working with encrypted files is the ability to edit the encrypted content with the ansible-vault edit
command:
ansible-vault edit encrypted_file.yml
This command prompts the user for the password, decrypts the content to a temporary file, allows the user to edit the encrypted content with the configured editor, and finally saves and re-encrypts the file.
3. Decrypting encrypted files
To permanently decrypt an encrypted file, use the ansible-vault decrypt
command. You will need to provide the encryption password:
ansible-vault decrypt file_to_be_encrypted.yml
Vault password:
Decryption successful
Now if we go back and check the content of that file, it will be human-readable again:
cat file_to_be_encrypted.yml
---
- name: Install htop
hosts: all
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
- name: Install htop
apt:
name: htop
state: present
Note: After running the ansible-vault decrypt
command, the file will be permanently decrypted. If you want to temporarily view or use the contents, consider using ansible-vault view
instead. Make sure you handle decrypted files securely to prevent accidental exposure of sensitive information.
4. Changing the password for encrypted files
Another common operation is to rotate or change the password used for encryption. As discussed briefly in the previous section, this can be achieved with the ansible-vault rekey
command.
To change the password for an encrypted file, use the command below, and pass the current and the new password when prompted:
ansible-vault rekey file_to_be_encrypted.yml
Vault password:
New Vault password:
Confirm New Vault password:
Rekey successful
You will need to provide the old password and then provide a new password and confirm it for this to work.
When you need to decrypt content from a playbook with encrypted variables that have been created with different passwords and vault IDs, pass multiple --vault-id
flags when executing the playbook.
For example:
ansible-playbook --vault-id prod@prod_password_file --vault-id dev@dev_password_file --test@test_password_file playbook.yml
If you use a specific vault ID or a password source more frequently than others, you can define default options and avoid passing them every time. Leverage DEFAULT_VAULT_DENY_LIST and DEFAULT_VAULT_PASSWORD_FILE to set this up.
Ansible Vault supports using an environment variable to specify the password for encrypting and decrypting Vault files. This helps avoid passing the password directly as a command-line argument or typing it manually, making it useful for automation in CI/CD pipelines.
The environment variable used by Ansible Vault is ANSIBLE_VAULT_PASSWORD_FILE
.
Let’s see an example.
First, create a file containing your Vault password.
echo "my_vault_password" > ~/.vault_pass
chmod 600 ~/.vault_pass
Set the ANSIBLE_VAULT_PASSWORD_FILE
environment variable to point to your password file:
export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_pass
With the environment variable set, Ansible Vault automatically uses the password from the specified file, so you don’t need to provide it interactively or via the --vault-password-file
option.
Encrypt a file:
ansible-vault encrypt vars.yml
Run a playbook that uses Vault-encrypted files:
ansible-playbook playbook.yml
Here are best practices to consider when you are using Ansible Vault:
- Use strong passwords for encryptions: You should avoid easily guessed passwords, and ensure your passwords are strong and complex.
- Avoid storing Vault passwords in VCS: Never commit Vault passwords to a git repository because this will result in instant password breaches
- Rotate secrets regularly: Regularly rotate secrets stored in Ansible Vault to reduce the risk of unauthorized access in case of a breach.
- Audit and review access: Ensure only authorized people have access to Vault files and passwords.
- Integrate with secret management Tools: If you require advanced features and integrations, Integrate with external secret management tools such as HashiCorp Vault or AWS Secrets Manager.
Spacelift’s vibrant ecosystem and excellent GitOps flow can greatly assist you in managing and orchestrating Ansible. By introducing Spacelift on top of Ansible, you can then easily create custom workflows based on pull requests and apply any necessary compliance checks for your organization.
Another great advantage of using Spacelift is that you can manage different infrastructure tools like Ansible, Terraform, Pulumi, AWS CloudFormation, and even Kubernetes from the same place and combine their Stacks with building workflows across tools.
Our latest Ansible enhancements solve three of the biggest challenges engineers face when they are using Ansible:
- Having a centralized place in which you can run your playbooks
- Combining IaC with configuration management to create a single workflow
- Getting insights into what ran and where
Provisioning, configuring, governing, and even orchestrating your containers can be performed with a single workflow, separating the elements into smaller chunks to identify issues more easily.
Would you like to see this in action – or just want a tl;dr? Check out this video I put together showing you Spacelift’s new Ansible functionality:
If you want to learn more about using Spacelift with Ansible, check our documentation, read our Ansible guide, or book a demo with one of our engineers.
In this blog post, we explored different options for encrypting sensitive information by leveraging Ansible Vault. We explained Ansible Vault’s main functionality and discussed various options for handling sensitive content, passwords, and files. Lastly, we reviewed examples and use cases of using encrypted content.
Manage Ansible Better with Spacelift
Managing large-scale playbook execution is hard. Spacelift enables you to automate Ansible playbook execution with visibility and control over resources, and seamlessly link provisioning and configuration workflows.