mirror of https://github.com/openclaw/openclaw.git
fix(gateway): pass process.env in status command probe auth to resolve SecretRef
Fixes #52360 resolveGatewayProbeAuthSafe was called from status-all.ts without an env argument, causing the credential resolution chain to fall back to an empty object instead of process.env. This made env-backed SecretRef tokens (gateway.auth.token, Telegram botToken, etc.) appear unresolved in the status command path even when the runtime was healthy. Added process.env as default fallback in buildGatewayProbeCredentialPolicy and passed env explicitly from status-all.ts callers. Related: #33070, #38973, #39415, #46014, #49730
This commit is contained in:
parent
042669d8c8
commit
3595ecba45
|
|
@ -14,7 +14,7 @@ import type { GatewayService } from "../daemon/service.js";
|
|||
import { resolveGatewayService } from "../daemon/service.js";
|
||||
import { buildGatewayConnectionDetails, callGateway } from "../gateway/call.js";
|
||||
import { normalizeControlUiBasePath } from "../gateway/control-ui-shared.js";
|
||||
import { resolveGatewayProbeAuthSafe } from "../gateway/probe-auth.js";
|
||||
import { resolveGatewayProbeAuthSafeWithSecretInputs } from "../gateway/probe-auth.js";
|
||||
import { probeGateway } from "../gateway/probe.js";
|
||||
import { collectChannelStatusIssues } from "../infra/channels-status-issues.js";
|
||||
import { resolveOpenClawPackageRoot } from "../infra/openclaw-root.js";
|
||||
|
|
@ -124,8 +124,16 @@ export async function statusAllCommand(
|
|||
const remoteUrlMissing = isRemoteMode && !remoteUrlRaw;
|
||||
const gatewayMode = isRemoteMode ? "remote" : "local";
|
||||
|
||||
const localProbeAuthResolution = resolveGatewayProbeAuthSafe({ cfg, mode: "local" });
|
||||
const remoteProbeAuthResolution = resolveGatewayProbeAuthSafe({ cfg, mode: "remote" });
|
||||
const localProbeAuthResolution = await resolveGatewayProbeAuthSafeWithSecretInputs({
|
||||
cfg,
|
||||
mode: "local",
|
||||
env: process.env,
|
||||
});
|
||||
const remoteProbeAuthResolution = await resolveGatewayProbeAuthSafeWithSecretInputs({
|
||||
cfg,
|
||||
mode: "remote",
|
||||
env: process.env,
|
||||
});
|
||||
const probeAuthResolution =
|
||||
isRemoteMode && !remoteUrlMissing ? remoteProbeAuthResolution : localProbeAuthResolution;
|
||||
const probeAuth = probeAuthResolution.auth;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest";
|
|||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import {
|
||||
resolveGatewayProbeAuthSafe,
|
||||
resolveGatewayProbeAuthSafeWithSecretInputs,
|
||||
resolveGatewayProbeAuthWithSecretInputs,
|
||||
} from "./probe-auth.js";
|
||||
|
||||
|
|
@ -107,6 +108,60 @@ describe("resolveGatewayProbeAuthSafe", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("resolveGatewayProbeAuthSafeWithSecretInputs", () => {
|
||||
it("resolves env SecretRef token via async secret-inputs path", async () => {
|
||||
const result = await resolveGatewayProbeAuthSafeWithSecretInputs({
|
||||
cfg: {
|
||||
gateway: {
|
||||
auth: {
|
||||
mode: "token",
|
||||
token: { source: "env", provider: "default", id: "OPENCLAW_GATEWAY_TOKEN" },
|
||||
},
|
||||
},
|
||||
secrets: {
|
||||
providers: {
|
||||
default: { source: "env" },
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
mode: "local",
|
||||
env: {
|
||||
OPENCLAW_GATEWAY_TOKEN: "test-token-from-env",
|
||||
} as NodeJS.ProcessEnv,
|
||||
});
|
||||
|
||||
expect(result.warning).toBeUndefined();
|
||||
expect(result.auth).toEqual({
|
||||
token: "test-token-from-env",
|
||||
password: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it("returns warning and empty auth when SecretRef cannot be resolved via async path", async () => {
|
||||
const result = await resolveGatewayProbeAuthSafeWithSecretInputs({
|
||||
cfg: {
|
||||
gateway: {
|
||||
auth: {
|
||||
mode: "token",
|
||||
token: { source: "env", provider: "default", id: "MISSING_TOKEN_XYZ" },
|
||||
},
|
||||
},
|
||||
secrets: {
|
||||
providers: {
|
||||
default: { source: "env" },
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
mode: "local",
|
||||
env: {} as NodeJS.ProcessEnv,
|
||||
});
|
||||
|
||||
expect(result.auth).toEqual({});
|
||||
expect(result.warning).toContain("gateway.auth.token");
|
||||
expect(result.warning).toContain("unresolved");
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveGatewayProbeAuthWithSecretInputs", () => {
|
||||
it("resolves local probe SecretRef values before shared credential selection", async () => {
|
||||
const auth = await resolveGatewayProbeAuthWithSecretInputs({
|
||||
|
|
|
|||
|
|
@ -50,6 +50,40 @@ export async function resolveGatewayProbeAuthWithSecretInputs(params: {
|
|||
});
|
||||
}
|
||||
|
||||
export async function resolveGatewayProbeAuthSafeWithSecretInputs(params: {
|
||||
cfg: OpenClawConfig;
|
||||
mode: "local" | "remote";
|
||||
env?: NodeJS.ProcessEnv;
|
||||
explicitAuth?: ExplicitGatewayAuth;
|
||||
}): Promise<{
|
||||
auth: { token?: string; password?: string };
|
||||
warning?: string;
|
||||
}> {
|
||||
const explicitToken = params.explicitAuth?.token?.trim();
|
||||
const explicitPassword = params.explicitAuth?.password?.trim();
|
||||
if (explicitToken || explicitPassword) {
|
||||
return {
|
||||
auth: {
|
||||
...(explicitToken ? { token: explicitToken } : {}),
|
||||
...(explicitPassword ? { password: explicitPassword } : {}),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const auth = await resolveGatewayProbeAuthWithSecretInputs(params);
|
||||
return { auth };
|
||||
} catch (error) {
|
||||
if (!isGatewaySecretRefUnavailableError(error)) {
|
||||
throw error;
|
||||
}
|
||||
return {
|
||||
auth: {},
|
||||
warning: `${error.path} SecretRef is unresolved in this command path; probing without configured auth credentials.`,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveGatewayProbeAuthSafe(params: {
|
||||
cfg: OpenClawConfig;
|
||||
mode: "local" | "remote";
|
||||
|
|
|
|||
Loading…
Reference in New Issue