Ansible Credentials and Variable Overrides
Let’s say we need to create mysql users. We’ll be overloading at the group_vars level, with group_vars/all/mysql_users.vault.yml
being overridden by the more specific group_vars/production/mysql_users.vault.yml
. Although we can set some basic stuff for all the hosts in a role, we want it to be available to both the database and the app roles without introducing dependencies. Hence, group_vars/all
.
In ansible, to get a merging rather than replace behaviour for hashes, we set hash_behaviour = merge
in ansible.cfg. The default behaviour is to replace the value and ONLY hashes can have the merge behaviour. The variables can be overriden in the group_vars directory and the variables set and loaded in all
are overriden in the specific environment group. The only time there may be confusion is if a host is part of two groups, let’s say production and app, and the variable is set in both places.
Sample group_vars/all/mysql_users.vault.yml:
mysql_users:
root:
password: test123
host: localhost
priv: '*.*:ALL,GRANT'
repl:
password: replpass
priv: '"*.*":"REPLICATION SLAVE,REPLICATION CLIENT"'
and we can override it in group_vars/production/mysql_users.vault.yml
mysql_users:
root:
password: therealpass
This gets called with the iterator with_dict
in a playbook:
- name: Create all the mysql users
tags: mysql_user
mysql_user: name={{ item.key }} password={{ item.value.password }} host={{ item.value.host | default("%") }} priv={{ item.value.priv | default("*.*:USAGE")}} state=present
with_dict: mysql_users
So that’s fairly straightforward. There are more complicated situations, for instance, creating a set of users with authorized_keys. I’m modifying the example given here which is using a list. But lists can’t be merged, so the data structure needs to be modified to a dict that works while using with_subelement
. What I’ve found works is below:
users:
alice:
name: alice
authorized:
- /tmp/alice/onekey.pub
- /tmp/alice/twokey.pub
bob:
name: bob
authorized:
- /tmp/bob/id_rsa.pub
- user: name={{ item.name }} state=present generate_ssh_key=yes
with_items: users
- authorized_key: "user={{ item.0.name }} key='{{ lookup('file', item.1) }}'"
with_subelements:
- users
- authorized
Modelling the data this way allows overrides and usage with ansible’s iterators.