4

I have a list of users in a yaml files, with a flag: state.

If the flag is undefined or if it is != "absent", I create the user :

    - name: "create account for {{item.name}}"
      user:
        name: "{{item.name}}"
        create_home: no
        shell: "/bin/bash"
      loop: "{{users}}"
      when:
      - item.state is undefined or item.state != "absent"

and on the contrary, I disallow "absent" users to connect:

    - name: "disable user {{item.name}}"
      user:
        name: "{{item.name}}"
        shell: "/sbin/nologin"
      loop: "{{users}}"
      when:
        - item.state is defined and item.state == "absent"

But How can I make it so that only existing users can be disabled ? (And not creating a user to set its shell as /sbin/nologin)

4

Q: "Only existing users can be disabled."

A: To modify present users only, use getent to read /etc/passwd and create a list of present users. Then use it in the condition. For example

    - getent:
        database: passwd
    - set_fact:
        users_present: "{{ getent_passwd.keys()|list }}"

    - name: "disable user {{ item.name }}"
      user:
        name: "{{ item.name }}"
        shell: /sbin/nologin
      loop: "{{ users }}"
      when:
        - item.name in users_present
        - item.state|default('present') == 'absent'

Note1: It's more robust to default state to 'present' instead of testing the existence of the attribute

    - name: "create account for {{ item.name }}"
      user:
        name: "{{ item.name }}"
        create_home: no
        shell: /bin/bash
      loop: "{{ users }}"
      when: item.state|default('present') != 'absent'

Note2: The module user doesn't complain that a 'name' isn't present when 'state=absent'. Hence, it's not necessary to test the presence of a user in this case. Simply disable the user. For example

    - name: "disable user {{ item.name }}"
      user:
        name: "{{ item.name }}"
        state: absent
      loop: "{{ users }}"
      when: item.state|default('present') == 'absent'
| improve this answer | |
  • If you look closely, you'll notice that I don't remove old users, I merely replace their shell with /sbin/nologin, but the second part of your answer tells me what I need to know. – Pierre-Antoine Guillaume Sep 28 at 16:07
  • Right. I updated the answer and shuffled the notes. – Vladimir Botka Sep 28 at 16:53
2

You can check if a user exists with getent with getent passwd {{ item }}.

Below is an example playbook:

---
  - name: "Check if User exists sample"
    hosts: localhost
    connection: local
    vars:
      users:
        - nginx
        - root
        - user4
        - user3

    tasks:
      - name: "check for user in /etc/passwd"
        command: getent passwd {{ item }}
        register: check_user
        ignore_errors: yes 
        loop: "{{ users }}"
        register: all_checks
      
      - name: "iterate over checks"
        debug:
          msg:
          - "{{ item.rc }}"
          - "{{ item.item }}"
        when:
          - item.rc == 0
        loop: "{{ all_checks.results }}"

So in your case you need to modify the section of your playbook you posted like this:

tasks:
      - name: "check for user in /etc/passwd"
        command: getent passwd {{ item }}
        register: check_user
        ignore_errors: yes 
        loop: "{{ users }}"
        register: all_checks
      
      - name: "iterate over checks"
        user:
          name: "{{item.item}}"
          shell: "/sbin/nologin" 
        when:
          - item.state is defined and item.state == "absent"
          - item.rc == 0
        loop: "{{ all_checks.results }}"
| 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.