forked from baron/baron-sso
136 lines
6.4 KiB
Bash
Executable File
136 lines
6.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
|
|
fail() {
|
|
echo "ERROR: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
source "$repo_root/scripts/backup/lib/common.sh"
|
|
source "$repo_root/scripts/backup/lib/manifest.sh"
|
|
source "$repo_root/scripts/backup/lib/report.sh"
|
|
|
|
assert_eq() {
|
|
local expected="$1"
|
|
local actual="$2"
|
|
local message="$3"
|
|
[[ "$actual" == "$expected" ]] || fail "$message: expected '$expected', got '$actual'"
|
|
}
|
|
|
|
all_services="$(normalize_service_filter "all")"
|
|
assert_eq "postgres ory-postgres clickhouse ory-clickhouse config" "$all_services" "all must expand to every supported service"
|
|
|
|
selected_services="$(normalize_service_filter "postgres,config")"
|
|
assert_eq "postgres config" "$selected_services" "comma-separated services must be normalized in input order"
|
|
|
|
ory_services="$(normalize_service_filter "ory-postgres,ory-clickhouse")"
|
|
assert_eq "ory-postgres ory-clickhouse" "$ory_services" "ory service filter must not expand to Baron services"
|
|
|
|
if service_enabled "postgres" "$ory_services"; then
|
|
fail "service_enabled must not match postgres inside ory-postgres"
|
|
fi
|
|
|
|
if service_enabled "clickhouse" "$ory_services"; then
|
|
fail "service_enabled must not match clickhouse inside ory-clickhouse"
|
|
fi
|
|
|
|
service_enabled "ory-postgres" "$ory_services" || fail "service_enabled must match exact ory-postgres token"
|
|
service_enabled "ory-clickhouse" "$ory_services" || fail "service_enabled must match exact ory-clickhouse token"
|
|
|
|
grep -Fq "drop database if exists" "$repo_root/scripts/backup/lib/clickhouse.sh" \
|
|
|| fail "ClickHouse restore must drop restored databases before replaying schema/data to avoid duplicate rows or init-table conflicts."
|
|
grep -Fq "FORMAT RawBLOB" "$repo_root/scripts/backup/lib/clickhouse.sh" \
|
|
|| fail "ClickHouse dump must store SHOW CREATE TABLE as raw SQL, not escaped TSV."
|
|
grep -Fq "render_clickhouse_schema" "$repo_root/scripts/backup/lib/clickhouse.sh" \
|
|
|| fail "ClickHouse restore must route schema files through the compatibility decoder."
|
|
grep -Fq "s{\\\\n}" "$repo_root/scripts/backup/lib/clickhouse.sh" \
|
|
|| fail "ClickHouse restore must decode escaped newlines from older schema dumps."
|
|
grep -Fq "x27" "$repo_root/scripts/backup/lib/clickhouse.sh" \
|
|
|| fail "ClickHouse restore must decode escaped single quotes from older schema dumps."
|
|
grep -Fq "filter_clickhouse_stable_row_counts" "$repo_root/scripts/backup/restore.sh" \
|
|
|| fail "restore verification must not fail on unstable ClickHouse aggregate/view physical row counts."
|
|
grep -Fq "collect_clickhouse_native_stable_row_counts" "$repo_root/scripts/backup/restore.sh" \
|
|
|| fail "restore verification must derive ClickHouse expected counts from Native data files."
|
|
|
|
if normalize_service_filter "postgres,unknown" >/tmp/baron-sso-service-filter.out 2>&1; then
|
|
fail "unknown backup service must be rejected"
|
|
fi
|
|
|
|
if ! grep -Fq "unknown backup service" /tmp/baron-sso-service-filter.out; then
|
|
fail "unknown service rejection must explain the service filter problem"
|
|
fi
|
|
|
|
tmp_dir="$(mktemp -d /tmp/baron-sso-backup-policy.XXXXXX)"
|
|
trap 'rm -rf "$tmp_dir"' EXIT INT TERM
|
|
|
|
mkdir -p "$tmp_dir/reports"
|
|
create_manifest "$tmp_dir" "maintenance" "postgres config"
|
|
|
|
manifest="$tmp_dir/manifest.json"
|
|
[[ -f "$manifest" ]] || fail "create_manifest must write manifest.json"
|
|
grep -Fq '"format_version": "1"' "$manifest" || fail "manifest must include format_version"
|
|
grep -Fq '"mode": "maintenance"' "$manifest" || fail "manifest must include backup mode"
|
|
grep -Fq '"services": [' "$manifest" || fail "manifest must include service list"
|
|
grep -Fq '"git_commit":' "$manifest" || fail "manifest must include git commit"
|
|
|
|
cat >"$tmp_dir/reports/baron-postgres-row-counts.txt" <<'EOF'
|
|
public.users:228
|
|
public.tenants:266
|
|
public.relying_parties:1
|
|
EOF
|
|
cat >"$tmp_dir/reports/ory_hydra-row-counts.txt" <<'EOF'
|
|
public.hydra_client:5
|
|
EOF
|
|
write_backup_markdown_report "$tmp_dir" "succeeded" "postgres config" '[{"service":"postgres","duration_seconds":2},{"service":"config","duration_seconds":1}]'
|
|
backup_md="$tmp_dir/reports/backup-report.md"
|
|
[[ -f "$backup_md" ]] || fail "backup markdown report must be created."
|
|
grep -Fq "# Baron SSO Backup Report" "$backup_md" || fail "backup report must have a markdown title."
|
|
grep -Fq "| 사용자 | 228 |" "$backup_md" || fail "backup report must include user count."
|
|
grep -Fq "| 테넌트 | 266 |" "$backup_md" || fail "backup report must include tenant count."
|
|
grep -Fq "| RP | 1 |" "$backup_md" || fail "backup report must include RP count."
|
|
grep -Fq "| postgres | 2 |" "$backup_md" || fail "backup report must include service duration."
|
|
|
|
printf 'original\n' >"$tmp_dir/example.txt"
|
|
(cd "$tmp_dir" && sha256sum example.txt > checksums.sha256)
|
|
printf 'changed\n' >"$tmp_dir/example.txt"
|
|
|
|
if BACKUP="$tmp_dir" "$repo_root/scripts/backup/verify-dump.sh" >/tmp/baron-sso-checksum.out 2>&1; then
|
|
fail "verify-dump must fail on checksum mismatch"
|
|
fi
|
|
|
|
if ! grep -Fq "checksum verification failed" /tmp/baron-sso-checksum.out; then
|
|
fail "checksum mismatch output must be explicit"
|
|
fi
|
|
|
|
if BACKUP="$tmp_dir" CONFIRM_RESTORE="baron-sso" RESTORE_TEST_NON_EMPTY=1 "$repo_root/scripts/backup/restore.sh" --dry-run >/tmp/baron-sso-non-empty-restore.out 2>&1; then
|
|
fail "restore must reject non-empty targets by default"
|
|
fi
|
|
|
|
if ! grep -Fq "non-empty restore target is not allowed" /tmp/baron-sso-non-empty-restore.out; then
|
|
fail "restore must explain the non-empty target guard"
|
|
fi
|
|
|
|
archive_source="$tmp_dir/archive-source"
|
|
mkdir -p "$archive_source/reports"
|
|
create_manifest "$archive_source" "maintenance" "postgres"
|
|
printf 'archive fixture\n' >"$archive_source/example.txt"
|
|
(cd "$archive_source" && sha256sum manifest.json example.txt > checksums.sha256)
|
|
archive_file="$tmp_dir/archive-source.tar.zst"
|
|
tar --zstd -cf "$archive_file" -C "$tmp_dir" archive-source
|
|
restore_report="$tmp_dir/restore-report.json"
|
|
|
|
DUMP_FILE="$archive_file" \
|
|
CONFIRM_RESTORE="baron-sso" \
|
|
RESTORE_REPORT="$restore_report" \
|
|
"$repo_root/scripts/backup/restore.sh" --dry-run >/tmp/baron-sso-dump-file-restore.out
|
|
|
|
[[ -f "$restore_report" ]] || fail "restore dry-run with DUMP_FILE must write RESTORE_REPORT."
|
|
jq -e \
|
|
--arg dump_file "$archive_file" \
|
|
'.status == "planned" and .dump_file == $dump_file and .backup_dir != null and (.services | index("postgres"))' \
|
|
"$restore_report" >/dev/null || fail "restore report must describe planned DUMP_FILE restore."
|
|
|
|
echo "OK: backup scripts enforce parser, manifest, checksum, and restore safety policies"
|