Files
llmgw/internal/router/adminauth_test.go
Ilker ManapandClaude Opus 5.5 c0421bc7ee Guard the admin API and pprof with a token only root and the server can read
The admin listener answered any local process: models added, nodes
upgraded, engine keys listed, the heap dumped. /api and /debug now demand
the token the server writes 0600 to its state directory on first start;
ctl, the console and node add send it (sudo, LLMGW_ADMIN_TOKEN or
--token-file). pprof is off unless debug_pprof. admin_listen off loopback
is refused unless admin_remote. Dashboard pages, /metrics and /health are
unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 10:02:44 +02:00

48 lines
1.7 KiB
Go

package router
import (
"net/http"
"net/http/httptest"
"testing"
)
func TestTheAdminAPIAndProfilerWantTheTokenAndThePagesDoNot(t *testing.T) {
ok := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) })
cases := []struct {
pprof bool
path, header string
want int
}{
{false, "/api/v1/models", "", http.StatusUnauthorized},
{false, "/api/v1/models", "Bearer wrong", http.StatusUnauthorized},
{false, "/api/v1/models", "Bearer s3cret-token-of-enough-length-000000", http.StatusOK},
{false, "/api/v1/replicas", "s3cret-token-of-enough-length-000000", http.StatusUnauthorized},
{false, "/debug/pprof/heap", "Bearer s3cret-token-of-enough-length-000000", http.StatusNotFound},
{true, "/debug/pprof/heap", "", http.StatusUnauthorized},
{true, "/debug/pprof/heap", "Bearer s3cret-token-of-enough-length-000000", http.StatusOK},
{false, "/", "", http.StatusOK},
{false, "/nodes/n1", "", http.StatusOK},
{false, "/metrics", "", http.StatusOK},
}
for _, c := range cases {
h := AdminAuth("s3cret-token-of-enough-length-000000", c.pprof, ok)
r := httptest.NewRequest("GET", c.path, nil)
if c.header != "" {
r.Header.Set("Authorization", c.header)
}
w := httptest.NewRecorder()
h.ServeHTTP(w, r)
if w.Code != c.want {
t.Errorf("pprof=%v %s %q: %d, want %d", c.pprof, c.path, c.header, w.Code, c.want)
}
}
// No token configured is no access, not open access.
w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/api/v1/models", nil)
r.Header.Set("Authorization", "Bearer ")
AdminAuth("", false, ok).ServeHTTP(w, r)
if w.Code != http.StatusUnauthorized {
t.Errorf("an empty token let a request in: %d", w.Code)
}
}