Introducing Ansible Vault
Ansible may need access to sensitive data such as passwords or API keys in order to configure managed hosts. Normally, this information might be stored as plain text in inventory variables or other Ansible files. In that case, however, any user with access to the Ansible files or a version control system which stores the Ansible files would have access to this sensitive data. This poses an obvious security risk.
Ansible Vault, which is included with Ansible, can be used to encrypt and decrypt any structured data file used by Ansible. To use Ansible Vault, a command-line tool named ansible-vault is used to create, edit, encrypt, decrypt, and view files. Ansible Vault can encrypt any structured data file used by Ansible. This might include inventory variables, included variable files in a playbook, variable files passed as arguments when executing the playbook, or variables defined in Ansible roles.
Creating an Encrypted File
To create a new encrypted file, use the ansible-vault create filename command. The command prompts for the new vault password and then opens a file using the default editor, vi. You can set and export the EDITOR environment variable to specify a different default editor by setting and exporting. For example, to set the default editor to nano, export EDITOR=nano.
[geek@demo ~]$ ansible-vault create secret.yml New Vault password: mypass Confirm New Vault password: mypass
Instead of entering the vault password through standard input, you can use a vault password file to store the vault password. You need to carefully protect this file using file permissions and other means.
[geek@demo ~]$ ansible-vault create --vault-password-file=vault-pass secret.yml
The cipher used to protect files is AES256 in recent versions of Ansible, but files encrypted with older versions may still use 128-bit AES.
Viewing an Encrypted File
You can use the ansible-vault view filename command to view an Ansible Vault- encrypted file without opening it for editing.
[geek@demo ~]$ ansible-vault view secret1.yml Vault password: secret less 458 (POSIX regular expressions) Copyright (C) 1984-2012 Mark Nudelman less comes with NO WARRANTY, to the extent permitted by law. For information about the terms of redistribution, see the file named README in the less distribution. Homepage: http://www.greenwoodsoftware.com/less my_secret: "yJJvPqhsiusmmPPZdnjndkdnYNDjdj782meUZcw"
Editing an Existing Encrypted File
To edit an existing encrypted file, Ansible Vault provides the ansible-vault edit filename command. This command decrypts the file to a temporary file and allows you to edit it. When saved, it copies the content and removes the temporary file.
[geek@demo ~]$ ansible-vault edit secret.yml Vault password: mypass
Encrypting an Existing File
To encrypt a file that already exists, use the ansible-vault encrypt filename command. This command can take the names of multiple files to be encrypted as arguments.
[geek@demo ~]$ ansible-vault encrypt secret1.yml secret2.yml New Vault password: mypass Confirm New Vault password: mypass Encryption successful
Use the –output=OUTPUT_FILE option to save the encrypted file with a new name. You can only use one input file with the –output option.
Decrypting an Existing File
An existing encrypted file can be permanently decrypted by using the ansible-vault decrypt filename command. When decrypting a single file, you can use the –output option to save the decrypted file under a different name.
[geek@demo ~]$ ansible-vault decrypt secret1.yml --output=secret1-decrypted.yml Vault password: mypass Decryption successful
Changing the Password of an Encrypted File
You can use the ansible-vault rekey filename command to change the password of an encrypted file. This command can rekey multiple data files at once. It prompts for the original password and then the new password.
[geek@demo ~]$ ansible-vault rekey secret.yml Vault password: mypass New Vault password: mypass01 Confirm New Vault password: mypass01 Rekey successful
When using a vault password file, use the –new-vault-password-file option:
[geek@demo ~]$ ansible-vault rekey --new-vault-password-file=NEW_VAULT_PASSWORD_FILE secret.yml
Playbook and Ansible Vault
To run a playbook that accesses files encrypted with Ansible Vault, you need to provide the encryption password to the ansible-playbook command. If you do not provide the password, the playbook returns an error:
[geek@demo ~]$ ansible-playbook site.yml ERROR: A vault password must be specified to decrypt vars/api_key.yml
To provide the vault password to the playbook, use the –vault-id option. For example, to provide the vault password interactively, use –vault-id @prompt as illustrated in the following example:
[geek@demo ~]$ ansible-playbook --vault-id @prompt site.yml Vault password (default): mypass
Note: If you are using a release of Ansible earlier than version 2.4, you need to use the –ask-vault-pass option to interactively provide the vault password. You can still use this option if all vault-encrypted files used by the playbook were encrypted with the same password.
[geek@demo ~]$ ansible-playbook --ask-vault-pass site.yml Vault password: mypass
Alternatively, you can use the –vault-password-file option to specify a file that stores the encryption password in plain text. The password should be a string stored as a single line in the file. Because that file contains the sensitive plain text password, it is vital that it be protected through file permissions and other security measures.
[geek@demo ~]$ ansible-playbook --vault-password-file=vault-pw-file site.yml
Note: Starting with Ansible 2.4, you can use multiple Ansible Vault passwords with ansible-playbook. To use multiple passwords, pass multiple –vault-id or –vault-password-file options to the ansible-playbook command.
[geek@demo ~]$ ansible-playbook --vault-id one@prompt --vault-id two@prompt site.yml Vault password (one): Vault password (two): ...output omitted...
The vault IDs one and two preceding @prompt can be anything and you can even omit them entirely. If you use the –vault-id id option when you encrypt a file with the ansible-vault command, however, when you run ansible-playbook then the password for the matching ID is tried before any others. If it does not match, the other passwords you provided will be tried next. The vault ID @prompt with no ID is actually shorthand for default@prompt, which means to prompt for the password for vault ID default.
Recommended Practices for Variable File Management
To simplify management, it makes sense to set up your Ansible project so that sensitive variables and all other variables are kept in separate files. The files containing sensitive variables can then be protected with the ansible-vault command. Remember that the preferred way to manage group variables and host variables is to create directories at the playbook level. The group_vars directory normally contains variable files with names matching host groups to which they apply. The host_vars directory normally contains variable files with names matching hostnames of managed hosts to which they apply.
However, instead of using files in group_vars or host_vars, you also can use directories for each host group or managed host. Those directories can then contain multiple variable files, all of which are used by the host group or managed host. For example, in the following project directory for playbook.yml, members of the webservers host group uses variables in the group_vars/ webservers/vars file, and demo.example.com uses the variables in both host_vars/demo.example.com/vars and host_vars/demo.example.com/vault:
├── ansible.cfg ├── group_vars │ └── webservers │ └── vars ├── host_vars │ └── demo.example.com │ ├── vars │ └── vault ├── inventory └── playbook.yml
In this scenario, the advantage is that most variables for demo.example.com can be placed in the vars file, but sensitive variables can be kept secret by placing them separately in the vault file. Then the administrator can use ansible-vault to encrypt the vault file while leaving the vars file as plain text. There is nothing special about the file names being used in this example inside the host_vars/ demo.example.com directory. That directory could contain more files, some encrypted by Ansible Vault, and some which are not.
Playbook variables (as opposed to inventory variables) can also be protected with Ansible Vault. Sensitive playbook variables can be placed in a separate file which is encrypted with Ansible Vault and which is included in the playbook through a vars_files directive. This can be useful because playbook variables take precedence over inventory variables. If you are using multiple vault passwords with your playbook, make sure that each encrypted file is assigned a vault ID, and that you enter the matching password with that vault ID when running the playbook. This ensures that the correct password is selected first when decrypting the vault- encrypted file, which is faster than forcing Ansible to try all the vault passwords you provided until it finds the right one.