mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-24 07:09:50 +00:00
327 lines
8.1 KiB
TypeScript
327 lines
8.1 KiB
TypeScript
import { NON_ENV_SECRETREF_MARKER } from "openclaw/plugin-sdk/provider-auth-runtime";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import {
|
|
isXaiToolEnabled,
|
|
resolveFallbackXaiAuth,
|
|
resolveFallbackXaiApiKey,
|
|
resolveXaiToolApiKey,
|
|
resolveXaiToolApiKeyWithAuth,
|
|
} from "./tool-auth-shared.js";
|
|
|
|
describe("xai tool auth helpers", () => {
|
|
afterEach(() => {
|
|
vi.unstubAllEnvs();
|
|
});
|
|
|
|
it("prefers plugin web search keys over legacy grok keys", () => {
|
|
expect(
|
|
resolveFallbackXaiApiKey({
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: "plugin-key", // pragma: allowlist secret
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
tools: {
|
|
web: {
|
|
search: {
|
|
grok: {
|
|
apiKey: "legacy-key", // pragma: allowlist secret
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toBe("plugin-key");
|
|
});
|
|
|
|
it("returns source metadata and managed markers for fallback auth", () => {
|
|
expect(
|
|
resolveFallbackXaiAuth({
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: { source: "file", provider: "vault", id: "/xai/tool-key" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toEqual({
|
|
apiKey: NON_ENV_SECRETREF_MARKER,
|
|
source: "plugins.entries.xai.config.webSearch.apiKey",
|
|
});
|
|
|
|
expect(
|
|
resolveFallbackXaiAuth({
|
|
tools: {
|
|
web: {
|
|
search: {
|
|
grok: {
|
|
apiKey: "legacy-key", // pragma: allowlist secret
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toEqual({
|
|
apiKey: "legacy-key",
|
|
source: "tools.web.search.grok.apiKey",
|
|
});
|
|
});
|
|
|
|
it("falls back to runtime, then source config, then env for tool auth", () => {
|
|
vi.stubEnv("XAI_API_KEY", "env-key");
|
|
|
|
expect(
|
|
resolveXaiToolApiKey({
|
|
runtimeConfig: {
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: "runtime-key", // pragma: allowlist secret
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
sourceConfig: {
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: "source-key", // pragma: allowlist secret
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toBe("runtime-key");
|
|
|
|
expect(
|
|
resolveXaiToolApiKey({
|
|
sourceConfig: {
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: "source-key", // pragma: allowlist secret
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toBe("source-key");
|
|
|
|
expect(resolveXaiToolApiKey({})).toBe("env-key");
|
|
});
|
|
|
|
it("honors explicit disabled flags before auth fallback", () => {
|
|
vi.stubEnv("XAI_API_KEY", "env-key");
|
|
expect(isXaiToolEnabled({ enabled: false })).toBe(false);
|
|
expect(isXaiToolEnabled({ enabled: true })).toBe(true);
|
|
});
|
|
|
|
it("uses xAI auth profiles when tool config and env are absent", async () => {
|
|
const auth = {
|
|
hasAuthForProvider: (providerId: string) => providerId === "xai",
|
|
resolveApiKeyForProvider: async (providerId: string) =>
|
|
providerId === "xai" ? "profile-key" : undefined, // pragma: allowlist secret
|
|
};
|
|
|
|
expect(isXaiToolEnabled({ auth })).toBe(true);
|
|
await expect(resolveXaiToolApiKeyWithAuth({ auth })).resolves.toBe("profile-key");
|
|
});
|
|
|
|
it("does not use env fallback when a non-env SecretRef is configured but unavailable", () => {
|
|
vi.stubEnv("XAI_API_KEY", "env-key");
|
|
|
|
expect(
|
|
resolveXaiToolApiKey({
|
|
sourceConfig: {
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: {
|
|
source: "file",
|
|
provider: "vault",
|
|
id: "/xai/tool-key",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toBeUndefined();
|
|
});
|
|
|
|
it("does not bypass blocked explicit tool config with auth profiles", async () => {
|
|
const auth = {
|
|
hasAuthForProvider: (providerId: string) => providerId === "xai",
|
|
resolveApiKeyForProvider: async () => "profile-key", // pragma: allowlist secret
|
|
};
|
|
|
|
const sourceConfig = {
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: {
|
|
source: "file",
|
|
provider: "vault",
|
|
id: "/xai/tool-key",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
expect(isXaiToolEnabled({ sourceConfig, auth })).toBe(false);
|
|
await expect(resolveXaiToolApiKeyWithAuth({ sourceConfig, auth })).resolves.toBeUndefined();
|
|
});
|
|
|
|
it("resolves env SecretRefs from source config when runtime snapshot is unavailable", () => {
|
|
vi.stubEnv("XAI_API_KEY", "xai-secretref-key");
|
|
|
|
expect(
|
|
resolveXaiToolApiKey({
|
|
sourceConfig: {
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: {
|
|
source: "env",
|
|
provider: "default",
|
|
id: "XAI_API_KEY",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toBe("xai-secretref-key");
|
|
});
|
|
|
|
it("does not read arbitrary env SecretRef ids for xAI tool auth", () => {
|
|
vi.stubEnv("UNRELATED_SECRET", "should-not-be-read");
|
|
|
|
expect(
|
|
resolveXaiToolApiKey({
|
|
sourceConfig: {
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: {
|
|
source: "env",
|
|
provider: "default",
|
|
id: "UNRELATED_SECRET",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toBeUndefined();
|
|
});
|
|
|
|
it("does not resolve env SecretRefs when provider allowlist excludes XAI_API_KEY", () => {
|
|
vi.stubEnv("XAI_API_KEY", "xai-secretref-key");
|
|
|
|
expect(
|
|
resolveXaiToolApiKey({
|
|
sourceConfig: {
|
|
secrets: {
|
|
providers: {
|
|
"xai-env": {
|
|
source: "env",
|
|
allowlist: ["OTHER_XAI_API_KEY"],
|
|
},
|
|
},
|
|
},
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: {
|
|
source: "env",
|
|
provider: "xai-env",
|
|
id: "XAI_API_KEY",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toBeUndefined();
|
|
});
|
|
|
|
it("does not resolve env SecretRefs when provider source is not env", () => {
|
|
vi.stubEnv("XAI_API_KEY", "xai-secretref-key");
|
|
|
|
expect(
|
|
resolveXaiToolApiKey({
|
|
sourceConfig: {
|
|
secrets: {
|
|
providers: {
|
|
"xai-env": {
|
|
source: "file",
|
|
path: "/tmp/secrets.json",
|
|
},
|
|
},
|
|
},
|
|
plugins: {
|
|
entries: {
|
|
xai: {
|
|
config: {
|
|
webSearch: {
|
|
apiKey: {
|
|
source: "env",
|
|
provider: "xai-env",
|
|
id: "XAI_API_KEY",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
).toBeUndefined();
|
|
});
|
|
});
|