Looping Ansible on Per-user Basis

When I moved my home network to Ansible, I had one problem repeating in many roles. How to do some action for every user?

For example, take setitng up a default .SSH configuration or Bash profile. While setting it for known users is easy enough, I wanted a role to setup things automatically for any user present on the system. Since searches of existing solutions didn't fully apply to my solution, I decided to roll my own.

The first part is getting list of users and here is where good old passwd comes into play. However, one needs to filter it first for all accounts that cannot log into the system.

grep -v -e '/nologin$' -e '/bin/false$' -e '/bin/sync$' /etc/passwd

In Ansible, collecting this data would look something like this:

- name: Find all users
  shell: "grep -v -e '/nologin$' -e '/bin/false$' -e '/bin/sync$' /etc/passwd"
  register: grep_users_result
  changed_when: false
  failed_when: false

With user list in hand, we can now include the other task and forward it data it needs. In my case, that would be user name and its directory.

- name: Setup user
  include_tasks: peruser.yml
  vars:
    user_name: "{{ item.split(':').0 }}"
    user_directory: "{{ item.split(':').5 }}"
  with_items: "{{ grep_users_result.stdout_lines | list }}"

Finally, we can use those variables in a separate task file:

- name: "Setup .ssh directory ({{ user_name }})"
  file:
    path: "{{ user_directory }}/.ssh"
    state: directory
    owner: "{{ user_name }}"
    group: "{{ user_name }}"
    mode: "0700"

Easy peasy.

Leave a Reply

Your email address will not be published. Required fields are marked *