Add API key authentication for proxy endpoints.
Support multiple API keys from config, env, and CLI, enforce auth on non-public endpoints, and pass keys through remote deploy verification. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,83 @@ func TestCapabilitiesAdvertiseAgentCompatibility(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthAllowsPublicHealthWithoutAPIKey(t *testing.T) {
|
||||
server := NewServer("", service.New(service.Config{
|
||||
Model: "Qwen3-Coder",
|
||||
Timeout: time.Second,
|
||||
APIKeys: []string{"key-1", "key-2"},
|
||||
}))
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/health", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
server.http.Handler.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d body = %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthRejectsProtectedEndpointWithoutAPIKey(t *testing.T) {
|
||||
server := NewServer("", service.New(service.Config{
|
||||
Model: "Qwen3-Coder",
|
||||
Timeout: time.Second,
|
||||
APIKeys: []string{"key-1", "key-2"},
|
||||
}))
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/capabilities", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
server.http.Handler.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusUnauthorized {
|
||||
t.Fatalf("status = %d body = %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
if !strings.Contains(rec.Body.String(), "authentication_error") {
|
||||
t.Fatalf("body = %s", rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthAcceptsBearerAndXAPIKey(t *testing.T) {
|
||||
server := NewServer("", service.New(service.Config{
|
||||
Model: "Qwen3-Coder",
|
||||
Timeout: time.Second,
|
||||
APIKeys: []string{"key-1", "key-2"},
|
||||
}))
|
||||
|
||||
bearerReq := httptest.NewRequest(http.MethodGet, "/capabilities", nil)
|
||||
bearerReq.Header.Set("Authorization", "Bearer key-2")
|
||||
bearerRec := httptest.NewRecorder()
|
||||
server.http.Handler.ServeHTTP(bearerRec, bearerReq)
|
||||
if bearerRec.Code != http.StatusOK {
|
||||
t.Fatalf("bearer status = %d body = %s", bearerRec.Code, bearerRec.Body.String())
|
||||
}
|
||||
|
||||
xReq := httptest.NewRequest(http.MethodGet, "/capabilities", nil)
|
||||
xReq.Header.Set("x-api-key", "key-1")
|
||||
xRec := httptest.NewRecorder()
|
||||
server.http.Handler.ServeHTTP(xRec, xReq)
|
||||
if xRec.Code != http.StatusOK {
|
||||
t.Fatalf("x-api-key status = %d body = %s", xRec.Code, xRec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnthropicAuthErrorShape(t *testing.T) {
|
||||
server := NewServer("", service.New(service.Config{
|
||||
Model: "Qwen3-Coder",
|
||||
Timeout: time.Second,
|
||||
APIKeys: []string{"key-1"},
|
||||
}))
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/v1/messages", strings.NewReader(`{"model":"kmodel","messages":[{"role":"user","content":"hello"}],"max_tokens":16}`))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
server.http.Handler.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusUnauthorized {
|
||||
t.Fatalf("status = %d body = %s", rec.Code, rec.Body.String())
|
||||
}
|
||||
if !strings.Contains(rec.Body.String(), `"type":"error"`) {
|
||||
t.Fatalf("body = %s", rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestNormalizeOpenAIRequestRejectsMissingUserAndAssistantMessages(t *testing.T) {
|
||||
req := openAIChatRequest{
|
||||
Model: "test-model",
|
||||
|
||||
Reference in New Issue
Block a user