0
votes

I am using an Ansible playbook to manage users (taken from https://keksi.io/tutorials/2016/12/05/how-to-manage-remote-server-users-with-ansible/):

vars/users.yml file (users, user to group assignments, passwords, SSH keys):

---
users:

  - username: user1
    comment: "User 1"
    group: admin
    password: "sha password"
    keys:
      active:
        - "ssh-rsa etc"
    admin: yes

  - username: user2
    comment: "User 2"
    group: users
    groups: deployer
    keys:
      active:
        - "ssh-rsa etc"

  - username: user3
    [...]

And this is the playbook:

- hosts: all
  become: true

  tasks:
    - include_vars: ../vars/users.yml

    - name: Install sudo
      apt: name=sudo state=present

    - name: Add the group admin
      group:
        name: admin
        state: present

    - name: Create users
      user:
        name: "{{ item.username }}"
        comment: "{{ item.comment | default('User {{item.username}}') }}"
        password: "{{ item.password | default('!') }}"
        state: "{{ item.state | default('present') }}"
        shell: "{{ item.shell | default('/bin/bash') }}"
        group: "{{ item.group | default('users') }}"
      when: item.username is defined
      with_items: '{{ users }}'

    - name: Setup administrator users with complete sudo access
      user: name={{ item.username }} groups=sudo append=yes
      with_items: '{{ users }}'
      when: item.admin is defined and item.admin == True

    - name: Add SSH-keys to users
      authorized_key:
        user: "{{ item.0.username }}"
        key: "{{ item.1 }}"
      with_subelements:
        - "{{ users }}"
        - keys.active
        - flags:
          skip_missing: True
      when: item.0.state is not defined or item.0.state != "absent"

    - name: Remove old SSH-keys from users
      authorized_key:
        user: "{{ item.0.username }}"
        key: "{{ item.1 }}"
        state: absent
      with_subelements:
        - "{{ users }}"
        - keys.disabled
        - flags:
          skip_missing: True
      when: item.0.state is not defined or item.0.state != "absent"

I can correctly execute this playbook on all servers and have admin and normal users created and managed on them.

Now I want to add a new step. I have several servers, and not every users should be configured on every server, and some users should be in an additional group only on some servers (for example developers on developing servers).

So I wish to create some assignments for users on hosts or host groups, something like:

- host: host1
  admins:
    - user1
    - user2
  deployers:
    - user2
    - user3
  users:
    - user4
    - user5

- host: hostgroup1
  admins:
    - user2
  users:
    - user3
    - user5

So I would like to be able to execute the playbook on all servers to have users created or updated based on this declarations, without writing a duplication of the playbook for every host.

I don't have any idea about how to achieve this, could you help me please?


Edit: I tried to add a new "hosts" key in my users.yml variable file, this way:

---
users:

  - username: user1
    comment: "User 1"
    group: admin
    password: "sha password"
    keys:
      active:
        - "ssh-rsa etc"
    admin: yes

  - username: user2
    comment: "User 2"
    group: users
    groups: deployer
    keys:
      active:
        - "ssh-rsa etc"
    hosts:
      user:
        - host1
        - host2
      deployer:
        - host3

And I modified the task this way:

- name: Create users
  user:
    name: "{{ item.username }}"
    comment: "{{ item.comment | default('User {{item.username}}') }}"
    password: "{{ item.password | default('!') }}"
    state: "{{ item.state | default('present') }}"
    shell: "{{ item.shell | default('/bin/bash') }}"
    group: "{{ item.group | default('users') }}"
  with_items: '{{ users }}'
  when: item.username is defined and ((item.admin is defined and item.admin == True) or (item.hosts is defined and item.hosts.user is defined and inventory_hostname in item.hosts.user)

My explanation: I need to create the user if it's admin (so it must be created on every host or if the current host's inventory_hostname is listed into one of the hosts subkeys arrays (in a second step I wish to extend this check also if the current host is in an hostgroup listed in one of item.hosts subkeys.

The problem is that this way user1 is created (because item.admin is True) but user2 not because the other condition is always False.

1
I created a new specific thread (stackoverflow.com/questions/53237393/…) for my "check in list" question. Thanks!Mat
Why not to create another level within users: Admins/ Dev/Support/ and then pass it to every host based on your tags/requirements. i.e. as default apply Admins to every host, an then if host_tag == something apply users.Support and so on. Let me know if this is something you want.MMT

1 Answers

0
votes

You could use host_vars or group_vars to store the users data instead of vars/users.yml

When you run the playbook against multiple hosts the appropriate values for each host or group member will be read from the related group_vars or host_cars file

See here for more information: https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#splitting-out-host-and-group-specific-data