From b80d3142aaadff5622c46aaad47886958c1d29e5 Mon Sep 17 00:00:00 2001 From: abiba-bot Date: Fri, 11 Sep 2026 16:59:55 +0000 Subject: [PATCH] no-mistakes(review): harden dsh token reload retry, legacy bypass, cookie verification --- scripts/capture-dsh-token.sh | 55 +++++++++++++++++++++++++++--------- zulip-health.prose.md | 28 +++++++++++++++--- 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/scripts/capture-dsh-token.sh b/scripts/capture-dsh-token.sh index 7b49bc8..7a9c1b6 100755 --- a/scripts/capture-dsh-token.sh +++ b/scripts/capture-dsh-token.sh @@ -19,8 +19,9 @@ # 2. records it in /etc/dsh-web/launch-token, # 3. regenerates the nginx include /etc/dsh-web/nginx-login.conf (the # `proxy_pass ...?token=` line consumed by /dsh-web-login), -# 4. validates with `nginx -t` and reloads ONLY when the token changed, -# rolling the include back if validation fails, +# 4. reloads nginx ONLY when the token differs from the token nginx actually +# loaded (tracked in an applied-state stamp written only after a successful +# reload), rolling the include back on failure so the next run retries, # 5. removes the legacy unauthenticated :8081 endpoint if it ever reappears. # # Idempotent and safe to run at any time (systemd ExecStartPost or timer). @@ -31,6 +32,7 @@ PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" JOURNAL_UNIT="dsh-web.service" TOKEN_FILE="/etc/dsh-web/launch-token" INCLUDE_FILE="/etc/dsh-web/nginx-login.conf" +STAMP_FILE="/etc/dsh-web/nginx-login.conf.applied" SITE_ENABLED="/etc/nginx/sites-enabled/dsh" LEGACY_8081="/etc/nginx/sites-enabled/dsh.token" STASH_DIR="/etc/nginx/sites-available" @@ -44,16 +46,16 @@ die() { printf 'capture-dsh-token: ERROR: %s\n' "$*" >&2; exit 1; } # It bypassed Authentik entirely (listened on 0.0.0.0:8081 with no auth_request) # and must never come back. Stash it rather than delete so it is auditable. if [ -e "$LEGACY_8081" ] || [ -L "$LEGACY_8081" ]; then - STAMP="$(date -u +%Y%m%dT%H%M%SZ)" - STASHED="$STASH_DIR/dsh.token.disabled-$STAMP" + TS="$(date -u +%Y%m%dT%H%M%SZ)" + STASHED="$STASH_DIR/dsh.token.disabled-$TS" mv "$LEGACY_8081" "$STASHED" - if nginx -t >/dev/null 2>&1; then - nginx -s reload - log "removed legacy :8081 endpoint -> $STASHED" - else - mv "$STASHED" "$LEGACY_8081" - die "nginx config test failed after removing $LEGACY_8081; restored it" + if ! nginx -t >/dev/null 2>&1; then + die "nginx config test failed after disabling $LEGACY_8081 (kept disabled at $STASHED). Fix the nginx config and rerun; the legacy :8081 endpoint will NOT be restored." fi + if ! nginx -s reload; then + die "nginx reload failed after disabling $LEGACY_8081 (kept disabled at $STASHED). Fix nginx and rerun; the legacy :8081 endpoint will NOT be restored." + fi + log "removed legacy :8081 endpoint -> $STASHED" fi # ── 1. Read the latest launch token from the RUNNING service ──────────────── @@ -107,9 +109,21 @@ NEW_INCLUDE="$(mktemp "$INCLUDE_FILE.XXXXXX")" printf 'proxy_pass http://127.0.0.1:3080/?token=%s;\n' "$TOKEN" > "$NEW_INCLUDE" chmod 600 "$NEW_INCLUDE" -if [ -f "$INCLUDE_FILE" ] && cmp -s "$NEW_INCLUDE" "$INCLUDE_FILE"; then - rm -f "$NEW_INCLUDE" - log "token unchanged; nginx not reloaded" +# The stamp records the token nginx actually loaded. Comparing against it (not +# the on-disk include) means a failed or interrupted reload is retried on the +# next run instead of being mistaken for success. +APPLIED="" +[ -f "$STAMP_FILE" ] && APPLIED="$(cat "$STAMP_FILE" 2>/dev/null || true)" + +if [ "$APPLIED" = "$TOKEN" ]; then + if [ -f "$INCLUDE_FILE" ] && cmp -s "$NEW_INCLUDE" "$INCLUDE_FILE"; then + rm -f "$NEW_INCLUDE" + log "token unchanged; nginx not reloaded" + exit 0 + fi + mv "$NEW_INCLUDE" "$INCLUDE_FILE" + chmod 600 "$INCLUDE_FILE" + log "include file repaired to match the token nginx already serves" exit 0 fi @@ -132,10 +146,23 @@ if ! nginx -t >/dev/null 2>&1; then fi die "nginx config test failed; previous include restored" fi + +if ! nginx -s reload; then + if [ -n "$RESTORE" ]; then + mv "$RESTORE" "$INCLUDE_FILE" + else + rm -f "$INCLUDE_FILE" + fi + die "nginx reload failed; previous include restored; will retry next run" +fi + if [ -n "$RESTORE" ]; then rm -f "$RESTORE" fi -nginx -s reload +printf '%s\n' "$TOKEN" > "$STAMP_FILE.tmp" +chmod 600 "$STAMP_FILE.tmp" +mv "$STAMP_FILE.tmp" "$STAMP_FILE" + log "token changed; nginx reloaded" log "login endpoint: https://tankodhs.sysloggh.net/dsh-web-login (Authentik-gated)" diff --git a/zulip-health.prose.md b/zulip-health.prose.md index e3392b6..349b439 100644 --- a/zulip-health.prose.md +++ b/zulip-health.prose.md @@ -295,7 +295,9 @@ proxy_pass http://127.0.0.1:3080/?token=; `scripts/capture-dsh-token.sh`) reads the latest launch token from the journal **of the service's current invocation**, writes `/etc/dsh-web/launch-token` and regenerates `/etc/dsh-web/nginx-login.conf`, reloading nginx only when the token -changed (`nginx -t` guards the reload, with rollback). It **never stops or +differs from the token nginx actually loaded (`nginx -t` guards the reload, and +the applied-state stamp is written only after a successful `nginx -s reload`, so +a failed or interrupted reload is retried on the next run). It **never stops or starts `dsh-web`**. It is triggered by the `dsh-web.service` drop-in `/etc/systemd/system/dsh-web.service.d/20-token-refresh.conf` (`ExecStartPost=/bin/systemctl --no-block start dsh-web-token.service`) and by @@ -359,20 +361,38 @@ ssh root@192.168.68.15 "pct exec 112 -- curl -s --max-time 3 -o /dev/null \ # 3. Backend cookie mint + reuse (exactly what /dsh-web-login proxies to). TOKEN=$(ssh root@192.168.68.15 "pct exec 112 -- cat /etc/dsh-web/launch-token") -ssh root@192.168.68.15 "pct exec 112 -- curl -s -D - -o /dev/null \ +ssh root@192.168.68.15 "pct exec 112 -- curl -s -c /tmp/dsh.jar -o /dev/null \ -H 'Host: tankodhs.sysloggh.net' 'http://127.0.0.1:3080/?token=$TOKEN'" -# Expected: HTTP/1.1 303 + set-cookie: dsh-auth-... (authority tankodhs.sysloggh.net) +ssh root@192.168.68.15 "pct exec 112 -- curl -s -b /tmp/dsh.jar -o /dev/null \ + -w '%{http_code}\n' -H 'Host: tankodhs.sysloggh.net' http://127.0.0.1:3080/" +# Expected: 200 — the minted dsh-auth-... cookie (authority +# tankodhs.sysloggh.net) is replayed on the next request and accepted. # 4. Token refresh is non-disruptive and idempotent. ssh root@192.168.68.15 "pct exec 112 -- /opt/deepseek-harness/capture-dsh-token.sh" # Expected: "token unchanged; nginx not reloaded" when nothing changed ``` -**Restart durability (acceptance):** after `systemctl restart dsh-web`, (a) a +**Restart durability (acceptance):** after `systemctl restart dsh-web`, (a) the cookie minted before the restart still returns `200` on `/`, and (b) the refreshed `/etc/dsh-web/nginx-login.conf` carries the new token and mints a fresh cookie. Both verified live 2026-09-11. +```bash +# 5. Cookie survives a dsh-web restart, and the new token mints a new cookie. +ssh root@192.168.68.15 "pct exec 112 -- systemctl restart dsh-web" +ssh root@192.168.68.15 "pct exec 112 -- /opt/deepseek-harness/capture-dsh-token.sh" +ssh root@192.168.68.15 "pct exec 112 -- curl -s -b /tmp/dsh.jar -o /dev/null \ + -w '%{http_code}\n' -H 'Host: tankodhs.sysloggh.net' http://127.0.0.1:3080/" +# Expected: 200 — the pre-restart cookie is still accepted. +TOKEN=$(ssh root@192.168.68.15 "pct exec 112 -- cat /etc/dsh-web/launch-token") +ssh root@192.168.68.15 "pct exec 112 -- curl -s -c /tmp/dsh-new.jar -o /dev/null \ + -H 'Host: tankodhs.sysloggh.net' 'http://127.0.0.1:3080/?token=$TOKEN'" +ssh root@192.168.68.15 "pct exec 112 -- curl -s -b /tmp/dsh-new.jar -o /dev/null \ + -w '%{http_code}\n' -H 'Host: tankodhs.sysloggh.net' http://127.0.0.1:3080/" +# Expected: 200 — the refreshed token minted a fresh cookie. +``` + ### Step 4: Platform C — Agent Zero (kagentz, CT 105 via Docker host .14)