feat(arbo): disable ENGINE_TOKEN bearer auth on prod (WireGuard = boundary)
Operator decision 2026-06-13 (relayed by comfy-dev, confirmed in-session): turn off the prod arbo engine's bearer auth and rely on the WireGuard perimeter. Reverses ADR-0001's open-auth-hole-closed posture (comfy-dev owns the ADR update on the vh/arbo side). The app's protected-gate no-ops only when ENGINE_TOKEN is ABSENT — an empty string still gates (verified: ENGINE_TOKEN="" -> /workflows 401). So both inject paths are removed: the compose environment line is commented out and the .env line deleted on the host. Result: tokenless GET /workflows 200 (was 401), matching the dev engine. Original token preserved in the host's .env.pre-auth-off.bak for re-enable. playbooks/arbo-disable-engine-token.yaml captures the reversible procedure.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# Disable bearer-token auth on the prod arbo engine (irv-ml1), leaning on
|
||||
# WireGuard as the access boundary. Operator decision 2026-06-13 (relayed by
|
||||
# comfy-dev, confirmed in-session). Deliberately reverses ADR-0001's
|
||||
# "open-auth hole closed (ENGINE_TOKEN minted)" line.
|
||||
#
|
||||
# GOTCHA (why .env-only is not enough): the app's `dependencies=protected`
|
||||
# gate no-ops only when ENGINE_TOKEN is ABSENT from the container env. An
|
||||
# empty string still gates (verified 2026-06-13: ENGINE_TOKEN="" -> /workflows
|
||||
# still 401). The var is injected by TWO paths, both must be removed:
|
||||
# 1. env_file: .env -> delete the ENGINE_TOKEN line from .env
|
||||
# 2. environment: - ENGINE_TOKEN=${ENGINE_TOKEN} -> commented out in compose
|
||||
# With both gone the var is unset in the container and the engine serves open,
|
||||
# exactly like the dev engine on nh3-dev.
|
||||
#
|
||||
# Reversible: the pre-change .env (with the real token) is backed up to
|
||||
# .env.pre-auth-off.bak. To re-lock: restore the ENGINE_TOKEN line in .env,
|
||||
# un-comment the compose line, `compose up -d`.
|
||||
#
|
||||
# No sudo: lkraven owns the compose dir + .env and is in the docker group.
|
||||
|
||||
vars:
|
||||
dir: /opt/docker/compose/arbo
|
||||
|
||||
steps:
|
||||
- name: Back up prod .env (preserves the real ENGINE_TOKEN for re-enable)
|
||||
shell: cp -p {{ dir }}/.env {{ dir }}/.env.pre-auth-off.bak
|
||||
# creates: guards the FIRST backup — never clobber it on a rerun.
|
||||
creates: "{{ dir }}/.env.pre-auth-off.bak"
|
||||
|
||||
- name: Remove the ENGINE_TOKEN line from .env entirely (must be ABSENT, not empty)
|
||||
shell: sed -i '/^ENGINE_TOKEN=/d' {{ dir }}/.env
|
||||
when: "grep -qE '^ENGINE_TOKEN=' {{ dir }}/.env"
|
||||
|
||||
- name: Push the corrected compose (ENGINE_TOKEN injection commented out)
|
||||
upload:
|
||||
src: stacks/arbo/compose.yaml
|
||||
dest: "{{ dir }}/compose.yaml"
|
||||
mode: "0644"
|
||||
|
||||
- name: Recreate the engine so ENGINE_TOKEN is absent from its env
|
||||
shell: docker compose -f {{ dir }}/compose.yaml up -d
|
||||
|
||||
verify:
|
||||
- name: .env no longer defines ENGINE_TOKEN
|
||||
shell: "! grep -qE '^ENGINE_TOKEN=' {{ dir }}/.env"
|
||||
changed_when: "false"
|
||||
|
||||
- name: Backup still carries the original token (reversibility intact)
|
||||
shell: grep -qE '^ENGINE_TOKEN=.+' {{ dir }}/.env.pre-auth-off.bak
|
||||
changed_when: "false"
|
||||
|
||||
- name: ENGINE_TOKEN is ABSENT from the running container env
|
||||
shell: "! docker exec arbo printenv ENGINE_TOKEN >/dev/null 2>&1"
|
||||
changed_when: "false"
|
||||
|
||||
- name: Protected endpoint serves tokenless after warmup (auth OFF — expect HTTP 200, was 401)
|
||||
shell: |
|
||||
port=$(docker port arbo 8200/tcp 2>/dev/null | sed -n 's/.*:\([0-9]\+\)$/\1/p' | head -1)
|
||||
final=000
|
||||
for i in $(seq 1 30); do
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 "http://localhost:${port}/workflows")
|
||||
if [ "$code" != "000" ]; then final=$code; break; fi
|
||||
sleep 2
|
||||
done
|
||||
echo "tokenless GET /workflows on :${port} -> HTTP ${final}"
|
||||
test "$final" = "200"
|
||||
changed_when: "false"
|
||||
@@ -16,9 +16,13 @@ ARBO_GID=1000
|
||||
ARBO_CATALOG_DIR=/worktank/arbo/repo
|
||||
|
||||
# ── Secrets (DO NOT COMMIT REAL VALUES) ──────────────────────────────
|
||||
# ENGINE_TOKEN: a real bearer token — auth is OPEN until this is set.
|
||||
# Mint a fresh one: openssl rand -hex 32
|
||||
ENGINE_TOKEN=
|
||||
# ENGINE_TOKEN: bearer auth is intentionally OFF (operator decision 2026-06-13,
|
||||
# WireGuard = the boundary). Leave it UNSET — the protected-gate no-ops only
|
||||
# when the var is ABSENT (an empty `ENGINE_TOKEN=` still gates), and the compose
|
||||
# injection is commented out to match. To re-lock: un-comment the compose line
|
||||
# `- ENGINE_TOKEN=${ENGINE_TOKEN}`, mint a bearer (`openssl rand -hex 32`), set
|
||||
# it below, `compose up -d`.
|
||||
# ENGINE_TOKEN=
|
||||
|
||||
# GRANITE_KEY: the LiteLLM virtual key scoped to arbo. The 'arbo-prompt-enhance'
|
||||
# vkey (comfy-dev, issued 2026-06-09) is extended to reach BOTH granite-4.1-8b
|
||||
|
||||
@@ -31,9 +31,14 @@ scripts/deploy-stack.sh irv-ml1 arbo # diffs vs live, prompts y/N
|
||||
Both injected via the on-host **`.env`** (gitignored; never the althing bus),
|
||||
the standard fleet pattern:
|
||||
|
||||
- **`ENGINE_TOKEN`** — auth is **OPEN today**. Mint a real bearer
|
||||
(`openssl rand -hex 32`), put it in `.env`. Closing this is the one security
|
||||
fix the move buys us.
|
||||
- **`ENGINE_TOKEN`** — bearer auth is **intentionally OFF** (operator decision
|
||||
2026-06-13). Prod is WireGuard-only; the perimeter is the boundary, so the
|
||||
per-browser token was friction with little added security. The compose
|
||||
`ENGINE_TOKEN` injection is commented out **and** the `.env` line removed — the
|
||||
app's protected-gate no-ops only when the var is **absent** (an empty string
|
||||
still gates). To re-lock: un-comment the compose line, set a bearer in `.env`
|
||||
(`openssl rand -hex 32`), `compose up -d`. Reverses ADR-0001 (comfy-dev owns
|
||||
that ADR's update). See `playbooks/arbo-disable-engine-token.yaml`.
|
||||
- **`GRANITE_KEY`** — the LiteLLM **virtual key scoped to arbo**. The
|
||||
`arbo-prompt-enhance` vkey (comfy-dev, issued 2026-06-09) was **extended**
|
||||
to reach **both** `granite-4.1-8b` (prompt-craft / `gen` step) **and**
|
||||
|
||||
@@ -48,7 +48,12 @@ services:
|
||||
# LiteLLM gateway for the granite hero/metadata calls:
|
||||
- GRANITE_ENDPOINT=http://10.250.50.70:4000/v1
|
||||
- GRANITE_KEY=${GRANITE_KEY} # arbo-prompt-enhance scoped vkey (.env)
|
||||
- ENGINE_TOKEN=${ENGINE_TOKEN} # real bearer — closes today's open auth (.env)
|
||||
# ENGINE_TOKEN intentionally NOT injected — bearer auth is OFF on prod by
|
||||
# operator decision (2026-06-13); WireGuard is the access boundary. The
|
||||
# app's protected-gate no-ops only when the var is ABSENT — an empty string
|
||||
# still gates — so it must not be set here OR in .env. Re-enable: restore
|
||||
# this line + set ENGINE_TOKEN in .env, then `compose up -d`. Reverses ADR-0001.
|
||||
#- ENGINE_TOKEN=${ENGINE_TOKEN}
|
||||
volumes:
|
||||
- arbo_db:/data
|
||||
- arbo_heroes:/heroes
|
||||
|
||||
Reference in New Issue
Block a user