5

We use Ansible to create users with this task:

- name: Create adm users
  user:
    name: "{{ item.name }}"
    group: "{{ common_adm_group }}"
    createhome: yes
    password: "!!"
    update_password: always
    state: present
  with_items: "{{ common_adm_users }}"

And common_adm_users is like this:

  - name: user1
    comment: "First Last"
    ssh_key: "ssh-rsa AAAAB3Nza..."

This works fine for creating users, but when someone leaves the team, just removing their user from common_adm_users doesn't cause it to be removed from the servers when we re-apply the role that includes this task.

What is the best practice to maintain an exact list of users?

  • You're correct, the ansible user module is very basic. For what you want you'll either be rolling your own role, using something from ansible galaxy, or using external auth (LDAP, AD, etc.). – jscott Feb 3 '17 at 1:10
  • Why don't you just state: absent the sacked users? – Michael Hampton Feb 3 '17 at 2:40
5

This is a similar answer to @Konstantin Suvorov's but a bit more refined, with some nuances clearly spelled out, and actually tested and in-use.

Using the following, you only need maintain a single list of usernames you wish to have access. Any additions or removals from that list will be reflected in host access.

Optional helpful tip: We actually choose to use our GitHub usernames for this list, as then we can easily add SSH keys as well. See the end for an example.

First, in our group_vars we define our list of developers we wish to have access (note that this can be defined in multiple ways, not just group_vars):

developers:
  - user1
  - user2
  - etc...

Second, we create a group for which we will assign our developers to:

- name: Create "developers" group
  group:
    name: developers
    state: present

Third, we add our developers to this group. NOTE that we add them via the groups and not group property. This adds it as a secondary group and ensures they appear in /etc/group. This is critical because if you add them as a primary group, they will not appear as a member of that group in /etc/group:

- name: Add user accounts
  user:
    name: "{{ item }}"
    shell: /bin/bash
    groups: [developers]
    state: present
  with_items: "{{ developers }}"

Fourth, we then get all users that currently belong to the developers group on the host (Note that this is dependent on the primary/secondary assumption mentioned in the prior step) :

- name: Determine existing users
  shell: 'grep developers /etc/group | cut -d: -f4 | tr "," "\n"'
  changed_when: false 
  register: existing_users

Fifth, determine which of those users should be removed (e.g. those that are not defined in our developers group_vars list):

- name: Determine removed users
  set_fact:
    removed_users: "{{ existing_users.stdout_lines | difference(developers) }}"

Sixth and last, remove them:

- name: Delete removed user accounts
  user:
    name: "{{ item }}"
    state: absent
  with_items: "{{ removed_users }}"

Optional helpful step - If adding users by GitHub username, you can easily grant them SSH access from the public key they have available on GitHub:

- name: Add public ssh keys of users
  authorized_key:
    user: "{{ item }}"
    exclusive: yes
    key: https://github.com/{{ item }}.keys
    state: present
  with_items: "{{ developers }}"
| improve this answer | |
  • 1
    Very well explained, this should be the accepted answer. – Karthik T Sep 18 '18 at 8:57
2

You need to do some extra tasks here.

After adding all required users, grab existing users, e.g.:

- shell: 'grep {{ common_adm_group }} /etc/group | cut -d: -f4 | tr "," "\n"'
  changed_when: false # Make task green
  register: existing_users

and remove stale ones:

- user:
    name: "{{ item }}"
    state: absent
  with_items: "{{ existing_users.stdout_lines | difference(common_adm_users | map(attribute='name') | list) }}"

Note: code is not tested, may contain typos etc.

| improve this answer | |
0

You could actually just add a field to your existing task:

- name: Create adm users
  user:
    name: "{{ item.name }}"
    group: "{{ common_adm_group }}"
    createhome: yes
    password: "!!"
    update_password: always
    state: "{{ item.state | default('present') }}"
  with_items: "{{ common_adm_users }}"

And then make the data for leaving team members look like:

- name: user1
    comment: "First Last"
    ssh_key: "ssh-rsa AAAAB3Nza..."
    state: "absent"
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.