Drei Dinge, die zusammengehoeren.
1. Falscher Satz raus. 'there is no direct-to-Gitea exception left' stand seit
eff643e (2026-08-02, von mir) achtzehn Zeilen ueber einem Absatz, der eine
laufende Ausnahme beschreibt - der Wiki-Umzug hatte die letzte Ausnahme auf
REPO-Ebene beseitigt, ich hatte das zu 'gar keine mehr' verallgemeinert.
2. Das Warum der Gitea-Kopie ergaenzt. Bisher stand nur der Mechanismus da
('the cluster pulls from Gitea'), nicht der Grund: git.lab haelt die
Bauplaene, Gitea eine Kopie, die der Cluster OHNE verfuegbares Lab erreicht.
Ohne diese Begruendung sieht der Aufbau nach Altbestand aus - eine spaetere
Session koennte die Flux-Quelle auf git.lab 'geradeziehen' und genau die
Lab-Unabhaengigkeit zerstoeren, fuer die sie da ist. Steht jetzt als
ausdrueckliche Warnung in beiden CLAUDE.md.
3. Den monatlichen Handgriff abgeschafft. Der Rotations-CronJob laeuft im
Cluster, erreicht git.lab nicht und pusht nach Gitea; von dort musste die
Rotation bisher per Hand ueber git.lab zurueck. Wird das vergessen,
ueberschreibt der naechste Mirror-Push sie und Flux spielt still das ALTE
Shared Secret wieder ein - ein Fehler ohne Symptom.
Der Schedule-Job canonize_rotation holt jetzt taeglich jeden
turn-secret-rotation-*-Branch von Gitea, der nicht in main steckt, merged
und pusht ueber git.lab. Taeglich statt monatlich zum Rotationstermin, weil
ein monatlicher Lauf genau einen Versuch haette.
Faellt etwas aus dem Rahmen - Merge-Konflikt oder ein Secret ohne ENC[ -,
bricht der Job ab und pusht NICHTS. Die rote Pipeline ist der Alarm; ein
zusaetzlicher Termin waere wieder ein Todo, das man vergessen kann.
Verifiziert: YAML parst, alle elf Script-Bloecke sind gueltige sh-Syntax, und
die Kernlogik gegen den echten Repo-Stand durchgespielt - beide vorhandenen
Rotations-Branches werden korrekt als 'schon in main' uebersprungen.
Noch offen (braucht Rechte, siehe Dateikopf): Project Access Token als
CANONIZE_TOKEN hinterlegen und den taeglichen Schedule anlegen.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
109 lines
5.1 KiB
YAML
109 lines
5.1 KiB
YAML
# Leichter Verifikations-Job, portiert aus .gitea/workflows/deploy-on-push.yml
|
|
# (Gitea-CI-Rueckbau, CFGMON-11, erledigt 2026-08-01). Deployt nichts - Flux reconciled
|
|
# weiterhin selbststaendig aus dem Gitea-Mirror. Repo-Topologie: git.lab ist
|
|
# kanonisch, rohana/Gitea ist Push-Mirror und Flux-Quelle.
|
|
|
|
verify:
|
|
image: alpine:3.20
|
|
rules:
|
|
- if: $CI_COMMIT_BRANCH == "main"
|
|
changes:
|
|
- apps/**/*
|
|
- clusters/**/*
|
|
- .gitlab-ci.yml
|
|
script:
|
|
- apk add --no-cache git >/dev/null
|
|
- |
|
|
echo "YAML-Manifest-Check..."
|
|
find apps clusters -name "*.yaml" -type f | while read f; do
|
|
grep -q "^apiVersion:" "$f" || echo "WARN: $f enthaelt kein apiVersion - evtl. kein K8s-Manifest"
|
|
done
|
|
- |
|
|
echo "SOPS-Check der in diesem Push geaenderten Secret-Dateien..."
|
|
for f in $(git diff --name-only HEAD~1..HEAD -- '**/secret*.yaml' '**/credentials*.yaml' 2>/dev/null || true); do
|
|
if grep -q "ENC\[" "$f"; then echo "OK: $f ist verschluesselt"; else echo "WARNUNG: $f ist moeglicherweise NICHT verschluesselt!"; fi
|
|
done
|
|
- echo "Flux reconciled die Aenderungen innerhalb ~1 Minute (Quelle Gitea-Mirror)."
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# TURN-Rotation kanonisieren (laeuft NUR als Pipeline-Schedule)
|
|
#
|
|
# Der Rotations-CronJob laeuft im Cluster und erreicht git.lab nicht - er pusht
|
|
# seinen Branch deshalb nach Gitea. Von dort muss die Rotation ueber git.lab
|
|
# zurueck, sonst ueberschreibt der naechste Mirror-Push sie und Flux spielt still
|
|
# das ALTE Shared Secret wieder ein. Frueher war das ein monatlicher Handgriff;
|
|
# dieser Job erledigt ihn.
|
|
#
|
|
# Einrichtung (einmalig, braucht Rechte - siehe CLAUDE.md):
|
|
# 1. Project Access Token, Rolle Maintainer, Scope write_repository
|
|
# -> CI/CD-Variable CANONIZE_TOKEN (masked + protected)
|
|
# 2. Pipeline-Schedule anlegen, taeglich, z. B. "17 5 * * *"
|
|
#
|
|
# Warum taeglich statt monatlich zum Rotationstermin: ein monatlicher Schedule
|
|
# hat genau einen Versuch. Faellt der Runner an dem Tag aus, faellt die
|
|
# Kanonisierung ein Monat lang aus. Taeglich holt der Job jede offene Rotation
|
|
# spaetestens am Folgetag nach und ist ansonsten in Sekunden fertig.
|
|
# ---------------------------------------------------------------------------
|
|
canonize_rotation:
|
|
image: alpine:3.20
|
|
rules:
|
|
- if: $CI_PIPELINE_SOURCE == "schedule"
|
|
variables:
|
|
GIT_DEPTH: "0" # volle Historie: wir brauchen merge-base
|
|
script:
|
|
- apk add --no-cache git ca-certificates >/dev/null
|
|
- |
|
|
# Lab-CA: der Runner legt sie je nach Version an unterschiedlichen Orten ab.
|
|
for c in /etc/gitlab-runner/certs/git.lab.crt /etc/gitlab-runner/certs/ca.crt; do
|
|
[ -f "$c" ] && export GIT_SSL_CAINFO="$c" && break
|
|
done
|
|
echo "CA: ${GIT_SSL_CAINFO:-Systemspeicher}"
|
|
- |
|
|
if [ -z "$CANONIZE_TOKEN" ]; then
|
|
echo "CANONIZE_TOKEN fehlt - siehe Kopf dieser Datei, Schritt 1."
|
|
exit 1
|
|
fi
|
|
- git config --global user.email "ci@axion1337.chat"
|
|
- git config --global user.name "TURN-Rotation (automatische Kanonisierung)"
|
|
- git remote add gitea https://rohana.axion1337.de/sorb/axion1337.chat-gitops.git
|
|
- git fetch --quiet gitea
|
|
- git fetch --quiet origin main
|
|
- git checkout -B main origin/main
|
|
- |
|
|
MERGED=0
|
|
for ref in $(git for-each-ref --format='%(refname:short)' 'refs/remotes/gitea/turn-secret-rotation-*'); do
|
|
SHA=$(git rev-parse "$ref")
|
|
if git merge-base --is-ancestor "$SHA" HEAD; then
|
|
echo "bereits kanonisiert: $ref"
|
|
continue
|
|
fi
|
|
echo "kanonisiere: $ref ($SHA)"
|
|
SUBJ="chore(coturn): TURN-Rotation aus ${ref#gitea/} uebernommen"
|
|
BODY="Automatisch kanonisiert: der Rotations-CronJob im Cluster erreicht git.lab nicht und pusht nach Gitea; dieser Commit bringt die Rotation auf den kanonischen Weg zurueck, bevor der Mirror sie ueberschreiben kann."
|
|
if ! git merge --no-ff -m "$SUBJ" -m "$BODY" "$SHA"; then
|
|
echo "MERGE-KONFLIKT in $ref - es wird nichts gepusht."
|
|
echo "Von Hand aufloesen, siehe CLAUDE.md (Abschnitt Repo Topology)."
|
|
exit 1
|
|
fi
|
|
MERGED=1
|
|
done
|
|
echo "MERGED=$MERGED" > .canonize_state
|
|
- |
|
|
. ./.canonize_state
|
|
if [ "$MERGED" = "0" ]; then
|
|
echo "Keine offene Rotation - nichts zu tun."
|
|
exit 0
|
|
fi
|
|
# Sicherheitsnetz: die Rotation fasst genau diese Secrets an. Kaeme hier
|
|
# etwas Unverschluesseltes durch, waere das Shared Secret im Klartext in Git.
|
|
for f in apps/production/coturn-secret.yaml apps/production/synapse-turn-secret.yaml; do
|
|
if ! grep -q "ENC\[" "$f"; then
|
|
echo "ABBRUCH: $f ist nicht SOPS-verschluesselt - es wird nichts gepusht."
|
|
exit 1
|
|
fi
|
|
echo "OK: $f ist verschluesselt"
|
|
done
|
|
git push "https://oauth2:${CANONIZE_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" HEAD:main
|
|
echo "Gepusht. Der Mirror traegt es nach Gitea zurueck, der PR schliesst sich dort selbst;"
|
|
echo "der Rotations-Branch existiert dann nur noch auf Gitea und wird vom Mirror entfernt."
|