fix: make opencode iframe auth traceable
This commit is contained in:
@@ -500,10 +500,15 @@ test("cloud web injects trace explorer runtime config from env", async () => {
|
||||
});
|
||||
|
||||
test("cloud web OpenCode proxy requires an authenticated HWLAB session", async () => {
|
||||
let authRequests = 0;
|
||||
const authRequests = [];
|
||||
let opencodeRequests = 0;
|
||||
const cloudApi = createServer((request, response) => {
|
||||
authRequests += 1;
|
||||
authRequests.push({
|
||||
traceparent: request.headers.traceparent,
|
||||
otelTraceId: request.headers["x-hwlab-otel-trace-id"],
|
||||
requestId: request.headers["x-request-id"],
|
||||
sourceServiceId: request.headers["x-source-service-id"]
|
||||
});
|
||||
request.resume();
|
||||
response.writeHead(401, { "content-type": "application/json" });
|
||||
response.end(JSON.stringify({ authenticated: false }));
|
||||
@@ -539,8 +544,19 @@ test("cloud web OpenCode proxy requires an authenticated HWLAB session", async (
|
||||
try {
|
||||
const response = await fetch(`${serverUrl(cloudWeb)}/`, { headers: { accept: "text/html" } });
|
||||
assert.equal(response.status, 401);
|
||||
assert.equal((await response.json()).error, "opencode_auth_required");
|
||||
assert.equal(authRequests, 1);
|
||||
const body = await response.json();
|
||||
assert.equal(body.error, "opencode_auth_required");
|
||||
assert.match(response.headers.get("traceparent") ?? "", /^00-[0-9a-f]{32}-[0-9a-f]{16}-01$/u);
|
||||
assert.match(response.headers.get("x-hwlab-otel-trace-id") ?? "", /^[0-9a-f]{32}$/u);
|
||||
assert.match(response.headers.get("x-request-id") ?? "", /^req_[0-9a-f]{32}$/u);
|
||||
assert.equal(body.diagnostic.traceId, response.headers.get("x-hwlab-otel-trace-id"));
|
||||
assert.equal(body.diagnostic.requestId, response.headers.get("x-request-id"));
|
||||
assert.deepEqual(authRequests, [{
|
||||
traceparent: response.headers.get("traceparent"),
|
||||
otelTraceId: response.headers.get("x-hwlab-otel-trace-id"),
|
||||
requestId: response.headers.get("x-request-id"),
|
||||
sourceServiceId: "hwlab-cloud-web"
|
||||
}]);
|
||||
assert.equal(opencodeRequests, 0);
|
||||
} finally {
|
||||
await close(cloudWeb);
|
||||
@@ -549,6 +565,89 @@ test("cloud web OpenCode proxy requires an authenticated HWLAB session", async (
|
||||
}
|
||||
});
|
||||
|
||||
test("cloud web OpenCode frame-url endpoint mints traced tickets", async () => {
|
||||
const restoreEnv = withEnv({
|
||||
HWLAB_CLOUD_WEB_DISPLAY_TIME_ZONE: "Asia/Shanghai",
|
||||
HWLAB_CLOUD_WEB_DISPLAY_TIME_LOCALE: "zh-CN",
|
||||
HWLAB_CLOUD_WEB_DISPLAY_TIME_LABEL: "北京时间",
|
||||
HWLAB_CLOUD_WEB_OPENCODE_URL: "https://opencode.example.test"
|
||||
});
|
||||
const cloudApiRequests = [];
|
||||
const opencodeRequests = [];
|
||||
const cloudApi = createServer((request, response) => {
|
||||
cloudApiRequests.push({
|
||||
cookie: request.headers.cookie,
|
||||
traceparent: request.headers.traceparent,
|
||||
otelTraceId: request.headers["x-hwlab-otel-trace-id"],
|
||||
requestId: request.headers["x-request-id"],
|
||||
sourceServiceId: request.headers["x-source-service-id"]
|
||||
});
|
||||
request.resume();
|
||||
response.writeHead(200, { "content-type": "application/json" });
|
||||
response.end(JSON.stringify({ authenticated: request.headers.cookie === "hwlab_session=session-a" }));
|
||||
});
|
||||
const opencode = createServer((request, response) => {
|
||||
opencodeRequests.push({ url: request.url, cookie: request.headers.cookie });
|
||||
request.resume();
|
||||
response.writeHead(200, { "content-type": "text/plain" });
|
||||
response.end("opencode ok\n");
|
||||
});
|
||||
await listen(cloudApi);
|
||||
await listen(opencode);
|
||||
|
||||
const cloudWeb = createCloudWebServer({
|
||||
serviceId: "hwlab-cloud-web",
|
||||
roots: [],
|
||||
cloudApiBaseUrl: serverUrl(cloudApi),
|
||||
cloudApiProxyTimeoutMs: 1000,
|
||||
opencodeUpstreamUrl: serverUrl(opencode),
|
||||
opencodeProxyHost: "",
|
||||
opencodeProxyTimeoutMs: 1000,
|
||||
opencodeUsername: "oc_user",
|
||||
opencodePassword: "oc_password",
|
||||
healthPayload: () => ({ status: "ok" }),
|
||||
sendJson(response, statusCode, body) {
|
||||
const payload = JSON.stringify(body);
|
||||
response.writeHead(statusCode, { "content-type": "application/json", "content-length": Buffer.byteLength(payload) });
|
||||
response.end(payload);
|
||||
}
|
||||
});
|
||||
await listen(cloudWeb);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${serverUrl(cloudWeb)}/opencode/frame-url`, {
|
||||
headers: { accept: "application/json", cookie: "hwlab_session=session-a", "x-request-id": "req_opencode_frame_url" }
|
||||
});
|
||||
assert.equal(response.status, 200);
|
||||
assert.equal(response.headers.get("x-request-id"), "req_opencode_frame_url");
|
||||
assert.match(response.headers.get("traceparent") ?? "", /^00-[0-9a-f]{32}-[0-9a-f]{16}-01$/u);
|
||||
const body = await response.json();
|
||||
const frameUrl = new URL(body.url);
|
||||
const ticket = frameUrl.searchParams.get("hwlab_opencode_ticket");
|
||||
assert.ok(ticket, "dynamic endpoint should append an OpenCode ticket");
|
||||
assert.equal(body.diagnostic.traceId, response.headers.get("x-hwlab-otel-trace-id"));
|
||||
assert.deepEqual(cloudApiRequests, [{
|
||||
cookie: "hwlab_session=session-a",
|
||||
traceparent: response.headers.get("traceparent"),
|
||||
otelTraceId: response.headers.get("x-hwlab-otel-trace-id"),
|
||||
requestId: "req_opencode_frame_url",
|
||||
sourceServiceId: "hwlab-cloud-web"
|
||||
}]);
|
||||
|
||||
const proxied = await fetch(`${serverUrl(cloudWeb)}/_opencode/?hwlab_opencode_ticket=${encodeURIComponent(ticket)}`, {
|
||||
headers: { accept: "text/plain" }
|
||||
});
|
||||
assert.equal(proxied.status, 200);
|
||||
assert.equal(await proxied.text(), "opencode ok\n");
|
||||
assert.deepEqual(opencodeRequests, [{ url: "/", cookie: undefined }]);
|
||||
} finally {
|
||||
restoreEnv();
|
||||
await close(cloudWeb);
|
||||
await close(opencode);
|
||||
await close(cloudApi);
|
||||
}
|
||||
});
|
||||
|
||||
test("cloud web OpenCode proxy injects upstream Basic Auth without forwarding HWLAB cookie", async () => {
|
||||
const opencodeRequests = [];
|
||||
const cloudApi = createServer((request, response) => {
|
||||
|
||||
Reference in New Issue
Block a user