---
# collect-luks-keys.yml — fetch LUKS backup keys from enrolled clients and store them
# on the ansipa-luks-keys SMB share (accessible only to KeyAdmin group members).
#
# Flow per host:
#   1. Fetch /_LUKS_BACKUP_KEY from the client to a local staging directory.
#   2. Upload the staged file to //IPA_SERVER/ansipa-luks-keys/ via smbclient.
#   3. Delete the local staging copy.
#
# The ansipa-luks-keys SMB share is write-only for 'luks-upload' and read-only
# for members of the 'KeyAdmin' group. Add a Samba user to KeyAdmin on the IPA
# container to grant read access:
#   useradd -r -G KeyAdmin <user> && smbpasswd -a <user>
#
# Usage:
#   ansible-playbook -i inventory collect-luks-keys.yml \
#       -e luks_smb_server=ipa.corp.example.com \
#       -e luks_upload_password=<LUKS_KEY_UPLOAD_PASSWORD>
#
# Or set defaults in group_vars / ansible-vault. The smb_server can also be
# auto-detected from /etc/ipa/default.conf on the clients.

- name: Collect and archive LUKS backup keys
  hosts: all
  become: yes

  vars:
    luks_key_path: /_LUKS_BACKUP_KEY
    # Local staging dir — files are deleted after a successful SMB upload.
    luks_keys_stage: "{{ playbook_dir }}/luks-keys-stage"
    luks_smb_server: "{{ luks_smb_server | mandatory('luks_smb_server is required — use -e luks_smb_server=<IPA host>') }}"
    luks_smb_share: ansipa-luks-keys
    luks_upload_user: luks-upload
    luks_upload_password: "{{ luks_upload_password | mandatory('luks_upload_password is required — use -e luks_upload_password=... or ansible-vault') }}"
    # Temp credentials file on the controller — removed at the end of the play.
    _smb_creds_file: "/tmp/.ansipa-luks-upload-{{ ansible_date_time.epoch }}.creds"

  tasks:

    - name: Ensure local staging directory exists
      file:
        path: "{{ luks_keys_stage }}"
        state: directory
        mode: '0700'
      delegate_to: localhost
      run_once: true
      become: false

    - name: Write temporary SMB credentials file on controller
      copy:
        dest: "{{ _smb_creds_file }}"
        mode: '0600'
        content: |
          username = {{ luks_upload_user }}
          password = {{ luks_upload_password }}
          domain = WORKGROUP
      delegate_to: localhost
      run_once: true
      become: false
      no_log: true

    - name: Check for LUKS backup key on client
      stat:
        path: "{{ luks_key_path }}"
      register: luks_key_stat

    - name: Fetch LUKS backup key to local staging area
      fetch:
        src: "{{ luks_key_path }}"
        dest: "{{ luks_keys_stage }}/{{ inventory_hostname }}_LUKS_BACKUP_KEY"
        flat: yes
      when: luks_key_stat.stat.exists
      register: luks_key_fetch

    - name: Secure staged key permissions
      file:
        path: "{{ luks_keys_stage }}/{{ inventory_hostname }}_LUKS_BACKUP_KEY"
        mode: '0400'
      delegate_to: localhost
      become: false
      when:
        - luks_key_stat.stat.exists
        - luks_key_fetch is changed

    - name: Upload key to ansipa-luks-keys SMB share
      shell: >
        smbclient "//{{ luks_smb_server }}/{{ luks_smb_share }}"
        -A "{{ _smb_creds_file }}"
        -c "put {{ luks_keys_stage }}/{{ inventory_hostname }}_LUKS_BACKUP_KEY {{ inventory_hostname }}_LUKS_BACKUP_KEY"
      delegate_to: localhost
      become: false
      when:
        - luks_key_stat.stat.exists
        - luks_key_fetch is changed
      register: smb_upload
      no_log: true

    - name: Remove local staging copy after successful upload
      file:
        path: "{{ luks_keys_stage }}/{{ inventory_hostname }}_LUKS_BACKUP_KEY"
        state: absent
      delegate_to: localhost
      become: false
      when:
        - luks_key_stat.stat.exists
        - luks_key_fetch is changed
        - smb_upload is succeeded

    - name: Report key status
      debug:
        msg: >-
          {{ inventory_hostname }}:
          {% if not luks_key_stat.stat.exists %}
            no /_LUKS_BACKUP_KEY present (unencrypted install or key already removed)
          {% elif luks_key_fetch is changed and smb_upload is succeeded %}
            key uploaded to //{{ luks_smb_server }}/{{ luks_smb_share }}/{{ inventory_hostname }}_LUKS_BACKUP_KEY
          {% elif luks_key_fetch is not changed %}
            key unchanged since last collection — skipped upload
          {% else %}
            WARNING: key fetched but SMB upload failed — check smbclient output
          {% endif %}

  post_tasks:
    - name: Remove temporary SMB credentials file
      file:
        path: "{{ _smb_creds_file }}"
        state: absent
      delegate_to: localhost
      run_once: true
      become: false
