One of the sweetest side of Ansible is its ultra easy learning curve which allows IT people to grasp it almost instantly.
Ansible is known for being entirely plain text which means that also passwords are unencrypted... Or not?
This is for you, who are looking for a way to protect your private data within playbooks.
What is Ansible Vault? And what are Vault IDs?
ansible-vault
is the Ansible tool for protecting secret information. It can create encrypted file and encrypt plain text ones.
Ansible-vault has the option to view
and edit
the encrypted file and allows for replacing the old password used to encrypt a file with a new one, and decrypts the file too!
It only has one issue: It does not support having multiple encrypted vaults in the same playbook. Starting with Ansible version 2.4, Vault IDs are the way to go when adding in your playbook multiple encrypted files.
We will go through setting up an Ansible Vault for showing how quick this process can be, with a major focus on the Vault IDs.
Create and operate your Vault
ansible-vault
comes as a utility when installing ansible
, which means you pretty much have it already in you system!
The vault file extension can be any, or none. Generally in Linux extensions don't matter, and for this reason ansible-vault
can be used to encrypt many types of file, but for their purpose in Ansible, we will encrypt files in YAML format because their content as key: value
is our secret variables and we will use them for our secret playbook!
How to use ansible-vault
You can start with a simple text file. Let's create a yaml file that stores our password
cat > mysecret.yml<<EOF
foo: bar
EOF
And encrypt it
ansible-vault encrypt mysecret.yml
You will be asked to provide a password. This password will unlock the file. As any other password, try not to forget it (:
New Vault password:
Confirm New Vault password:
Encryption successful
You can now use this vault file in your playbook and run it as ansible-playbook play-vault-file.yml --ask-vault-pass
- name: test password file
hosts: localhost
gather_facts: false
vars_file:
- mysecret.yml
tasks:
- debug:
var: foo
You can also create a file and encrypt it already:
ansible-vault create vault.yml
And other useful commands to operate with your vault are:
-
View
ansible-vault view vault.yml
-
Edit
ansible-vault edit vault.yml
-
Update vault key (rekey)
ansible-vault rekey vault.yml
-
Decrypt
ansible-vault decrypt vault.yml
-
Encrypt string
ansible-vault encrypt_string "hello Ansible" --name mysecretvar
The option encrypt_string
doesn't directly operate on vault files but it is particularly useful for encrypting a string on-the-fly and use it in a playbook as extra vars:
Quoting from the ansible-vault doc:
Typing secret content directly at the command line (without a prompt) leaves the secret string in your shell history. Do not do this outside of testing.
So, maybe, instead of using the format above it is suggested to get the secret from --stdin
:
ansible-vault encrypt_string --stdin-name 'new_user_password'
New Vault password:
Confirm New Vault password:
Reading plaintext input from stdin. (ctrl-d to end input, twice if your content does not already have a newline)
myNewNotSoSecurePassword!
Encryption successful
new_user_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
39623231313438633166383138633162636638333435336331343830303763643161663831316462
3239386139633239666333353730343663353164316163650a643663376665393063336134633561
63616266396263353231636438613232306430646331366366653464386161333837346661643761
3732353133653037320a363536666664663963356339663563613837326432366262613038663236
3862
Which we can then use in a playbook and run it as ansible-playbook play-vault-var.yml --ask-vault-pass
- name: test password var
hosts: localhost
gather_facts: false
vars:
new_user_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
39623231313438633166383138633162636638333435336331343830303763643161663831316462
3239386139633239666333353730343663353164316163650a643663376665393063336134633561
63616266396263353231636438613232306430646331366366653464386161333837346661643761
3732353133653037320a363536666664663963356339663563613837326432366262613038663236
3862
tasks:
- debug:
var: new_user_password
And this, people, is what you should avoid!
Technically, this is not wrong. There are better ways to manage and call vault variables and files.
I'll see you in the next chapter, where we introduce the Vault IDs and Ansible tweaks for storing master passwords!
Meet the Ansible Vault IDs
The Ansible Vault ID is a user-defined string that helps identify a particular vault password. It's like giving a name or label to a specific vault password.
With Vault ID we can use different vault passwords for different files or environments.
How to Use Vault ID
When working with Vault ID with files, you can specify a Vault ID using the --vault-id
option.
- Create the vault.yml
This creates vault.yml
using the vault password associated with the vault ID my-vault-id
.
ansible-vault create --vault-id my-vault-id@prompt vault.yml
New vault password (my-vault-id):
Confirm new vault password (my-vault-id):
- Decrypt the vault.yml
This decrypts the vault.yml
using the vault password associated with the vault ID my-vault-id
.
ansible-vault decrypt --vault-id my-vault-id@prompt vault.yml
Vault password (my-vault-id):
Decryption successful
Other operations are also allowed, same as the basic vault files.
Handling multiple Vault file
Have you noticed the @prompt
?
This option allows us to type in the password of the vault file similar to --ask-vault-pass
that we used earlier. The main difference is --ask-vault-pass
can be called only once when launching the playbook:
ansible-playbook play-vault-var.yml --ask-vault-pass
While with @prompt
we can feed multiple vault files:
ansible-playbook playbook.yml --vault-id dev-vault@prompt --vault-id prod-vault@prompt
Although this is not exactly related to @prompt
rather to --vault-id
, it's the best example for showing why Vault ID is the preferred choice when working with multiple vault files.
Playbook example with multiple Vault ID
Let's go for a full run of how to use multiple Vault ID in Ansible!
1) Create the vault files in plain text.
prod.yml
---
prod: This is Prod
dev.yml
---
dev: This is Dev
2) Encrypt the vault files. Choose a different password for each vault.
ansible-vault encrypt --vault-id prod@prompt prod.yml
ansible-vault encrypt --vault-id dev@prompt dev.yml
3) Create the playbook play-vault.yml
.
- name: Test multiple vaults
hosts: localhost
vars_files:
- dev.yml
- prod.yml
gather_facts: false
tasks:
- debug:
msg: "DEV: {{ dev }}"
- debug:
msg: "PROD: {{ prod }}"
4) Run the playbook.
ansible-playbook play-vault.yml --vault-id dev@prompt --vault-id prod@prompt
5) Look at the output.
ansible-playbook play-vault.yml --vault-id dev@prompt --vault-id prod@prompt
Vault password (dev):
Vault password (prod):
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [test password] ************************************************************************************************************************************************************************
TASK [debug] ********************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "DEV: this is Dev"
}
TASK [debug] ********************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "PROD: this is Prod"
}
PLAY RECAP **********************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Do not ask for passwords!
Whether we're using the simplest form of Vaults or the Vault ID, we can set them up so when we run the playbook it doesn't ask us for the password. And not only for playbooks. This option has effect anytime we work with vaults. ansible-vault view
, create
, encrypt
and so on.
In the ansible.cfg
we can find the option named vault_password_file
. We can uncomment it and update its value to point to a file that contains the password for unlocking the vault.
...
vault_password_file=/home/user/mysecret.txt
And the password for the vault inside mysecret.txt
(no, the .txt extension is not required, but it helps to recognize the kind of file instantly):
mypassword
While this approach works great with simple Ansible vaults because the option vault_password_file
accepts strings only, it is not ideal for Vault ID.
With Vault ID we can replace @prompt
with the path to the secret file.
ansible-playbook play-vault.yml --vault-id dev@dev-vault.txt --vault-id prod@prod-vault.txt
Conclusions
In a nutshell, Ansible Vault is like the superhero of secret-keeping for your playbooks. It effortlessly locks away your sensitive info, ensuring passwords and secrets stay as classified as a top-secret spy mission.
With a user-friendly vibe, it turns the daunting task of encryption into a walk in the digital park. Plus, the magic touch of using different vault passwords? It's like having personalized security guards for your 'Dev' and 'Prod' environments.
So, in the world of Ansible, consider Ansible Vault your trusty sidekick, ensuring your playbook secrets are safe and sound.