---
- name: Prompt for parameters
  hosts: localhost
  gather_facts: false
  vars_prompt:
  - name: bootstrap_hostname
    prompt: Enter hostname (or IP address) of bootstrap target
    private: false
  - name: bootstrap_username
    prompt: Enter username to use for connecting to boostrap target
    default: root
    private: false
  - name: bootstrap_password
    prompt: Enter password to use for connecting to boostrap target
    private: true
    default: skylab
  - name: bootstrap_port
    prompt: Enter SSH port to connect to on bootstrap target
    default: 22
    private: false
  tasks:
  - name: Add boostrap host
    changed_when: false
    ansible.builtin.add_host:
      hostname: bootstrap
      ansible_host: "{{ bootstrap_hostname }}"
      ansible_user: "{{ bootstrap_username }}"
      ansible_ssh_pass: "{{ bootstrap_password }}"
      ansible_port: "{{ bootstrap_port }}"

- name: Bootstrap remote
  hosts: bootstrap
  vars:
    ansible_host_key_checking: false
  vars_prompt:
  - name: vault_password
    prompt: Enter Ansible vault password for generating user secrets
    private: true
    confirm: true
  tasks:
  - name: Fetch install path
    ansible.builtin.stat:
      path: /var/lib/skylab
    register: _skylab_install_path

  - name: Check OS requirements
    ansible.builtin.assert:
      that:
      - ansible_distribution == 'Rocky'
      - ansible_distribution_major_version in ['8', '9']
      success_msg: >-
        Host is running supported OS {{ ansible_distribution }} {{ ansible_distribution_version }}
      fail_msg: >-
        Unsupported operating system ({{ ansible_distribution }} {{ ansible_distribution_major_version }}),
        only RockyLinux 8 and RockyLinux 9 are supported.

  - name: Check boostrap state
    ansible.builtin.assert:
      that:
      - not _skylab_install_path.stat.exists
      success_msg: >-
        Host is ready for boostrapping
      fail_msg: >-
        Host has already been boostrapped

  - name: Check that management keys are defined
    ansible.builtin.assert:
      that:
        - skylab_mgmt_keys is defined
        - skylab_mgmt_keys != []
      success_msg: >-
        Found {{ skylab_mgmt_keys | length }} SSH keys to install to the Ansible management user
      fail_msg: >-
        No management keys were found for installation to the Ansible management user. Aborting to avoid
        locking out SSH access to the boostrap host. Please define the 'skylab_mgmt_keys' variable with
        a list of SSH public keys to install to the Ansible management user.

  - name: Create skylab group
    ansible.builtin.group:
      name: skylab
      state: present
      gid: 1400

  - name: Update ansible user authorized keys
    ansible.posix.authorized_key:
      user: ansible
      exclusive: true
      key: "{{ skylab_mgmt_keys | join('\n') }}"

  - name: Generate ansible user account password
    delegate_to: localhost
    no_log: true
    changed_when: false
    ansible.builtin.shell:
      cmd: >
        command mpw -qq -F none -t max -u ansible {{ ansible_host }} -p <<<
        '{{ vault_password }}' |
        python3 -c 'import crypt; print(crypt.crypt(input(), crypt.mksalt(crypt.METHOD_SHA512)))'
      executable: /bin/bash
    register: _password_ansible

  - name: Update ansible user account
    ansible.builtin.user:
      name: ansible
      state: present
      group: skylab
      groups:
        - skylab
        - wheel
      uid: 1400
      password: "{{ _password_ansible.stdout }}"

  - name: Remove ansible user group
    ansible.builtin.group:
      name: ansible
      state: absent

  - name: Update root user authorized keys
    ansible.posix.authorized_key:
      user: root
      exclusive: true
      key: ""

  - name: Disable sudo password for WHEEL group
    become: true
    ansible.builtin.copy:
      content: "%wheel ALL=(ALL) NOPASSWD: ALL"
      dest: /etc/sudoers.d/30-wheel
      owner: root
      group: skylab
      mode: 0644

  - name: Disable SSHD password auth
    ansible.builtin.replace:
      path: /etc/ssh/sshd_config
      regexp: '^(#?)PasswordAuthentication .*$'
      replace: 'PasswordAuthentication no'

  - name: Disable SSHD root login
    ansible.builtin.replace:
      path: /etc/ssh/sshd_config
      regexp: '^(#?)PermitRootLogin .*$'
      replace: 'PermitRootLogin no'

  - name: Update OS
    ansible.builtin.dnf:
      name: "*"
      state: latest
      allowerasing: true

  - name: Generate root user account password
    delegate_to: localhost
    no_log: true
    changed_when: false
    ansible.builtin.shell:
      cmd: >
        command mpw -qq -F none -t max -u ansible {{ ansible_host }} -p <<<
        '{{ vault_password }}' |
        python3 -c 'import crypt; print(crypt.crypt(input(), crypt.mksalt(crypt.METHOD_SHA512)))'
      executable: /bin/bash
    register: _password_root

  - name: Update root user account
    ansible.builtin.user:
      name: root
      state: present
      password: "{{ _password_root.stdout }}"

  - name: Create SkyLab directory
    ansible.builtin.file:
      state: directory
      path: /var/lib/skylab
      owner: ansible
      group: skylab
      mode: 0750
