What is Ansible Vault

Ansible Vault is a tool, from the Ansible suite, that allows to encrypt and decrypt security sensitive secrets, such as passwords, private keys, etc. It's specifically built for the purpose of working automatically with ansible-playbook when deploying playbooks which rely on previously encrypted secrets.

Why Use Ansible Vault

The simplest answer is for security. Sooner or later there will be a case when either a password or API access token will have to be stored as part of a role or a playbook code. The code may end of being stored in a private or public version control like GitHub, either for sharing, archiving or code review.

In such case any security sensitive things would need to be taken out of the code, stored separately in a secure manner, and then re-added to the code before a deployment. All of that would have to be documented and the procedure followed carefully in order to make all of it work. This introduces additional layers of complexity prone to human errors.

Having a central, encrypted store for security sensitive secrets also makes it easier to keep track of all secrets used throughout the code. This way it may be more difficult to let some individuals slip through the cracks.

How to Use Ansible Vault

ansible-vault command is built-in, it comes with the base install of Ansible.

It uses a very easy command syntax and just a handful of common options:

--ask-vault-pass - ask for vault password

--new-vault-id=NEW_VAULT_ID - the new vault identity to use for rekey

--new-vault-password-file=NEW_VAULT_PASSWORD_FILE - new vault password file for rekey

--vault-id=VAULT_IDS - the vault identity to use

--vault-password-file=VAULT_PASSWORD_FILES - vault password file

Individual functions:

encrypt - encrypt the supplied file using the provided vault secret

decrypt - decrypt the supplied file using the provided vault secret

rekey - re-encrypt a vaulted file with a new secret, the previous secret is required

encrypt_string - encrypt the supplied string using the provided vault secret

edit - open and decrypt an existing vaulted file in an editor, that will be encryped again when closed

create - create and open a file in an editor that will be encryped with the provided vault secret when closed

view - open, decrypt and view an existing vaulted file using a pager using the supplied vault secret

File Encryption

To encrypt a file:

ansible-vault encrypt path/to/secret_file

New Vault password:
Confirm New Vault password:
Encryption successful

To decrypt a file:

ansible-vault decrypt path/to/secret_file

Vault password:
Decryption successful

That's all there is to it in most cases.

Automatically Decrypt Vaulted Files in These Locations

Files in the following locations can be encrypted with ansible-vault and then decrypted on-the-fly by ansible-playbook:

  • role variables in role/vars
  • role defaults in role/defaults
  • group_vars
  • host_vars
  • vars included via include_vars or vars_files
  • variable files included on the command line via the -e @vars.yml option

In addition to the default above files the following can also be encrypted for special cases:

  • tasks
  • handlers
  • any other data files

Store Vault Password Locally for Frequent Deployments, Testing, or Automation

--vault-password-file=VAULT_PASSWORD_FILES

Typing in a long, complex, secure vault password every time while testing or debugging a playbook gets annoying quickly. One method to address this is to set up a vault password file containing the password and then telling ansible-playbook to use that file with the --vault-password-file option.

Keep in mind to set strict file permissions chown user:user password.file and chmod 400 password.file should prevent it from being accessible for anyone else. Remember to remove the file once the work is done.

Perhaps Ansible itself could be used to handle the vault password files setup. All the vault password files could be stored vaulted in their own dedicated role then with a single ansibile-playbook command and a single vault password entered at the prompt they can be put in place on demand and removed once all deploys are done. Just an idea for those who don't like the thought of clear text password files laying around the file system.

Encrypting Variables

Vaulting secrets is very useful when dealing with variables. One such scenario is any playbook that includes tasks requiring AWS credentials. Keeping them in the playbook or in a variables file is a big security risk, definitely not something anyone would want to share publicly and a big red flag for any security compliant business.

One way to approach this issue is to have unencrypted AWS keys variables point at their vaulted equivalents:

in roles/awesome-role/vars/main.yml

aws_access_key: "{{ aws_access_key_vault }}"
aws_secret_key: "{{ aws_secret_key_vault }}"

in roles/awesome-role/vars/vault.yml (which is encrypted)

aws_access_key_vault: abc123321cbaabc123321cbaabc123
aws_secret_key_vault: AbCdEfGhIjAbCdEfGhIjAbCdEfGhIj

This way while the actual keys are safely encrypted all the time it's still possible to look for and find the actual variables pointing to them. These variables can also be stored in the same clear text file with other variables for better visibility.

Then by simply including either --ask-vault-pass or --vault-id ~/.vault_pass.txt or --vault-id @prompt with the ansible-playbook command the vault vars file can be decrypted on the fly making it all work transparently in the background.

The cool thing about this is that it works very well with host_vars and group_vars.

How to encrypt in-line variables and secrets in Playbooks

This is a feature that lets to encrypt/decrypt just blocks of strings which then allows to include secrets directly in playbooks in-line. I can't think of a scenario where this may be a better solution then having secrets in dedicated vault variable files. Maybe someone who prefers putting everything in a single file playbook can find this useful. Another scenario where this may be useful is when mixing clear text and vaulted secrets in one variables file.

Encrypt a string without any advanced options:

ansible-vault encrypt_string `string`
New Vault password:
Confirm New Vault password:
!vault |
          $ANSIBLE_VAULT;1.1;AES256
          30336562306530333164366430636165653132356462333938316465626131646662666466313032
          3234313534366539613266373338313736616666643562620a613435386134323638626537336665
          65363931323963666436353538333633343065643066643231383533313165306339633036373861
          3831623931343333300a323530306464333263643464663835623530333237366639663764666562
          3666

Encrypt a string from a prompt with a custom name. This method will not leave the secret in the command line history:

ansible-vault encrypt_string --stdin-name 'secret'
New Vault password:
Confirm New Vault password:
Reading plaintext input from stdin. (ctrl-d to end input)
test
secret: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          30333836663233633939613137303363313631343463383834353164633237303734383733316439
          3264653461633139373035643438313936623966313938620a366537393133333663663339326265
          62313061343733336233646639623239343031343263323763306163666566343364626366656630
          3937383066666561350a616533626165396532636438323437613738333634616563653163656338
          3938
Encryption successful

To check the content of the in-line vaulted secret (assuming it's in vars.yml file):

ansible localhost -m debug -a var="secret" -e "@vars.yml" --ask-vault-pass
Vault password:

localhost | SUCCESS => {
    "secret": "pa$$word"
}

The variable can be referenced anywhere in the playbook just like any other variable:

{{ secret }}

How to Handle Multiple Passwords

Similarly to --vault-password-file the --vault-id option allows to retrieve vault password from a file. However, with this option it's possible to specify more than one password in a single command. This is very useful in environments with multiple teams use multiple passwords.

To use multiple passwords:

ansible-playbook --vault-id password-file1 --vault-id password-file2 ... etc.

Another very useful feature of --vault-id is labeling. Labels can be used to identity multiple passwords.

To use multiple passwords with labels:

ansible-playbook --vault-id dev@password-file1 --vault-id test@password-file2 ... etc.

Getting the vault password from prompts can be combined with multiple other passwords. This may be useful when the option of storing a password is not possible, for example for a production environment variables:

ansible-playbook --vault-id dev@password-file1 --vault-id test@password-file2 --vault-id prod@prompt ...

In the last example Ansible will iterate through all the given passwords when decrypting vaulted files. If it doesn't find a working one, it'll prompt for one.

To create a vault label use the --vault-id option:

ansible-vault encrypt --vault-id LABEL@prompt vault.txt

CLI output:

notice the vault label added in clear text to the encrypted file

$ANSIBLE_VAULT;1.2;AES256;LABEL

[mariusz@flip Documents]$ ansible-vault encrypt --vault-id LABEL@prompt test.txt
New vault password (LABEL):
Confirm new vault password (LABEL):
Encryption successful

[mariusz@flip Documents]$ cat test.txt
$ANSIBLE_VAULT;1.2;AES256;LABEL
63623630333936623465393539666362323030366236616338656537333530306631643638653865
6230636137323437636230653937376138646539663333370a643438383061623865326239393732
35346565663735636430386461663164343036323038653839303837333339663764623436633662
3263666661326665630a363661656561653962373732646535363636613031313366363135363836
3737

Having these labels in vaulted files makes it easy to identify which password needs to be used to succesfully decrypt it without exposing the secrets inside.

Multiple Passwords and Vault IDs Stored in a File

In order to have Ansible go through a list of vault password files or just one of them without specifing it on the command line add this key to the ansible.cfg configuration file under the defaults section:

vault_identity_list = label-1@~/ansible/.password-1,label-2@~/ansible/.password-2,label-3@~/ansible/.password-3 etc.

The content of the above password files should be simply as follows.

$ cat ~/ansible/.password-1
pa$$w0rd-1

$ cat ~/ansible/.password-2
pa$$w0rd-2

$ cat ~/ansible/.password-3
pa$$w0rd-3

Then when doing encryption or decryption refer just to the labels as defined in the ansible.cfg, the ansible-vault command will map them properly.

ansible-vault encrypt --encrypt-vault-id label-1 vars/vars.yml

When running a playbook using a vault ansible-playbook will go through the list of all password files specified in ansible.cfg and decrypt the secrets once it find a password that works. No --vault-id or --vault-password-file options are needed.

One downside of this method is that all passwords used in encrypting the vault files must be listed in the configuration otherwise decryption will fail and prompt will not work. In order to get a password prompt, comment out the vault_identity_list key in ansible.cfg and run the playbook with --vault-id @prompt.

Speed Up Crypt Performance

To speed up encryption/decryption of a large number of vault files install cryptography Python package replacing the default PyCrypto:

pip install cryptography

Video Ansible Vault Tutorial

TBD


Reading Time

~6 min read

Published

Category

Ansible

Tags

Contact