Files
management/docs/issues/0015-cfgmon-15-token-hygiene-einmal-tokens-der.md
T

142 lines
8.1 KiB
Markdown
Raw Normal View History

---
type: issue
id: "0015"
status: waiting
created: 2026-08-01
milestone: M2
priority: medium
due: 2026-08-31
wartegrund: "Entscheidung sorb 2026-08-15: Rotation erfolgt gebuendelt EINMAL bei der Abnahme der Plattform, nicht stueckweise vorher. Die Bestandsaufnahme (24 PATs, 6 Mirrors) liegt vor, die Reihenfolge steht — es fehlt nur der Ausloeser."
host: cfgmon
area: security
gitlab_iid: "15"
related: [docs/issues/0027-audit-01-acht-widersprueche-aus-dem-labnet-02.md]
---
# CFGMON-15: Token-Hygiene — Einmal-Tokens der LABNET-02-Nacht widerrufen
> Import aus [management#15](https://git.lab/axion1337.chat/management/-/issues/15) (2026-08-11). Kommentare und Verlauf bleiben dort; kanonisch ist ab jetzt diese Datei (ADR-0012).
Gemeldet von der CFGMON-Session am Ende der LABNET-02-Nacht.
Während der Arbeit entstanden **vier Einmal-Tokens** für Issue-Kommentare/Pushes, dazu existiert noch das **erste git.lab-Token** aus dem Erstzugang. Alle sind nach Abschluss von LABNET-02 funktionslos.
**Zu tun:** Bestand aufnehmen (Gitea-Access-Tokens + GitLab-PATs), nicht mehr benötigte widerrufen, verbleibende mit Ablaufdatum und sprechendem Namen versehen.
⚠️ **Randbedingung aus der Mirror-Diskussion:** Welcher Token in den Push-Mirrors der fünf gespiegelten Repos hinterlegt ist, ist derzeit **nicht rekonstruierbar** (die API maskiert ihn, in keiner Session dokumentiert). Ein Widerruf kann deshalb still einen Mirror brechen. Vor der Rotation: entweder die Mirror-Credentials bewusst neu setzen, oder nach dem Widerruf jeden Mirror-Status einmal prüfen (`GET /projects/<id>/remote_mirrors``last_error`).
## Bestandsaufnahme 2026-08-15
### git.lab-PATs: 24 Stück, davon 13 aktiv
Abgefragt über `GET /personal_access_tokens`**nur Metadaten, keine Werte** (die gibt die API
ohnehin nur bei der Erzeugung heraus). `last_used_at` ist dabei der eigentliche Hebel: er
trennt „wird gebraucht" von „liegt herum".
**Aktiv und nachweislich in Gebrauch — NICHT anfassen:**
| id | Name | Scopes | zuletzt genutzt |
|---|---|---|---|
| 6 | gitlab claude token | api | 2026-08-15 (heute — Session-Zugang) |
| 24 | wiki-canonize | write_repository | 2026-08-15 (CI-Kanonisierung) |
| 8 | Gitea-push-token | api, write_registry | 2026-08-14 |
| 19 | management#31 | read_api | 2026-08-14 |
**Aktiv, aber NIE benutzt — die eigentliche Hygiene-Baustelle:**
| id | Name | Scopes | angelegt |
|---|---|---|---|
| 18 | oskar light | api, read_api, **manage_runner, k8s** | 2026-08-04 |
| 9 | registry-cleanup | api, read/write_registry | 2026-08-03 |
| 11 | herold-hive | read/write_repository | 2026-08-04 |
| 15 | oskar read | read_service_ping, read_user, … | 2026-08-04 |
| 23 | wiki-canonize | write_repository | 2026-08-13 — **Dublette zu id=24** |
**Aktiv, einmal benutzt, seither still:** id=4 `tabby` (27.07.), id=10 `SORB API` (04.08.),
id=13 `herold` (04.08.), id=17 `oskar analyse` (09.08.).
**Bereits inaktiv (nichts zu tun):** ids 1, 2, 3, 5, 7, 12, 14, 16, 20, 21, 22.
Auffällig ist ein Muster: mehrere Namen existieren **doppelt**, einmal aktiv und einmal
inaktiv (`herold`, `oskar read`, `oskar analyse`, `wiki-canonize`) — offenbar wurde jeweils
neu erzeugt, ohne das alte zu widerrufen. Genau daraus entsteht der Wildwuchs, den dieses
Issue adressiert.
### Push-Mirrors: alle gesund, Konto aber weiterhin unbekannt
Sechs Mirrors, **alle `finished`, kein `last_error`** (Stand 2026-08-15): ThreadNet-Web,
gitops, thread-net-git, threadnet-call, threadnet-operating, management.
⚠️ Die Warnung des Issues bestätigt sich: GitLab maskiert in `remote_mirrors` **beide** Teile
der URL (`https://*****:*****@rohana…`). Es ist also **weder Konto noch Token rekonstruierbar**.
Und: die Mirrors authentifizieren sich gegen **Gitea**, das gesuchte Credential ist damit ein
**Gitea**-Token, kein git.lab-PAT — die PAT-Liste oben kann die Frage gar nicht beantworten.
*(Nebenbefund: `gameserver` hat wirklich keinen Mirror → bestätigt #0032. `notfallhandbuch`
bewusst nicht → ADR-0016. `threadnet-wiki` braucht keinen, es läuft in Gegenrichtung.)*
### Empfehlung — Reihenfolge zählt
1. **Mirror-Credential bewusst neu setzen, bevor irgendetwas widerrufen wird.** Ein
dedizierter Gitea-Token (Name z.B. `gitlab-mirror`, Scope `write:repository`, mit
Ablaufdatum), auf allen sechs Mirrors hinterlegt. Danach ist bekannt und dokumentiert,
woran sie hängen — die Unklarheit verschwindet, statt umschifft zu werden.
2. **Erst dann Gitea-Alttokens widerrufen**, anschließend alle sechs Mirrors einmal prüfen
(`GET /projects/<id>/remote_mirrors``last_error`).
3. **git.lab-PATs aufräumen:** die fünf nie benutzten zuerst (id 18, 9, 11, 15, 23) — id=18
ist wegen `manage_runner`+`k8s` der unangenehmste Fund. Danach die vier Einmal-Nutzer
(4, 10, 13, 17), sofern die zugehörigen Werkzeuge nicht mehr laufen.
4. **Verbleibende** mit sprechendem Namen **und Ablaufdatum** versehen — mehrere laufen Ende
August/Anfang September ohnehin aus, das ist der natürliche Zeitpunkt.
**Die Widerrufe selbst gehören sorb** (Credentials legt/entfernt der Mensch); ich habe
bewusst nichts widerrufen — bei Namen wie `herold`, `oskar`, `tabby` ist von hier nicht
erkennbar, ob dahinter ein laufendes Werkzeug steht. `last_used_at = None` heißt „nie
benutzt", nicht „nicht gebraucht": ein hinterlegter, aber noch nicht ausgelöster Token sieht
genauso aus.
### Bezug zu #0027 (W4/W5)
- **W5 aufgelöst:** Die Secrets-Regel in `AGENTS.md` hat jetzt eine **Bootstrap-Ausnahme**
auf einem Host, wo sorb die Datei nicht selbst anlegen kann, darf eine Session das
Credential schreiben, aber es gilt als exponiert (Rotationspflicht), wird mit Pfad+Zweck
festgehalten und bekommt ein fälliges Issue. Damit ist die Regel erfüllbar, ohne sie zu
brechen.
- **W4 Punkt 5** (Rotation der in der LABNET-02-Nacht exponierten Werte) ist inhaltlich
**dieses Issue** — der WG-Private-Key gehört ausdrücklich dazu und ist oben **nicht**
abgedeckt (er ist kein API-Token): separat rotieren.
- **W4 Punkt 4** (Repo-Zuhause für `lab.conf`, systemd-Drop-in, Root-CA) ist **nachweislich
offen**: `gitops:host-config/` existiert als Muster, enthält aber nur `maintenance-notify`.
Die Schließung von #16 war für diesen Punkt also verfrüht.
## Entscheidung 2026-08-15 — gebündelte Rotation bei der Abnahme
sorb: **Alle Tokens werden einmal gemeinsam rotiert, wenn die Plattform abgenommen ist**
nicht jetzt stückweise.
Das ist die risikoärmere Reihenfolge: Ein Widerruf mitten im Betrieb kann still einen der
sechs Push-Mirrors brechen (das Mirror-Credential ist nach wie vor nicht rekonstruierbar,
s.o.), und die Mirrors beliefern unter anderem die **Flux-Quelle**. Einmal koordiniert
rotieren, mit allen Beteiligten am Tisch, ist sauberer als vier Einzeleingriffe mit je
eigener Bruchstelle.
**Die Vorarbeit bleibt gültig und macht die spätere Rotation kurz:** Bestand der 24 PATs
(inkl. der fünf nie benutzten und der Dubletten), Zustand aller sechs Mirrors, und die
festgelegte Reihenfolge — erst dediziertes Mirror-Credential setzen, dann widerrufen, dann
Mirror-Status prüfen. Beim Abnahmetermin ist das abzuarbeiten, nicht neu zu erarbeiten.
⚠️ **Was mit der Vertagung bewusst in Kauf genommen wird** (gehört benannt, nicht
stillschweigend):
- Die in der LABNET-02-Nacht exponierten Werte — **WireGuard-Private-Key** und die beiden
git.lab-PATs — bleiben bis zur Abnahme gültig. Nach der Secrets-Regel („anzeigen =
Exposure = Rotation") ist das eine **bewusste Ausnahme**, kein Versehen.
- Fünf aktive, nie benutzte Tokens bleiben bestehen, darunter id=18 (`oskar light`) mit
`manage_runner` + `k8s` — der breiteste Scope im Bestand.
- **„Abnahme" ist kein datierter Meilenstein.** Genau so bleibt Sicherheitsarbeit liegen:
vertagt auf ein Ereignis ohne Datum. Das `due` dieses Issues (2026-08-31) bleibt deshalb
stehen — nicht als Rotationsfrist, sondern als **Wiedervorlage**: Ist die Abnahme dann
nicht in Sicht, wird die Vertagung neu bewertet statt weiterzulaufen.
Wenn die Vertagung dauerhaft gelten soll, gehört sie nach dem Framework in einen ADR
(bewusste Ausnahme von der Secrets-Regel) — bislang steht sie nur hier.