Hello!

What if we need to create a user in the database and store their password securely in code? This can be done using ansible vault. Ansible vault allows you to encrypt both the entire file and individual variables.

Encrypted file

Let’s create a file that will contain our variables.

db_password: secure_password!
admin_password: super_securee_password!

We cannot simply leave this file because it stores passwords. But it can be encrypted using the ansible-vault encrypt VAR_FILE command. You will need to enter a password that will be used for decryption.

$ ansible-vault encrypt 1.yml
New Vault password:
Confirm New Vault password:
Encryption successful

And the file itself will look like this and can be added to source control.

$ANSIBLE_VAULT;1.1;AES256
32393936363535383238323361373334376664613530346332336333653066366437336232313761
3638396339376462636630336161376161396637366338360a653962326431616266656463613966
32366130613763343937366363623864646263616664323231633662626333353331613537613733
3132393337346431660a613037333166626563306634346461303538383237376263373734626666
64623136336535323230303631313736376162363633626264346538646163363339643438396633
62653234373230323538616563306130353334333931616338363561346530633335346562363837
62656166613939303139653233346466393636666637353438376230393935336638363664303037
64313162363661396161

This file is a normal file with variables, but when running ansible-playbook you need to pass a password for decryption. There are several ways to do it. First, with `–ask-vault-pass’ key, in this case, Ansible will ask for a password at startup. Accordingly, this option is not suitable for automatically starting Ansible, because the password must be entered every time.

Let’s use the following code for the test, where vars are our encrypted variables

---
- name: Run locally
  hosts: localhost
  connection: local
  vars_files:
  - vars.yml

  tasks:
  - name: Print var
    debug:
      msg: "{{ db_password }}"
$ ansible-playbook -i "localhost," main.yml --ask-vault-pass
Vault password:

PLAY [Run locally] *****************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************
ok: [localhost]

TASK [Print var] ******************************************************************************************************************
ok: [localhost] => {
    "msg": "secure_password"
}

PLAY RECAP ************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

The next option is using a file with a password. For this, a file is created in which the password will be stored and ansible is launched with the key --vault-password-file PATH_TO_FILE

$ ansible-playbook -i "localhost," main.yml --vault-password-file .vault_pass

PLAY [Run localy] *****************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************
ok: [localhost]

TASK [Print var] ******************************************************************************************************************
ok: [localhost] => {
    "msg": "secure_password"
}

PLAY RECAP ************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

If you run it without these variables, you will get

ansible-playbook -i "localhost," main.yml
ERROR! Attempting to decrypt but no vault secrets found

Decrypt file

To edit the encrypted file, you can use the ansible-vault edit ENCRYPTED_FILE command, enter the password and edit the file.

Change vault password

The password can be changed using the ansible-vault rekey VAULT_FILE command

ansible-vault rekey vars.yml
Vault password:
New Vault password:
Confirm New Vault password:
Rekey successful

Encrypted variable

If you do not need to encrypt an entire file, but only one parameter, this can also be done using the `ansible-vault encrypt_string ‘TEXT_TO_ENCRYPT’ –name ‘VARIABLE_NAME’’ command.

ansible-vault encrypt_string 'secure' --name db_password
New Vault password:
Confirm New Vault password:
Encryption successful
db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          32613335323933306136303139616131303039396139646332656337343532383034336439363739
          3032376165376462653533633731626366613337356234340a353662343931366436643635383666
          32313163373765333666623065373930616431333365656331376362316464363038636136346138
          3033376563636437630a663533383336353434336566633935396137373737303662636432326433
          3630

As a result, we get a parameter that can be added to other unencrypted variables. But as with an encrypted file, when you run ansible, you need to pass the password for decryption. If we encrypt several variables, they must have one password for decryption

app_port: 8080
db_user: postgres
db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          32613335323933306136303139616131303039396139646332656337343532383034336439363739
          3032376165376462653533633731626366613337356234340a353662343931366436643635383666
          32313163373765333666623065373930616431333365656331376362316464363038636136346138
          3033376563636437630a663533383336353434336566633935396137373737303662636432326433
          3630

To not specify the password in the terminal when encrypting, you can also use a file with a password using the --vault-password-file key.

ansible-vault encrypt_string --vault-password-file pass 'secure' --name db_password
Encryption successful
db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          31623232663866376238643739353231323835646530326531333766623831363637396130363330
          6139303362643962343432353765643639623339396134370a653236336433613064303530623933
          34633765636536333935363833323537356134653333326562363435653437366639393136316336
          6462363437633130330a366439653933353766326565623464353364626234623862666265643539
          3338

For the test, we will use the following code:

---
- name: Run locally
  hosts: localhost
  connection: local
  vars:
    admin_password: !vault |
              $ANSIBLE_VAULT;1.1;AES256
              31386261643538643135333865383233656435366161333865393232643035393265393963646331
              6130636537343866653733623938363030333739313031300a393663356165343038656164323365
              32303230376536306633633936303430396234343961393862323434663435626136313062663032
              3661653564353539650a323733376635306562383263613738383934313931353062633266323762
              34343231386139303737613538346430633336383165333065303532373738636661

  tasks:
  - name: Print var
    debug:
      msg: "{{ admin_password }}"

And I will get the result

$ ansible-playbook -i "localhost," main.yml --vault-password-file .vault_pass

PLAY [Run localy] *****************************************************************************************************************

TASK [Gathering Facts] ************************************************************************************************************
ok: [localhost]

TASK [Print var] ******************************************************************************************************************
ok: [localhost] => {
    "msg": "secure_admin_password"
}

PLAY RECAP ************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Video