Ansible Manage the Same Users Across Servers with Different Passwords

Saturday, April 19, 2014

Recently, I was setting up a handful of servers that all needed the same user created but with a different password for that user on each server. Searching around the internet, I did not find a definitive way to manage users and most of what I found consisted of bits and pieces of what I was looking for. I ultimately settled on the following solution.

This solution can definitely be improved upon by using group_vars and variable overrides to remove redundant attributes.

This post assumes you have some experience with Ansible and already have an existing Ansible Environment. If you do not, see this post to get started.

Ansible Directory

My Ansible Environment exists within directory ~/Development/ansible-lab on my workstation. Any files or directories created in this post will be created within this directory.

Ansible Inventory File

As mentioned above, I had five servers that all needed the same user created but with a different password for that user on each server, so I created file ~/Development/ansible-lab/hosts with the following contents:

server1.example.com
server2.example.com
server3.example.com
server4.example.com
server5.example.com

Ansible Host Variables

Next, I created a host_vars directory and changed into that directory:

mkdir ~/Development/ansible-lab/host_vars

cd ~/Development/ansible-lab/host_vars

Inside the host_vars directory, I created five files named after the sever’s Ansible Inventory Name, so one file named server1.example.com, a second file named server2.example.com, etc. The host_vars files must be named exactly as they are named in the Ansible Inventory File so the Ansible Task can reference the variables.

Each host_vars file contained the following contents but the hashed password would be different for each file (see this post on how to hash passwords):

---
users:
 mal:
   password: $1$.NUoqVPD$RX8Bkhy/LBuuO0MDztQU.1
   shell: /bin/bash
   state: present

Ansible Playbook

Next, I changed back into the ansible-lab directory:

cd ~/Development/ansible-lab

I created a playbooks directory and changed into that directory:

mkdir ~/Development/ansible-lab/playbooks

cd ~/Development/ansible-lab/playbooks

Inside of the playbooks directory, I created an Ansible Playbook called users.yml with the following contents:

---
- hosts: all

  tasks:
  - name: Add users from host_vars file
    action: user name={{ item.key }} password={{ item.value.password }} shell={{ item.value.shell }} state={{ item.value.state }} update_password=always
    with_dict: users

This particular task will loop through all of the users defined in each server’s host_vars file. Because there is only one user, only one user will be created, but if there were N number of users, N number of users would be created.

If a particular user’s password needs to be changed, go to the particular host_vars file for the server the user’s password needs to be changed on, modify the password, and re-run the users.yml Ansible Playbook to update the user’s password.

In addition, if a particular user needs to be removed from a particular server, go to the particular host_vars file for the server that the user needs to be removed from, change the value of the state attribute from present to absent, and re-run the users.yml Ansible Playbook to remove that user.

Additional functionality can be added to this Ansible Task by using the other attributes available in the Ansible User Module.

References

Centralized User List

Variable precedence: inventory versus host_vars



comments powered by Disqus