161 lines
6.2 KiB
Bash
Executable File
161 lines
6.2 KiB
Bash
Executable File
#!/bin/sh
|
|
# =============================================================================
|
|
# Sicherung zurueckspielen
|
|
# =============================================================================
|
|
#
|
|
# docker compose exec sicherung /bin/sh /wiederherstellung.sh /backups/cockpit_2026-08-22_0315.dump.enc
|
|
#
|
|
# Das Skript spielt eine verschluesselte Sicherung zurueck. Es fragt
|
|
# ausdruecklich nach, weil dabei der aktuelle Datenbestand ueberschrieben
|
|
# wird.
|
|
#
|
|
# DREI DINGE, DIE MAN VORHER WISSEN MUSS:
|
|
#
|
|
# 1. Die Sicherung enthaelt die anwendungsseitig verschluesselten Felder,
|
|
# aber NICHT den Schluessel. Ohne den passenden ENC_KEY_Vn aus der .env
|
|
# bleiben Diagnosen, IBANs, Versicherungsnummern und Notizen unlesbar -
|
|
# die Datenbank ist dann zwar da, aber halb blind.
|
|
#
|
|
# 2. Ein Backup, das nie zurueckgespielt wurde, ist kein Backup. Probiere
|
|
# das hier einmal im Jahr auf einer Testdatenbank aus, bevor du es im
|
|
# Ernstfall zum ersten Mal brauchst. Siehe README, Abschnitt
|
|
# "Wiederherstellung ueben".
|
|
#
|
|
# 3. Die Dokumente werden NICHT selbsttaetig an ihren Platz geschrieben.
|
|
# Dieses Skript packt sie nach ./backups aus und sagt, wie es
|
|
# weitergeht. Grund: Der Sicherungsdienst hat auf das Ablageverzeichnis
|
|
# bewusst nur Lesezugriff (siehe docker-compose.yml), und in ein
|
|
# laufendes MinIO hineinzuschreiben wuerde dessen Datenbestand
|
|
# beschaedigen. Der letzte Handgriff bleibt beim Menschen - er ist ein
|
|
# Einzeiler und im Klartext beschrieben.
|
|
# =============================================================================
|
|
|
|
set -eu
|
|
|
|
DATEI="${1:-}"
|
|
|
|
if [ -z "$DATEI" ]; then
|
|
echo "Aufruf: $0 <pfad-zur-sicherung.dump.enc>" >&2
|
|
echo "" >&2
|
|
echo "Vorhandene Sicherungen:" >&2
|
|
ls -lh "${SICHERUNG_ZIEL:-/backups}"/cockpit_*.dump.enc 2>/dev/null >&2 || echo " keine gefunden" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "$DATEI" ]; then
|
|
echo "FEHLER: $DATEI gibt es nicht." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "${SICHERUNG_PASSWORT:-}" ]; then
|
|
echo "FEHLER: SICHERUNG_PASSWORT ist nicht gesetzt." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# --- Pruefsumme -------------------------------------------------------------
|
|
if [ -f "$DATEI.sha256" ]; then
|
|
echo "Pruefsumme wird geprueft ..."
|
|
if sha256sum -c "$DATEI.sha256" >/dev/null 2>&1; then
|
|
echo " in Ordnung."
|
|
else
|
|
echo "FEHLER: Die Pruefsumme stimmt nicht. Die Datei ist beschaedigt." >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "WARNUNG: Keine Pruefsummendatei gefunden - es wird ungeprueft fortgefahren."
|
|
fi
|
|
|
|
# --- Sicherheitsabfrage ------------------------------------------------------
|
|
echo ""
|
|
echo "Es wird zurueckgespielt nach:"
|
|
echo " Datenbank: ${PGDATABASE:-?} auf ${PGHOST:-?}"
|
|
echo " Aus Datei: $DATEI"
|
|
echo ""
|
|
echo "DER AKTUELLE DATENBESTAND WIRD DABEI UEBERSCHRIEBEN."
|
|
echo ""
|
|
|
|
if [ "${SICHERUNG_OHNE_RUECKFRAGE:-}" != "ja" ]; then
|
|
printf "Zum Fortfahren bitte JA eingeben: "
|
|
read -r antwort
|
|
if [ "$antwort" != "JA" ]; then
|
|
echo "Abgebrochen."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# --- Zurueckspielen ----------------------------------------------------------
|
|
echo ""
|
|
echo "$(date -Iseconds) Wiederherstellung beginnt ..."
|
|
|
|
# --clean --if-exists raeumt vorhandene Objekte ab, bevor sie neu angelegt
|
|
# werden. --no-owner, weil der Eigentuemer auf einem anderen Server anders
|
|
# heissen kann.
|
|
openssl enc -d -aes-256-cbc -pbkdf2 -iter 200000 \
|
|
-pass env:SICHERUNG_PASSWORT -in "$DATEI" \
|
|
| pg_restore --clean --if-exists --no-owner --no-privileges \
|
|
--dbname="${PGDATABASE:-postgres}" --exit-on-error
|
|
|
|
echo "$(date -Iseconds) Datenbank wiederhergestellt."
|
|
|
|
# --- Dokumente ---------------------------------------------------------------
|
|
# Zu "cockpit_2026-09-01_0315.dump.enc" gehoert
|
|
# "dokumente_2026-09-01_0315.tar.gz.enc" - gleicher Zeitstempel, anderer
|
|
# Name. Fehlt sie, stammt die Sicherung aus einer Fassung vor v1.12.0.
|
|
ZEITSTEMPEL="$(basename "$DATEI" | sed -n 's/^cockpit_\(.*\)\.dump\.enc$/\1/p')"
|
|
DOKUMENTE_DATEI="$(dirname "$DATEI")/dokumente_${ZEITSTEMPEL}.tar.gz.enc"
|
|
AUSPACKZIEL="$(dirname "$DATEI")/dokumente-wiederhergestellt_${ZEITSTEMPEL}"
|
|
|
|
if [ ! -f "$DOKUMENTE_DATEI" ]; then
|
|
echo ""
|
|
echo "WARNUNG: Zu dieser Sicherung gibt es kein Dokumentenarchiv."
|
|
echo " Erwartet wurde: $DOKUMENTE_DATEI"
|
|
echo " Sicherungen aus Fassungen vor v1.12.0 enthalten nur die"
|
|
echo " Datenbank. Die Akte ist dann vollstaendig, die Dateien"
|
|
echo " dahinter fehlen."
|
|
else
|
|
if [ -f "$DOKUMENTE_DATEI.sha256" ]; then
|
|
echo "Pruefsumme des Dokumentenarchivs wird geprueft ..."
|
|
if sha256sum -c "$DOKUMENTE_DATEI.sha256" >/dev/null 2>&1; then
|
|
echo " in Ordnung."
|
|
else
|
|
echo "FEHLER: Die Pruefsumme des Dokumentenarchivs stimmt nicht." >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
mkdir -p "$AUSPACKZIEL"
|
|
openssl enc -d -aes-256-cbc -pbkdf2 -iter 200000 \
|
|
-pass env:SICHERUNG_PASSWORT -in "$DOKUMENTE_DATEI" \
|
|
| tar -xzf - -C "$AUSPACKZIEL"
|
|
|
|
ANZAHL="$(find "$AUSPACKZIEL" -type f | wc -l)"
|
|
echo "$(date -Iseconds) Dokumente ausgepackt: $ANZAHL Dateien nach"
|
|
echo " $AUSPACKZIEL"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Naechste Schritte:"
|
|
echo " 1. Die SQL-Skripte erneut ausfuehren (Volltextsuche und Audit-Schutz):"
|
|
echo " docker compose exec app npm run db:sql"
|
|
echo " 2. Pruefen, ob ENC_KEY_V1 in der .env zu diesem Bestand passt -"
|
|
echo " ohne den richtigen Schluessel bleiben die verschluesselten"
|
|
echo " Felder unlesbar."
|
|
echo " 3. Die Dokumente an ihren Platz bringen. Dazu MinIO anhalten, das"
|
|
echo " Datenverzeichnis ersetzen und wieder starten - auf dem Host,"
|
|
echo " nicht in diesem Behaelter:"
|
|
echo ""
|
|
echo " docker compose stop minio app"
|
|
echo " docker run --rm \\"
|
|
echo " -v betreuungs-cockpit_minio-daten:/ziel \\"
|
|
echo " -v \"\$PWD/backups:/quelle:ro\" alpine \\"
|
|
echo " sh -c 'rm -rf /ziel/* /ziel/..?* && cp -a /quelle/dokumente-wiederhergestellt_*/. /ziel/'"
|
|
echo " docker compose up -d"
|
|
echo ""
|
|
echo " Steht mehr als ein ausgepacktes Verzeichnis unter ./backups,"
|
|
echo " vorher das richtige auswaehlen statt des Sternchens."
|
|
echo ""
|
|
echo " 4. In der Anwendung eine betreute Person oeffnen und nachsehen, ob"
|
|
echo " die Diagnosen im Klartext erscheinen. Dann ein Dokument"
|
|
echo " herunterladen. Erst wenn beides klappt, ist die"
|
|
echo " Wiederherstellung wirklich gelungen."
|