From e0e4d244282f2b122e12cc9aa1cad2f588cef84b Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 4 Feb 2026 11:56:16 +0000 Subject: [PATCH] Cover setup token access for SSH endpoints --- internal/api/security_regression_test.go | 45 ++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/internal/api/security_regression_test.go b/internal/api/security_regression_test.go index 99f82e2118..8ee78a3cea 100644 --- a/internal/api/security_regression_test.go +++ b/internal/api/security_regression_test.go @@ -2742,3 +2742,48 @@ func TestStateRequiresMonitoringReadScope(t *testing.T) { t.Fatalf("expected missing scope response to mention %q, got %q", config.ScopeMonitoringRead, rec.Body.String()) } } + +func TestVerifyTemperatureSSHAllowsSetupToken(t *testing.T) { + cfg := newTestConfigWithTokens(t) + router := NewRouter(cfg, nil, nil, nil, nil, "1.0.0") + + token := "0123456789abcdef0123456789abcdef" + tokenHash := auth.HashAPIToken(token) + router.configHandlers.codeMutex.Lock() + router.configHandlers.setupCodes[tokenHash] = &SetupCode{ExpiresAt: time.Now().Add(time.Minute)} + router.configHandlers.codeMutex.Unlock() + + req := httptest.NewRequest(http.MethodPost, "/api/system/verify-temperature-ssh", strings.NewReader(`{"nodes":""}`)) + req.Header.Set("X-Setup-Token", token) + rec := httptest.NewRecorder() + router.Handler().ServeHTTP(rec, req) + if rec.Code != http.StatusOK { + t.Fatalf("expected 200 with setup token, got %d", rec.Code) + } + if !strings.Contains(rec.Body.String(), "No nodes to verify") { + t.Fatalf("expected verify response, got %q", rec.Body.String()) + } +} + +func TestSSHConfigAllowsSetupToken(t *testing.T) { + cfg := newTestConfigWithTokens(t) + router := NewRouter(cfg, nil, nil, nil, nil, "1.0.0") + t.Setenv("HOME", t.TempDir()) + + token := "abcdef0123456789abcdef0123456789" + tokenHash := auth.HashAPIToken(token) + router.configHandlers.codeMutex.Lock() + router.configHandlers.setupCodes[tokenHash] = &SetupCode{ExpiresAt: time.Now().Add(time.Minute)} + router.configHandlers.codeMutex.Unlock() + + req := httptest.NewRequest(http.MethodPost, "/api/system/ssh-config", strings.NewReader("Host example\nHostname example\n")) + req.Header.Set("X-Setup-Token", token) + rec := httptest.NewRecorder() + router.Handler().ServeHTTP(rec, req) + if rec.Code != http.StatusOK { + t.Fatalf("expected 200 with setup token, got %d", rec.Code) + } + if !strings.Contains(rec.Body.String(), `"success":true`) { + t.Fatalf("expected success response, got %q", rec.Body.String()) + } +}