Search code examples
ansibleansible-vault

Ansible Vault: How to access vault keys dynamically


I inherited a project where all database users have the same password (bad!). This password is stored in an Ansible Vault (good). I want to modify the roles so that each user has a unique password stored in the vault.

Current Vault:

---
DB_USER: secretpass

Current Vars:

mysql_remote_users_enabled:
  - user: user1
    host: ip_address1
  - user: user2
    host: ip_address2

Current Task:

- name: "mysql remote users present"
  mysql_user:
    login_user: root
    login_password: "{{ mysql_root_passwd }}"
    name: "{{ remote_user.user }}"
    host: "{{ remote_user.host }}"
    password: "{{ DB_PASS }}"
    state: present
  with_items:
    "{{ mysql_remote_users_enabled }}"
  loop_control:
    loop_var: remote_user

How can I store a unique password for each user in the vault and access these vault variables dynamically in my Ansible task?


Solution

  • The more practical way of doing it is to do the encryption at the value level:

    ## The password for those two vaulted value is `foobar`
    mysql_remote_users_enabled:
      - user: user1
        host: ip_address1
        password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          3633353366323334653265343961373732346331363565336139326136623
          1343661633131323938383465396565363364333237383436323139633232
          3336310a62316362623361393730343765346234343266386165663038636
          2656562363834653534376565653335623432646366646433363735333034
          313662646166620a653965646263366133336362376332333435653932313
          2613664353533326230
      - user: user2
        host: ip_address2
        password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          3538333130323831313136653338316261643832336237646639646264343
          5303832306663663936383637326233643733316565323133356536613432
          6530640a31373161323238663062623035346338613766653239633432393
          2396666666437336235316334353463643737356262313662646339633831
          393833646162630a656636636331633532396532373863666366636162663
          2303366666538663962
    

    Then, use it in the task:

    - name: MySQL remote users
      mysql_user:
        login_user: root
        login_password: "{{ mysql_root_passwd }}"
        name: "{{ remote_user.user }}"
        host: "{{ remote_user.host }}"
        password: "{{ remote_user.password }}"
        state: present
      loop: "{{ mysql_remote_users_enabled }}"
      loop_control:
        loop_var: remote_user
    

    To vault a single value, use the encrypt_string command of ansible-vault:

    # For example to encrypt `foo`
    $ ansible-vault encrypt_string 'foo'
    New Vault password: 
    Confirm New Vault password: 
    Encryption successful
    !vault |
          $ANSIBLE_VAULT;1.1;AES256
          3633353366323334653265343961373732346331363565336139326136623
          1343661633131323938383465396565363364333237383436323139633232
          3336310a62316362623361393730343765346234343266386165663038636
          2656562363834653534376565653335623432646366646433363735333034
          313662646166620a653965646263366133336362376332333435653932313
          2613664353533326230
    

    Note: you can also use it with a different vault ID or a password files, for more options see the documentation, or the --help of ansible-vault.


    As for accessing a variable dynamically, this is unrelated to vaulting, the way to access a dynamic variable, vaulted or not, is to use the vars lookup.

    For example:

    - debug:
        msg: "{{ lookup('vars', 'DB_' ~ remote_user.user | upper ~ '_PASS') }}"
      vars:
        remote_user:
          user: user1
        DB_USER1_PASS: foobar
    

    Would yield

    ok: [localhost] => 
      msg: foobar