mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-07 15:21:06 +00:00
Gateway: avoid secret-ref auth disconnect churn
This commit is contained in:
committed by
Peter Steinberger
parent
97558f2325
commit
c742963fd9
@@ -1,4 +1,5 @@
|
||||
import { execFile } from "node:child_process";
|
||||
import { isDeepStrictEqual } from "node:util";
|
||||
import {
|
||||
createConfigIO,
|
||||
parseConfigJson5,
|
||||
@@ -225,8 +226,8 @@ function didSharedGatewayAuthChange(prev: OpenClawConfig, next: OpenClawConfig):
|
||||
const nextAuth = next.gateway?.auth;
|
||||
return (
|
||||
prevAuth?.mode !== nextAuth?.mode ||
|
||||
prevAuth?.token !== nextAuth?.token ||
|
||||
prevAuth?.password !== nextAuth?.password
|
||||
!isDeepStrictEqual(prevAuth?.token, nextAuth?.token) ||
|
||||
!isDeepStrictEqual(prevAuth?.password, nextAuth?.password)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,11 @@ import {
|
||||
installGatewayTestHooks({ scope: "suite" });
|
||||
|
||||
const ORIGINAL_GATEWAY_AUTH = testState.gatewayAuth;
|
||||
const ORIGINAL_GATEWAY_TOKEN_ENV = process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
const OLD_TOKEN = "shared-token-old";
|
||||
const NEW_TOKEN = "shared-token-new";
|
||||
const TEST_METHODS = ["config.set", "config.patch", "config.apply"] as const;
|
||||
const SECRET_REF_TOKEN_ID = "OPENCLAW_SHARED_AUTH_ROTATION_SECRET_REF";
|
||||
|
||||
let server: Awaited<ReturnType<typeof startGatewayServer>>;
|
||||
let port = 0;
|
||||
@@ -30,6 +32,11 @@ beforeAll(async () => {
|
||||
|
||||
afterAll(async () => {
|
||||
testState.gatewayAuth = ORIGINAL_GATEWAY_AUTH;
|
||||
if (ORIGINAL_GATEWAY_TOKEN_ENV === undefined) {
|
||||
delete process.env.OPENCLAW_GATEWAY_TOKEN;
|
||||
} else {
|
||||
process.env.OPENCLAW_GATEWAY_TOKEN = ORIGINAL_GATEWAY_TOKEN_ENV;
|
||||
}
|
||||
await server.close();
|
||||
});
|
||||
|
||||
@@ -149,3 +156,58 @@ describe("gateway shared auth rotation", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("gateway shared auth rotation with unchanged SecretRefs", () => {
|
||||
let secretRefServer: Awaited<ReturnType<typeof startGatewayServer>>;
|
||||
let secretRefPort = 0;
|
||||
|
||||
beforeAll(async () => {
|
||||
secretRefPort = await getFreePort();
|
||||
process.env[SECRET_REF_TOKEN_ID] = OLD_TOKEN;
|
||||
testState.gatewayAuth = {
|
||||
mode: "token",
|
||||
token: { source: "env", provider: "default", id: SECRET_REF_TOKEN_ID },
|
||||
};
|
||||
secretRefServer = await startGatewayServer(secretRefPort, { controlUiEnabled: true });
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
delete process.env[SECRET_REF_TOKEN_ID];
|
||||
testState.gatewayAuth = ORIGINAL_GATEWAY_AUTH;
|
||||
await secretRefServer.close();
|
||||
});
|
||||
|
||||
async function openSecretRefAuthenticatedWs(): Promise<WebSocket> {
|
||||
const ws = new WebSocket(`ws://127.0.0.1:${secretRefPort}`);
|
||||
trackConnectChallengeNonce(ws);
|
||||
await new Promise<void>((resolve) => ws.once("open", resolve));
|
||||
await connectOk(ws, { token: OLD_TOKEN });
|
||||
return ws;
|
||||
}
|
||||
|
||||
for (const method of ["config.set", "config.apply"] as const) {
|
||||
it(`keeps shared-auth websocket sessions connected when ${method} reapplies an unchanged SecretRef token`, async () => {
|
||||
const ws = await openSecretRefAuthenticatedWs();
|
||||
try {
|
||||
const current = await rpcReq<{
|
||||
hash?: string;
|
||||
config?: Record<string, unknown>;
|
||||
}>(ws, "config.get", {});
|
||||
expect(current.ok).toBe(true);
|
||||
expect(typeof current.payload?.hash).toBe("string");
|
||||
|
||||
const res = await rpcReq(ws, method, {
|
||||
raw: JSON.stringify(current.payload?.config ?? {}, null, 2),
|
||||
...(method === "config.set" ? { baseHash: current.payload?.hash } : {}),
|
||||
});
|
||||
expect(res.ok).toBe(true);
|
||||
|
||||
const followUp = await rpcReq<{ hash?: string }>(ws, "config.get", {});
|
||||
expect(followUp.ok).toBe(true);
|
||||
expect(typeof followUp.payload?.hash).toBe("string");
|
||||
} finally {
|
||||
ws.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user