package openai import ( "encoding/json" "net/http" "net/http/httptest" "reflect" "strings" "testing" "time" "iop/apps/edge/internal/authprojection" edgeservice "iop/apps/edge/internal/service" "iop/packages/go/config" ) func managedCredentialMigrationServer(t *testing.T, fake *providerFakeRunService) *Server { t.Helper() now := time.Date(2026, 8, 2, 0, 0, 0, 0, time.UTC) cache := authprojection.NewCache(authprojection.DefaultLimits(), func() time.Time { return now }) projection := makeTestProjection(1, now, time.Hour, map[string]string{ "managed-iop-token": "principal-one", }, map[string]authprojection.Route{ "route": { RouteID: "public-route", PrincipalRef: "principal-one", CredentialSlotRef: "slot-ref-one", ProfileID: "openai", UpstreamModel: "served-model", ResourceSelector: "openai-provider", RouteRevision: 3, CredentialRevision: 7, }, }) if err := cache.Apply(projection); err != nil { t.Fatal(err) } srv := NewServer(config.EdgeOpenAIConf{}, fake, nil) setManagedPrincipalProjection(srv, cache) srv.SetModelCatalog([]config.ModelCatalogEntry{{ ID: "internal-model", Providers: map[string]string{"openai-provider": "served-model"}, }}) return srv } func TestManagedCredentialModeRejectsCallerProviderHeadersBeforeEverySurface(t *testing.T) { fake := &providerFakeRunService{} srv := managedCredentialMigrationServer(t, fake) tests := []struct { name string path string body string anthropic bool }{ {name: "chat", path: "/v1/chat/completions", body: `{"model":"public-route","messages":[{"role":"user","content":"hello"}]}`}, {name: "responses", path: "/v1/responses", body: `{"model":"public-route","input":"hello"}`}, {name: "anthropic", path: "/v1/messages", body: `{"model":"public-route","max_tokens":8,"messages":[{"role":"user","content":"hello"}]}`, anthropic: true}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { req := httptest.NewRequest(http.MethodPost, tc.path, strings.NewReader(tc.body)) req.Header.Set("Authorization", "Bearer managed-iop-token") req.Header.Set(legacyProviderCredentialHeader, "provider-secret-sentinel") if tc.anthropic { req.Header.Set(anthropicVersionHeader, anthropicSupportedVersion) } w := httptest.NewRecorder() srv.routes().ServeHTTP(w, req) if w.Code != http.StatusBadRequest { t.Fatalf("status = %d, want 400; body=%s", w.Code, w.Body.String()) } if strings.Contains(w.Body.String(), "provider-secret-sentinel") { t.Fatalf("rejection echoed caller credential: %s", w.Body.String()) } var body map[string]any if err := json.Unmarshal(w.Body.Bytes(), &body); err != nil { t.Fatalf("decode rejection: %v", err) } if tc.anthropic { if !reflect.DeepEqual(sortedMapKeys(body), []string{"error", "type"}) || body["type"] != "error" { t.Fatalf("Anthropic rejection schema changed: %v", body) } } else if !reflect.DeepEqual(sortedMapKeys(body), []string{"error"}) { t.Fatalf("OpenAI rejection schema changed: %v", body) } }) } if got := fake.poolSubmitCountSnapshot(); got != 0 { t.Fatalf("managed caller credential reached provider-pool dispatch %d times", got) } if got := len(fake.tunnelReqsSnapshot()); got != 0 { t.Fatalf("managed caller credential reached provider tunnel %d times", got) } } func sortedMapKeys(values map[string]any) []string { keys := make([]string, 0, len(values)) for key := range values { keys = append(keys, key) } if len(keys) == 2 && keys[0] > keys[1] { keys[0], keys[1] = keys[1], keys[0] } return keys } func TestLegacyCredentialModeForwardsOnlyTheDedicatedProviderHeader(t *testing.T) { for _, tc := range []struct { name string path string body string anthropic bool }{ {name: "chat", path: "/v1/chat/completions", body: `{"model":"legacy-model","messages":[{"role":"user","content":"hello"}]}`}, {name: "responses", path: "/v1/responses", body: `{"model":"legacy-model","input":"hello"}`}, {name: "anthropic", path: "/v1/messages", body: `{"model":"legacy-model","max_tokens":8,"messages":[{"role":"user","content":"hello"}]}`, anthropic: true}, } { t.Run(tc.name, func(t *testing.T) { fake := &providerFakeRunService{poolDispatchPath: string(edgeservice.ProviderPoolPathTunnel)} if tc.anthropic { fake.poolSelectedCandidate = anthropicTestCandidate(t, "anthropic") fake.tunnelFrames = anthropicTunnelFrames(http.StatusOK, "application/json", []byte(`{"type":"message","role":"assistant","content":[],"stop_reason":"end_turn","usage":{"input_tokens":1,"output_tokens":1}}`)) } else { fake.tunnelFrames = staticProviderTunnelFrames(`{"id":"fixture","object":"response"}`) } cfg := config.EdgeOpenAIConf{ BearerToken: "legacy-iop-token", ProviderAuth: config.EdgeOpenAIProviderAuthConf{ Enabled: true, FromHeader: legacyProviderCredentialHeader, TargetHeader: "Authorization", Scheme: "Bearer", Required: true, }, } srv := NewServer(cfg, fake, nil) srv.SetModelCatalog([]config.ModelCatalogEntry{{ ID: "legacy-model", Providers: map[string]string{"legacy-provider": "served-model"}, }}) req := httptest.NewRequest(http.MethodPost, tc.path, strings.NewReader(tc.body)) req.Header.Set("Authorization", "Bearer legacy-iop-token") req.Header.Set(legacyProviderCredentialHeader, "legacy-provider-token") if tc.anthropic { req.Header.Set(anthropicVersionHeader, anthropicSupportedVersion) } w := httptest.NewRecorder() srv.routes().ServeHTTP(w, req) if w.Code != http.StatusOK { t.Fatalf("status = %d, want 200; body=%s", w.Code, w.Body.String()) } requests := fake.tunnelReqsSnapshot() if len(requests) != 1 { t.Fatalf("provider tunnel calls = %d, want 1", len(requests)) } found := 0 for header, value := range requests[0].Headers { if strings.Contains(value, "legacy-provider-token") { found++ if tc.anthropic && !strings.EqualFold(header, "x-api-key") { t.Fatalf("Anthropic credential header = %q, want x-api-key", header) } } if strings.Contains(value, "legacy-iop-token") { t.Fatalf("inbound IOP token was reused as provider credential in %q", header) } } if found != 1 { t.Fatalf("provider credential occurrences = %d, want 1; headers=%v", found, requests[0].Headers) } }) } } func TestManagedResponsesProviderSchemaRemainsUnchanged(t *testing.T) { profile, err := config.ResolveProtocolProfile("openai", "", config.BuiltInProtocolProfileCatalog()) if err != nil { t.Fatal(err) } want := `{"id":"resp-managed","object":"response","status":"completed","output":[{"type":"message","content":[{"type":"output_text","text":"ok"}]}],"usage":{"input_tokens":2,"output_tokens":1}}` fake := &providerFakeRunService{ tunnelFrames: staticProviderTunnelFrames(want), poolSelectedCandidate: edgeservice.ProviderPoolCandidate{ ProviderID: "openai-provider", ActualModel: "served-model", ExecutionPath: string(edgeservice.ProviderPoolPathTunnel), ProfileID: profile.ID, ProfileDriver: string(profile.Driver), ProfileCapabilities: append([]string(nil), profile.Capabilities...), ProtocolProfile: &profile, }, } srv := managedCredentialMigrationServer(t, fake) req := httptest.NewRequest(http.MethodPost, "/v1/responses", strings.NewReader(`{"model":"public-route","input":"hello"}`)) req.Header.Set("Authorization", "Bearer managed-iop-token") w := httptest.NewRecorder() srv.routes().ServeHTTP(w, req) if w.Code != http.StatusOK || w.Body.String() != want { t.Fatalf("managed Responses schema/body changed: status=%d\n got=%s\nwant=%s", w.Code, w.Body.String(), want) } }