fix(agent-url): decouple session LAB_URL from --base-url; harden labctl vs auth proxies (#30) #31
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab!31
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/agent-url-loopback"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Fixes labctl breaking behind an SSO/auth proxy (nginx + Authelia).
--base-urldid double duty — the external browser origin and theLAB_URLhanded to every session — so labctl's run-token/agent/v1calls hairpinned out to the public FQDN, got 302'd to the Authelia login page, and (following the redirect) failed decoding the HTML as JSON (invalid character '<'). The agent API self-authenticates with run tokens and is mounted outside the operator auth/CSRF middleware, so machine traffic must never touch the proxy.Implements approach A + C (decided with the maintainer in the issue).
A — dedicated session-facing URL, loopback by default
--agent-url/LAB_AGENT_URLserver knob (config.AgentURL), validated as an absolute http(s) URL exactly like--base-url(sharedvalidateHTTPURLhelper).labURL()precedence is now agent-URL → base-URL →http://127.0.0.1:<port>.services.lab.agentUrl, defaulting to a loopback URL derived fromlistenAddrand passed as--agent-url— so a proxy-fronted deployment keeps machine traffic on loopback with zero operator config.nullfalls back to lab's own precedence.--base-urlkeeps its Secure-cookie / CSRF-Origin role unchanged.C — labctl fails loudly instead of parsing HTML as JSON
CheckRedirect = ErrUseLastResponse— no more silent redirect-following.Location+ an "LAB_URLmay be behind an auth proxy" hint.Content-Typeor a leading<) at any status surfaces the same hint — including 2xx, so a proxy answering200 text/htmlto a mutating command (issue close/comment/label, which decode nothing) can never report a lost write as success.Tests
--agent-urlprecedence + validation (incl. barehost:port→ actionable http(s) hint).labURL()precedence (newcmd/lab/main_test.go).200/401/502HTML across read and mutating commands.flake.nixnixos-modulecheck asserts the unit defaults--agent-urlto loopback even with an externalbaseUrl.Verification
go build,gofmt,go vet, fullgo test ./...— green.nix build .#checks.x86_64-linux.nixos-module— exit 0 (real build).Out of scope
utils/modules/coding-lab/default.nix) — follow-up once this lands./agent/v1/unauthenticated.--base-url's cookie/CSRF role.Fixes #30
Landing audit — PASS
Verification signal relied on: CI
ci / flake-check (pull_request)green (run #34, 12m3s) — realgo test ./...+golangci-lint+nix buildof the nixos-module. Not re-run.Checked:
fix(agent-url): …); nosecrets.yaml/system.stateVersionedits; NixOS module changes are additive options.Fixes #30present → merge will auto-close the issue.--agent-url/LAB_AGENT_URLadded, validated as an absolute http(s) URL via the sharedvalidateHTTPURL(barehost:portfolded into the same actionable message).labURL()precedence is now agent-URL → base-URL →http://127.0.0.1:<port>.CheckRedirect: noRedirect; a 3xx surfaces the redirectLocation+ auth-proxy hint; an HTML body (Content-Type or leading<) is rejected at any status — including a 2xx on a mutating command, so a proxied login page can't report a lost write as success.services.lab.agentUrldefaults to a loopback URL derived fromlistenAddr, passed as--agent-url;nullfalls back to lab's own precedence.labURL()precedence, and labctl 302 + 200/401/502 HTML across read and mutating commands; the flake nixos-module check asserts the loopback--agent-urldefault even with an externalbaseUrl.Verdict: PASS — cleared for merge pending the maintainer's free-text go-ahead.