refactor: unify gateway SecretRef auth resolution paths

This commit is contained in:
Peter Steinberger
2026-03-07 21:32:42 +00:00
parent 5f26970200
commit fecca6fd8d
9 changed files with 318 additions and 189 deletions

View File

@@ -1,12 +1,10 @@
import { readConfigFileSnapshot, resolveGatewayPort } from "../config/config.js";
import type { OpenClawConfig } from "../config/types.js";
import { resolveSecretInputRef } from "../config/types.secrets.js";
import { readGatewayTokenEnv } from "../gateway/credentials.js";
import { resolveConfiguredSecretInputWithFallback } from "../gateway/resolve-configured-secret-input-string.js";
import { copyToClipboard } from "../infra/clipboard.js";
import type { RuntimeEnv } from "../runtime.js";
import { defaultRuntime } from "../runtime.js";
import { secretRefKey } from "../secrets/ref-contract.js";
import { resolveSecretRefValues } from "../secrets/resolve.js";
import {
detectBrowserOpenSupport,
formatControlUiSshHint,
@@ -27,49 +25,26 @@ async function resolveDashboardToken(
unresolvedRefReason?: string;
tokenSecretRefConfigured: boolean;
}> {
const { ref } = resolveSecretInputRef({
const resolved = await resolveConfiguredSecretInputWithFallback({
config: cfg,
env,
value: cfg.gateway?.auth?.token,
defaults: cfg.secrets?.defaults,
path: "gateway.auth.token",
readFallback: () => readGatewayTokenEnv(env),
});
const configToken =
ref || typeof cfg.gateway?.auth?.token !== "string"
? undefined
: cfg.gateway.auth.token.trim() || undefined;
if (configToken) {
return { token: configToken, source: "config", tokenSecretRefConfigured: false };
}
if (!ref) {
const envToken = readGatewayTokenEnv(env);
return envToken
? { token: envToken, source: "env", tokenSecretRefConfigured: false }
: { tokenSecretRefConfigured: false };
}
const refLabel = `${ref.source}:${ref.provider}:${ref.id}`;
try {
const resolved = await resolveSecretRefValues([ref], {
config: cfg,
env,
});
const value = resolved.get(secretRefKey(ref));
if (typeof value === "string" && value.trim().length > 0) {
return { token: value.trim(), source: "secretRef", tokenSecretRefConfigured: true };
}
const envToken = readGatewayTokenEnv(env);
return envToken
? { token: envToken, source: "env", tokenSecretRefConfigured: true }
: {
unresolvedRefReason: `gateway.auth.token SecretRef is unresolved (${refLabel}).`,
tokenSecretRefConfigured: true,
};
} catch {
const envToken = readGatewayTokenEnv(env);
return envToken
? { token: envToken, source: "env", tokenSecretRefConfigured: true }
: {
unresolvedRefReason: `gateway.auth.token SecretRef is unresolved (${refLabel}).`,
tokenSecretRefConfigured: true,
};
}
return {
token: resolved.value,
source:
resolved.source === "config"
? "config"
: resolved.source === "secretRef"
? "secretRef"
: resolved.source === "fallback"
? "env"
: undefined,
unresolvedRefReason: resolved.unresolvedRefReason,
tokenSecretRefConfigured: resolved.secretRefConfigured,
};
}
export async function dashboardCommand(

View File

@@ -1,49 +1,30 @@
import type { OpenClawConfig } from "../config/config.js";
import { resolveSecretInputRef } from "../config/types.secrets.js";
export { shouldRequireGatewayTokenForInstall } from "../gateway/auth-install-policy.js";
import { readGatewayTokenEnv } from "../gateway/credentials.js";
import { secretRefKey } from "../secrets/ref-contract.js";
import { resolveSecretRefValues } from "../secrets/resolve.js";
import { resolveConfiguredSecretInputWithFallback } from "../gateway/resolve-configured-secret-input-string.js";
export async function resolveGatewayAuthTokenForService(
cfg: OpenClawConfig,
env: NodeJS.ProcessEnv,
): Promise<{ token?: string; unavailableReason?: string }> {
const { ref } = resolveSecretInputRef({
const resolved = await resolveConfiguredSecretInputWithFallback({
config: cfg,
env,
value: cfg.gateway?.auth?.token,
defaults: cfg.secrets?.defaults,
path: "gateway.auth.token",
unresolvedReasonStyle: "detailed",
readFallback: () => readGatewayTokenEnv(env),
});
const configToken =
ref || typeof cfg.gateway?.auth?.token !== "string"
? undefined
: cfg.gateway.auth.token.trim() || undefined;
if (configToken) {
return { token: configToken };
if (resolved.value) {
return { token: resolved.value };
}
if (ref) {
try {
const resolved = await resolveSecretRefValues([ref], {
config: cfg,
env,
});
const value = resolved.get(secretRefKey(ref));
if (typeof value === "string" && value.trim().length > 0) {
return { token: value.trim() };
}
const envToken = readGatewayTokenEnv(env);
if (envToken) {
return { token: envToken };
}
return { unavailableReason: "gateway.auth.token SecretRef resolved to an empty value." };
} catch (err) {
const envToken = readGatewayTokenEnv(env);
if (envToken) {
return { token: envToken };
}
return {
unavailableReason: `gateway.auth.token SecretRef is configured but unresolved (${String(err)}).`,
};
}
if (!resolved.secretRefConfigured) {
return {};
}
return { token: readGatewayTokenEnv(env) };
if (resolved.unresolvedRefReason?.includes("resolved to an empty value")) {
return { unavailableReason: resolved.unresolvedRefReason };
}
return {
unavailableReason: `gateway.auth.token SecretRef is configured but unresolved (${resolved.unresolvedRefReason ?? "unknown reason"}).`,
};
}