diff --git a/README.md b/README.md index ead0d36..c32b000 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,13 @@ ansible-pull -U --tags ,,... -i localhost, site.yml ## Aktueller Stand -Alle Rollen sind Platzhalter — sie hinterlegen nur eine Marker-Datei unter `/run/tuxflotte/agent/applied/.marker`, um die End-to-End-Pipeline (Server → Agent → ansible-pull → Rolle) nachzuweisen. Echte Rolleninhalte folgen später. +Alle drei Rollen haben echten Inhalt (Stand 2026-08-04) — die Marker-Dateien unter `/run/tuxflotte/agent/applied/.marker` bleiben zusätzlich als schneller E2E-Nachweis bestehen, sind aber nicht mehr der eigentliche Effekt der Rollen: + +- **`guest-session`**: echte flüchtige Gastsitzung. Lokaler User `gast`, Login ohne Passwort über die `nopasswdlogin`-Gruppenkonvention, `$HOME` per `pam_namespace`-Polyinstantiation (`/etc/security/namespace.conf`) als tmpfs — wird bei Sitzungsende automatisch verworfen, kein Cleanup-Skript nötig. PAM-Dateilayout unterscheidet sich zwischen RedHat- (`gdm-password`/`postlogin`) und Debian-Familie (`lightdm`/`common-session`) und wird über `ansible_facts['os_family']` erkannt, da derselbe Rollenname für beide Backends (`fedora`, `mint`) verwendet wird. +- **`brave-fedora`**: Installation von Brave via Flatpak/Flathub (`community.general.flatpak`). Unterstützt zusätzlich die Auftragskatalog-Option `standardbrowser` (siehe unten). +- **`onlyoffice-fedora`**: Installation von OnlyOffice Desktop Editors via Flatpak/Flathub. + +**Neue Abhängigkeit:** die `community.general`-Collection (Module `flatpak`, `flatpak_remote`, `ini_file`). Auf der Zielplattform muss sie installiert sein — auf der bisherigen Test-VM (Linux Mint) bereits vorhanden (`ansible-collection-community-general`), auf frisch installierten Fedora-Geräten ggf. per `ansible-galaxy collection install community.general` oder passendes RPM-Paket sicherstellen. ## present/absent (Auftragskatalog, ADR-0010) @@ -36,6 +42,12 @@ Jede Rolle, die katalogfähig werden soll, muss deshalb ihre Tasks auf `tuxflott Rollen, die nie katalogfähig werden (rein workspace-komponierte Merkmale), brauchen keinen `absent`-Zweig — das ist bewusst kein Zwang für alle Rollen, nur für die, die tatsächlich im Auftragskatalog landen. +## optionen (Auswahl-Parameter je Zuweisung) + +Über die reine present/absent-Zuweisung hinaus kann eine Auftragskatalog-Zuweisung zusätzliche, rollenspezifische Optionen tragen (`device_merkmale.optionen`, JSONB) — z.B. `{"standardbrowser": true}` bei `browser-brave`. Der Server kennt die Bedeutung dieser Optionen nicht, reicht sie nur unverändert durch (Check-in-Antwort `auftraege[].optionen`). + +Der Agent baut daraus `tuxflotte_auftrag_optionen` (Rollenname → optionen-Dict) als zweites `--extra-vars`-Feld neben `tuxflotte_auftrag_states`. `site.yml` reicht es pro Rolle als `tuxflotte_optionen` durch (Default `{}`, falls die Rolle nicht in der Map auftaucht). Nur Rollen, die tatsächlich Optionen brauchen, lesen die Variable (aktuell nur `brave-fedora`) — für alle anderen ist sie ungenutzt. + ## Neue Rolle hinzufügen 1. `roles//tasks/main.yml` anlegen diff --git a/roles/brave-fedora/defaults/main.yml b/roles/brave-fedora/defaults/main.yml index 94c225a..59ad55e 100644 --- a/roles/brave-fedora/defaults/main.yml +++ b/roles/brave-fedora/defaults/main.yml @@ -1 +1,2 @@ tuxflotte_state: present +tuxflotte_optionen: {} diff --git a/roles/brave-fedora/tasks/main.yml b/roles/brave-fedora/tasks/main.yml index a3361bd..e501e89 100644 --- a/roles/brave-fedora/tasks/main.yml +++ b/roles/brave-fedora/tasks/main.yml @@ -4,6 +4,68 @@ state: directory mode: "0755" +- name: Ensure flathub remote is configured + community.general.flatpak_remote: + name: flathub + flatpakrepo_url: https://flathub.org/repo/flathub.flatpakrepo + state: present + method: system + when: tuxflotte_state == "present" + +- name: Install Brave via Flatpak + community.general.flatpak: + name: com.brave.Browser + remote: flathub + state: present + method: system + when: tuxflotte_state == "present" + +# Systemweiter Default (nicht pro Benutzer), da ansible-pull als root ohne +# Sitzungskontext läuft. /etc/xdg/mimeapps.list gilt für jeden Benutzer ohne +# eigene ~/.config/mimeapps.list. Jeder Lauf erzwingt deterministisch einen +# der beiden Werte - kein Tracking, ob ein Admin manuell etwas anderes +# gesetzt hat (bekannte Einschränkung, siehe README). +- name: Set Brave as system default browser (standardbrowser-Option aktiv) + community.general.ini_file: + path: /etc/xdg/mimeapps.list + section: Default Applications + option: "{{ item }}" + value: com.brave.Browser.desktop + mode: "0644" + no_extra_spaces: true + loop: + - text/html + - x-scheme-handler/http + - x-scheme-handler/https + when: tuxflotte_state == "present" and (tuxflotte_optionen.standardbrowser | default(false)) + +# Nur zurücksetzen, wenn Brave aktuell tatsächlich als Default eingetragen +# ist - sonst würde jeder Lauf auf jedem Gerät ohne Brave-Auswahl einen +# eventuell fremd (manuell) gesetzten Standardbrowser überschreiben. +- name: Check whether Brave is currently the configured default browser + ansible.builtin.command: + cmd: grep -q com.brave.Browser.desktop /etc/xdg/mimeapps.list + register: tuxflotte_brave_is_default + changed_when: false + failed_when: false + when: tuxflotte_state == "absent" or not (tuxflotte_optionen.standardbrowser | default(false)) + +- name: Reset default browser to Firefox (standardbrowser-Option inaktiv oder Auftrag abgewählt) + community.general.ini_file: + path: /etc/xdg/mimeapps.list + section: Default Applications + option: "{{ item }}" + value: firefox.desktop + mode: "0644" + no_extra_spaces: true + loop: + - text/html + - x-scheme-handler/http + - x-scheme-handler/https + when: > + (tuxflotte_state == "absent" or not (tuxflotte_optionen.standardbrowser | default(false))) + and tuxflotte_brave_is_default.rc is defined and tuxflotte_brave_is_default.rc == 0 + - name: Record that the brave-fedora role ran ansible.builtin.copy: dest: /run/tuxflotte/agent/applied/brave-fedora.marker @@ -11,6 +73,13 @@ mode: "0644" when: tuxflotte_state == "present" +- name: Remove Brave Flatpak (Auftrag abgewählt) + community.general.flatpak: + name: com.brave.Browser + state: absent + method: system + when: tuxflotte_state == "absent" + - name: Remove brave-fedora marker (Auftrag abgewählt) ansible.builtin.file: path: /run/tuxflotte/agent/applied/brave-fedora.marker diff --git a/roles/guest-session/tasks/main.yml b/roles/guest-session/tasks/main.yml index 1d96006..5ec8982 100644 --- a/roles/guest-session/tasks/main.yml +++ b/roles/guest-session/tasks/main.yml @@ -4,6 +4,56 @@ state: directory mode: "0755" +# PAM-Dateilayout unterscheidet sich zwischen RedHat- (GDM/authselect) und +# Debian-Familie (LightDM/common-*) - beide Backends (fedora, mint) nutzen +# denselben Rollennamen "guest-session" (siehe blueprints-Seed), die Rolle +# muss also auf beiden funktionieren. +- name: Determine PAM file locations for this distribution family + ansible.builtin.set_fact: + tuxflotte_guest_pam_auth_file: "{{ '/etc/pam.d/gdm-password' if ansible_facts['os_family'] == 'RedHat' else '/etc/pam.d/lightdm' }}" + tuxflotte_guest_pam_session_file: "{{ '/etc/pam.d/postlogin' if ansible_facts['os_family'] == 'RedHat' else '/etc/pam.d/common-session' }}" + +- name: Ensure nopasswdlogin group exists (present) + ansible.builtin.group: + name: nopasswdlogin + state: present + when: tuxflotte_state == "present" + +- name: Ensure gast user exists (present) + ansible.builtin.user: + name: gast + comment: "Tuxflotte Gastsitzung" + groups: nopasswdlogin + append: true + shell: /bin/bash + password_lock: true + when: tuxflotte_state == "present" + +# Debian/LightDM bringt diese Zeile bereits standardmäßig mit (idempotent, +# lineinfile dupliziert nicht) - auf Fedora/GDM muss sie ergänzt werden. +- name: Allow passwordless login for nopasswdlogin group + ansible.builtin.lineinfile: + path: "{{ tuxflotte_guest_pam_auth_file }}" + line: "auth sufficient pam_succeed_if.so user ingroup nopasswdlogin" + insertbefore: BOF + state: present + when: tuxflotte_state == "present" + +- name: Ensure ephemeral tmpfs home for gast (pam_namespace polyinstantiation) + ansible.builtin.lineinfile: + path: /etc/security/namespace.conf + line: "/home/gast tmpfs tmpfs:mntopts=size=2G,mode=0700 root,gast" + regexp: '^/home/gast\s' + state: present + when: tuxflotte_state == "present" + +- name: Enable pam_namespace for login sessions + ansible.builtin.lineinfile: + path: "{{ tuxflotte_guest_pam_session_file }}" + line: "session required pam_namespace.so" + state: present + when: tuxflotte_state == "present" + - name: Record that the guest-session role ran ansible.builtin.copy: dest: /run/tuxflotte/agent/applied/guest-session.marker @@ -11,6 +61,32 @@ mode: "0644" when: tuxflotte_state == "present" +- name: Remove ephemeral tmpfs home entry for gast (Auftrag abgewählt) + ansible.builtin.lineinfile: + path: /etc/security/namespace.conf + regexp: '^/home/gast\s' + state: absent + when: tuxflotte_state == "absent" + +# Entfernt die nopasswdlogin-Regel vollständig, nicht nur den gast-Account - +# betrifft auf Debian/LightDM auch den distributionseigenen Default-Eintrag. +# Bewusst in Kauf genommen: diese Rolle ist der einzige Verwalter der +# nopasswdlogin-Konvention in diesem Katalog, Wiederherstellung beim +# nächsten present-Lauf ist kostenlos. +- name: Remove passwordless login rule for nopasswdlogin group (Auftrag abgewählt) + ansible.builtin.lineinfile: + path: "{{ tuxflotte_guest_pam_auth_file }}" + line: "auth sufficient pam_succeed_if.so user ingroup nopasswdlogin" + state: absent + when: tuxflotte_state == "absent" + +- name: Remove gast user and home (Auftrag abgewählt) + ansible.builtin.user: + name: gast + state: absent + remove: true + when: tuxflotte_state == "absent" + - name: Remove guest-session marker (Auftrag abgewählt) ansible.builtin.file: path: /run/tuxflotte/agent/applied/guest-session.marker diff --git a/roles/onlyoffice-fedora/tasks/main.yml b/roles/onlyoffice-fedora/tasks/main.yml index 69b829a..337b118 100644 --- a/roles/onlyoffice-fedora/tasks/main.yml +++ b/roles/onlyoffice-fedora/tasks/main.yml @@ -4,6 +4,22 @@ state: directory mode: "0755" +- name: Ensure flathub remote is configured + community.general.flatpak_remote: + name: flathub + flatpakrepo_url: https://flathub.org/repo/flathub.flatpakrepo + state: present + method: system + when: tuxflotte_state == "present" + +- name: Install OnlyOffice via Flatpak + community.general.flatpak: + name: org.onlyoffice.desktopeditors + remote: flathub + state: present + method: system + when: tuxflotte_state == "present" + - name: Record that the onlyoffice-fedora role ran ansible.builtin.copy: dest: /run/tuxflotte/agent/applied/onlyoffice-fedora.marker @@ -11,6 +27,13 @@ mode: "0644" when: tuxflotte_state == "present" +- name: Remove OnlyOffice Flatpak (Auftrag abgewählt) + community.general.flatpak: + name: org.onlyoffice.desktopeditors + state: absent + method: system + when: tuxflotte_state == "absent" + - name: Remove onlyoffice-fedora marker (Auftrag abgewählt) ansible.builtin.file: path: /run/tuxflotte/agent/applied/onlyoffice-fedora.marker diff --git a/site.yml b/site.yml index c6c676d..6c2eb24 100644 --- a/site.yml +++ b/site.yml @@ -7,6 +7,10 @@ # die hier nicht auftauchen (z.B. weil sie nur workspace-komponiert sind), # bleiben beim Default "present" - unverändert additives Verhalten. tuxflotte_auftrag_states: {} + # Rollenname -> optionen-Dict aus der Auswahl-API (device_merkmale.optionen), + # z.B. {"standardbrowser": true} bei brave-fedora. Rein additiv, opak für + # den Server/Agenten - nur die jeweilige Rolle kennt die Bedeutung. + tuxflotte_auftrag_optionen: {} tasks: - include_role: name: guest-session @@ -14,6 +18,7 @@ tags: guest-session vars: tuxflotte_state: "{{ tuxflotte_auftrag_states.get('guest-session', 'present') }}" + tuxflotte_optionen: "{{ tuxflotte_auftrag_optionen.get('guest-session', {}) }}" tags: guest-session - include_role: @@ -22,6 +27,7 @@ tags: brave-fedora vars: tuxflotte_state: "{{ tuxflotte_auftrag_states.get('brave-fedora', 'present') }}" + tuxflotte_optionen: "{{ tuxflotte_auftrag_optionen.get('brave-fedora', {}) }}" tags: brave-fedora - include_role: @@ -30,4 +36,5 @@ tags: onlyoffice-fedora vars: tuxflotte_state: "{{ tuxflotte_auftrag_states.get('onlyoffice-fedora', 'present') }}" + tuxflotte_optionen: "{{ tuxflotte_auftrag_optionen.get('onlyoffice-fedora', {}) }}" tags: onlyoffice-fedora