diff --git a/scripts/verify.sh b/scripts/verify.sh index d1361ed..d2003e9 100644 --- a/scripts/verify.sh +++ b/scripts/verify.sh @@ -53,12 +53,23 @@ else fi head_ "Public endpoints - expect 302 to the auth portal" +# Run this from OUTSIDE the VNet as well. lin001 resolves yokogawa.tech through +# the DC, which holds pinpoint records only - ai and influx have one, lf, api +# and cube do not. So on this host those three do not resolve at all, and that +# says nothing about whether they work from a browser. The check reports the +# two cases separately rather than calling both a failure. for host in lf.yokogawa.tech cube.yokogawa.tech api.yokogawa.tech ai.yokogawa.tech; do + if ! getent hosts "$host" >/dev/null 2>&1; then + printf ' ?? %s does not resolve FROM THIS HOST (no DC pinpoint record) - check it from outside the VNet +' "$host" + continue + fi code=$(curl -s -o /dev/null -w '%{http_code}' -I "https://$host" --max-time 10 || echo "000") case "$code" in 302|303) ok "$host -> $code (auth portal)" ;; 200) bad "$host -> 200 WITHOUT AUTH - check 'import authelia' in ~/Caddyfile" ;; - 000) bad "$host unreachable - DNS A record missing, or Caddy has no certificate" ;; + 403) bad "$host -> 403 - Caddy is serving it but Authelia has no access_control rule, so default_policy: deny applies. Add the hostname (authelia/access-rules.md)" ;; + 000) bad "$host unreachable - Caddy has no certificate, or nothing is listening" ;; *) bad "$host -> $code" ;; esac done @@ -71,6 +82,7 @@ head_ "The operator page and the API share an origin" code=$(curl -s -o /dev/null -w '%{http_code}' -X POST "https://ai.yokogawa.tech/ask" -H 'Content-Type: application/json' -d '{}' --max-time 10 || echo "000") case "$code" in 302|303) ok "ai.yokogawa.tech/ask -> $code (routed to ai-api, gated)" ;; + 403) bad "ai.yokogawa.tech/ask -> 403 - Authelia has no rule for this hostname yet; the route cannot be proved until it does" ;; 404) bad "ai.yokogawa.tech/ask -> 404 - the /ask route is missing from the Caddy block; ai-web is answering" ;; 000) bad "ai.yokogawa.tech/ask unreachable" ;; *) bad "ai.yokogawa.tech/ask -> $code" ;; @@ -84,6 +96,17 @@ else ok "ai-web bundle carries no cross-origin API hostname" fi +# Runs BEFORE the agent_ro test on purpose. That test deliberately attempts an +# INSERT it is not allowed to make, which pg-ai logs as "permission denied for +# table equipment" - in the other order verify.sh flags, every single run, an +# error line it created itself. +head_ "Recent errors in the logs" +for name in pg-ai cube ai-api ai-web; do + errors=$(docker logs --tail 200 "$name" 2>&1 | grep -icE 'error|fatal|panic' || true) + [ "${errors:-0}" -eq 0 ] && ok "$name logs clean (last 200 lines)" \ + || bad "$name has $errors error lines - docker logs --tail 200 $name" +done + head_ "agent_ro is read-only" if docker exec pg-ai psql -U agent_ro -d plant -tAc 'SELECT count(*) FROM equipment' >/dev/null 2>&1; then ok "agent_ro can SELECT" @@ -125,12 +148,5 @@ fi head_ "Disk" df -h / /datadisk | sed 's/^/ /' -head_ "Recent errors in the logs" -for name in pg-ai cube ai-api ai-web; do - errors=$(docker logs --tail 200 "$name" 2>&1 | grep -icE 'error|fatal|panic' || true) - [ "${errors:-0}" -eq 0 ] && ok "$name logs clean (last 200 lines)" \ - || bad "$name has $errors error lines - docker logs --tail 200 $name" -done - printf '\n%s passed, %s failed\n' "$PASS" "$FAIL" exit "$FAIL"