Web UI: optional HTTP basic auth via UI_USER/UI_PASS

Both must be set together and require LISTEN_UI; constant-time compares,
challenge on every endpoint. Startup warns when LISTEN_UI binds a
non-loopback address without auth. Bind address and port were already
covered by LISTEN_UI itself (host:port).
This commit is contained in:
mram
2026-09-22 18:53:00 +02:00
parent 0796092b80
commit 18a7336c02
8 changed files with 139 additions and 8 deletions
+24
View File
@@ -97,6 +97,30 @@ func TestComfyCmdRequiresURL(t *testing.T) {
}
}
func TestUIAuthPairing(t *testing.T) {
env := func(set map[string]string) func(string) string {
return func(k string) string { return set[k] }
}
// Only one of UI_USER/UI_PASS: error.
_, err := Load(env(map[string]string{"OLLAMA_URL": "http://x", "LISTEN_UI": "127.0.0.1:7860", "UI_USER": "admin"}))
if err == nil || !strings.Contains(err.Error(), "UI_USER and UI_PASS must be set together") {
t.Fatalf("err = %v, want pairing error", err)
}
// Auth without LISTEN_UI: error.
_, err = Load(env(map[string]string{"OLLAMA_URL": "http://x", "UI_USER": "admin", "UI_PASS": "x"}))
if err == nil || !strings.Contains(err.Error(), "no effect without LISTEN_UI") {
t.Fatalf("err = %v, want LISTEN_UI error", err)
}
// Both with LISTEN_UI: loads.
cfg, err := Load(env(map[string]string{"OLLAMA_URL": "http://x", "LISTEN_UI": "127.0.0.1:7860", "UI_USER": "admin", "UI_PASS": "x"}))
if err != nil {
t.Fatalf("auth pair with LISTEN_UI must load: %v", err)
}
if cfg.UIUser != "admin" || cfg.UIPass != "x" {
t.Errorf("got %q/%q", cfg.UIUser, cfg.UIPass)
}
}
func TestParseEnvFile(t *testing.T) {
input := `# comment
OLLAMA_URL=http://host:11435