Search code examples
ansibleansible-inventoryansible-templateansible-vault

How do I store 'ansible' hosts credentials in a different file using 'ansible-vault'?


Right now my inventory file looks like this: (using password-based authentication)

[testvm]
104.231.213.32 ansible_user=worker ansible_password=Worker@12345
52.176.22.203 ansible_user=worker2 ansible_password=Worker2@12345

How do I store the username and password in a different file using ansible-vault and use that file in runtime?

I have tried encrypting single variables and reformatting the hosts file in .yml by using:

ansible-vault encrypt_string 'Worker@12345'--vault-id admin@prompt --name 'ansible_password'

This results in:

all:
  children:
    ubuntu:
      hosts:
        104.231.213.32:
          ansible_user: !vault |
            $ANSIBLE_VAULT;1.2;AES256;admin
            33363434333133333263396366373038613637626233666136383431346532626561343633323034
            6133653864353638353830323462363832633131633566300a396236656564366665656466383436
            35643631373230393762636638346564376361343864653833343864346262633734393863336335
            3133633534646631620a353865323561363966396461626664353163313430653064396431633637
            3962
          ansible_password: !vault |
            $ANSIBLE_VAULT;1.2;AES256;admin
            32353137656161646166626661353763363235643634383338623735623964626134343035383430
            3564346262653066383565636236313462663862336361300a623139373831633662633734626166
            62316465386531333261323935383264383262623039346664393036313030306131633936646631
            6233373962373966370a373363343432353662363037343837653463366337653230623161313633
            3633
        52.176.22.203:
          ansible_user: !vault |
            $ANSIBLE_VAULT;1.2;AES256;admin
            38663536393035633533333538646365306439306133343861343363323164663366653430393333
            3235383435386630343231323338383366353462616265610a316338613861383334336436373337
            63616538656439396162626264356566313837613564663365356337386134363936616166623436
            3436663933373537320a653536396538636165376239653637653465323461313764323630383533
            3661
          ansible_password: !vault |
            $ANSIBLE_VAULT;1.2;AES256;admin
            65306434346538643464353464633762663765613636396638373735333465356237613033616666
            3336366262363064396538373664636564616561323231360a616537366261613332333633666439
            36303130353166613339366432386330333964643734633235346137316238633132316661346563
            6138666136653536640a393637383038363266646239306663626632663766396663643632633934
            6537

The problem with this approach is that if I have different usernames and passwords across multiple servers, I have to encrypt each credential separately with the same vault id and password. If I want to group the hosts differently I'd have to rearrange the whole file which is already too bulky.

Instead, I am looking for a solution that lets me keep my IPs in a single file (So that I can group them however I want) and store the credentials associated with the said IPs in a different encrypted file and use that file in runtime.

So, the final structure should look something like this:

The hosts IP file:

# /ansible/inventory/hostsIP
[testvm]
104.231.213.32
52.176.22.203

The hosts credentials file: (Encrypted Ofcourse)

# /ansible/inventory/hostsCredentials
104.231.213.32 ansible_user=worker ansible_password=Worker@12345
52.176.22.203 ansible_user=worker2 ansible_password=Worker2@12345

and some commands with which I can link the two during runtime.


Solution

  • Here is how I would do this:

    ./inventory/group_vars/all/credentials.yaml

    ---
    credentials:
      104.231.213.32:
        user: a_user
        password: a_password
      52.176.22.203:
        user: an_other_user
        password: an_other_password
    

    Note: above is the unencrypted content. You should encrypt this with ansible-vault encrypt ... and later edit with ansible-vault edit ...

    ./inventory/group_vars/all/main.yml

    ---
    ansible_user: "{{ credentials[inventory_hostname].user | d('default_user') }}"
    ansible_password: "{{ credentials[inventory_hostname].password | d('default_password') }}"
    

    ./inventory/main.yml

    ---
    testvm:
      hosts:
        104.231.213.32:
        52.176.22.203:
    

    And you can test that this is working with a simple ad-hoc command:

    ansible all -i inventory/ -m debug -a "msg='User: {{ ansible_user }} / Password: {{ ansible_password }}'"
    

    Which should give in the above case:

    $ ansible all --ask-vault-pass -i inventory/ -m debug -a "msg='User: {{ ansible_user }} / Password: {{ ansible_password }}'"
    Vault password: 
    104.231.213.32 | SUCCESS => {
        "msg": "User: a_user / Password: a_password"
    }
    52.176.22.203 | SUCCESS => {
        "msg": "User: an_other_user / Password: an_other_password"
    }