#!/bin/bash # ESPO-13-Secrets-setzen - legt Secrets auf der VM ab oder aktualisiert sie. # Aufruf ueber den RMM-Task, der jeden Wert per Heredoc einliest und als Umgebungsvariable uebergibt - # nie als Argument, denn Argumente stehen in der Prozessliste. # Ein leerer Wert oder ein nicht ersetzter Platzhalter (@Name@) laesst das bestehende Secret unveraendert. # Geschrieben wird erst, wenn alle uebergebenen Werte geprueft sind - alles oder nichts. set -u # Standzeile: zeigt im Protokoll, welche Fassung tatsaechlich gelaufen ist. echo "ESPO-13-Secrets-setzen, Skriptstand 2026-09-30" ZIEL=/srv/espo/secrets GITEA=https://gitea.subcura.net GITEA_BENUTZER=system # Bekannte Secrets in der Reihenfolge der Ausgabe: Datei|Umgebungsvariable|Format. # Ein neues Secret ist eine Zeile hier und ein Parameter im Task. SECRETS=' gitea_package_token|ESPO_GITEA_PACKAGE_TOKEN|^[0-9a-f]{40}$ ' fehler() { echo "FEHLER: $*"; echo "ESPO13_ERGEBNIS: FEHLER"; exit 1; } # Das RMM setzt einen leer gelassenen Parameter wortwoertlich als @Name@ ein (gemessen 30.09.2026). nicht_uebergeben() { [ -z "$1" ] || [[ "$1" =~ ^@[A-Za-z0-9_]+@$ ]]; } # Probeabruf der Package Registry mit einem Token. Der Token geht als netrc ueber einen Dateideskriptor # an curl und erscheint so weder in der Prozessliste noch in der Ausgabe. Liefert den HTTP-Code. registry_probe() { curl -s -o /dev/null -w '%{http_code}' --max-time 20 \ --netrc-file <(printf 'machine gitea.subcura.net login %s password %s\n' "$GITEA_BENUTZER" "$1") \ "$GITEA/api/v1/packages/EspoCRM_Packages?type=generic&limit=1" } # Funktionspruefung je Secret, zusaetzlich zum Format. Gibt 0 zurueck, wenn der Wert traegt. funktioniert() { # funktioniert local code case "$1" in gitea_package_token) code="$(registry_probe "$2")" [ "$code" = "200" ] && return 0 [ "$code" = "000" ] && echo " $1: Gitea nicht erreichbar" || echo " $1: Registry lehnt den Token ab (HTTP $code)" return 1 ;; esac return 0 } [ "$(id -u)" -eq 0 ] || fehler "nicht als root gestartet" # 1. Alle uebergebenen Werte pruefen: erst das Format, dann ob sie tatsaechlich funktionieren. # Ein Token mit gueltigem Format, der nicht traegt, soll keinen funktionierenden ersetzen. ZU_SCHREIBEN=" " while IFS='|' read -r NAME VAR FORMAT; do [ -n "$NAME" ] || continue WERT="${!VAR-}" nicht_uebergeben "$WERT" && continue [[ "$WERT" =~ $FORMAT ]] || fehler "$NAME hat nicht das erwartete Format - es wurde nichts geschrieben" funktioniert "$NAME" "$WERT" || fehler "$NAME funktioniert nicht - es wurde nichts geschrieben" ZU_SCHREIBEN="$ZU_SCHREIBEN$NAME " done <<< "$SECRETS" # 2. Schreiben: atomar ueber eine temporaere Datei im selben Verzeichnis, Rechte 0600, ohne Zeilenumbruch. install -d -m 0700 "$ZIEL" || fehler "Verzeichnis $ZIEL nicht anlegbar" FEHLT=0 while IFS='|' read -r NAME VAR FORMAT; do [ -n "$NAME" ] || continue if [[ "$ZU_SCHREIBEN" == *" $NAME "* ]]; then TMP="$(mktemp "$ZIEL/.$NAME.XXXXXX")" || fehler "temporaere Datei fuer $NAME nicht anlegbar" if printf '%s' "${!VAR}" > "$TMP" && chmod 0600 "$TMP" && mv -f "$TMP" "$ZIEL/$NAME"; then echo "$NAME: gesetzt" else rm -f "$TMP"; fehler "$NAME nicht geschrieben" fi elif [ -s "$ZIEL/$NAME" ]; then # Unveraendert heisst nicht ungeprueft: ein vorhandenes Secret, das nicht mehr traegt, ist ein Fehler. if funktioniert "$NAME" "$(cat "$ZIEL/$NAME")"; then echo "$NAME: unveraendert, funktioniert" else echo "$NAME: unveraendert, funktioniert NICHT"; FEHLT=1 fi else echo "$NAME: fehlt - weder vorhanden noch uebergeben"; FEHLT=1 fi done <<< "$SECRETS" if [ "$FEHLT" -eq 0 ]; then echo "ESPO13_ERGEBNIS: OK"; exit 0; else echo "ESPO13_ERGEBNIS: FEHLER"; exit 1; fi