- Python 47.5%
- HTML 32.9%
- CSS 18.4%
- Dockerfile 1.2%
Web-UI zur Verwaltung von TeamSpeak-6-Servergruppen und Bans fuer offline Nutzer. Rollenmodell auf Basis der Authentik-Gruppen: Elite, Co-Leader und Server Admin duerfen nur von Co-Leadern und Server Admins vergeben, entzogen oder gebannt werden. Absicherung: Proxy-Secret gegen direkte Container-Zugriffe, Origin-Pruefung gegen CSRF, Query-Passwort per Pipe-fd statt argv an sshpass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| static | ||
| templates | ||
| .env.example | ||
| .gitignore | ||
| app.py | ||
| docker-compose.yaml | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
| requirements.txt | ||
TSPerms
Kleines Web-UI zur Verwaltung von TeamSpeak-6-Servergruppen und Bans — auch für Nutzer, die gerade offline sind. Flask-App, die per SSH-ServerQuery mit dem TeamSpeak-Server spricht.
Funktionen
- Client-Liste aus der TS-Datenbank, sortiert nach letztem Login, mit Suche
- Servergruppen eines Clients setzen und entziehen
- Bannen (UID, optional zusätzlich letzte IP) mit Grund und Dauer
- Ban-Übersicht mit Entbannen
- Rollenmodell auf Basis der Authentik-Gruppen des eingeloggten Nutzers
Rollenmodell
Die App steht hinter Traefik mit einer Authentik-forwardAuth-Middleware und
wertet die durchgereichten Header X-authentik-username und
X-authentik-groups aus.
| Aktion | Elite | Co-Leader / Server Admin |
|---|---|---|
| Elite, Co-Leader, Server Admin vergeben/entziehen | nein | ja |
| übrige Gruppen (Member, Gäste, Music Bot) | ja | ja |
| Member/Gäste bannen | ja | ja |
| Elite, Co-Leader, Server Admin bannen | nein | ja |
| Entbannen | ja | ja |
Die Servergruppe Server Admin kann grundsätzlich nicht über das Web
entfernt werden, auch nicht von der Leitung (PROTECTED_GROUPS).
Wer als Leitung gilt, ergibt sich allein aus der Authentik-Gruppenmitgliedschaft — es gibt keine Nutzerliste in der App.
Konfiguration
| Variable | Default | Bedeutung |
|---|---|---|
TS_HOST |
— | Hostname des TeamSpeak-Containers |
TS_PORT |
10022 |
SSH-ServerQuery-Port |
TS_USER |
serveradmin |
Query-Benutzer |
TS_PASS |
— | Query-Passwort |
TS_SID |
1 |
Virtual Server ID |
LEADER_ONLY_SGIDS |
6,9,10 |
Servergruppen, die nur die Leitung vergeben darf |
LEADER_AK_GROUPS |
Co-Leader,Server Admin,authentik Admins |
Authentik-Gruppen, die als Leitung gelten |
PROXY_SECRET |
leer | Gemeinsames Geheimnis mit der Traefik-Middleware |
APP_ORIGIN |
https://ts-perms.joshuahirsig.xyz |
Erlaubter Origin für schreibende Requests |
FLASK_SECRET |
zufällig | Session-Secret für Flash-Meldungen |
PORT |
5000 |
Listen-Port |
Absicherung
Die App führt selbst keine Anmeldung durch, sondern verlässt sich auf den
vorgelagerten Proxy. Damit das kein blindes Vertrauen ist, prüft sie bei jedem
Request (außer /health und /static):
X-Proxy-Secretmuss zuPROXY_SECRETpassen. Traefik setzt den Header per Middleware; Requests, die den Container direkt erreichen (etwa aus einem anderen Container im selben Docker-Netz), werden mit 403 abgewiesen und können deshalb auch keine Auth-Header fälschen.X-authentik-usernamemuss gesetzt sein.- Bei schreibenden Requests muss
Originbzw.ReferermitAPP_ORIGINbeginnen (CSRF-Schutz).
Zusätzlich wird das Query-Passwort über einen Pipe-Filedescriptor an sshpass
übergeben (-d), damit es nicht in der Prozessliste des Containers steht.
Die Traefik-Middleware dazu (File-Provider), vor der Authentik-Middleware in die Router-Kette hängen:
http:
middlewares:
tsperms-proxy:
headers:
customRequestHeaders:
X-Proxy-Secret: "<gleicher Wert wie PROXY_SECRET>"
Deployment
cp .env.example .env # und ausfüllen
docker compose up -d --build
Der Container braucht Zugriff auf das Docker-Netz des TeamSpeak-Servers sowie
auf das proxy-Netz von Traefik.
Lizenz
0BSD — BSD Zero Clause License.