no-mistakes(review): harden dsh token reload retry, legacy bypass, cookie verification

This commit is contained in:
2026-09-11 16:59:55 +00:00
parent 266fa1f835
commit b80d3142aa
2 changed files with 65 additions and 18 deletions
+41 -14
View File
@@ -19,8 +19,9 @@
# 2. records it in /etc/dsh-web/launch-token, # 2. records it in /etc/dsh-web/launch-token,
# 3. regenerates the nginx include /etc/dsh-web/nginx-login.conf (the # 3. regenerates the nginx include /etc/dsh-web/nginx-login.conf (the
# `proxy_pass ...?token=` line consumed by /dsh-web-login), # `proxy_pass ...?token=` line consumed by /dsh-web-login),
# 4. validates with `nginx -t` and reloads ONLY when the token changed, # 4. reloads nginx ONLY when the token differs from the token nginx actually
# rolling the include back if validation fails, # 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. # 5. removes the legacy unauthenticated :8081 endpoint if it ever reappears.
# #
# Idempotent and safe to run at any time (systemd ExecStartPost or timer). # 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" JOURNAL_UNIT="dsh-web.service"
TOKEN_FILE="/etc/dsh-web/launch-token" TOKEN_FILE="/etc/dsh-web/launch-token"
INCLUDE_FILE="/etc/dsh-web/nginx-login.conf" INCLUDE_FILE="/etc/dsh-web/nginx-login.conf"
STAMP_FILE="/etc/dsh-web/nginx-login.conf.applied"
SITE_ENABLED="/etc/nginx/sites-enabled/dsh" SITE_ENABLED="/etc/nginx/sites-enabled/dsh"
LEGACY_8081="/etc/nginx/sites-enabled/dsh.token" LEGACY_8081="/etc/nginx/sites-enabled/dsh.token"
STASH_DIR="/etc/nginx/sites-available" 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) # 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. # and must never come back. Stash it rather than delete so it is auditable.
if [ -e "$LEGACY_8081" ] || [ -L "$LEGACY_8081" ]; then if [ -e "$LEGACY_8081" ] || [ -L "$LEGACY_8081" ]; then
STAMP="$(date -u +%Y%m%dT%H%M%SZ)" TS="$(date -u +%Y%m%dT%H%M%SZ)"
STASHED="$STASH_DIR/dsh.token.disabled-$STAMP" STASHED="$STASH_DIR/dsh.token.disabled-$TS"
mv "$LEGACY_8081" "$STASHED" mv "$LEGACY_8081" "$STASHED"
if nginx -t >/dev/null 2>&1; then if ! nginx -t >/dev/null 2>&1; then
nginx -s reload 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."
log "removed legacy :8081 endpoint -> $STASHED"
else
mv "$STASHED" "$LEGACY_8081"
die "nginx config test failed after removing $LEGACY_8081; restored it"
fi 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 fi
# ── 1. Read the latest launch token from the RUNNING service ──────────────── # ── 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" printf 'proxy_pass http://127.0.0.1:3080/?token=%s;\n' "$TOKEN" > "$NEW_INCLUDE"
chmod 600 "$NEW_INCLUDE" chmod 600 "$NEW_INCLUDE"
if [ -f "$INCLUDE_FILE" ] && cmp -s "$NEW_INCLUDE" "$INCLUDE_FILE"; then # The stamp records the token nginx actually loaded. Comparing against it (not
rm -f "$NEW_INCLUDE" # the on-disk include) means a failed or interrupted reload is retried on the
log "token unchanged; nginx not reloaded" # 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 exit 0
fi fi
@@ -132,10 +146,23 @@ if ! nginx -t >/dev/null 2>&1; then
fi fi
die "nginx config test failed; previous include restored" die "nginx config test failed; previous include restored"
fi 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 if [ -n "$RESTORE" ]; then
rm -f "$RESTORE" rm -f "$RESTORE"
fi 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 "token changed; nginx reloaded"
log "login endpoint: https://tankodhs.sysloggh.net/dsh-web-login (Authentik-gated)" log "login endpoint: https://tankodhs.sysloggh.net/dsh-web-login (Authentik-gated)"
+24 -4
View File
@@ -295,7 +295,9 @@ proxy_pass http://127.0.0.1:3080/?token=<TOKEN>;
`scripts/capture-dsh-token.sh`) reads the latest launch token from the journal `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 **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 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 starts `dsh-web`**. It is triggered by the `dsh-web.service` drop-in
`/etc/systemd/system/dsh-web.service.d/20-token-refresh.conf` `/etc/systemd/system/dsh-web.service.d/20-token-refresh.conf`
(`ExecStartPost=/bin/systemctl --no-block start dsh-web-token.service`) and by (`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). # 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") 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'" -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. # 4. Token refresh is non-disruptive and idempotent.
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 -- /opt/deepseek-harness/capture-dsh-token.sh"
# Expected: "token unchanged; nginx not reloaded" when nothing changed # 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 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 refreshed `/etc/dsh-web/nginx-login.conf` carries the new token and mints a
fresh cookie. Both verified live 2026-09-11. 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) ### Step 4: Platform C — Agent Zero (kagentz, CT 105 via Docker host .14)