forked from bai/curriculum-project-hub
feat: secure organization provider credentials
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
import { createServer } from "node:http";
|
||||
import { once } from "node:events";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { ProviderReadinessError, probeOpenRouterCredential } from "../../src/connections/providerReadiness.js";
|
||||
|
||||
const servers: ReturnType<typeof createServer>[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(servers.splice(0).map(async (server) => {
|
||||
server.closeAllConnections();
|
||||
if (server.listening) {
|
||||
server.close();
|
||||
await once(server, "close");
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
describe("provider credential readiness", () => {
|
||||
it("authenticates the OpenRouter key endpoint before activation", async () => {
|
||||
const requests: Array<{ url: string | undefined; authorization: string | undefined }> = [];
|
||||
const server = createServer((request, response) => {
|
||||
requests.push({ url: request.url, authorization: request.headers.authorization });
|
||||
response.writeHead(200, { "content-type": "application/json" });
|
||||
response.end('{"data":{"label":"test"}}');
|
||||
});
|
||||
servers.push(server);
|
||||
server.listen(0, "127.0.0.1");
|
||||
await once(server, "listening");
|
||||
const address = server.address();
|
||||
if (address === null || typeof address === "string") throw new Error("expected TCP address");
|
||||
|
||||
await expect(probeOpenRouterCredential({
|
||||
providerId: "openrouter",
|
||||
baseUrl: `http://127.0.0.1:${address.port}/api`,
|
||||
authToken: "readiness-secret",
|
||||
anthropicApiKey: "",
|
||||
})).resolves.toBeUndefined();
|
||||
expect(requests).toEqual([{
|
||||
url: "/api/v1/key",
|
||||
authorization: "Bearer readiness-secret",
|
||||
}]);
|
||||
});
|
||||
|
||||
it("fails closed on rejected credentials without exposing them in the error", async () => {
|
||||
const server = createServer((_request, response) => {
|
||||
response.writeHead(401, { "content-type": "application/json" });
|
||||
response.end('{"error":"token rejected"}');
|
||||
});
|
||||
servers.push(server);
|
||||
server.listen(0, "127.0.0.1");
|
||||
await once(server, "listening");
|
||||
const address = server.address();
|
||||
if (address === null || typeof address === "string") throw new Error("expected TCP address");
|
||||
|
||||
let message = "";
|
||||
try {
|
||||
await probeOpenRouterCredential({
|
||||
providerId: "openrouter",
|
||||
baseUrl: `http://127.0.0.1:${address.port}`,
|
||||
authToken: "never-return-readiness-secret",
|
||||
anthropicApiKey: "",
|
||||
});
|
||||
} catch (error) {
|
||||
message = error instanceof Error ? error.message : String(error);
|
||||
}
|
||||
expect(message).toBe("provider credential readiness check failed: status 401");
|
||||
expect(message).not.toContain("never-return-readiness-secret");
|
||||
});
|
||||
|
||||
it("does not follow redirects with the provider credential", async () => {
|
||||
let redirected = 0;
|
||||
const target = createServer((_request, response) => {
|
||||
redirected += 1;
|
||||
response.end("leaked");
|
||||
});
|
||||
servers.push(target);
|
||||
target.listen(0, "127.0.0.1");
|
||||
await once(target, "listening");
|
||||
const targetAddress = target.address();
|
||||
if (targetAddress === null || typeof targetAddress === "string") throw new Error("expected target address");
|
||||
const provider = createServer((_request, response) => {
|
||||
response.writeHead(307, { location: `http://127.0.0.1:${targetAddress.port}/capture` });
|
||||
response.end();
|
||||
});
|
||||
servers.push(provider);
|
||||
provider.listen(0, "127.0.0.1");
|
||||
await once(provider, "listening");
|
||||
const providerAddress = provider.address();
|
||||
if (providerAddress === null || typeof providerAddress === "string") throw new Error("expected provider address");
|
||||
|
||||
await expect(probeOpenRouterCredential({
|
||||
providerId: "openrouter",
|
||||
baseUrl: `http://127.0.0.1:${providerAddress.port}`,
|
||||
authToken: "redirect-secret",
|
||||
anthropicApiKey: "",
|
||||
})).rejects.toThrow("status 307");
|
||||
expect(redirected).toBe(0);
|
||||
});
|
||||
|
||||
it("preserves a redacted network category for observability", async () => {
|
||||
const server = createServer();
|
||||
server.listen(0, "127.0.0.1");
|
||||
await once(server, "listening");
|
||||
const address = server.address();
|
||||
if (address === null || typeof address === "string") throw new Error("expected provider address");
|
||||
server.close();
|
||||
await once(server, "close");
|
||||
|
||||
let failure: unknown;
|
||||
try {
|
||||
await probeOpenRouterCredential({
|
||||
providerId: "openrouter",
|
||||
baseUrl: `http://127.0.0.1:${address.port}`,
|
||||
authToken: "network-secret",
|
||||
anthropicApiKey: "",
|
||||
});
|
||||
} catch (error) {
|
||||
failure = error;
|
||||
}
|
||||
expect(failure).toBeInstanceOf(ProviderReadinessError);
|
||||
expect(failure).toMatchObject({
|
||||
code: "provider_readiness_unreachable",
|
||||
category: "connection",
|
||||
message: "provider credential readiness check could not reach provider",
|
||||
});
|
||||
expect(JSON.stringify(failure)).not.toContain("network-secret");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user