MONPAGES_REQUIRE_PUBLIC=0 turns missing public pages into WARN. FrancPaysan host-agent wrappers default to 0 until Infomaniak vhosts serve /monitoring*. GOA/koopa keep require=1.
245 lines
7.8 KiB
Bash
Executable file
245 lines
7.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# check_monitoring_pages.sh — verify public monitoring HTML pages via FQDN
|
|
#
|
|
# Outside-in: curl https://<fqdn>/<path>/ and require a real HTML monitoring page.
|
|
# Catches: merchant JSON code 21 (Caddy handle missing), WP 404, empty stubs, deploy skip.
|
|
#
|
|
# Env (same knobs as host-agent HTML layout):
|
|
# MON_HOSTS space-separated FQDNs (default from TALER_DOMAIN)
|
|
# HTML_URL_OK path for OK page (default /monitoring/)
|
|
# HTML_URL_ERR optional err path; checked if MONPAGES_CHECK_ERR=1
|
|
# MONITORING_PAGE_URLS optional full URL list (overrides host+path construction)
|
|
# MONPAGES_EXTRA_URLS additional absolute URLs (space-separated)
|
|
# TIMEOUT curl timeout (from lib.sh)
|
|
# MONPAGES_STAGING_BASE / HTML_OUT optional staging root for diagnosis
|
|
# HTML_OK_DIR staging subdir (default monitoring)
|
|
#
|
|
set -euo pipefail
|
|
ROOT=$(cd "$(dirname "$0")" && pwd)
|
|
# shellcheck source=lib.sh
|
|
source "$ROOT/lib.sh"
|
|
|
|
set_area monpages
|
|
section "monpages · public monitoring HTML via FQDN (outside-in)"
|
|
|
|
# MONPAGES_REQUIRE_PUBLIC=0 → missing public pages are WARN (staging-only stacks / FP until vhost)
|
|
: "${MONPAGES_REQUIRE_PUBLIC:=1}"
|
|
|
|
# Default hosts from domain (mirror run-host-report.sh)
|
|
if [ -z "${MON_HOSTS:-}" ]; then
|
|
case "${TALER_DOMAIN:-}" in
|
|
hacktivism.ch|koopa)
|
|
MON_HOSTS="bank.hacktivism.ch exchange.hacktivism.ch taler.hacktivism.ch"
|
|
;;
|
|
stage.lefrancpaysan.ch|stage.*lefrancpaysan*)
|
|
MON_HOSTS="stage.bank.lefrancpaysan.ch stage.exchange.lefrancpaysan.ch stage.monnaie.lefrancpaysan.ch"
|
|
;;
|
|
lefrancpaysan.ch)
|
|
MON_HOSTS="bank.lefrancpaysan.ch exchange.lefrancpaysan.ch monnaie.lefrancpaysan.ch"
|
|
;;
|
|
*)
|
|
MON_HOSTS="${TALER_DOMAIN:-}"
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
HTML_URL_OK="${HTML_URL_OK:-/monitoring/}"
|
|
HTML_URL_ERR="${HTML_URL_ERR:-/monitoring_err/}"
|
|
# ensure leading + trailing slash
|
|
case "$HTML_URL_OK" in
|
|
/*) ;;
|
|
*) HTML_URL_OK="/$HTML_URL_OK" ;;
|
|
esac
|
|
case "$HTML_URL_OK" in
|
|
*/) ;;
|
|
*) HTML_URL_OK="${HTML_URL_OK}/" ;;
|
|
esac
|
|
|
|
build_urls() {
|
|
local h p
|
|
if [ -n "${MONITORING_PAGE_URLS:-}" ]; then
|
|
# shellcheck disable=SC2086
|
|
printf '%s\n' $MONITORING_PAGE_URLS
|
|
else
|
|
for h in $MON_HOSTS; do
|
|
[ -z "$h" ] && continue
|
|
printf 'https://%s%s\n' "$h" "$HTML_URL_OK"
|
|
if [ "${MONPAGES_CHECK_ERR:-0}" = "1" ]; then
|
|
p="$HTML_URL_ERR"
|
|
case "$p" in /*) ;; *) p="/$p" ;; esac
|
|
case "$p" in */) ;; *) p="${p}/" ;; esac
|
|
printf 'https://%s%s\n' "$h" "$p"
|
|
fi
|
|
done
|
|
fi
|
|
if [ -n "${MONPAGES_EXTRA_URLS:-}" ]; then
|
|
# shellcheck disable=SC2086
|
|
printf '%s\n' $MONPAGES_EXTRA_URLS
|
|
fi
|
|
}
|
|
|
|
# True if body looks like our monitoring HTML (not merchant API / WP 404).
|
|
is_monitoring_html() {
|
|
local f="$1"
|
|
if grep -qE '"code"[[:space:]]*:[[:space:]]*21' "$f" 2>/dev/null; then
|
|
return 1
|
|
fi
|
|
if grep -qiE 'There is no endpoint defined for the URL' "$f" 2>/dev/null; then
|
|
return 1
|
|
fi
|
|
if grep -qiE 'wp-content|wordpress' "$f" 2>/dev/null \
|
|
&& grep -qiE '404|not found|page introuvable' "$f" 2>/dev/null; then
|
|
return 1
|
|
fi
|
|
if grep -qE 'sticky-bar|version-link|taler-monitoring|class="sticky' "$f" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
if head -c 4096 "$f" | grep -qiE '<!DOCTYPE html|<html' \
|
|
&& grep -qiE 'monitoring|mon ·|host-agent' "$f" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
if head -c 512 "$f" | grep -qiE '<!DOCTYPE html|<html'; then
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
_is_bare_url() {
|
|
local url="$1"
|
|
case " ${MONPAGES_BARE_URLS:-} " in
|
|
*" $url "*) return 0 ;;
|
|
esac
|
|
case "$url" in
|
|
*/) return 1 ;;
|
|
*) return 0 ;;
|
|
esac
|
|
}
|
|
|
|
|
|
_mon_fail_or_soft() {
|
|
local label="$1" detail="$2"
|
|
if [ "${MONPAGES_REQUIRE_PUBLIC:-1}" != "1" ]; then
|
|
warn "$label" "$detail (MONPAGES_REQUIRE_PUBLIC=0)"
|
|
return 0
|
|
fi
|
|
fail "$label" "$detail"
|
|
return 1
|
|
}
|
|
|
|
check_one() {
|
|
local url="$1"
|
|
local body code hint soft=0
|
|
body=$(mktemp)
|
|
code=$(curl -skS -L --max-redirs 5 -m "${TIMEOUT}" -o "$body" -w '%{http_code}' "$url" 2>/dev/null || echo 000)
|
|
if _is_bare_url "$url" && [ "${MONPAGES_BARE_STRICT:-0}" != "1" ]; then
|
|
soft=1
|
|
fi
|
|
if grep -qE '"code"[[:space:]]*:[[:space:]]*21' "$body" 2>/dev/null \
|
|
|| grep -qiE 'There is no endpoint defined for the URL' "$body" 2>/dev/null; then
|
|
if [ "$soft" = "1" ]; then
|
|
warn "public mon page bare URL" \
|
|
"$url -> HTTP $code code 21 (prefer trailing slash; set MONPAGES_BARE_STRICT=1 to ERROR)"
|
|
rm -f "$body"
|
|
return 0
|
|
fi
|
|
_mon_fail_or_soft "public mon page missing" \
|
|
"$url -> HTTP $code merchant/API JSON code 21 (publish HTML + reverse-proxy handle /monitoring*)" || { rm -f "$body"; return 1; }
|
|
rm -f "$body"
|
|
return 0
|
|
fi
|
|
if [ "$code" != "200" ]; then
|
|
if [ "$soft" = "1" ]; then
|
|
warn "public mon page bare URL" "$url -> HTTP $code (prefer trailing slash form)"
|
|
rm -f "$body"
|
|
return 0
|
|
fi
|
|
_mon_fail_or_soft "public mon page" "$url -> HTTP $code (want 200 HTML)" || { rm -f "$body"; return 1; }
|
|
rm -f "$body"
|
|
return 0
|
|
fi
|
|
if is_monitoring_html "$body"; then
|
|
if grep -qE 'sticky-bar|version-link' "$body" 2>/dev/null; then
|
|
ok "public mon page" "$url -> HTTP 200 monitoring HTML"
|
|
else
|
|
warn "public mon page" "$url -> HTTP 200 HTML but weak markers (stub/bootstrap?)"
|
|
fi
|
|
rm -f "$body"
|
|
return 0
|
|
fi
|
|
hint=$(head -c 120 "$body" | tr '\n' ' ' | tr -cd '[:print:] ')
|
|
_mon_fail_or_soft "public mon page not monitoring HTML" "$url -> HTTP 200 body!=suite (${hint}...)" || { rm -f "$body"; return 1; }
|
|
rm -f "$body"
|
|
return 0
|
|
}
|
|
|
|
URLS=()
|
|
while IFS= read -r line; do
|
|
[ -n "$line" ] || continue
|
|
# dedupe
|
|
skip=0
|
|
for e in "${URLS[@]+"${URLS[@]}"}"; do
|
|
[ "$e" = "$line" ] && skip=1 && break
|
|
done
|
|
[ "$skip" = "1" ] && continue
|
|
URLS+=("$line")
|
|
done < <(build_urls)
|
|
|
|
# Bare URLs without trailing slash: optional soft check (default on).
|
|
# Many reverse proxies only redirect /monitoring → /monitoring/; bare may hit the app (code 21).
|
|
# MONPAGES_CHECK_BARE=0 → skip bare entirely
|
|
# MONPAGES_BARE_STRICT=1 → bare failures are ERROR (default: WARN if slash form exists)
|
|
if [ "${MONPAGES_CHECK_BARE:-1}" = "1" ]; then
|
|
_extra=()
|
|
for u in "${URLS[@]}"; do
|
|
case "$u" in
|
|
*/) _bare=${u%/}; [ -n "$_bare" ] && _extra+=("$_bare") ;;
|
|
esac
|
|
done
|
|
for u in "${_extra[@]+"${_extra[@]}"}"; do
|
|
skip=0
|
|
for e in "${URLS[@]+"${URLS[@]}"}"; do
|
|
[ "$e" = "$u" ] && skip=1 && break
|
|
done
|
|
[ "$skip" = "1" ] && continue
|
|
URLS+=("$u")
|
|
# mark bare for soft handling via env list
|
|
MONPAGES_BARE_URLS="${MONPAGES_BARE_URLS:-} $u"
|
|
done
|
|
export MONPAGES_BARE_URLS
|
|
fi
|
|
|
|
if [ "${#URLS[@]}" -eq 0 ]; then
|
|
fail "monpages" "no URLs to check (set MON_HOSTS or MONITORING_PAGE_URLS)"
|
|
exit 1
|
|
fi
|
|
|
|
echo " checking ${#URLS[@]} URL(s) via FQDN..."
|
|
ec=0
|
|
for u in "${URLS[@]}"; do
|
|
check_one "$u" || ec=1
|
|
done
|
|
|
|
if [ "$ec" -ne 0 ]; then
|
|
echo " hint: public monitoring HTML not served (404 / merchant code 21)"
|
|
echo " publish staging HTML + configure reverse-proxy/Caddy handle for /monitoring*"
|
|
echo " (on koopa: sudo ~/koopa-caddy/apply-monitoring-live.sh)"
|
|
# Staging vs public diagnosis (host-agent sets MONPAGES_STAGING_BASE / HTML_OUT)
|
|
_stg="${MONPAGES_STAGING_BASE:-${HTML_OUT:-${HTML_BASE:-$HOME/monitoring-sites-staging}}}"
|
|
_ok_dir="${HTML_OK_DIR:-monitoring}"
|
|
if [ -n "${MON_HOSTS:-}" ] && [ -n "$_stg" ]; then
|
|
for _h in $MON_HOSTS; do
|
|
_f="$_stg/$_h/${_ok_dir}/index.html"
|
|
if [ -f "$_f" ]; then
|
|
echo " staging OK: $_f ($(wc -c <"$_f" | tr -d " ") bytes) — not published/served"
|
|
else
|
|
echo " staging missing: $_f"
|
|
fi
|
|
done
|
|
fi
|
|
_www="${DEPLOY_WWW_ROOT:-/var/www/monitoring-sites}"
|
|
if [ -e "$_www" ] && [ ! -w "$_www" ]; then
|
|
echo " DEPLOY_WWW_ROOT=$_www not writable by $(id -un 2>/dev/null || echo user)"
|
|
fi
|
|
fi
|
|
|
|
exit "$ec"
|