feat: switch Prosody to JWT auth (HS256, Embertime as issuer)
All checks were successful
deploy / deploy (push) Successful in 4s
All checks were successful
deploy / deploy (push) Successful in 4s
Replaces the anonymous-OK setup with JWT-gated joins. Only participants that Embertime invited get a valid token — random URL-guessers can no longer enter rooms even if they discover the slug. - ConfigMap: ENABLE_AUTH=1 + AUTH_TYPE=jwt + JWT_APP_ID=embertime - 20-secrets.yaml.example: JWT_APP_SECRET placeholder with docs - CLAUDE.md: documents the new auth model + rotation flow Pipeline rolls config out; the secret itself stays out-of-band — admin copies it from Embertime UI (Settings → Meeting-Server) or queries the embertime DB directly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d946046773
commit
8e76a96668
13
CLAUDE.md
13
CLAUDE.md
@ -39,9 +39,20 @@ Inter-Component-Auth über shared XMPP-Component-Secrets (im Kubernetes-Secret,
|
|||||||
|
|
||||||
Danach: Pipeline rollt aus, in ~3 Min steht `https://meet.it.financeflow.de`.
|
Danach: Pipeline rollt aus, in ~3 Min steht `https://meet.it.financeflow.de`.
|
||||||
|
|
||||||
|
## Auth-Modell (JWT, Stand 2026-05-11)
|
||||||
|
|
||||||
|
Prosody ist auf **`AUTH_TYPE=jwt`** (HS256) konfiguriert — Joins ohne signiertes Token werden abgelehnt. Embertime ist der einzige Token-Issuer:
|
||||||
|
|
||||||
|
- HMAC-Secret lebt in `app_settings.meeting_jwt_secret` (Embertime-DB)
|
||||||
|
- Wird auch im k8s-Secret `jitsi-secrets` als `JWT_APP_SECRET` benötigt — beide müssen identisch sein
|
||||||
|
- Embertime-Endpoint `GET /meetings/:id/join` mintet pro Teilnehmer + Meeting ein zeitlich begrenztes Token (gültig bis Meeting-Ende + 2h)
|
||||||
|
- Token-Payload enthält `room` (= room_slug), `context.user` (Display-Name + email + moderator-Flag)
|
||||||
|
|
||||||
|
Bei Secret-Rotation: neuer Wert über Embertime-Admin-UI sichtbar, dann `kubectl -n jitsi patch secret jitsi-secrets ...` + `kubectl -n jitsi rollout restart deployment` (sonst gilt noch der alte JWT_APP_SECRET in den laufenden Pods).
|
||||||
|
|
||||||
## Was NICHT machen
|
## Was NICHT machen
|
||||||
|
|
||||||
- Keine Authentifizierung aktivieren — der Witz ist, dass der Service ohne Login funktioniert. `ENABLE_AUTH=0` ist Pflicht.
|
- `ENABLE_AUTH=0` zurücksetzen — würde das ganze Auth-Modell unwirksam machen. Wenn du eine offene Instanz brauchst, lieber zweite Jitsi-Instanz auf anderem Subdomain.
|
||||||
- Keinen Jibri (Recording) ohne expliziten Auftrag — braucht extra Pod mit Chrome + viel mehr Ressourcen
|
- Keinen Jibri (Recording) ohne expliziten Auftrag — braucht extra Pod mit Chrome + viel mehr Ressourcen
|
||||||
- Kein Helm — bleibt beim raw-Manifest-Pattern wie Embertime
|
- Kein Helm — bleibt beim raw-Manifest-Pattern wie Embertime
|
||||||
- Nicht `replicas > 1` für prosody/jicofo — beide sind stateful Single-Instance
|
- Nicht `replicas > 1` für prosody/jicofo — beide sind stateful Single-Instance
|
||||||
|
|||||||
@ -22,11 +22,18 @@ data:
|
|||||||
XMPP_SERVER: "prosody.jitsi.svc.cluster.local"
|
XMPP_SERVER: "prosody.jitsi.svc.cluster.local"
|
||||||
XMPP_BOSH_URL_BASE: "http://prosody.jitsi.svc.cluster.local:5280"
|
XMPP_BOSH_URL_BASE: "http://prosody.jitsi.svc.cluster.local:5280"
|
||||||
|
|
||||||
# === Auth disabled — anyone with the URL can start a room. That's the
|
# === JWT-based auth — Prosody validates HS256 tokens signed by
|
||||||
# whole point of self-hosting (avoids the meet.jit.si Google/GitHub
|
# Embertime. Only invited participants get a valid token (with
|
||||||
# moderator gate). ===
|
# context.user populated, optional moderator flag). The shared HMAC
|
||||||
ENABLE_AUTH: "0"
|
# secret lives in the Kubernetes Secret as JWT_APP_SECRET. Guests are
|
||||||
|
# disabled — a missing/invalid token means no entry. ===
|
||||||
|
ENABLE_AUTH: "1"
|
||||||
|
AUTH_TYPE: "jwt"
|
||||||
ENABLE_GUESTS: "0"
|
ENABLE_GUESTS: "0"
|
||||||
|
JWT_APP_ID: "embertime"
|
||||||
|
JWT_ACCEPTED_ISSUERS: "embertime"
|
||||||
|
JWT_ACCEPTED_AUDIENCES: "embertime"
|
||||||
|
TOKEN_AUTH_URL: ""
|
||||||
|
|
||||||
# === TLS handled by ingress cert-manager, not by the jitsi/web container ===
|
# === TLS handled by ingress cert-manager, not by the jitsi/web container ===
|
||||||
ENABLE_LETSENCRYPT: "0"
|
ENABLE_LETSENCRYPT: "0"
|
||||||
|
|||||||
@ -13,8 +13,15 @@ metadata:
|
|||||||
namespace: jitsi
|
namespace: jitsi
|
||||||
type: Opaque
|
type: Opaque
|
||||||
stringData:
|
stringData:
|
||||||
|
# Inter-component passwords — generate fresh via generate-secrets.sh
|
||||||
JICOFO_COMPONENT_SECRET: "REPLACE_WITH_32_RANDOM_CHARS"
|
JICOFO_COMPONENT_SECRET: "REPLACE_WITH_32_RANDOM_CHARS"
|
||||||
JICOFO_AUTH_USER: "focus"
|
JICOFO_AUTH_USER: "focus"
|
||||||
JICOFO_AUTH_PASSWORD: "REPLACE_WITH_32_RANDOM_CHARS"
|
JICOFO_AUTH_PASSWORD: "REPLACE_WITH_32_RANDOM_CHARS"
|
||||||
JVB_AUTH_USER: "jvb"
|
JVB_AUTH_USER: "jvb"
|
||||||
JVB_AUTH_PASSWORD: "REPLACE_WITH_32_RANDOM_CHARS"
|
JVB_AUTH_PASSWORD: "REPLACE_WITH_32_RANDOM_CHARS"
|
||||||
|
# HMAC key shared with Embertime — must match app_settings.meeting_jwt_secret
|
||||||
|
# in Embertime's DB. Get it from the Embertime UI (Settings → Meeting-Server
|
||||||
|
# → "Secret rotieren") OR query the DB directly with:
|
||||||
|
# kubectl -n embertime exec -it deploy/embertime-postgres -- \
|
||||||
|
# psql -U embertime -t -c "select meeting_jwt_secret from app_settings"
|
||||||
|
JWT_APP_SECRET: "REPLACE_WITH_VALUE_FROM_EMBERTIME"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user