Home > Back-end >  Validation of Ansible Playbook To Create Users and Groups
Validation of Ansible Playbook To Create Users and Groups

Time:01-15

I have the following playbook that is supposed to create user, group, disable remote password login etc.,

---
- name: Create groups & users
  hosts: all
  gather_facts: false
  become: true
  vars:
    # Define group and user as variable
    user_group: myuserhrp
    user_name_1: myuser

  tasks:
    - name: Create group
      group:
        name: "{{ user_group }}"
        state: present

    - name: Create user
      user:
        name: "{{ item }}"
        state: present
        password: "{{ default_user_password | password_hash('sha512','A512') }}"
        shell: /bin/bash
        group: "{{ openelectrons_k3s_group }}"
      loop:
        - "{{ user_name_1 }}"

    - name: Add user to the sudoers
      copy:
        dest: "/etc/sudoers.d/{{ item }}"
        content: "devops  ALL=(ALL)  NOPASSWD: ALL"
      loop:
        - "{{ user_name_1 }}"

    - name: Deploy SSH Public Key
      ansible.posix.authorized_key:
        user: "{{ item }}"
        state: present
        key: "{{ lookup('file', '/home/{{ item }}/.ssh/id_rsa.pub') }}"
      loop:
        - "{{ user_name_1 }}"

    - name: Disable Password Authentication
      lineinfile:
        dest=/etc/ssh/sshd_config
        regexp='^PasswordAuthentication'
        line="PasswordAuthentication no"
        state=present
        backup=yes

    - name: Disable Root Login
      lineinfile:
        dest=/etc/ssh/sshd_config
        regexp='^PermitRootLogin'
        line="PermitRootLogin no"
        state=present
        backup=yes
      notify:
        - restart ssh

  handlers:
  - name: restart ssh
    service:
      name=sshd
      state=restarted

I would like to know if that playbook is correct before I apply it on my set of hosts. I have the following questions:

  1. Is my way of looping over user's correct when I create them?
  2. With which user will this playbook run on my remote hosts? Should those users be created upfront on all my remote hosts? Can I for this purpose, use any default users? For example., I have a set of Ubuntu 22.04 servers which are my hosts and there is a default user called ubuntu. Can I use this user to run this playbook?

CodePudding user response:

Is my way of looping over user's correct when I create them?

Although it is not absolutely wrong, it's definitely not the most efficient as it will not scale when you add more users either because of their number or the needed information to declare them.

As a first step, what I would do in a such a scenario is define a list of usernames in my play vars (or elsewhere as in my host_vars, group_vars, extra_vars, ...)

  vars:
    users:
      - myuser1
      - myuser2

You can the easilly extend that list when needed and use it in a loop that you don't have to modify when it grows:

    - name: Create user
      user:
        name: "{{ item }}"
        state: present
        password: "{{ default_user_password | password_hash('sha512','A512') }}"
        shell: /bin/bash
        group: "{{ openelectrons_k3s_group }}"
      loop: "{{ users }}"

A second step to make this even more scalable is to transform that list to a list of dicts so that you can define more user specific fields. The following is just an example to widen your perspective. Adapt to your real needs. The list could be transformed to:

  vars:
    default_group: some_default
    users:
      - name: myuser1
      - name: myuser2
        primary_group: my_toto_group
        password: totopipo # This one should be encrypted with ansible-vault
        shell: /bin/zsh
        full_sudo: false
        key: /custom/path/to/key_id_ed25519.pub
    all_groups: "{{ users | selectattr('primary_group', 'defined')
      | map(attribute='primary_group')   [default_group] }}"


As you can see, the first user does not declare any custom values whereas the second overrides quite a few. The corresponding tasks taking this into account could then be turned to:

    - name: make sure all declared primary groups exist on target
      ansible.builtin.group:
        name: "{{ item }}"
        state: present
      loop: "{{ all_groups }}"

    - name: Create user
      ansible.builtin.user:
        name: "{{ item.name }}"
        state: present
        password: "{{ item.password | d(default_user_password) | password_hash('sha512','A512') }}"
        shell: "{{ item.shell | d('/bin/bash') }}"
        group: "{{ item.primary_group | d(default_group) }}"
      loop: "{{ users }}"

    - name: Add user to the full sudoers if asked
      ansible.builtin.copy:
        dest: "/etc/sudoers.d/{{ item.name }}"
        content: "{{ item.name }}  ALL=(ALL)  NOPASSWD: ALL"
      loop: "{{ users }}"
      when: "{{ item.full_sudo | d(true) | bool }}"

    - name: Deploy SSH Public Key
      ansible.posix.authorized_key:
        user: "{{ item.name }}"
        state: present
        key: "{{ lookup('file', item.key | d('/home/{{ item.name }}/.ssh/id_rsa.pub')) }}"
      loop: "{{ users }}"

With which user will this playbook run on my remote hosts?

With the one you declare. By default it will the one currently running the playbook on the controller. But this can be overridden on the command line, in your play, at task level, in your inventory... As an overview and entry point to the subject, see https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_environment.html

  • Related