# 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."