533 lines
14 KiB
Markdown
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)
|