From cab59c16582e6898e06e530fb6a70504e451435d Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Sat, 18 Jul 2026 19:36:54 +0000 Subject: [PATCH] added readmes (#1) Co-authored-by: DerLinkman Reviewed-on: https://gitea.cloudlorean.de/DerLinkman/ansible-playbooks/pulls/1 --- README.md | 138 ++++++++++++++++++++++++++++++++ roles/bootstrap/README.md | 119 +++++++++++++++++++++++++++ roles/docker/README.md | 102 +++++++++++++++++++++++ roles/hawser/README.md | 94 ++++++++++++++++++++++ roles/healthcheck/README.md | 97 ++++++++++++++++++++++ roles/manage-ssh-keys/README.md | 104 ++++++++++++++++++++++++ roles/os-updates/README.md | 128 +++++++++++++++++++++++++++++ 7 files changed, 782 insertions(+) create mode 100644 README.md create mode 100644 roles/bootstrap/README.md create mode 100644 roles/docker/README.md create mode 100644 roles/hawser/README.md create mode 100644 roles/healthcheck/README.md create mode 100644 roles/manage-ssh-keys/README.md create mode 100644 roles/os-updates/README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..ef314be --- /dev/null +++ b/README.md @@ -0,0 +1,138 @@ +# Ansible Playbooks + +Zentrale Ansible-Sammlung für die Bereitstellung, Härtung, Aktualisierung und +Überwachung von Debian-Hosts. Das Repository enthält eigenständige Rollen, +zugehörige Playbooks, mehrere Inventories sowie eine Docker-basierte +Ausführungsumgebung, sodass Playbooks direkt aus einem Container heraus +gestartet werden können. + +## Inhaltsübersicht + +``` +. +├── ansible.cfg # Globale Ansible-Konfiguration +├── bootstrap.yml # Top-Level-Playbook für die Ersteinrichtung +├── execute.sh # Startet die Docker-Ausführungsumgebung +├── setenv.sh # Umgebungsvariablen für Proxmox (nicht im Repo) +├── vault.yml # Ansible-Vault-verschlüsselte Secrets +├── docker/ # Dockerfile & Requirements für die Laufzeit-Umgebung +├── inventory/ # Inventories mit group_vars +├── logs/ # Update-Logs (git-ignored) +├── playbooks/ # Playbooks, die die Rollen einbinden +└── roles/ # Wiederverwendbare Ansible-Rollen +``` + +## Voraussetzungen + +- **Ansible** >= 2.20 (im Docker-Image bereits enthalten) +- **Ziel-Hosts**: Debian (alle Playbooks prüfen `os_family == "Debian"`) +- **Ansible-Collections**: `ansible.posix`, `community.general`, + `community.docker`, `community.zabbix` (siehe `docker/requirements.yml`) +- **Zugang**: SSH-Zugang als Benutzer `admin` mit hinterlegtem Public Key + +### Docker-Ausführungsumgebung + +Damit Playbooks nicht lokal installiert werden müssen, liefert das Repository +ein fertiges Docker-Image. `execute.sh` erstellt ein IPv6-fähiges Bridge-Netzwerk, +startet einen interaktiven Container und mountet das Repository nach `/ansible`: + +```bash +./execute.sh +``` + +Im Container stehen Aliase wie `ap` (ansible-playbook), `ag` (ansible-galaxy) +und `av` (ansible-vault) zur Verfügung. Das Image wird über +`docker/Dockerfile` gebaut, die benötigten Collections werden beim Build +automatisch installiert. + +## Inventories + +Alle Inventories liegen unter `inventory/`. Pro Inventory existiert eine +gleichnamige Datei sowie ein Eintrag in `group_vars/`: + +| Inventory | Datei | group_vars | Beschreibung | +|------------------|--------------------|------------------------|-------------------------------------------------| +| DMC12 (Umgebung) | `dmc12.yml` | `debian.yml` | Debian-Hosts & Proxmox-Knoten | +| Home | `home.yml` | `home.yml` | Heimisches Netzwerk (10.13.37.0/24) | +| External | `external.yml` | `external.yml` | Externe Hosts (IPv6) | + +Die `group_vars` definieren standortspezifische Werte wie Zabbix-Server, +Spiegelserver und autorisierte SSH-Keys. + +## Playbooks + +| Playbook | Rolle(n) | Zweck | +|---------------------------------------|-----------------------------------|--------------------------------------------------------| +| `bootstrap.yml` | bootstrap | Vollständige Ersteinrichtung eines Debian-Hosts | +| `playbooks/docker.yml` | docker | Docker Engine installieren | +| `playbooks/monitoring.yml` | monitoring | Zabbix Agent 2 installieren & registrieren | +| `playbooks/os-updates-deb.yml` | os-updates, healthcheck | Pakete aktualisieren + Healthcheck | +| `playbooks/upgrade-hawser.yml` | hawser | Hawser-Stack aktualisieren | +| `playbooks/hardening/manage-ssh-keys.yml` | manage-ssh-keys | SSH-Schlüssel hartieren | + +### Aufrufbeispiele + +```bash +# Ersteinrichtung aller Hosts im DMC12-Inventory +ansible-playbook -i inventory/dmc12.yml bootstrap.yml + +# Nur Docker auf einem einzelnen Host installieren +ansible-playbook -i inventory/home.yml playbooks/docker.yml -l rp + +# OS-Updates inkl. Healthcheck +ansible-playbook -i inventory/dmc12.yml playbooks/os-updates-deb.yml + +# Hawser aktualisieren +ansible-playbook -i inventory/dmc12.yml playbooks/upgrade-hawser.yml + +# SSH-Keys härtene +ansible-playbook -i inventory/dmc12.yml playbooks/hardening/manage-ssh-keys.yml +``` + +## Rollen + +| Rolle | Kurzbeschreibung | Dokumentation | +|---------------------|-----------------------------------------------------------------------------|-------------------------------------| +| `bootstrap` | Ersteinrichtung: Pakete, Admin-User, SSH, MOTD, sysctl, Docker, Monitoring | [roles/bootstrap/README.md](roles/bootstrap/README.md) | +| `docker` | Installation der Docker Engine über das offizielle Repository | [roles/docker/README.md](roles/docker/README.md) | +| `hawser` | Aktualisierung des Hawser Docker-Compose-Stacks | [roles/hawser/README.md](roles/hawser/README.md) | +| `healthcheck` | Quality-Gate: prüft laufende Container nach Updates | [roles/healthcheck/README.md](roles/healthcheck/README.md) | +| `manage-ssh-keys` | Verwaltung erwünschter/unerwünschter SSH-Keys (Hardening) | [roles/manage-ssh-keys/README.md](roles/manage-ssh-keys/README.md) | +| `monitoring` | Zabbix Agent 2: Installation, TLS-PSK, Docker-Plugin, API-Registrierung | [roles/monitoring/README.md](roles/monitoring/README.md) | +| `os-updates` | Debian-Paketaktualisierung mit Spiegel-Wechsel, Reboot & Logging | [roles/os-updates/README.md](roles/os-updates/README.md) | + +## Secrets & Vault + +Sensible Werte (z. B. `monitoring_zabbix_api_password`, `admin_password`) +liegen verschlüsselt in `vault.yml`. Zum Entschlüsseln wird eine Vault-Passwort +benötigt, die in `.vault_pass` hinterlegt ist (git-ignored). Beim Aufruf muss +Ansible die Vault-Passwort-Datei kennen: + +```bash +ansible-playbook -i inventory/dmc12.yml --vault-password-file .vault_pass bootstrap.yml +``` + +> **Hinweis:** Die Datei `setenv.sh` enthält Zugangsdaten für Proxmox und ist +> bewusst nicht für eine Veröffentlichung vorgesehen. `.vault_pass` und +> `setenv.sh` stehen in `.gitignore`. + +## Logging + +Die Rollen `os-updates` und `healthcheck` schreiben pro Host ein Update-Log +unter `logs///update.log`. Das Verzeichnis `logs/` ist +git-ignored und dient als lokales Audit-Trail. + +## Konfiguration + +`ansible.cfg` deaktiviert Host-Key-Checking und legt `./roles` als +Rollen-Pfad fest. SSH-Verbindungen verwenden +`StrictHostKeyChecking=no` sowie `/dev/null` als KnownHosts-Datei, was die +Ersteinrichtung neuer Hosts erleichtert – in produktiven Umgebungen +entsprechend restriktiver konfigurieren. + +## Beitragen + +1. Änderungen lokal testen – idealerweise über `./execute.sh` im Container. +2. Variablen in `defaults/main.yml` der jeweiligen Rolle pflegen und in der + Rollen-README dokumentieren. +3. Keine Secrets unverschlüsselt committen (Vault nutzen). \ No newline at end of file diff --git a/roles/bootstrap/README.md b/roles/bootstrap/README.md new file mode 100644 index 0000000..34b215b --- /dev/null +++ b/roles/bootstrap/README.md @@ -0,0 +1,119 @@ +# Rolle `bootstrap` + +Ersteinrichtung (Provisioning) eines frischen Debian-Hosts. Die Rolle legt den +Admin-User an, installiert Basispakete, härtet die SSH-Konfiguration, verteilt +autorisierte SSH-Keys, konfiguriert Tastaturlayout, MOTD, Bash-Aliase und +sysctl, und bindet optional die Rollen `docker` und `monitoring` ein. + +> Siehe auch das Top-Level-Playbook `bootstrap.yml` sowie die +> [Repo-README](../../README.md). + +## Voraussetzungen + +- Debian-Ziel-Host +- SSH-Zugang als Benutzer, der `become` darf (Playbook nutzt `user: admin`) +- `ansible.posix` Collection (für `sysctl`-Modul) + +## Einbindung + +Die Rolle wird normalerweise über das Top-Level-Playbook `bootstrap.yml` +aufgerufen, kann aber auch direkt per `include_role`/`import_role` eingebunden +werden: + +```yaml +- hosts: all + become: true + user: admin + roles: + - role: bootstrap +``` + +```bash +ansible-playbook -i inventory/dmc12.yml --vault-password-file .vault_pass bootstrap.yml +``` + +## Funktionsweise + +`tasks/main.yml` reiht die Subtasks nacheinander aus und bindet am Ende +bedarfsabhängig die Rollen `docker` und `monitoring` ein: + +1. `install-basicpackages.yml` – Basispakete installieren +2. `create-admin-user.yml` – Admin-User anlegen + sudoers +3. `set-motd.yml` – MOTD via fastfetch (`tags: motd`) +4. `set-keyboardlayout.yml` – QWERTZ-Layout +5. `install-openssh.yml` – OpenSSH Server/Client (`tags: ssh`) +6. `configure-ssh.yml` – sshd_config härtbar (`tags: ssh`) +7. `add-ssh-keys.yml` – authorized_keys verteilen (`tags: ssh`) +8. `setup-bashrc.yml` – nützliche Aliase (`tags: bashrc`) +9. `configure-sysctl.yml` – vm.swappiness = 10 (`tags: sysctl`) +10. `import_role: docker` (sofern nicht `skip_docker`) +11. `import_role: monitoring` (sofern nicht `skip_monitoring`) + +### Installierte Basispakete + +`fastfetch`, `htop`, `curl`, `wget`, `git`, `sudo`, `console-setup`, +`qemu-guest-agent`, `cron`, `net-tools`, `tcpdump`, `locales-all`. + +### SSH-Härtung + +Die Vorlage `templates/sshd.conf.j2` deaktiviert Root-Login und +Passwort-Authentifizierung, erlaubt ausschließlich Publickey-Auth und setzt +restriktive Forwarding-/Logging-Optionen. Nach Änderung wird der sshd via +Handler neu gestartet. + +## Variablen + +| Variable | Typ | Default | Beschreibung | +|-------------------------|----------|-------------------|-----------------------------------------------------| +| `admin_authorized_keys` | list | siehe `defaults/` | Liste von `{ key, comment }`-Einträgen für `admin` | +| `admin_password` | string | siehe `defaults/` | SHA-512-Hash des Admin-Passworts | + +### Steuer-Variablen (keine Defaults, optional setzen) + +| Variable | Typ | Default | Beschreibung | +|--------------------|--------|---------|-----------------------------------------------------------| +| `skip_docker` | bool | `false` | Wenn `true`, wird die `docker`-Rolle übersprungen | +| `skip_monitoring` | bool | `false` | Wenn `true`, wird die `monitoring`-Rolle übersprungen | +| `ssh_service_name` | string | `sshd` | Name des SSH-Service (überschrieben bspw. für `ssh`) | + +`admin_authorized_keys` wird auch pro Inventory in `group_vars/external.yml` +überschrieben. Der Handler `Restart sshd` verwendet `ssh_service_name`, sofern +gesetzt (z. B. `ssh` für `gitea`/`ipam` in `inventory/dmc12.yml`). + +## Templates + +| Template | Ziel | +|------------------------|------------------------------------------------| +| `sshd.conf.j2` | `/etc/ssh/sshd_config` (validiert via `sshd -T`) | +| `authorized_keys.j2` | `/home/admin/.ssh/authorized_keys` | +| `sudoers-admin.j2` | `/etc/sudoers.d/10-admin` (validiert via `visudo -cf`) | +| `keyboard.j2` | `/etc/default/keyboard` | + +## Handler + +| Handler | Auslöser | +|-------------------------|-------------------------------------------| +| `Restart sshd` | Änderung an `sshd_config` | +| `Reload keyboard layout`| Änderung an `/etc/default/keyboard` | + +## Tags + +`motd`, `ssh`, `bashrc`, `sysctl` – ermöglichen das gezielte Re-Apply einzelner +Teile, z. B.: + +```bash +ansible-playbook bootstrap.yml -i inventory/dmc12.yml -t ssh +``` + +## Abhängigkeiten + +- `docker` (optional, via `import_role`) +- `monitoring` (optional, via `import_role`) + +## Hinweise + +- `configure-sysctl.yml` wird auf LXC-Containern übersprungen + (`virtualization_type != "lxc"`). +- `setup-bashrc.yml` legt Aliase für alle regulären User inkl. root an. +- `install-openssh.yml` entfernt ggf. das Meta-Paket `ssh` vor der + Installation von `openssh-server`/`openssh-client`. \ No newline at end of file diff --git a/roles/docker/README.md b/roles/docker/README.md new file mode 100644 index 0000000..d3923b7 --- /dev/null +++ b/roles/docker/README.md @@ -0,0 +1,102 @@ +# Rolle `docker` + +Installiert die Docker Engine über das offizielle Docker-Repository für Debian. +Die Rolle fügt den Docker-GPG-Key hinzu, richtet eine APT-Quelle im deb822-Format +ein und installiert alle benötigten Pakete (Engine, CLI, containerd, Buildx- und +Compose-Plugin). + +> Siehe auch das Playbook `playbooks/docker.yml` sowie die +> [Repo-README](../../README.md). + +## Voraussetzungen + +- Debian-Ziel-Host +- Internetzugang zum Docker-Repository (`download.docker.com`) +- Benutzer mit `become`-Rechten + +## Einbindung + +Die Rolle wird typischerweise über das Playbook `playbooks/docker.yml` oder +automatisch durch die `bootstrap`-Rolle (`import_role`) aufgerufen. Direkte +Einbindung per `import_role`: + +```yaml +- hosts: all + become: true + user: admin + roles: + - role: docker +``` + +```bash +ansible-playbook -i inventory/dmc12.yml playbooks/docker.yml +``` + +## Funktionsweise + +`tasks/main.yml` inkludiert die eigentliche Installations-Logik aus +`tasks/install-docker.yml`: + +1. **apt-Cache aktualisieren** – `cache_valid_time: 3600` +2. **Voraussetzungen installieren** – `ca-certificates`, `curl` +3. **Keyring-Verzeichnis anlegen** – `/etc/apt/keyrings` (Mode `0755`) +4. **Docker GPG-Key herunterladen** – nach `/etc/apt/keyrings/docker.asc` +5. **APT-Quelle einrichten** – Template `sources.list.j2` nach + `/etc/apt/sources.list.d/docker.sources` (deb822-Format) +6. **apt-Cache aktualisieren** – nach Repository-Hinzufügung +7. **Docker-Pakete installieren** – `docker_packages` (benachrichtigt Handler + `Start Docker`) + +## Variablen + +| Variable | Typ | Default | Beschreibung | +|----------------------|---------|--------------------------------------|-------------------------------------------------------| +| `docker_mirror` | string | `https://download.docker.com/linux/debian` | Basis-URL des Docker-APT-Repositories | +| `os_version_codename`| string | `{{ ansible_lsb.codename }}` | Codename der Distribution (für `Suites:`) | +| `docker_packages` | list | siehe unten | Liste der zu installierenden Docker-Pakete | + +Default `docker_packages`: + +```yaml +docker_packages: + - docker-ce + - docker-ce-cli + - containerd.io + - docker-buildx-plugin + - docker-compose-plugin +``` + +`os_version_codename` wird standardmäßig automatisch anhand von +`ansible_lsb.codename` ermittelt und kann bei Bedarf überschrieben werden. + +## Templates + +| Template | Ziel | +|-------------------|-------------------------------------------------| +| `sources.list.j2` | `/etc/apt/sources.list.d/docker.sources` (deb822) | + +## Handler + +| Handler | Auslöser | +|------------------|-----------------------------------------------------| +| `Start Docker` | Installation/Aktualisierung der Docker-Pakete | +| `Restart Docker` | (reserviert) systemd-Neustart | +| `Reload Docker` | (reserviert) systemd-Reload | + +## Tags + +Die Rolle vergibt keine eigenen Tags. Bei Bedarf über das Playbook steuerbar. + +## Abhängigkeiten + +- Keine weiteren Rollen. +- Collections: `ansible.builtin` (Bordmittel). + +## Hinweise + +- Die APT-Quelle liegt im **deb822-Format** vor, was ab Debian 12+ empfohlen + wird. Das签ierte-Keyfile liegt unter `/etc/apt/keyrings/docker.asc`. +- Der Handler `Start Docker` aktiviert und startet den Service, ohne bereits + laufende Container zu beeinflussen. +- Wird die Rolle innerhalb von `bootstrap` aufgerufen, übernimmt das Top-Level + Playbook das `become`/`user`-Handling. \ No newline at end of file diff --git a/roles/hawser/README.md b/roles/hawser/README.md new file mode 100644 index 0000000..536af56 --- /dev/null +++ b/roles/hawser/README.md @@ -0,0 +1,94 @@ +# Rolle `hawser` + +Aktualisiert den [Hawser](https://ghcr.io/finsys/hawser) Docker-Compose-Stack +auf den Ziel-Hosts. Hawser ist ein Docker-Management-Agent, der das Docker- +Socket nach außen freigibt. Die Rolle deployt die Compose-Datei aus einem +Template und zieht stets die neuesten Images (`pull: always`). + +> Siehe auch das Playbook `playbooks/upgrade-hawser.yml` sowie die +> [Repo-README](../../README.md). + +## Voraussetzungen + +- Debian-Ziel-Host mit installierter Docker Engine (Rolle `docker`) +- Bereits vorhandene Hawser-Installation + (`/opt/hawser/docker-compose.yml` muss existieren) +- `community.docker` Collection + +## Einbindung + +```yaml +- hosts: all + become: true + user: admin + roles: + - role: hawser +``` + +```bash +ansible-playbook -i inventory/dmc12.yml playbooks/upgrade-hawser.yml +``` + +## Funktionsweise + +`tasks/main.yml` importiert `tasks/update-stack.yml`: + +1. **Docker-Host-Info sammeln** – prüft, ob Docker erreichbar ist + (`community.docker.docker_host_info`). Bei Fehler werden nachfolgende + Tasks übersprungen. +2. **Compose-Datei prüfen** – `stat` auf `/docker-compose.yml`. + Fehlt die Datei, wird kein Update durchgeführt (Bestandsschutz). +3. **Compose-Datei ausliefern** – Template `docker-compose.yml.j2` wird nur + geschrieben, wenn Docker erreichbar UND bereits eine Compose-Datei + vorhanden ist. +4. **Stack aktualisieren** – `community.docker.docker_compose_v2` mit + `pull: always` und `state: present` zieht die neuesten Images und + erneuert die Container. + +## Variablen + +| Variable | Typ | Default | Beschreibung | +|--------------------------------|--------|----------------|-----------------------------------------------------------| +| `hawser_project_name` | string | `hawser` | Name des Docker-Compose-Projekts | +| `hawser_compose_dir` | string | `/opt/hawser` | Verzeichnis der Compose-Datei auf dem Zielhost | +| `hawser_port` | string | `2376` | Freigegebener Port des Hawser-Agents (Host-Port) | +| `hawser_stacks_volume` | string | `hawser_stacks`| Name des externen Docker-Volumes für Stack-Dateien | +| `hawser_allow_insecure_no_auth`| bool | `true` | `ALLOW_INSECURE_NO_AUTH` – Standard-Mode ohne Token | + +> **Achtung:** `hawser_allow_insecure_no_auth: true` erlaubt den Betrieb ohne +> Token-Authentifizierung auch auf Nicht-Loopback-Adressen. Nur setzen, wenn +> das Netzwerk durch andere Maßnahmen (Firewall, VPN) abgesichert ist. + +## Templates + +| Template | Ziel | +|------------------------|--------------------------------------------| +| `docker-compose.yml.j2`| `/docker-compose.yml` | + +Das Template konfiguriert den Hawser-Container mit Socket-Mount, externem +Volume, Port-Mapping, Environment-Variablen, `image: ghcr.io/finsys/hawser:latest` +und `restart: always`. + +## Handler + +Keine Handler erforderlich – `docker compose up -d` ersetzt laufende Container +eigenständig. + +## Tags + +Die Rolle vergibt keine eigenen Tags. + +## Abhängigkeiten + +- `community.docker` Collection (`docker_host_info`, `docker_compose_v2`) +- Vorherige Installation der `docker`-Rolle + +## Hinweise + +- Die Rolle **erzeugt keine Neuinstallation** – die Compose-Datei wird nur + geschrieben, wenn bereits eine existiert. So wird verhindert, dass Hawser + versehentlich auf Hosts ausgebracht wird, auf denen es nicht vorgesehen ist. +- Das externe Volume `hawser_stacks` muss vor dem ersten Start manuell + erstellt werden (`docker volume create hawser_stacks`). +- `pull: always` sorgt für aktuelle Images, erfordert aber Internetzugang + zum ghcr.io-Registry. \ No newline at end of file diff --git a/roles/healthcheck/README.md b/roles/healthcheck/README.md new file mode 100644 index 0000000..df70312 --- /dev/null +++ b/roles/healthcheck/README.md @@ -0,0 +1,97 @@ +# Rolle `healthcheck` + +Post-Update Quality-Gate. Die Rolle prüft nach einem OS-Update, ob alle +Docker-Container wieder laufen, und protokolliert das Ergebnis im selben +Update-Log, das auch von der `os-updates`-Rolle verwendet wird. + +> Siehe auch das Playbook `playbooks/os-updates-deb.yml` sowie die +> [Repo-README](../../README.md). + +## Voraussetzungen + +- Debian-Ziel-Host +- Optional installiertes Docker (wird automatisch erkannt) +- Idealerweise vorheriger Lauf der `os-updates`-Rolle (für gemeinsames Log) + +## Einbindung + +Die Rolle ist fest in `playbooks/os-updates-deb.yml` nach der `os-updates`- +Rolle eingebunden und wird in der Regel nicht separat aufgerufen: + +```yaml +- hosts: all + become: true + user: admin + roles: + - role: os-updates + - role: healthcheck +``` + +```bash +ansible-playbook -i inventory/dmc12.yml playbooks/os-updates-deb.yml +``` + +## Funktionsweise + +`tasks/main.yml` führt nacheinander folgende Schritte aus: + +1. **Docker-Binary erkennen** – `which docker` (fehlertolerant) +2. **Docker-Präsenz festhalten** – Fakt `healthcheck_docker_installed` +3. **Alle Container auflisten** – `docker ps -a --format {{.Names}}` +4. **Laufende Container auflisten** – `docker ps --filter status=running` +5. **Container-Health bewerten** – Differenz aus allen und laufenden + Containern ergibt `healthcheck_non_running_containers` +6. **Gesamtergebnis bestimmen** – `healthcheck_all_running`, + `healthcheck_passed` +7. **Default-Ergebnis ohne Docker** – falls Docker nicht installiert ist, + gilt der Healthcheck als bestanden (`passed: true`, 0 Container) +8. **Log-Verzeichnis sicherstellen** – delegiert an localhost +9. **Quality-Gate in Update-Log schreiben** – `blockinfile` mit Marker + `# {mark} ANSIBLE-HEALTHCHECK`, Abschnitt `quality_gate:` +10. **Fehlschlagen bei ungesunden Containern** – nur wenn + `healthcheck_fail_on_unhealthy` gesetzt ist + +## Variablen + +| Variable | Typ | Default | Beschreibung | +|------------------------------|-------|------------------------------------------------------------------|-----------------------------------------------| +| `healthcheck_logging_enabled`| bool | `{{ os_update_logging_enabled \| default(true) }}` | Logging aktivieren | +| `healthcheck_log_dir` | string| `{{ os_update_log_dir \| default('/ansible/logs') }}` | Basis-Verzeichnis für Logs | +| `healthcheck_log_inventory` | string| `{{ inventory_file \| basename \| splitext \| first }}` | Inventory-Name (abgeleitet) | +| `healthcheck_log_file` | string| `///update.log` | Pfad zur Update-Log-Datei | +| `healthcheck_fail_on_unhealthy`| bool| `false` | Playbook fehlschlagen lassen, wenn Container nicht laufen | + +Die Variablen leiten sich standardmäßig aus den Werten der `os-updates`-Rolle +ab, sodass beide Rollen in dasselbe Log schreiben. + +## Templates + +Keine Templates. + +## Handler + +Keine Handler. + +## Tags + +Die Rolle vergibt keine eigenen Tags. + +## Abhängigkeiten + +- Keine weiteren Rollen. +- Collections: `ansible.builtin` (Bordmittel). +- Empfohlener Partner: `os-updates`-Rolle (für gemeinsames Log-Format). + +## Hinweise + +- Wird Docker nicht gefunden, gilt der Healthcheck als bestanden – nützlich + für Hosts, die keine Container betreiben. +- Das Log wird **delegiert auf localhost** geschrieben (auf dem Ansible- + Controller), nicht auf dem Zielhost. Das Verzeichnis `logs/` ist + git-ignored. +- Die `quality_gate`-Sektion im Log ist an denselben Eintrag gekoppelt wie + der `os-updates`-Preflight, sodass ein Update-Lauf inkl. Healthcheck + nachvollziehbar dokumentiert ist. +- `healthcheck_fail_on_unhealthy: false` (Default) bricht das Playbook nicht + ab – bewusst gewählt, damit nach Updates nicht versehentlich ganze + Host-Gruppen blockiert werden. Für kritische Hosts individuell setzen. \ No newline at end of file diff --git a/roles/manage-ssh-keys/README.md b/roles/manage-ssh-keys/README.md new file mode 100644 index 0000000..be8c76f --- /dev/null +++ b/roles/manage-ssh-keys/README.md @@ -0,0 +1,104 @@ +# Rolle `manage-ssh-keys` + +Hardening-Rolle zur Verwaltung autorisierter SSH-Schlüssel. Sie fügt +erwünschte ("Good") Keys hinzu und entfernt unerwünschte ("Bad") Keys aus der +`authorized_keys`-Datei des Zielbenutzers. + +> Siehe auch das Playbook `playbooks/hardening/manage-ssh-keys.yml` sowie die +> [Repo-README](../../README.md). + +## Voraussetzungen + +- Debian-Ziel-Host +- SSH-Zugang als Zielbenutzer (Default: `admin`) +- `lineinfile`-/`blockinfile`-Module (Bordmittel) + +## Einbindung + +```yaml +- hosts: all + user: admin + roles: + - role: manage-ssh-keys +``` + +```bash +ansible-playbook -i inventory/dmc12.yml playbooks/hardening/manage-ssh-keys.yml +``` + +Good/Bad-Keys können per Inventory überschrieben oder über Umgebungsvariablen +übergeben werden (siehe auskommentiertes Beispiel im Playbook): + +```yaml +# vars: +# good_keys: "{{ lookup('env', 'good_keys') | from_json }}" +# bad_keys: "{{ lookup('env', 'bad_keys') | from_json }}" +``` + +## Funktionsweise + +`tasks/main.yml` steuert den modularen Ablauf: + +1. **`validate-authorized-keys.yml`** – stellt das `.ssh`-Verzeichnis des + eingeloggten Users sicher (Mode `0700`). +2. **`add-goodkeys.yml`** – fügt jeden Key aus `good_keys` per `lineinfile` + zur `authorized_keys` hinzu (idempotent). Benachrichtigt Handler + `Cleanup Comments` und `Add Comment`. +3. **`remove-badkeys.yml`** – entfernt jeden Key aus `bad_keys` per + `lineinfile` (state: absent). Benachrichtigt ebenfalls die Handler. + +Die Handler bereinigen alle Kommentarzeilen (`^#.*$`) und fügen einen +eindeutigen "Modified by Ansible"-Block mit Datum/Uhrzeit ein. + +## Variablen + +| Variable | Typ | Default | Beschreibung | +|-----------------------|---------|----------------|------------------------------------------------------| +| `ssh_user` | string | `admin` | (Referenz) Zielbenutzer – Aktionen laufen als dieser User | +| `good_keys` | list | siehe `defaults/` | Liste erwünschter SSH-Keys (vollständige Key-Zeilen) | +| `bad_keys` | list | siehe `defaults/` | Liste unerwünschter SSH-Keys (vollständige Key-Zeilen) | + +### Steuer-Variablen (keine Defaults) + +| Variable | Typ | Beschreibung | +|-----------------------|--------|-----------------------------------------------------------| +| `authorized_keys_file`| string | Pfad zur `authorized_keys`-Datei (muss gesetzt sein) | + +> `authorized_keys_file` wird im Playbook bzw. Inventory gesetzt und muss +> auf die Datei des Zielusers verweisen (z. B. +> `/home/admin/.ssh/authorized_keys`). + +Default `good_keys` enthält die Admin-Keys (Niklas, Dennis, Generic Ansible). +Default `bad_keys` enthält einen veralteten RSA-Key als Beispiel. + +## Templates + +Keine Templates. + +## Handler + +| Handler | Auslöser | Beschreibung | +|-------------------|-------------------------------------------|----------------------------------------------------------| +| `Cleanup Comments`| Good/Bad-Key-Änderung | Entfernt alle Kommentarzeilen (`^#.*$`) aus der Datei | +| `Add Comment` | Good/Bad-Key-Änderung | Fügt "Modified by Ansible on at " ein | + +## Tags + +Die Rolle vergibt keine eigenen Tags. + +## Abhängigkeiten + +- Keine weiteren Rollen. +- Collections: `ansible.builtin` (Bordmittel). + +## Hinweise + +- Die Rolle ist **idempotent**: mehrfaches Ausführen führt zu keinem + geänderten Zustand, wenn Keys bereits vorhanden/abwesend sind. +- Good/Bad-Keys sind **vollständige Key-Zeilen** inkl. Typ, Key und + Kommentar (z. B. `ssh-ed25519 AAAA... user@host`). Der Vergleich erfolgt + zeilenbasiert. +- Handler laufen erst am Ende des Playbook-Laufs – bei mehreren Key-Änderungen + wird die Datei nur einmal bereinigt. +- Vorsicht bei der Definition von `bad_keys`: zu weit gefasste Patterns + könnten legitime Keys entfernen. Immer die exakte Key-Zeile angeben. \ No newline at end of file diff --git a/roles/os-updates/README.md b/roles/os-updates/README.md new file mode 100644 index 0000000..4e6c0cf --- /dev/null +++ b/roles/os-updates/README.md @@ -0,0 +1,128 @@ +# Rolle `os-updates` + +Aktualisiert alle installierten Pakete auf Debian-Hosts, optional mit +Spiegel-Wechsel (Mirror-Switch) und Codename-Anpassung. Die Rolle führt bei +Bedarf einen Reboot durch (nur bei neuem Kernel, nicht in LXC-Containern) +und schreibt ein detailliertes Update-Log auf den Ansible-Controller. + +> Siehe auch das Playbook `playbooks/os-updates-deb.yml` (in dem direkt im +> Anschluss die `healthcheck`-Rolle läuft) sowie die +> [Repo-README](../../README.md). + +## Voraussetzungen + +- Debian-Ziel-Host +- Benutzer mit `become`-Rechten +- Schreibrecht auf dem Controller für das Log (delegiert nach localhost) + +## Einbindung + +```yaml +- hosts: all + become: true + user: admin + roles: + - role: os-updates +``` + +```bash +ansible-playbook -i inventory/dmc12.yml playbooks/os-updates-deb.yml +``` + +## Funktionsweise + +`tasks/main.yml` steuert den Ablauf: + +1. **`update_mirrors.yml`** (nur wenn `os_also_update_mirror`): + - Führt ggf. ein vorangestelltes `apt upgrade dist` durch, falls der + Codename des Hosts nicht dem Ziel-Codename entspricht. + - Sichert `/etc/apt/sources.list` (Debian <= 12). + - Entfernt `/etc/apt/sources.list` ab Debian 13 (Umstieg auf deb822). + - Schreibt das Template `sources.list-deb822.j2` nach + `/etc/apt/sources.list.d/debian.sources` (Debian >= 13) bzw. + `sources.list.j2` nach `/etc/apt/sources.list` (Debian < 13). + - Erkennt `.list`- und `.sources`-Fragmente in + `/etc/apt/sources.list.d` und ersetzt Codenames (z. B. `bookworm` → + `trixie`) per `replace`, sofern sie in `os_update_debian_codenames` + gelistet sind. + - Aktualisiert den apt-Cache, wenn sich Quellen geändert haben. +2. **`upgrade_packages.yml`**: + - `logging_preflight.yml` – ermittelt Anzahl und Liste der upgradbaren + Pakete, zeichnet Start-Zeitpunkt auf. + - `apt upgrade: full` – vollständiges Upgrade aller Pakete. Benachrichtigt + Handler `apt cleanup` und `apt autoremove`. + - `reboot.yml` – entscheidet über Reboot-Vergleich von laufendem und + installiertem Kernel, rebootet asynchron, wartet auf Wiederkehr, + erfasst Downtime. Wird in LXC-Containern übersprungen. + - `logging_postflight.yml` – berechnet Dauer, schreibt Log-Eintrag mit + allen Fakten in `os_update_log_file` (delegiert an localhost). + +### Reboot-Entscheidung + +- Läuft ein älterer Kernel als installiert, gilt `reboot_required: true`. +- Der Reboot erfolgt mit `async: 1`, `poll: 0`, gefolgt von + `wait_for_connection` (Delay 10s, Timeout 600s). +- In LXC-Containern (`virtualization_type == "lxc"`) wird der gesamte + Reboot-Block übersprungen. + +## Variablen + +| Variable | Typ | Default | Beschreibung | +|-----------------------------|--------|----------------------------------------------------------|-------------------------------------------------------------| +| `os_update_auto_upgrade` | bool | `true` | (Steuer-Vorbereitung) Auto-Upgrade erlauben | +| `os_also_update_mirror` | bool | `false` | Spiegel-Wechsel und Codename-Rewrite durchführen | +| `os_update_logging_enabled`| bool | `true` | Update-Logging aktivieren | +| `os_update_log_dir` | string | `/ansible/logs` | Basis-Verzeichnis für Logs | +| `os_update_log_inventory` | string | `{{ inventory_file \| basename \| splitext \| first }}` | Inventory-Name (abgeleitet) | +| `os_update_log_file` | string | `///update.log` | Pfad zur Update-Log-Datei (Controller-seitig) | +| `os_update_mirrors` | list | siehe `defaults/` | Zwei Spiegel: `[0]` Haupt-Spiegel, `[1]` Security-Spiegel | +| `os_update_version_codename`| string | `{{ ansible_facts['distribution_release'] }}` | Ziel-Codename für Template-Ausfüllung | +| `os_update_debian_codenames`| list | `[trixie, bookworm, bullseye]` | Erlaubte Codenames, die in `.list`/`.sources` umgeschrieben werden | + +> **Achtung:** `os_update_version_codename` wird in +> `inventory/group_vars/debian.yml` auf `trixie` überschrieben. Nicht blind +> ändern – der Wert steuert die Template-Ausfüllung der `sources.list`. + +## Templates + +| Template | Ziel | Debian-Version | +|---------------------------|-------------------------------------------------|----------------| +| `sources.list.j2` | `/etc/apt/sources.list` | < 13 | +| `sources.list-deb822.j2` | `/etc/apt/sources.list.d/debian.sources` | >= 13 | + +Beide Templates erzeugen `main`, `-updates`, `-backports` und `-security` +Einträge mit `main contrib non-free non-free-firmware`. + +## Handler + +| Handler | Auslöser | Beschreibung | +|------------------|-----------------------------------|-----------------------------------| +| `apt cleanup` | `apt upgrade: full` | `apt clean` + `apt autoclean` | +| `apt autoremove` | `apt upgrade: full` | `apt autoremove` | + +## Tags + +Die Rolle vergibt keine eigenen Tags. + +## Abhängigkeiten + +- Keine weiteren Rollen. +- Collections: `ansible.builtin` (Bordmittel). +- Empfohlener Partner: `healthcheck`-Rolle (für Quality-Gate nach Update). + +## Hinweise + +- **Logging**: Das Log wird **delegiert an localhost** geschrieben unter + `logs///update.log`. Das Verzeichnis `logs/` ist + git-ignored. Die Struktur ist so gewählt, dass die `healthcheck`-Rolle + ihre `quality_gate`-Sektion an denselben Log-Eintrag anhängen kann. +- **Spiegel-Wechsel** (`os_also_update_mirror: true`) ist potenziell + destruktiv: bestehende `sources.list` wird gesichert bzw. entfernt. + Vorsicht beim Wechsel auf andere Debian-Releases. +- **Codename-Rewrite** greift nur bei Codenames aus + `os_update_debian_codenames` – schützt davor, Drittrepositories + versehentlich umzuschreiben. +- **LXC**: In Containern wird der Reboot-Block komplett übersprungen + (`virtualization_type != "lxc"`). +- **Idempotenz**: `apt upgrade: full` meldet `changed`, wenn Pakete + aktualisiert wurden; ohne anstehende Updates ist der Lauf "ok". \ No newline at end of file