#!/usr/bin/env bash set -Eeuo pipefail cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." tmp="$(mktemp -d)" trap 'rm -rf -- "$tmp"' EXIT awk '/^ cat > "\$BACKUP_RUNNER" <<.BACKUP_RUNNER_EOF/ { copying=1; next } copying && /^BACKUP_RUNNER_EOF$/ { exit } copying { print }' ochenstarik-server-backup-7.sh > "$tmp/runner" awk '/^\[\[ "\$EUID"/ { exit } { print }' "$tmp/runner" > "$tmp/runner-functions" bash -n "$tmp/runner-functions" source "$tmp/runner-functions" # Exercise the real create_backup early-return path with only the SSH transport # replaced. This never connects to a host or reads the real filesystem. protect_initial_files() { :; } mkdir -p "$tmp/bin" cat > "$tmp/bin/scp" <<'SCP_STUB' #!/usr/bin/env bash set -Eeuo pipefail printf '%s\n' "$*" >> "$SCP_CALLS" exit "${SCP_EXIT_CODE:-0}" SCP_STUB chmod +x "$tmp/bin/scp" export PATH="$tmp/bin:$PATH" SCP_CALLS="$tmp/scp-calls" BACKUP_ROOT="$tmp/encrypted-root" BACKUP_ENCRYPTION=age AGE_RECIPIENT='age1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq' OFFSITE_TARGET='backup@example.test' OFFSITE_PATH='/srv/backups' OFFSITE_KNOWN_HOSTS="$tmp/known_hosts" mkdir -p "$BACKUP_ROOT/initial" touch "$OFFSITE_KNOWN_HOSTS" archive="$BACKUP_ROOT/initial/initial-20261023-120000.tar.zst.age" printf 'ciphertext fixture\n' > "$archive" ( cd "$BACKUP_ROOT/initial" sha256sum "$(basename "$archive")" > "$(basename "$archive").sha256" ) checksum="${archive}.sha256" # A failed first offsite upload must leave both immutable local files intact, # return failure, and retry those exact files on the next invocation. if (SCP_EXIT_CODE=42 create_backup initial 0) > "$tmp/failed.out" 2>&1; then printf 'Initial offsite failure was accepted as success.\n' >&2 exit 1 fi if grep -Fq 'Первичный снимок уже существует' "$tmp/failed.out"; then printf 'Failed upload was reported as a successful existing backup.\n' >&2 exit 1 fi [[ -f "$archive" && -f "$checksum" ]] ( cd "$BACKUP_ROOT/initial" sha256sum --check --status "$(basename "$checksum")" ) [[ "$(wc -l < "$SCP_CALLS")" == 1 ]] grep -Fq -- "$archive" "$SCP_CALLS" grep -Fq -- "$checksum" "$SCP_CALLS" create_backup initial 0 > "$tmp/retry.out" grep -Fq 'Первичный снимок уже существует' "$tmp/retry.out" [[ "$(wc -l < "$SCP_CALLS")" == 2 ]] [[ "$(sha256sum "$archive" | awk '{print $1}')" == \ "$(cd "$BACKUP_ROOT/initial" && sha256sum --check --status "$(basename "$checksum")" && sha256sum "$(basename "$archive")" | awk '{print $1}')" ]] # Selecting age cannot silently accept an existing plaintext initial snapshot. plain_root="$tmp/plain-root" mkdir -p "$plain_root/initial" plain_archive="$plain_root/initial/initial-20261022-120000.tar.zst" printf 'plaintext fixture\n' > "$plain_archive" ( cd "$plain_root/initial" sha256sum "$(basename "$plain_archive")" > "$(basename "$plain_archive").sha256" ) BACKUP_ROOT="$plain_root" if (create_backup initial 0) > "$tmp/plain.out" 2>&1; then printf 'Age policy silently accepted an existing plaintext snapshot.\n' >&2 exit 1 fi grep -Fq 'уже создан без шифрования' "$tmp/plain.out" [[ -f "$plain_archive" && "$(wc -l < "$SCP_CALLS")" == 2 ]] printf 'Initial backup retry and encryption-policy tests passed.\n'