#!/usr/bin/env bash set -Eeuo pipefail cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." tmp="$(mktemp -d)" trap 'rm -rf -- "$tmp"' EXIT mkdir -p "$tmp/bin" # Extract and run the exact hook template without writing to PAM or contacting # Telegram. The stubs record invocation and deliberately make curl slow. awk '/^cat > "\$NOTIFY_SCRIPT" <<.HOOK/ { copying=1; next } copying && /^HOOK$/ { exit } copying { print }' ochenstarik-server-tg-4.sh > "$tmp/notify-hook" [[ -s "$tmp/notify-hook" ]] # Relocate only the extracted fixture; production PAM paths are fixed and do # not trust session-provided test overrides. sed -i "s|/etc/ochenstarik-server/telegram.conf|$tmp/config|g; s|/var/log/ochenstarik-ssh-login-telegram.log|$tmp/notify.log|g; s|/usr/bin/setsid|$tmp/bin/setsid|g" "$tmp/notify-hook" bash -n "$tmp/notify-hook" chmod 700 "$tmp/notify-hook" cat > "$tmp/config" <<'CONFIG' TG_BOT_TOKEN=123456:secret-token-marker TG_CHAT_ID=12345 SERVER_IP=192.0.2.1 CONFIG chmod 600 "$tmp/config" cat > "$tmp/bin/setsid" <<'SETSID_STUB' #!/usr/bin/env bash set -Eeuo pipefail printf 'called\n' >> "$SETSID_LOG" exec /usr/bin/setsid "$@" SETSID_STUB cat > "$tmp/bin/curl" <<'CURL_STUB' #!/usr/bin/env bash set -Eeuo pipefail printf '%s\n' "$*" >> "$CURL_ARGS_LOG" cat > "$CURL_CONFIG_LOG" touch "$CURL_STARTED" sleep 1 touch "$CURL_DONE" printf '200\n' >&2 exit 0 CURL_STUB chmod +x "$tmp/bin/setsid" "$tmp/bin/curl" export PATH="$tmp/bin:$PATH" export SETSID_LOG="$tmp/setsid.log" CURL_ARGS_LOG="$tmp/curl-args" export CURL_CONFIG_LOG="$tmp/curl-config" CURL_STARTED="$tmp/curl-started" export CURL_DONE="$tmp/curl-done" export PAM_USER=test-user PAM_RHOST=192.0.2.7 PAM_SERVICE=sshd PAM_TTY=pts/1 PAM_TYPE=close_session "$tmp/notify-hook" [[ ! -e "$SETSID_LOG" && ! -e "$CURL_STARTED" ]] started_ns="$(date +%s%N)" PAM_TYPE=open_session "$tmp/notify-hook" elapsed_ms=$(( ($(date +%s%N) - started_ns) / 1000000 )) ((elapsed_ms < 500)) || { printf 'PAM hook waited %s ms for background work.\n' "$elapsed_ms" >&2; exit 1; } for _ in {1..60}; do [[ -e "$CURL_STARTED" ]] && break sleep 0.05 done [[ -e "$CURL_STARTED" ]] [[ "$(wc -l < "$SETSID_LOG")" == 1 ]] ! grep -Fq 'secret-token-marker' "$CURL_ARGS_LOG" grep -Fq 'url = "https://api.telegram.org/bot123456:secret-token-marker/sendMessage"' "$CURL_CONFIG_LOG" # Verify the generated backup runner's opt-in encryption and strict offsite # transport contract without invoking it against the host filesystem. awk '/^ cat > "\$BACKUP_RUNNER" <<.BACKUP_RUNNER_EOF/ { copying=1; next } copying && /^BACKUP_RUNNER_EOF$/ { exit } copying { print }' ochenstarik-server-backup-7.sh > "$tmp/backup-runner" bash -n "$tmp/backup-runner" grep -Fq 'BACKUP_ENCRYPTION=none' "$tmp/backup-runner" grep -Fq 'age --encrypt --recipient "$AGE_RECIPIENT" --output "$temporary"' "$tmp/backup-runner" grep -Fq 'StrictHostKeyChecking=yes' "$tmp/backup-runner" grep -Fq 'BatchMode=yes' "$tmp/backup-runner" grep -Fq 'UserKnownHostsFile=$OFFSITE_KNOWN_HOSTS' "$tmp/backup-runner" grep -Fq 'Выгрузка на заданный SSH-хост не удалась' "$tmp/backup-runner" if grep -Fq 'ssh-keyscan' ochenstarik-server-backup-7.sh; then printf 'Backup setup must not trust an unverified ssh-keyscan result.\n' >&2 exit 1 fi awk '/^upload_offsite\(\)/ { copying=1 } copying { print } copying && /^}/ { exit }' "$tmp/backup-runner" > "$tmp/upload-function" source "$tmp/upload-function" log() { :; } die() { printf '%s\n' "$*" >&2; exit 1; } cat > "$tmp/bin/scp" <<'SCP_STUB' #!/usr/bin/env bash set -Eeuo pipefail printf '%s\n' "$*" >> "$SCP_ARGS_LOG" exit "${SCP_EXIT_CODE:-0}" SCP_STUB chmod +x "$tmp/bin/scp" export SCP_ARGS_LOG="$tmp/scp-args" OFFSITE_TARGET='backup@example.test' OFFSITE_PATH='/srv/backups' OFFSITE_KNOWN_HOSTS="$tmp/known_hosts" touch "$OFFSITE_KNOWN_HOSTS" "$tmp/archive.tar.zst.age" "$tmp/archive.sha256" SCP_EXIT_CODE=0 upload_offsite "$tmp/archive.tar.zst.age" "$tmp/archive.sha256" grep -Fq -- '-o BatchMode=yes' "$SCP_ARGS_LOG" grep -Fq -- '-o StrictHostKeyChecking=yes' "$SCP_ARGS_LOG" grep -Fq -- "-o UserKnownHostsFile=$OFFSITE_KNOWN_HOSTS" "$SCP_ARGS_LOG" if (SCP_EXIT_CODE=42 upload_offsite "$tmp/archive.tar.zst.age" "$tmp/archive.sha256") \ >/dev/null 2>&1; then printf 'Offsite upload failure was accepted as success.\n' >&2 exit 1 fi for _ in {1..60}; do [[ -e "$CURL_DONE" ]] && break sleep 0.05 done [[ -e "$CURL_DONE" ]] printf 'Notification and backup security tests passed.\n'