ansibleansible-2.x

Get users and users dirs using getent


I am newbie in ansible, so excuse me. I didn't find or may be understand related information from ansible docs.

I need to put some ssh keys by blocks in .ssh/autorized_keys of all users in the system (Debian 9) without using the shell in tasks. Ansible 2.7.5

My plan was:

I am trying to get all users from the passwd file with a getent module below.

- getent:
    database: passwd
    key:
  register: allusers

# - debug:
#     var: allusers
# - debug:
#       msg: "{{ ansible_facts.getent_passwd }}"

# - name: Select actual users
#   set_fact:
#       passwd_user: "{{ item.key }}"
#       passwd_hdir: "{{ item.value.4 }}"
#   loop: "{{ allusers.ansible_facts.getent_passwd | dict2items }}"

- name: "Show file path only"
  debug:
    msg:
      - "Located user: {{ item.key }}"
      - "Home Dir: {{ item.value.4 }}"
  loop: "{{ allusers.ansible_facts.getent_passwd | dict2items }}"

Here I got a dict with key: users and value: home dir. But I don't know how to filter it by shell type and how to assign all users and there dirs to var.

- name: "Add ssh keys"
  blockinfile:
      path: "{{ passwd_hdir }}/.ssh/authorized_keys"
      create: yes
      owner: "{{ passwd_user }}"
      group: "{{ passwd_user }}"
      block: "{{ item }}"
  with_file:
    - "defaults/main.yml"  # file in role's dir with ssh-keys

Ass a result I add keys only for one user. How to make a loop from that task with a list of users as loop variable.

P.S.

Second part of my problem it's how to work with variables results: list, string, dict. I think I understand how to convert using filters, but where I can read more about detecting var type, and exract data from it. It's not clear for me: https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html

Thank you.


Solution

  • Q: "How to loop a list of users?"

    A: Read passwd. The variable getent_passwd will be created automatically by the module getent

        - getent:
            database: passwd
    

    Create the list of users by selecting records that contain shell /bin/bash

      users_sh: "{{ getent_passwd | dict2items |
                    selectattr('value', 'contains', '/bin/bash') |
                    map(attribute='key') }}"
    

    Loop the list and use authorized_key to configure authorized_keys

        - authorized_key:
            user: "{{ item }}"
            key: "{{ lookup('file', 'defaults/main.yml') }}"
          loop: "{{ users_sh }}"
    

    Example of a complete playbook for testing

    - hosts: all
    
      vars:
    
        users_sh: "{{ getent_passwd | dict2items |
                      selectattr('value', 'contains', '/bin/bash') |
                      map(attribute='key') }}"
        users_nl: "{{ getent_passwd | dict2items |
                      selectattr('value', 'contains', '/usr/sbin/nologin') |
                      map(attribute='key') }}"
      tasks:
    
        - getent:
            database: passwd
    
        - debug:
            var: users_sh | to_yaml
        - debug:
            var: users_nl | to_yaml
    
        - authorized_key:
            user: "{{ item }}"
            key: "{{ lookup('file', 'defaults/main.yml') }}"
          loop: "{{ users_sh }}"
          when: not_dry_run | d(false) | bool