Bookmark this page

Managing Secrets

Objectives

  • Encrypt sensitive variables by using Ansible Vault, and run playbooks that reference Vault-encrypted variable files.

Introducing Ansible Vault

Ansible might need access to sensitive data, such as passwords or API keys, to configure managed hosts. Normally, this information is 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 that 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 data file used by Ansible. To use Ansible Vault, use the command-line tool named ansible-vault to create, edit, encrypt, decrypt, and view files.

Ansible Vault can encrypt any 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.

Important

Ansible Vault does not implement its own cryptographic functions but rather uses an external Python toolkit. Files are protected with symmetric encryption using AES256 with a password as the secret key. Note that the way this is done has not been formally audited by a third party.

Creating an Encrypted File

To create a new encrypted file, use the ansible-vault create filename command. This command prompts for the new Vault password and then opens a file using the default editor, vi. You can export the EDITOR environment variable to specify a different default editor. For example, to set the default editor to nano, run the export EDITOR=nano command.

[student@demo ~]$ ansible-vault create secret.yml
New Vault password: redhat
Confirm New Vault password: redhat

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.

[student@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 earlier versions might 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.

[student@demo ~]$ ansible-vault view secret1.yml
Vault password: secret
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.

[student@demo ~]$ ansible-vault edit secret.yml
Vault password: redhat

Note

The edit subcommand always rewrites the file, so you should only use it when making changes. This can have implications when the file is kept under version control. You should always use the view subcommand to view the file's contents without making changes.

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.

[student@demo ~]$ ansible-vault encrypt secret1.yml secret2.yml
New Vault password: redhat
Confirm New Vault password: redhat
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.

[student@demo ~]$ ansible-vault decrypt secret1.yml --output=secret1-decrypted.yml
Vault password: redhat
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 the same time. It prompts for the original password and then the new password.

[student@demo ~]$ ansible-vault rekey secret.yml
Vault password: redhat
New Vault password: RedHat
Confirm New Vault password: RedHat
Rekey successful

When using a Vault password file, use the --new-vault-password-file option:

[student@demo ~]$ ansible-vault rekey \
> --new-vault-password-file=NEW_VAULT_PASSWORD_FILE secret.yml

Playbooks and Ansible Vault

To run a playbook that accesses files encrypted with Ansible Vault, you need to provide the encryption password to the ansible-navigator command. If you do not provide the password, the playbook returns an error:

[student@demo ~]$ ansible-navigator run -m stdout test-secret.yml
ERROR! Attempting to decrypt but no vault secrets found

You can provide the Vault password using one of the following options:

  • Prompt interactively

  • Specify the Vault password file

  • Use the ANSIBLE_VAULT_PASSWORD_FILE environment variable

To provide the Vault password interactively, use --playbook-artifact-enable false and --vault-id @prompt as illustrated in the following example:

[student@demo ~]$ ansible-navigator run -m stdout \
> --playbook-artifact-enable false \
> site.yml --vault-id @prompt
Vault password (default): redhat

Important

You must disable playbook artifacts to enter the Vault password interactively. The ansible-navigator command hangs if it needs to prompt you for an interactive Vault password and playbook artifacts are not disabled. Playbook artifacts are enabled by default.

You can use the ansible-navigator --playbook-artifact-enable false command to disable playbook artifacts.

You can also disable playbook artifacts by modifying your project ansible-navigator.yml file or the .ansible-navigator.yml file in your home directory. Set the playbook-artifact setting in that file to enable: false.

The following minimal ansible-navigator.yml file disables playbook artifacts:

ansible-navigator:
  playbook-artifact:
    enable: false

Instead of providing the Vault encryption password interactively, you can specify a file that stores the encryption password in plain text by using the --vault-password-file option.

The password must 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.

[student@demo ~]$ ansible-navigator run -m stdout site.yml \
> --vault-password-file=vault-pw-file

You can also use the ANSIBLE_VAULT_PASSWORD_FILE environment variable to specify the default location of the password file.

Important

You can use multiple Ansible Vault passwords with ansible-navigator.

To use multiple passwords, pass multiple --vault-id or --vault-password-file options to the ansible-navigator command.

[student@demo ~]$ ansible-navigator run -m stdout  \
> --playbook-artifact-enable false site.yml \
> --vault-id one@prompt --vault-id two@prompt
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, then the password for the matching ID is the first password tried when running the ansible-navigator command. If it does not match, then ansible-navigator tries the other passwords that you provided. 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 that match the host groups to which they apply. The host_vars directory normally contains variable files with names that match the hostnames of managed hosts to which they apply.

You can use subdirectories within the group_vars or host_vars directories for each host group or managed host. Those directories can contain multiple variable files, and all of those files are used by the host group or managed host.

In the following example project directory for the playbook.yml playbook, members of the webservers host group use variables in the group_vars/webservers/vars file. The demo.example.com host uses the variables in both the host_vars/demo.example.com/vars and host_vars/demo.example.com/vault files.:

.
├── ansible.cfg
├── group_vars
│   └── webservers
│       └── vars
├── host_vars
│   └── demo.example.com
│       ├── vars
│       └── vault
├── inventory
└── playbook.yml

If you do create subdirectories for each host group or managed host, most variables for demo.example.com can be placed in the vars file, but sensitive variables can be kept secret by placing them in the vault file. You can use ansible-vault to encrypt the vault file and leave the vars file as plain text.

You can name files in the host_vars/demo.example.com any valid file name you choose. The file names used in the host_vars/demo.example.com directory are examples only; they have no special significance. That directory could contain more files, some that are encrypted by Ansible Vault, and some that are not.

Playbook variables (as opposed to inventory variables) can also be protected with Ansible Vault. You can place sensitive playbook variables in a separate file that is encrypted with Ansible Vault, then include that encrypted variables file in a playbook by using 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 each of the Vault passwords that you provided until it finds the right one.

Revision: rh294-9.0-c95c7de