#!/usr/bin/env bash # Verificare de restaurare pentru backup-urile SQLite criptate (T2/P0-4). # # Un backup neverificat nu e backup: decripteaza + dezarhiveaza (intr-un fisier temporar, # NU suprascrie baza vie) ultimul backup (sau cel indicat explicit) si ruleaza # PRAGMA integrity_check + un SELECT count(*) FROM submissions. Iese cu cod != 0 daca # ceva esueaza sau daca integritatea nu e "ok". # # Utilizare: # AUTOPASS_BACKUP_PASSPHRASE_FILE=/run/secrets/backup_pass tools/restore_check.sh # tools/restore_check.sh /data/backups/autopass-20260706-120000.db.gz.gpg set -euo pipefail BACKUP_DIR="${AUTOPASS_BACKUP_DIR:-/data/backups}" log() { echo "[restore_check] $*"; } err() { echo "[restore_check] EROARE: $*" >&2; } CLEANUP_PATHS=() cleanup() { local p for p in "${CLEANUP_PATHS[@]:-}"; do [[ -n "$p" ]] && rm -rf "$p" done } trap cleanup EXIT if [[ -n "${AUTOPASS_BACKUP_PASSPHRASE_FILE:-}" ]]; then if [[ ! -f "$AUTOPASS_BACKUP_PASSPHRASE_FILE" ]]; then err "AUTOPASS_BACKUP_PASSPHRASE_FILE indica un fisier inexistent: $AUTOPASS_BACKUP_PASSPHRASE_FILE" exit 1 fi PASSPHRASE_FILE="$AUTOPASS_BACKUP_PASSPHRASE_FILE" elif [[ -n "${AUTOPASS_BACKUP_PASSPHRASE:-}" ]]; then PASSPHRASE_FILE="$(mktemp)" chmod 600 "$PASSPHRASE_FILE" CLEANUP_PATHS+=("$PASSPHRASE_FILE") printf '%s' "$AUTOPASS_BACKUP_PASSPHRASE" > "$PASSPHRASE_FILE" else err "lipseste parola de decriptare." err "seteaza AUTOPASS_BACKUP_PASSPHRASE_FILE (recomandat) sau AUTOPASS_BACKUP_PASSPHRASE." exit 1 fi if [[ "${1:-}" != "" ]]; then TARGET="$1" else TARGET="$(ls -1t "$BACKUP_DIR"/autopass-*.db.gz.gpg 2>/dev/null | head -n1 || true)" fi if [[ -z "$TARGET" || ! -f "$TARGET" ]]; then err "niciun backup gasit de verificat (director: $BACKUP_DIR)" exit 1 fi log "verific: $TARGET" TMP_DIR="$(mktemp -d)" CLEANUP_PATHS+=("$TMP_DIR") GZ_FILE="$TMP_DIR/snapshot.db.gz" DB_FILE="$TMP_DIR/snapshot.db" log "decriptez (gpg)" gpg --batch --yes --decrypt --passphrase-file "$PASSPHRASE_FILE" \ --output "$GZ_FILE" "$TARGET" log "dezarhivez (gzip)" gzip -d "$GZ_FILE" if [[ ! -s "$DB_FILE" ]]; then err "fisierul restaurat e gol sau lipseste: $DB_FILE" exit 1 fi log "PRAGMA integrity_check + count(submissions)" set +e RESULT="$(python3 - "$DB_FILE" <<'PYEOF' import sqlite3 import sys conn = sqlite3.connect(sys.argv[1]) try: integrity = conn.execute("PRAGMA integrity_check").fetchone()[0] try: count = conn.execute("SELECT count(*) FROM submissions").fetchone()[0] except sqlite3.OperationalError as exc: print(f"integrity={integrity}") print(f"eroare_count_submissions={exc}") sys.exit(1) print(f"integrity={integrity}") print(f"count_submissions={count}") finally: conn.close() PYEOF )" STATUS=$? set -e echo "$RESULT" if [[ $STATUS -ne 0 ]]; then err "verificare esuata (vezi mesajul de mai sus)" exit 1 fi if ! grep -q "^integrity=ok$" <<<"$RESULT"; then err "PRAGMA integrity_check NU a raportat 'ok'" exit 1 fi log "backup valid: restaurabil, integritate ok."