refactor: share gateway auth and approval helpers

This commit is contained in:
Peter Steinberger
2026-04-06 07:40:16 +01:00
parent 1d8d2ddaa1
commit bb01e49192
31 changed files with 1768 additions and 1347 deletions

View File

@@ -1,8 +1,7 @@
import type { OpenClawConfig } from "../../config/config.js";
import { resolveSecretInputRef } from "../../config/types.secrets.js";
import { createGatewayCredentialPlan, trimToUndefined } from "../../gateway/credential-planner.js";
import { resolveGatewayAuthToken } from "../../gateway/auth-token-resolution.js";
import { createGatewayCredentialPlan } from "../../gateway/credential-planner.js";
import { GatewaySecretRefUnavailableError } from "../../gateway/credentials.js";
import { resolveConfiguredSecretInputString } from "../../gateway/resolve-configured-secret-input-string.js";
function authModeDisablesToken(mode: string | undefined): boolean {
return mode === "password" || mode === "none" || mode === "trusted-proxy";
@@ -35,24 +34,17 @@ export async function resolveGatewayTokenForDriftCheck(params: {
return undefined;
}
const tokenInput = params.cfg.gateway?.auth?.token;
const tokenRef = resolveSecretInputRef({
value: tokenInput,
defaults: params.cfg.secrets?.defaults,
}).ref;
if (!tokenRef) {
return trimToUndefined(tokenInput);
}
const resolved = await resolveConfiguredSecretInputString({
config: params.cfg,
const resolved = await resolveGatewayAuthToken({
cfg: params.cfg,
env,
value: tokenInput,
path: "gateway.auth.token",
envFallback: "never",
unresolvedReasonStyle: "detailed",
});
if (resolved.value) {
return resolved.value;
if (resolved.token) {
return resolved.token;
}
if (!resolved.secretRefConfigured) {
return undefined;
}
throw new GatewaySecretRefUnavailableError("gateway.auth.token");
}

View File

@@ -15,11 +15,7 @@ import type { FindExtraGatewayServicesOptions } from "../../daemon/inspect.js";
import type { ServiceConfigAudit } from "../../daemon/service-audit.js";
import type { GatewayServiceRuntime } from "../../daemon/service-runtime.js";
import { resolveGatewayService } from "../../daemon/service.js";
import {
isGatewaySecretRefUnavailableError,
resolveGatewayProbeCredentialsFromConfig,
trimToUndefined,
} from "../../gateway/credentials.js";
import { trimToUndefined } from "../../gateway/credentials.js";
import {
inspectBestEffortPrimaryTailnetIPv4,
resolveBestEffortGatewayBindHostForDisplay,
@@ -190,10 +186,6 @@ function shouldReportPortUsage(status: PortUsageStatus | undefined, rpcOk?: bool
return true;
}
function parseGatewaySecretRefPathFromError(error: unknown): string | null {
return isGatewaySecretRefUnavailableError(error) ? error.path : null;
}
async function loadDaemonConfigContext(
serviceEnv?: Record<string, string>,
): Promise<DaemonConfigContext> {
@@ -408,43 +400,20 @@ export async function gatherDaemonStatus(
let rpcAuthWarning: string | undefined;
if (opts.probe) {
const probeMode = daemonCfg.gateway?.mode === "remote" ? "remote" : "local";
try {
daemonProbeAuth = resolveGatewayProbeCredentialsFromConfig({
cfg: daemonCfg,
mode: probeMode,
env: mergedDaemonEnv as NodeJS.ProcessEnv,
explicitAuth: {
token: opts.rpc.token,
password: opts.rpc.password,
},
});
} catch (error) {
const refPath = parseGatewaySecretRefPathFromError(error);
if (!refPath) {
throw error;
}
try {
daemonProbeAuth = await loadGatewayProbeAuthModule().then(
({ resolveGatewayProbeAuthWithSecretInputs }) =>
resolveGatewayProbeAuthWithSecretInputs({
cfg: daemonCfg,
mode: probeMode,
env: mergedDaemonEnv as NodeJS.ProcessEnv,
explicitAuth: {
token: opts.rpc.token,
password: opts.rpc.password,
},
}),
);
} catch (fallbackError) {
const fallbackRefPath = parseGatewaySecretRefPathFromError(fallbackError);
if (!fallbackRefPath) {
throw fallbackError;
}
daemonProbeAuth = undefined;
rpcAuthWarning = `${fallbackRefPath} SecretRef is unavailable in this command path; probing without configured auth credentials.`;
}
}
const probeAuthResolution = await loadGatewayProbeAuthModule().then(
({ resolveGatewayProbeAuthSafeWithSecretInputs }) =>
resolveGatewayProbeAuthSafeWithSecretInputs({
cfg: daemonCfg,
mode: probeMode,
env: mergedDaemonEnv as NodeJS.ProcessEnv,
explicitAuth: {
token: opts.rpc.token,
password: opts.rpc.password,
},
}),
);
daemonProbeAuth = probeAuthResolution.auth;
rpcAuthWarning = probeAuthResolution.warning;
}
const rpc = opts.probe