koopa-admin-log/scripts/taler-merchant/check_merchant-health.sh

222 lines
6.9 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# Health check for manual taler-merchant (container taler-hacktivism).
# Style: check_exchange-health.sh — [OK] / [FAIL] / [WARN], exit 1 on critical fail.
#
# Keys checks: for each enabled [merchant-exchange-*] with EXCHANGE_BASE_URL,
# GET …/keys and (if set) verify MASTER_KEY appears in the response.
CONF="${TALER_MERCHANT_CONFIG:-/etc/taler-merchant/taler-merchant.conf}"
OVERRIDES=/etc/taler-merchant/merchant-overrides.conf
SOCK="/var/run/taler-merchant/httpd/merchant-http.sock"
SS_BIN=$(command -v ss)
CURL_BIN=$(command -v curl)
green() { echo -e "\e[32m$1\e[0m"; }
red() { echo -e "\e[31m$1\e[0m"; }
yellow() { echo -e "\e[33m$1\e[0m"; }
fail=0
ok() { green "[OK] $1"; }
bad() { red "[FAIL] $1"; fail=1; }
warn() { yellow "[WARN] $1"; }
is_url() {
case "$1" in
http://*|https://*) return 0 ;;
*) return 1 ;;
esac
}
# GET /keys; try primary URL then optional host-local fallbacks for same exchange.
# Writes body to $1 (path). Returns 0 on HTTP success with non-empty body.
fetch_keys() {
local out="$1"
local primary="$2"
shift 2
local url
for url in "$primary" "$@"; do
[ -z "$url" ] && continue
if $CURL_BIN -skf -m 6 "$url" -o "$out" 2>/dev/null \
|| $CURL_BIN -sf -m 6 "$url" -o "$out" 2>/dev/null; then
if [ -s "$out" ] && grep -qE 'master_public_key|"currency"' "$out" 2>/dev/null; then
echo "$url"
return 0
fi
fi
done
return 1
}
echo "=== Taler Merchant Health Check ==="
# --- 14: local service ---
if [ -S "$SOCK" ]; then
ok "socket exists: $SOCK"
else
bad "socket does NOT exist: $SOCK"
fi
if [ -n "$SS_BIN" ] && $SS_BIN -xl 2>/dev/null | grep -q "$SOCK"; then
ok "Merchant-HTTPD listening on socket"
elif [ -n "$SS_BIN" ]; then
bad "no listener on socket"
else
warn "ss not available — skip socket listener check"
fi
if pgrep -f taler-merchant-httpd >/dev/null 2>&1; then
ok "process taler-merchant-httpd"
else
bad "process taler-merchant-httpd is NOT running"
fi
if pgrep -f "nginx: master" >/dev/null 2>&1; then
ok "nginx master process"
else
bad "nginx master process is NOT running"
fi
# --- 5: merchant /config ---
if [ -n "$CURL_BIN" ]; then
cfg_ok=0
if [ -S "$SOCK" ] && $CURL_BIN -sf -m 3 --unix-socket "$SOCK" "http://localhost/config" >/dev/null 2>&1; then
ok "merchant /config via unix socket"
cfg_ok=1
elif $CURL_BIN -skf -m 3 "https://127.0.0.1:9010/config" >/dev/null 2>&1; then
ok "merchant /config via https://127.0.0.1:9010/config"
cfg_ok=1
elif $CURL_BIN -sf -m 3 "http://127.0.0.1:9010/config" >/dev/null 2>&1; then
ok "merchant /config via http://127.0.0.1:9010/config"
cfg_ok=1
fi
[ "$cfg_ok" -eq 0 ] && bad "merchant /config unreachable (socket and :9010)"
else
warn "curl missing — skip /config"
fi
# --- 6: exchange /keys for configured exchanges ---
echo "--- configured exchanges (/keys) ---"
# Emit lines: SECTION|DISABLED|BASE|MASTER (from overrides + optional taler-config)
list_exchanges() {
# Prefer site overrides file (authoritative for this host)
if [ -f "$OVERRIDES" ]; then
awk '
BEGIN { sec=""; dis="NO"; base=""; master="" }
/^\[merchant-exchange-/ {
if (sec != "") printf "%s|%s|%s|%s\n", sec, dis, base, master
sec=$0; gsub(/[\[\] \t\r]/, "", sec)
dis="NO"; base=""; master=""
next
}
/^\[/ {
if (sec != "") printf "%s|%s|%s|%s\n", sec, dis, base, master
sec=""; next
}
sec=="" { next }
/^[ \t]*#/ { next }
{
line=$0
sub(/[ \t]*#.*$/, "", line)
if (match(line, /^[ \t]*DISABLED[ \t]*=[ \t]*/)) {
dis=substr(line, RSTART+RLENGTH); gsub(/^[ \t]+|[ \t]+$/, "", dis)
} else if (match(line, /^[ \t]*EXCHANGE_BASE_URL[ \t]*=[ \t]*/)) {
base=substr(line, RSTART+RLENGTH); gsub(/^[ \t]+|[ \t]+$/, "", base)
} else if (match(line, /^[ \t]*MASTER_KEY[ \t]*=[ \t]*/)) {
master=substr(line, RSTART+RLENGTH); gsub(/^[ \t]+|[ \t]+$/, "", master)
}
}
END { if (sec != "") printf "%s|%s|%s|%s\n", sec, dis, base, master }
' "$OVERRIDES"
fi
}
if [ -z "$CURL_BIN" ]; then
bad "curl missing — cannot check exchange /keys"
else
exch_count=0
while IFS='|' read -r sec dis base master; do
[ -z "$sec" ] && continue
case "${dis:-NO}" in
YES|yes|true|True|1)
warn "exchange $sec: DISABLED — skip /keys"
continue
;;
esac
if ! is_url "$base"; then
# package stubs without URL (e.g. kudos only DISABLED)
warn "exchange $sec: no EXCHANGE_BASE_URL — skip"
continue
fi
exch_count=$((exch_count + 1))
base_slash="${base%/}/"
primary="${base_slash}keys"
keys_tmp=$(mktemp 2>/dev/null || echo "/tmp/m-keys-$$-${exch_count}.json")
# Fallbacks when public name is not reachable from container:
# host loopback ports published by podman (exchange :9011).
got_url=
if got_url=$(fetch_keys "$keys_tmp" "$primary" \
"http://127.0.0.1:9011/keys" \
"http://host.containers.internal:9011/keys" \
"http://10.0.2.2:9011/keys"); then
ok "exchange $sec: /keys reachable ($got_url)"
if [ -n "$master" ]; then
if grep -qF "$master" "$keys_tmp" 2>/dev/null; then
ok "exchange $sec: MASTER_KEY matches /keys"
else
mpks=$(grep -oE '"master_public_key"[[:space:]]*:[[:space:]]*"[^"]+"' "$keys_tmp" 2>/dev/null | head -2)
bad "exchange $sec: MASTER_KEY does not match /keys (config MASTER_KEY=$master)"
[ -n "$mpks" ] && warn " seen in /keys: $mpks"
fi
else
warn "exchange $sec: no MASTER_KEY in config — skip key match"
fi
else
bad "exchange $sec: no /keys from $primary (and local :9011 fallbacks)"
fi
rm -f "$keys_tmp" 2>/dev/null || true
done <<EOF
$(list_exchanges)
EOF
[ "$exch_count" -eq 0 ] && warn "no enabled exchanges with EXCHANGE_BASE_URL"
fi
# --- 7: helpers — ensure (no systemd) then require ---
if [ "${SKIP_ENSURE:-0}" != "1" ]; then
if [ -x /usr/local/bin/ensure_merchant_helpers.sh ]; then
echo "--- ensure_merchant_helpers ---"
/usr/local/bin/ensure_merchant_helpers.sh || warn "ensure_merchant_helpers exited non-zero"
elif [ -x "$(dirname "$0")/ensure_merchant_helpers.sh" ]; then
echo "--- ensure_merchant_helpers ---"
"$(dirname "$0")/ensure_merchant_helpers.sh" || warn "ensure_merchant_helpers exited non-zero"
fi
fi
live_helper() {
local p="$1"
pgrep -f "(^|/)(${p})( |$)" >/dev/null 2>&1
}
# Settlement needs wirewatch + depositcheck; others needed for ops.
for p in \
taler-merchant-webhook \
taler-merchant-kyccheck \
taler-merchant-wirewatch \
taler-merchant-depositcheck \
taler-merchant-exchangekeyupdate \
taler-merchant-reconciliation
do
if live_helper "$p"; then
ok "process $p"
else
bad "process $p not running"
fi
done
if [ "$fail" -eq 0 ]; then
green "=== ALL CRITICAL CHECKS PASSED ==="
exit 0
fi
red "=== SOME CHECKS FAILED ==="
exit 1