Files
operating-automation/docs/05-Security-Hardening.md
Ansible Servercow da81549161 add docs
2026-06-11 18:04:41 +02:00

533 lines
14 KiB
Markdown

# Security & Hardening
## Übersicht
Diese Kategorie umfasst Playbooks und Rollen zur Verbesserung der Systemsicherheit, insbesondere SSH-Zugriffsverwaltung und Härtung.
**Anwendungsfälle**:
- Verwaltung autorisierter SSH-Schlüssel
- Entfernung kompromittierter oder veralteter Schlüssel
- SSH-Zugriffskontrolle über Whitelisting und Blacklisting
- Zentrale SSH-Schlüssel-Verwaltung über mehrere Hosts
---
## Playbooks
### hardening/manage-ssh-keys.yaml
Verwaltung von SSH-Schlüsseln für Systemzugriff (Hinzufügen/Entfernen).
**Datei**: `playbooks/hardening/manage-ssh-keys.yaml`
**Zweck**: Zentrale Verwaltung von SSH-Public-Keys mit Whitelisting (erlaubte Schlüssel) und Blacklisting (zu entfernende Schlüssel) auf allen verwalteten Hosts.
**Ziel-Hosts**: `all`
**Benutzer**: `tincadmin` (mit sudo-Rechten)
**Verwendete Rollen**:
- `manage-ssh-keys`
**Wichtige Variablen**:
| Variable | Typ | Beschreibung |
|----------|-----|-------------|
| `good_keys` | Liste | Autorisierte SSH-Public-Keys (werden hinzugefügt) |
| `bad_keys` | Liste | Zu entfernende SSH-Public-Keys (Blacklist) |
| `ssh_user` | String | Zielbenutzer für SSH-Schlüssel (Default: `root`) |
**Verwendungsbeispiel**:
```bash
# Mit Variablen aus Rolle (defaults/main.yml)
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml \
-i inventories/icp-fra-pve1.yml \
-K
# Mit externen Variablen (JSON-Format)
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml \
-i inventories/icp-fra-pve1.yml \
-e '{"good_keys": ["ssh-ed25519 AAAA... user@host"]}' \
-e '{"bad_keys": ["ssh-rsa AAAA... old-key"]}' \
-K
# Nur auf einzelnem Host
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml \
-i inventories/icp-fra-pve1.yml \
--limit critical-server.example.com \
-K
# Für spezifischen User (nicht root)
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml \
-i inventories/icp-fra-pve1.yml \
-e "ssh_user=tincadmin" \
-K
```
**Abhängigkeiten**:
- `manage-ssh-keys` Rolle
- Sudo-Rechte auf Zielhosts
- SSH-Zugriff zu Hosts
**Besonderheiten**:
- **Kommentierte Variablen** für externe Übergabe im Playbook
- **Validierung** von Schlüsseln vor Anwendung
- **Idempotent**: Mehrfache Ausführung sicher
- **Atomare Operationen**: Erst Validierung, dann Änderung
- **Automatisches Backup**: Vor jeder Änderung
**Workflow**:
1. Validiert SSH-Schlüssel-Format (good_keys und bad_keys)
2. Überprüft `.ssh`-Verzeichnis-Existenz (erstellt falls nötig)
3. Entfernt Schlüssel aus Blacklist (`bad_keys`)
4. Fügt Schlüssel aus Whitelist (`good_keys`) hinzu
5. Bereinigt Kommentare in authorized_keys
6. Fügt Änderungs-Timestamp hinzu
**Sicherheitsaspekte**:
- ✅ Whitelisting-Ansatz (explizite Erlaubnis)
- ✅ Blacklisting für Revokation kompromittierter Schlüssel
- ✅ Automatische Bereinigung alter Einträge
- ✅ Audit-Trail durch Timestamps
- ✅ Validierung verhindert fehlerhafte Schlüssel
---
## Rollen
### Rolle: manage-ssh-keys
**Zweck**: Verwaltet SSH-Schlüssel mit Whitelisting und Blacklisting-Mechanismen für sicheren Systemzugriff.
**Pfad**: `roles/manage-ssh-keys/`
**Hauptaufgaben**:
#### 1. validate-keys.yml
Stellt sicher, dass `.ssh`-Verzeichnis existiert und korrekte Berechtigungen hat.
**Funktionen**:
- Erstellt `.ssh`-Verzeichnis (falls nicht vorhanden)
- Setzt Berechtigungen: `0700` (nur Owner kann lesen/schreiben/ausführen)
- Erstellt `authorized_keys`-Datei (falls nicht vorhanden)
- Setzt Berechtigungen für `authorized_keys`: `0600`
**Ausgeführt für User**:
```yaml
ssh_user: "root" # Standard, kann überschrieben werden
```
#### 2. add-goodkeys.yml
Fügt autorisierte SSH-Public-Keys hinzu.
**Funktionen**:
- Iteriert über `good_keys`-Liste
- Fügt jeden Schlüssel zu `authorized_keys` hinzu
- Verhindert Duplikate (idempotent)
- Verwendet `authorized_key`-Modul von Ansible
**Beispiel good_keys**:
```yaml
good_keys:
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKey1 admin@workstation"
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC... admin@laptop"
```
#### 3. remove-badkeys.yml
Entfernt nicht autorisierte oder kompromittierte Schlüssel.
**Funktionen**:
- Iteriert über `bad_keys`-Liste
- Entfernt jeden Schlüssel aus `authorized_keys`
- Verwendet `absent`-State in `authorized_key`-Modul
- Sicher bei nicht vorhandenen Schlüsseln (idempotent)
**Beispiel bad_keys**:
```yaml
bad_keys:
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC... old-compromised-key"
- "ssh-dss AAAAB3NzaC1kc3MAAACBAP... deprecated-dsa-key"
```
**Standardvariablen** (`defaults/main.yml`):
```yaml
# User für SSH-Schlüsselverwaltung
ssh_user: "root"
# Pfad zu authorized_keys
authorized_keys_file: "/{{ ssh_user }}/.ssh/authorized_keys"
# Whitelist: Autorisierte SSH-Schlüssel (ca. 20+ Schlüssel)
good_keys:
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKey1"
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExampleKey2"
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC..."
# ... weitere autorisierte Schlüssel
# Blacklist: Zu entfernende Schlüssel (6+ revozierte Schlüssel)
bad_keys:
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC... old-key-1"
- "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD... compromised-key"
# ... weitere zu entfernende Schlüssel
```
**Handler**:
| Handler | Funktion |
|---------|----------|
| `Cleanup Comments` | Entfernt alte Kommentare aus authorized_keys |
| `Add Comment` | Fügt Änderungs-Timestamp hinzu |
**Verwendung in Playbooks**:
```yaml
# Vollständige Rolle
- name: Manage SSH Keys
hosts: all
become: true
roles:
- manage-ssh-keys
# Mit custom Variablen
- name: Manage SSH Keys for tincadmin user
hosts: all
become: true
roles:
- role: manage-ssh-keys
vars:
ssh_user: tincadmin
good_keys:
- "ssh-ed25519 AAAAC3... new-admin-key"
bad_keys:
- "ssh-rsa AAAAB3... old-admin-key"
# Einzelne Tasks
- name: Add authorized keys only
include_role:
name: manage-ssh-keys
tasks_from: add-goodkeys.yml
```
---
## SSH-Schlüssel-Typen
### Empfohlene Schlüsseltypen (2026)
| Typ | Sicherheit | Empfehlung | Verwendung in Projekt |
|-----|------------|------------|----------------------|
| **Ed25519** | ⭐⭐⭐⭐⭐ Höchste | ✅ Bevorzugt | Ja (~15+ Schlüssel) |
| **RSA 4096** | ⭐⭐⭐⭐ Hoch | ✅ Akzeptabel | Ja (~5+ Schlüssel) |
| **ECDSA** | ⭐⭐⭐ Mittel | ⚠️ Mäßig | Nicht im Projekt |
| **RSA 2048** | ⭐⭐ Niedrig | ⚠️ Veraltet | Einige Legacy-Keys |
| **DSA** | ⭐ Sehr niedrig | ❌ Deprecated | Sollte entfernt werden |
### Schlüssel-Generierung
**Ed25519 (empfohlen)**:
```bash
ssh-keygen -t ed25519 -C "admin@workstation-$(date +%Y%m%d)"
```
**RSA 4096**:
```bash
ssh-keygen -t rsa -b 4096 -C "admin@workstation-$(date +%Y%m%d)"
```
---
## Best Practices
### 1. Regelmäßiges Key-Rotation
Erneuern Sie SSH-Schlüssel regelmäßig:
```bash
# Quartalsweise
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml \
-i inventories/icp-fra-pve1.yml \
-e '{"good_keys": [...neue Schlüssel...]}' \
-e '{"bad_keys": [...alte Schlüssel...]}' \
-K
```
### 2. Zentrale Schlüsselverwaltung
Pflegen Sie `good_keys` und `bad_keys` in:
- `roles/manage-ssh-keys/defaults/main.yml` (Standard)
- Externe Variablendateien für verschiedene Umgebungen
- Vault-Datei für sensible Schlüssel
### 3. Audit-Trail
Dokumentieren Sie Schlüssel-Änderungen:
```bash
# Vor Änderung: Backup erstellen
ansible all -i inventories/icp-fra-pve1.yml \
-m fetch \
-a "src=/root/.ssh/authorized_keys dest=/backup/ssh-keys/{{ inventory_hostname }}-{{ ansible_date_time.date }}" \
-b
# Änderung durchführen
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml ...
# Verifizierung
ansible all -i inventories/icp-fra-pve1.yml \
-m shell -a "wc -l /root/.ssh/authorized_keys" \
-b
```
### 4. Kompromittierte Schlüssel sofort entfernen
Bei Sicherheitsvorfällen:
```bash
# Notfall-Entfernung kompromittierter Schlüssel
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml \
-i inventories/all.yml \
-e '{"bad_keys": ["ssh-rsa AAAA... KOMPROMITTIERT"]}' \
-K
```
### 5. Test auf Non-Production zuerst
```bash
# Test auf einzelnem Host
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml \
-i inventories/icp-fra-pve1.yml \
--limit test-host.example.com \
-e '{"good_keys": [...]}' \
-K
# Nach Verifizierung: Rollout
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml \
-i inventories/icp-fra-pve1.yml \
-K
```
### 6. Mehrfache Admin-Keys
Verwenden Sie mehrere Admin-Schlüssel für Redundanz:
```yaml
good_keys:
- "ssh-ed25519 ... primary-admin@workstation"
- "ssh-ed25519 ... secondary-admin@laptop"
- "ssh-ed25519 ... emergency-admin@spare"
```
---
## SSH-Daemon-Härtung
Während dieses Playbook die Schlüssel verwaltet, sollten Sie auch SSH-Daemon-Konfiguration härten.
### Empfohlene sshd_config-Einstellungen
```ini
# /etc/ssh/sshd_config
# Nur Public-Key-Authentifizierung
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no
# Kein Root-Login mit Passwort
PermitRootLogin prohibit-password
# Moderne Krypto-Algorithmen
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
# Weitere Härtungen
PermitEmptyPasswords no
X11Forwarding no
MaxAuthTries 3
LoginGraceTime 20
```
### Anwendung mit Ansible
**Siehe**: [`system` Rolle → ssh-hardening.yaml](07-Basis-System.md#rolle-system)
```bash
# SSH-Daemon härten (falls implementiert in system Rolle)
ansible-playbook playbooks/hardening/harden-sshd.yml \
-i inventories/icp-fra-pve1.yml \
-K
```
---
## Fehlerbehebung
### Problem: Aussperrung nach Schlüssel-Entfernung
**Symptome**: Kein SSH-Zugriff mehr nach Ausführung
**Prävention**:
1. **Immer** mindestens einen funktionierenden Schlüssel in `good_keys` behalten
2. Testen Sie auf einzelnem Host zuerst (`--limit`)
3. Halten Sie Console-Zugriff bereit (z.B. Proxmox VNC)
**Lösung bei Aussperrung**:
1. Zugriff über Console (Proxmox, IPMI, etc.)
2. Manuelle Wiederherstellung:
```bash
# Via Console
echo "ssh-ed25519 AAAA... emergency-key" >> /root/.ssh/authorized_keys
```
3. Führen Sie Playbook erneut aus mit korrekten Schlüsseln
### Problem: Schlüssel werden nicht hinzugefügt
**Symptome**: `good_keys` werden nicht in authorized_keys eingetragen
**Lösung**:
1. Überprüfen Sie Schlüssel-Format:
```bash
ssh-keygen -l -f /path/to/public_key.pub
```
2. Überprüfen Sie Berechtigungen:
```bash
ansible all -i inventories/... \
-m shell -a "ls -la /root/.ssh/" \
-b
```
3. Führen Sie validate-keys Task manuell aus:
```yaml
- include_role:
name: manage-ssh-keys
tasks_from: validate-keys.yml
```
### Problem: Handler werden nicht ausgeführt
**Symptome**: Timestamps oder Kommentare fehlen
**Lösung**:
- Handler laufen erst am Ende des Plays
- Erzwingen Sie Handler-Ausführung:
```yaml
- meta: flush_handlers
```
- Oder führen Sie Playbook mit `--force-handlers` aus
### Problem: Unterschiedliche Schlüssel pro Umgebung
**Symptome**: Dev/Prod benötigen verschiedene Schlüssel-Sets
**Lösung**:
Verwenden Sie separate Variablendateien:
```bash
# Development
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml \
-i inventories/dev.yml \
-e "@vars/ssh-keys-dev.yml" \
-K
# Production
ansible-playbook playbooks/hardening/manage-ssh-keys.yaml \
-i inventories/prod.yml \
-e "@vars/ssh-keys-prod.yml" \
-K
```
**vars/ssh-keys-prod.yml**:
```yaml
good_keys:
- "ssh-ed25519 ... prod-admin-1"
- "ssh-ed25519 ... prod-admin-2"
bad_keys:
- "ssh-rsa ... old-dev-key"
```
---
## Compliance und Audit
### DSGVO / Datenschutz
SSH-Schlüssel-Management unterstützt Compliance durch:
- ✅ **Access Control**: Nur autorisierte Personen
- ✅ **Audit Trail**: Timestamps in authorized_keys
- ✅ **Revocation**: Schnelle Entfernung kompromittierter Keys
- ✅ **Least Privilege**: Spezifische User-Zuordnung
### Audit-Kommandos
```bash
# Liste aller autorisierten Schlüssel
ansible all -i inventories/icp-fra-pve1.yml \
-m shell -a "cat /root/.ssh/authorized_keys" \
-b
# Zähle Schlüssel pro Host
ansible all -i inventories/icp-fra-pve1.yml \
-m shell -a "wc -l /root/.ssh/authorized_keys" \
-b
# Prüfe auf DSA-Schlüssel (veraltet)
ansible all -i inventories/icp-fra-pve1.yml \
-m shell -a "grep 'ssh-dss' /root/.ssh/authorized_keys || echo 'None found'" \
-b
# Letzte Änderung
ansible all -i inventories/icp-fra-pve1.yml \
-m stat -a "path=/root/.ssh/authorized_keys" \
-b
```
---
## Weitere Sicherheits-Maßnahmen
Neben SSH-Schlüssel-Verwaltung gibt es weitere Härtungs-Maßnahmen im Projekt:
### 1. Fail2Ban (nicht implementiert)
Schutz vor Brute-Force-Attacken
### 2. UFW/Firewall (nicht implementiert)
Netzwerk-Level-Zugriffsschutz
### 3. Sudo-Beschränkungen
Siehe `system` Rolle für zukünftige Implementierung
### 4. SELinux/AppArmor
OS-Level Mandatory Access Control
---
## Nützliche Kommandos
### SSH-Schlüssel-Informationen abrufen
```bash
# Alle Schlüssel auf Hosts anzeigen
ansible all -i inventories/icp-fra-pve1.yml \
-m shell \
-a "cat /root/.ssh/authorized_keys | grep -v '^#' | while read line; do echo \$line | ssh-keygen -l -f - 2>/dev/null || echo 'Invalid: '\$line; done" \
-b
# Schlüssel-Typen zählen
ansible all -i inventories/icp-fra-pve1.yml \
-m shell \
-a "cat /root/.ssh/authorized_keys | grep -v '^#' | awk '{print \$1}' | sort | uniq -c" \
-b
```
### Backup erstellen
```bash
# Backup aller authorized_keys Dateien
ansible all -i inventories/icp-fra-pve1.yml \
-m fetch \
-a "src=/root/.ssh/authorized_keys dest=/backup/ssh-keys/{{ inventory_hostname }}-{{ ansible_date_time.date }}/" \
-b
```
---
**Navigation**: [← Zurück: Mail-Server-Verwaltung](04-Mail-Server-Verwaltung.md) | [Nächstes: Virtualisierung →](06-Virtualisierung.md)