#SPDX-License-Identifier: MIT-0
---
# tasks file for roles/init-vps
- name: Checking whether administrative or root login used
  when: ansible_user not in (admins | map(attribute="username") | list) and ansible_user != "root"
  ansible.builtin.fail:
    msg: Must use administrative or root user for subsequent tasks
- name: Starting user and group creation for SSH access
  block:
    - name: Creating group remote for managing SSH access
      become: true
      ansible.builtin.group:
        name: remote
        system: true
        state: present
      register: remote_group
      tags:
        - lan
    - name: Managing passwords
      when: prehashed_passwords is undefined or prehashed_passwords == None
      block:
        - name: Acquiring users lacking passwords
          ansible.builtin.set_fact:
            passwordless_admins: "{{ admins | selectattr('password', '==', 'null') | list }}"
        - name: Pausing to acquire password for a user
          when: item.password is undefined or item.password == None
          ansible.builtin.pause:
            prompt: "Provide a password for the administrative user, {{ item.username }}"
            echo: false
          loop: "{{ passwordless_admins }}"
          register: prompted_passwords
        - name: Processing inputted password per user
          when: prompted_passwords is defined and prompted_passwords != None
          ansible.builtin.set_fact:
            prehashed_passwords: "{{ (prompted_passwords.results | default([])) | map(attribute='user_input') | list }}"
        - name: Pairing inputted passwords with associated user
          when: prehashed_passwords is defined or prehashed_passwords != None
          ansible.builtin.set_fact:
            prehashed_passwords: "{{ dict(passwordless_admins | map(attribute='username') | zip(prehashed_passwords) | list) }}"
    - name: Creating an administrative user
      become: true
      ansible.builtin.user:
        name: "{{ item.username }}"
        comment: administrator
        groups:
          - "{{ remote_group.name | default('remote') }}"
          - sudo # @NOTE used by Debian
        append: true
        generate_ssh_key: true
        create_home: true
        password: "{{ item.password | default((prehashed_passwords[item.username] | password_hash(hashtype='sha512'))) }}"
        shell: "/bin/bash"
      loop: "{{ admins }}"
      register: admin_users
      tags:
        - lan
    - name: Finding SSH public keys for an administrative user
      delegate_facts: true
      delegate_to: localhost
      when: item.username in (admin_users.results | map(attribute="name") | list)
      ansible.builtin.find:
        paths: "{{ local_facts['user_dir'] }}/.ssh" # @TODO define 'cnode_homedir' in playbook
        patterns: "{{ ['^'] | product(item.ssh_keys) | map('join') | list }}"
        file_type: file
        use_regex: true
      loop: "{{ admins }}"
      register: admin_ssh_keypairs
    - name: Creating list wherein each SSH public key is associated with a user
      ansible.builtin.set_fact:
        pubkey_users: "{{ [admin_users.results[idx].name] | product(admin_ssh_keypairs.results[idx].files | selectattr('path', 'search', '\\.pub$') | map(attribute='path')) }}"
      loop: "{{ admins }}"
      loop_control:
        index_var: idx
    - name: Authorizing SSH public key for an administrative user
      become: true
      ansible.posix.authorized_key:
        user: "{{ item[0] }}"
        key: "{{ lookup('file', item[1]) }}"
        state: present
      loop: "{{ pubkey_users }}"
      register: ssh_authorizations
      tags:
        - lan
- name: Setting approved SSH authentication procedures
  when: harden and ansible_facts["system"] == "Linux"
  become: true
  ansible.builtin.copy:
    src: sshd_config.d/auth.conf
    dest: /etc/ssh/sshd_config.d/auth.conf
    owner: root
    group: root
    mode: "644"
    force: true
    backup: true
    validate: "sshd -t -f %s"
  register: ssh_authenticator
  tags:
    - lan
    - ssh_secure_auth
- name: Allowing sole SSH access to users in group remote
  when: ansible_facts["system"] == "Linux"
  become: true
  ansible.builtin.template:
    src: sshd_config.d/allowance.conf.j2 # @TODO create corresponding role template file
    dest: /etc/ssh/sshd_config.d/allowance.conf
    owner: root
    group: root
    mode: "644"
    force: true
    backup: true
    validate: "sshd -t -f %s"
  register: ssh_gatekept
  tags:
    - lan