chore(coturn): automated TURN shared-secret rotation #46

Closed
sorb wants to merge 76 commits from turn-secret-rotation-20260801-020001 into main
3 changed files with 47 additions and 23 deletions
Showing only changes of commit 8a3274dd33 - Show all commits
+2 -1
View File
@@ -367,7 +367,8 @@ und [#15](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/15), Det
### Moderation & Anti-Abuse
- [x] **Draupnir Moderationsbot** → [Issue #18](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/18) (2026-07-29, deployed + live getestet)
- [ ] **Content Scanner für Media** → [Issue #19](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/19) (geplant, noch nicht umgesetzt - siehe Scoping-Einschränkung im Deployment-Guide)
- [x] **Content Scanner für Media** → [Issue #19](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/19) (2026-07-29, eigenes Synapse-Modul + ClamAV, live getestet - schützt nur unverschlüsselte Räume/DMs, siehe Deployment-Guide)
- [ ] **Grafana-Dashboard für ClamAV-Erkennungen** → [Issue #43](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/43)
### Secrets Management
- [ ] **External-Secrets Operator vs. SOPS-Setup** → [Issue #20](https://rohana.axion1337.de/sorb/axion1337.chat-gitops/issues/20)
@@ -1,7 +1,7 @@
# Moderation Bot & Content Scanning
**Status**: ✅ Draupnir deployed (2026-07-29, Closes Issue #18) | Content Scanner geplant, noch nicht umgesetzt (Issue #19)
**Konfiguration**: `apps/production/draupnir*.yaml`
**Status**: ✅ Draupnir deployed (2026-07-29, Closes Issue #18) | Content Scanner deployed + live getestet (2026-07-29, Closes Issue #19)
**Konfiguration**: `apps/production/draupnir*.yaml`, `apps/production/clamav*.yaml`, `apps/production/clamav_spam_checker.py`
## 1. Draupnir (Moderationsbot)
@@ -86,24 +86,47 @@ Alle Befehle im (verschlüsselten) Management-Room, Präfix `!draupnir`:
`ban`+Liste erfolgreich aus dem geschützten Raum entfernt. Kernmechanismus bestätigt
funktionsfähig.
## 2. Content Scanner (Issue #19, LOW - noch nicht umgesetzt)
## 2. Content Scanner (Issue #19)
**Wichtige Einschränkung, vorab geklärt**: `matrix-content-scanner-python` ist ein Proxy, den
der **Client** explizit statt der normalen Media-Endpunkte aufrufen muss - Synapse selbst
leitet nichts automatisch dorthin um. Diese client-seitige Unterstützung existiert nur noch in
den veralteten, nicht mehr gepflegten Android/iOS-SDKs. Weder aktuelles Element Web
(matrix-js-sdk, was hier läuft) noch Element X unterstützen das. Zusätzlich hat Synapse bei
verschlüsselten Anhängen ohnehin nie den Schlüssel - nur ein kooperierender Client kann ihn dem
Scanner geben.
**Verworfener erster Ansatz**: `matrix-content-scanner-python` ist ein Proxy, den der
**Client** explizit statt der normalen Media-Endpunkte aufrufen muss - Synapse selbst leitet
nichts automatisch dorthin um. Diese client-seitige Unterstützung existiert nur noch in
veralteten, nicht mehr gepflegten Android/iOS-SDKs; weder aktuelles Element Web noch Element X
unterstützen das (geprüft: kein `content_scanner`-Hook im offenen `element-x-android`-Repo).
Element selbst hat echtes serverseitiges Scanning - aber nur in der kommerziellen
**Element Pro** + **ESS Pro**-Kombination, nicht in unserer offenen ESS-Community-Installation.
**Konsequenz**: Falls umgesetzt, schützt der Scanner **keinen echten Nutzer-Traffic
automatisch** - nur manuelle/skriptgesteuerte Admin-Prüfungen sind möglich (z.B.
`kubectl port-forward` + `curl` nach manuellem Upload). Eine echte, transparente Absicherung
bräuchte entweder einen Client-Fork oder ein eigenes Synapse-`check_media_file_for_spam`-Modul
(deutlich größerer, separater Aufwand).
**Tatsächlich umgesetzt**: ein eigenes, kleines Synapse-Modul (`clamav_spam_checker.py`),
das Synapses echten, dokumentierten Hook `check_media_file_for_spam` nutzt - läuft
**serverseitig**, transparent für jeden Client, ganz ohne Mitwirkung des Clients. Kein
fertiges Modul dafür existiert (auch das verbreitete `synapse-http-antispam`-Brückenmodul
schließt genau diesen Callback explizit aus), daher selbst geschrieben.
Geplante Komponenten bei Umsetzung: ClamAV (`clamav/clamav:1.5.3`, eigene PVC für die
Signatur-DB) + `vectorim/matrix-content-scanner` (Config-Keys `scan.script`/
`scan.temp_directory`/`crypto.request_secret_path` - aus dem echten `config.sample.yaml`
bestätigt). Kein Ingress, keine NetworkPolicy-Ausnahme nötig, da nichts im Cluster oder von
außen automatisch darauf zugreift.
**Architektur**:
- ClamAV (`clamav/clamav:1.5.3`) läuft als eigener Pod, PVC für die Signatur-Datenbank.
- Das Modul (`apps/production/clamav_spam_checker.py`) wird per ConfigMap gemounted und über
`PYTHONPATH` importierbar gemacht (`synapse.extraVolumes`/`extraVolumeMounts`/`extraEnv` -
kein Custom-Synapse-Image nötig).
- Spricht ClamAVs natives INSTREAM-Protokoll direkt über **Twisted**-Netzwerk-Primitives
(`HostnameEndpoint`/`connectProtocol`), nicht über `asyncio` - Synapse läuft auf Twisteds
Reactor, nicht auf einer laufenden asyncio-Event-Loop. Ein erster Versuch mit
`asyncio.open_connection`/`wait_for` schlug live mit `RuntimeError: no running event loop`
fehl und fiel dadurch (durch das eigene Fail-Open-Verhalten) unbemerkt auf "durchlassen"
zurück - die EICAR-Testdatei wurde beim ersten Versuch nicht erkannt. Nach Umstellung auf
Twisted-Primitives funktioniert es sauber.
- **Fail-open** bei Scanner-Fehlern (Verbindungsfehler/Timeout → Datei wird durchgelassen,
laut geloggt) - ein ClamAV-Ausfall soll nicht alle Uploads auf dem Homeserver blockieren.
**Live getestet und bestätigt** (2026-07-29):
- Normale Datei in unverschlüsseltem Raum → läuft durch (kein Regressionsschaden).
- EICAR-Testdatei in unverschlüsseltem Raum → zuverlässig blockiert
(`ClamAV rejected an upload: Eicar-Test-Signature`, Client bekommt `400 Bad content` -
Synapse gibt bewusst keine Begründung an den Client zurück, nur in den Server-Logs sichtbar).
- EICAR-Testdatei in verschlüsseltem Raum/DM → **läuft durch** - erwartete, strukturelle
Grenze: Synapse hat bei E2EE nie den Entschlüsselungsschlüssel, sieht nur Ciphertext. Nur
ein kooperierender Client könnte das lösen (siehe oben, existiert nicht offen verfügbar).
**Bekannte Deckungslücke**: schützt nur unverschlüsselte Räume/DMs (viele öffentliche/
föderierte Räume) - keine Warnung/Kennzeichnung für Nutzer in verschlüsselten Räumen, dass
dort kein Scanning stattfindet. Folgeidee (Issue #43, LOW): Grafana-Dashboard über die
bestehenden Loki-Logs, um Erkennungen/Scanner-Ausfälle sichtbar zu machen.
+2 -2
View File
@@ -13,7 +13,7 @@ Die Implementierungen wurden in dieser Reihenfolge durchgeführt. Für neue Setu
| 3 | Monitoring mit Alloy/Prometheus/Loki | `03-monitoring-integration.md` | ✅ Deployed | lokal (10.0.0.3) |
| 4 | Element Web Anpassung & Desktop-Apps | `04-element-customization.md` | ✅ Deployed | `axion1337.chat` |
| 5 | Room Policies (Retention, Publication, Auto-Join) | `05-room-policies.md` | ✅ Deployed | Matrix Synapse |
| 6 | Moderationsbot (Draupnir) & Content Scanning | `06-moderation-content-scanning.md` | ✅ Draupnir deployed / ⏳ Scanner geplant | Matrix Synapse |
| 6 | Moderationsbot (Draupnir) & Content Scanning | `06-moderation-content-scanning.md` | ✅ Deployed | Matrix Synapse |
---
@@ -87,7 +87,7 @@ Custom Themes, Desktop-Setup-Scripts, Element Admin.
Message Retention, Room Publication, Auto-Join Policies.
### [06-moderation-content-scanning.md](06-moderation-content-scanning.md)
Draupnir Moderationsbot (Bans, Policy-Listen), Content Scanner (geplant, Issue #19).
Draupnir Moderationsbot (Bans, Policy-Listen), Content Scanner via eigenes Synapse-Modul (Issue #19) - beide live getestet.
---