openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
135 lines (134 loc) • 5.99 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs";
import { g as resolveSecretInputRef, o as hasConfiguredSecretInput } from "./types.secrets-DsPRn9Dz.mjs";
import { t as formatCliCommand } from "./command-format-DwEdrDKL.mjs";
import { i as assertGatewayServiceUpdateCurrent, o as isUpdateOwnedGatewayServiceCommand } from "./service-update-authority-CoX8GMUL.mjs";
import { S as isUnsafeGatewayTailscaleNoAuth, x as formatUnsafeGatewayTailscaleNoAuthMessage } from "./validation-core-C5DCruFP.mjs";
import { r as replaceConfigFile } from "./mutate-DJq1JylX.mjs";
import { O as collectDurableServiceEnvVars } from "./systemd-service-files-Cc5QKjzs.mjs";
import { r as resolveGatewayAuth } from "./auth-resolve-BmUDP1m_.mjs";
import { t as randomToken } from "./random-token-Sl4a6KEQ.mjs";
import { n as hasAmbiguousGatewayAuthModeConfig } from "./auth-mode-policy-DzNSJi11.mjs";
import "./auth-BfNXsaOg.mjs";
import { t as resolveGatewayAuthToken } from "./auth-token-resolution-B9VLhqWq.mjs";
//#region src/gateway/auth-install-policy.ts
/** Decide whether install should require token auth when no durable password source exists. */
function shouldRequireGatewayTokenForInstall(cfg, env) {
switch (cfg.gateway?.auth?.mode) {
case "token": return true;
case "password":
case "none":
case "trusted-proxy": return false;
case void 0:
}
if (hasConfiguredSecretInput(cfg.gateway?.auth?.password, cfg.secrets?.defaults)) return false;
const durableServiceEnv = collectDurableServiceEnvVars({
env,
config: cfg
});
return !(normalizeOptionalString(durableServiceEnv.OPENCLAW_GATEWAY_PASSWORD) || normalizeOptionalString(durableServiceEnv.CLAWDBOT_GATEWAY_PASSWORD));
}
//#endregion
//#region src/commands/gateway-install-token.ts
async function maybePersistAutoGeneratedGatewayInstallToken(params) {
try {
const { snapshot, writeOptions } = params.generation;
if (snapshot.exists && !snapshot.valid) {
params.warnings.push("Warning: config file exists but is invalid; skipping token persistence.");
return;
}
const baseConfig = snapshot.exists ? snapshot.sourceConfig ?? snapshot.config : {};
const existingTokenRef = resolveSecretInputRef({
value: baseConfig.gateway?.auth?.token,
defaults: baseConfig.secrets?.defaults
}).ref;
const baseConfigToken = existingTokenRef || typeof baseConfig.gateway?.auth?.token !== "string" ? void 0 : normalizeOptionalString(baseConfig.gateway.auth.token);
if (!existingTokenRef && !baseConfigToken) {
await replaceConfigFile({
sourceConfig: {
...baseConfig,
gateway: {
...baseConfig.gateway,
auth: {
...baseConfig.gateway?.auth,
mode: baseConfig.gateway?.auth?.mode ?? "token",
token: params.token
}
}
},
snapshot,
writeOptions: {
baseSnapshot: snapshot,
...writeOptions,
...isUpdateOwnedGatewayServiceCommand() ? { assertCurrent: () => {
writeOptions.assertCurrent?.();
assertGatewayServiceUpdateCurrent();
} } : {},
skipRuntimeSnapshotRefresh: true
},
afterWrite: { mode: "auto" }
});
return;
}
if (baseConfigToken) return;
params.warnings.push("Warning: gateway.auth.token is SecretRef-managed; skipping plaintext token persistence.");
} catch (err) {
params.warnings.push(`Warning: could not persist token to config: ${String(err)}`);
}
}
function formatAmbiguousGatewayAuthModeReason() {
return ["gateway.auth.token and gateway.auth.password are both configured while gateway.auth.mode is unset.", `Set ${formatCliCommand("openclaw config set gateway.auth.mode token")} or ${formatCliCommand("openclaw config set gateway.auth.mode password")}.`].join(" ");
}
/** Validate install auth, using the caller's captured write preparation for token generation. */
async function resolveGatewayInstallToken(options) {
const cfg = options.config;
const warnings = [];
if (hasAmbiguousGatewayAuthModeConfig(cfg)) return {
unavailableReason: formatAmbiguousGatewayAuthModeReason(),
warnings
};
const resolvedAuth = resolveGatewayAuth({
authConfig: cfg.gateway?.auth,
env: options.env,
tailscaleMode: cfg.gateway?.tailscale?.mode ?? "off"
});
const tailscaleMode = cfg.gateway?.tailscale?.mode ?? "off";
if (isUnsafeGatewayTailscaleNoAuth({
authMode: resolvedAuth.mode,
tailscaleMode
})) return {
unavailableReason: formatUnsafeGatewayTailscaleNoAuthMessage(tailscaleMode),
warnings
};
if (!(shouldRequireGatewayTokenForInstall(cfg, options.env) && !resolvedAuth.allowTailscale)) return {
unavailableReason: void 0,
warnings
};
const resolvedToken = await resolveGatewayAuthToken({
cfg,
env: options.env,
explicitToken: options.explicitToken,
envFallback: "no-secret-ref",
unresolvedReasonStyle: "detailed"
});
const tokenRefConfigured = resolvedToken.secretRefConfigured;
const token = resolvedToken.source === "secretRef" ? void 0 : resolvedToken.token;
let unavailableReason;
if (tokenRefConfigured && resolvedToken.source === "secretRef") warnings.push("gateway.auth.token is SecretRef-managed; install will not persist a resolved token in service environment. Ensure the SecretRef is resolvable in the daemon runtime context.");
else if (tokenRefConfigured && !token) unavailableReason = `gateway.auth.token SecretRef is configured but unresolved (${resolvedToken.unresolvedRefReason ?? "unknown reason"}).`;
if (!token && !tokenRefConfigured && options.requireExisting) unavailableReason = "Deferred service load requires an existing Gateway token.";
else if (!token && !tokenRefConfigured && options.generateIfMissing) {
const generatedToken = randomToken();
warnings.push("No gateway token found. Auto-generated one and saving to config.");
await maybePersistAutoGeneratedGatewayInstallToken({
token: generatedToken,
generation: options.generateIfMissing,
warnings
});
}
return {
unavailableReason,
warnings
};
}
//#endregion
export { resolveGatewayInstallToken as t };