sorb's call. The goal is already met where secrets actually move: the ESS chart rolls its components on config change via pod-template hash labels, and coturn plus Synapse are handled by the rotation job's annotation bump — the one case with regular unattended rotation, solved precisely because of that. What is left are three services whose secrets change rarely and by deliberate act, at the very moment someone is already watching and ADR-0011 applies. A permanent controller allowed to patch arbitrary deployments is the worse trade for that. The map is the outcome here, not an installation: the assumption had been that MAS was uncovered, and a reloader would have been aimed at a solved problem. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
119 lines
6.1 KiB
Markdown
119 lines
6.1 KiB
Markdown
---
|
||
type: issue
|
||
id: "0044"
|
||
status: done
|
||
created: 2026-08-11
|
||
milestone: M5
|
||
priority: low
|
||
area: infrastructure
|
||
related: [docs/adr/0011-enrollment-localpart-kollision-verweigern.md]
|
||
---
|
||
# SOPS-Values-Secret-Änderung startet den konsumierenden Dienst nicht neu
|
||
|
||
## Problem / Motivation
|
||
|
||
Beim Ausrollen des `on_conflict: fail`-Fixes (ADR-0011) trat ein Footgun zutage:
|
||
Flux aktualisierte das SOPS-verwaltete Secret `ess-mas-values-secret`, aber der
|
||
laufende MAS-Pod war älter als die Änderung und behielt die alte Config im
|
||
Speicher — MAS liest seine Config nur beim Start. Der Sicherheits-Fix stand auf
|
||
der Platte, war im Prozess aber **nicht aktiv**, bis ein manueller
|
||
`kubectl rollout restart` folgte. „committet ≠ deployed ≠ aktiv."
|
||
|
||
Das betrifft nicht nur MAS: jeder Dienst, der ein von Flux/SOPS gepflegtes
|
||
Values-Secret nur beim Start liest, hat dieselbe stille Lücke. Aktuell ist die
|
||
einzige Absicherung die in ADR-0011 festgeschriebene **manuelle** Restart-und-
|
||
Verifikations-Regel — leicht zu vergessen.
|
||
|
||
## Acceptance
|
||
|
||
- Änderungen an einem konsumierten Values-Secret lösen automatisch einen Rollout
|
||
des abhängigen Deployments aus (z. B. Checksum-/Hash-Annotation auf dem
|
||
Pod-Template, ein Reloader wie stakater/Reloader, oder ein
|
||
`configMapGenerator`/`secretGenerator`-Namenshash in kustomize).
|
||
- Verifiziert an MAS: Änderung am Secret → neuer Pod ohne Handeingriff, jünger als
|
||
die Änderung.
|
||
- Mindestens MAS abgedeckt; idealerweise als wiederverwendbares Muster für weitere
|
||
von SOPS-Secrets gespeiste Dienste.
|
||
|
||
## Notes
|
||
|
||
Automatisiert nur den bereits in ADR-0011 vorgeschriebenen manuellen Schritt —
|
||
daher `priority: low`. M5, weil die Fähigkeit (Auto-Reload) neu ist, nicht kaputt.
|
||
|
||
## Untersuchung 2026-08-15 — die Abdeckung ist deutlich besser als angenommen
|
||
|
||
Vor dem Einbau eines Reloaders geprüft, wo die Lücke **tatsächlich** klafft. Ergebnis: der im
|
||
Issue beschriebene Fall (MAS) ist bereits abgedeckt, und zwar von der Chart selbst.
|
||
|
||
**MAS ist abgedeckt — verifiziert am laufenden Deployment.** Die ESS-Chart hängt Prüfsummen
|
||
als **Labels** ans Pod-Template (`templates/matrix-authentication-service/deployment.yaml`):
|
||
|
||
```
|
||
k8s.element.io/matrix-authentication-service-config-hash: sha1sum(configmap-data)
|
||
k8s.element.io/matrix-authentication-service-secret-hash: sha1sum(secret-data)
|
||
```
|
||
|
||
Ein geändertes Label ändert das Pod-Template — Kubernetes rollt also von selbst aus. Live
|
||
vorhanden (drei Hash-Labels am MAS-Deployment). Und der HelmRelease steht auf `interval: 1m`,
|
||
Flux liest `valuesFrom` also jede Minute neu ein und rendert bei Änderung neu.
|
||
|
||
**Damit ist die Ursachenannahme des Issues zu korrigieren:** Der Mechanismus fehlte nicht.
|
||
Wahrscheinlicher ist, dass beim ADR-0011-Vorfall innerhalb des ersten Reconcile-Fensters
|
||
geprüft wurde — „committet ≠ deployed" stimmt, aber die Lücke war **zeitlich**, nicht
|
||
strukturell. Das ändert nichts an der Richtigkeit der ADR-0011-Regel (nach einem
|
||
Sicherheits-Fix aktiv verifizieren), wohl aber an der Diagnose.
|
||
|
||
**Abdeckung im Überblick** (Hash-Labels am Pod-Template gezählt):
|
||
|
||
| Abgedeckt | wodurch |
|
||
|---|---|
|
||
| MAS (3), element-web (2), haproxy (3), matrix-rtc (1–2) | ESS-Chart-Hash-Labels |
|
||
| coturn + Synapse (TURN-Secret) | eigener Mechanismus: der Rotations-CronJob hebt `rotated-at`/Checksum-Annotationen, der Merge startet beide Verbraucher neu (#38) |
|
||
|
||
| Nicht abgedeckt | konsumiertes Secret |
|
||
|---|---|
|
||
| `draupnir` | `draupnir-config` |
|
||
| `wikijs` | `wikijs-postgres-secret` |
|
||
| `concierge-bot` | `concierge-credentials` |
|
||
|
||
**Bewertung.** Übrig bleiben drei Dienste mit Secrets, die sich **selten und stets absichtlich**
|
||
ändern — anders als das monatlich rotierende TURN-Secret, das genau deshalb bereits einen
|
||
eigenen Trigger hat. Ein zusätzlicher Controller (stakater/Reloader) bräuchte Rechte, Deployments
|
||
zu patchen, und würde eine Dauerkomponente für ein Risiko einführen, das bei den wirklich
|
||
bewegten Secrets bereits gelöst ist.
|
||
|
||
**Empfehlung: nicht einbauen**, sondern diese Abdeckungskarte als Ergebnis festhalten und die
|
||
ADR-0011-Regel (aktiv verifizieren) für die drei Nachzügler gelten lassen. Wer anderer Meinung
|
||
ist, hat mit Reloader einen sauberen Weg — die Chart erlaubt Annotationen je Komponente
|
||
(`matrixAuthenticationService.annotations`, schema-geprüft), sie landen am Deployment **und** am
|
||
Pod-Template.
|
||
|
||
## Geschlossen 2026-08-15 — Entscheidung sorb: kein Reloader
|
||
|
||
Die Abdeckungskarte oben ist das Ergebnis; ein zusätzlicher Controller wird **bewusst nicht**
|
||
eingebaut.
|
||
|
||
**Begründung.** Das Ziel des Issues — „Änderungen an einem konsumierten Values-Secret lösen
|
||
automatisch einen Rollout aus" — ist für die Dienste, bei denen sich Secrets real bewegen,
|
||
**bereits erfüllt**, nur anders als vermutet:
|
||
|
||
- **MAS und die übrigen ESS-Komponenten** über die Hash-Labels der Chart am Pod-Template
|
||
(live verifiziert), zusammen mit `interval: 1m` am HelmRelease.
|
||
- **coturn und Synapse** über den `rotated-at`-Bump des Rotations-CronJobs — der einzige Fall
|
||
mit regelmäßiger, unbeaufsichtigter Secret-Änderung, und genau deshalb schon gelöst (#38).
|
||
|
||
Übrig bleiben `draupnir`, `wikijs` und `concierge-bot`: Secrets, die sich **selten und stets
|
||
durch bewusstes Handeln** ändern — also in dem Moment, in dem ohnehin jemand hinschaut und die
|
||
ADR-0011-Regel (aktiv verifizieren) greift. Dafür einen Dauer-Controller mit Rechten, beliebige
|
||
Deployments zu patchen, in die Produktion zu stellen, ist der schlechtere Tausch: bleibende
|
||
Angriffsfläche und Wartungslast gegen ein Restrisiko, das genau dort klein ist, wo es zählt.
|
||
|
||
**Das eigentliche Ergebnis dieses Issues ist die Karte, nicht der Einbau.** Vorher wusste
|
||
niemand, dass MAS abgedeckt ist — die Annahme war das Gegenteil, und ein Reloader wäre auf ein
|
||
bereits gelöstes Problem gesetzt worden.
|
||
|
||
**Falls die Entscheidung später kippt** (etwa wenn ein Dienst dazukommt, dessen Secret
|
||
automatisiert rotiert): Der Weg ist vorbereitet — die ESS-Chart erlaubt Annotationen je
|
||
Komponente (`matrixAuthenticationService.annotations`, schema-geprüft), und sie landen sowohl am
|
||
Deployment als auch am Pod-Template, also genau dort, wo stakater/Reloader sie liest.
|