feat: secure organization provider credentials

This commit is contained in:
2026-07-10 22:04:43 +08:00
parent e049cb6880
commit 848f913597
51 changed files with 3280 additions and 230 deletions
+10 -10
View File
@@ -11,14 +11,14 @@ describe("agent subprocess security policy", () => {
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
});
it("passes only provider and safe runtime variables and protects provider credentials from tools", async () => {
it("passes only the run proxy capability and safe runtime variables and protects the capability from tools", async () => {
const { workspaceRoot, workspace } = await makeWorkspace();
const policy = await createAgentSecurityPolicy({
workspaceRoot,
workspaceDir: workspace,
providerEnv: {
ANTHROPIC_BASE_URL: "https://openrouter.ai/api",
ANTHROPIC_AUTH_TOKEN: "provider-secret",
providerProxyEnv: {
ANTHROPIC_BASE_URL: "http://127.0.0.1:43123",
ANTHROPIC_AUTH_TOKEN: "run-proxy-capability",
ANTHROPIC_API_KEY: "",
},
hostEnv: {
@@ -37,8 +37,8 @@ describe("agent subprocess security policy", () => {
PATH: "/usr/local/bin:/usr/bin:/bin",
LANG: "C.UTF-8",
CPH_BIN: "/usr/local/bin/cph",
ANTHROPIC_BASE_URL: "https://openrouter.ai/api",
ANTHROPIC_AUTH_TOKEN: "provider-secret",
ANTHROPIC_BASE_URL: "http://127.0.0.1:43123",
ANTHROPIC_AUTH_TOKEN: "run-proxy-capability",
ANTHROPIC_API_KEY: "",
});
expect(policy.env).not.toHaveProperty("DATABASE_URL");
@@ -73,8 +73,8 @@ describe("agent subprocess security policy", () => {
await expect(createAgentSecurityPolicy({
workspaceRoot,
workspaceDir: workspace,
providerEnv: {
ANTHROPIC_AUTH_TOKEN: "provider-secret",
providerProxyEnv: {
ANTHROPIC_AUTH_TOKEN: "run-proxy-capability",
DATABASE_URL: "must-not-cross-boundary",
},
hostEnv: { PATH: "/usr/bin:/bin" },
@@ -109,7 +109,7 @@ describe("agent subprocess security policy", () => {
await expect(createAgentSecurityPolicy({
workspaceRoot,
workspaceDir: linked,
providerEnv: { ANTHROPIC_AUTH_TOKEN: "provider-secret" },
providerProxyEnv: { ANTHROPIC_AUTH_TOKEN: "run-proxy-capability" },
hostEnv: { PATH: "/usr/bin:/bin" },
})).rejects.toThrow("project workspace contains a symlink");
});
@@ -124,7 +124,7 @@ describe("agent subprocess security policy", () => {
await expect(createAgentSecurityPolicy({
workspaceRoot,
workspaceDir: linked,
providerEnv: { ANTHROPIC_AUTH_TOKEN: "provider-secret" },
providerProxyEnv: { ANTHROPIC_AUTH_TOKEN: "run-proxy-capability" },
hostEnv: { PATH: "/usr/bin:/bin" },
})).rejects.toThrow("symlink");
});
+3 -8
View File
@@ -8,9 +8,6 @@ import {
const VALID_ENV = {
NODE_ENV: "production",
DATABASE_URL: "postgresql://hub:secret@127.0.0.1:5432/hub",
ANTHROPIC_BASE_URL: "https://openrouter.ai/api",
ANTHROPIC_AUTH_TOKEN: "provider-token",
ANTHROPIC_API_KEY: "",
FEISHU_APP_ID: "cli_app_id",
FEISHU_APP_SECRET: "feishu-app-secret",
FEISHU_BOT_OPEN_ID: "ou_bot",
@@ -82,7 +79,6 @@ describe("validateDeploymentPreflight", () => {
input({
env: {
...VALID_ENV,
ANTHROPIC_AUTH_TOKEN: "",
FEISHU_APP_SECRET: "",
HUB_PUBLIC_BASE_URL: "http://hub.example.com",
HUB_SESSION_SECRET: "short",
@@ -93,7 +89,6 @@ describe("validateDeploymentPreflight", () => {
expect(error).toBeInstanceOf(DeploymentPreflightError);
expect((error as Error).message).toMatchInlineSnapshot(`
"deployment preflight failed:
- ANTHROPIC_AUTH_TOKEN is required
- FEISHU_APP_SECRET is required
- HUB_PUBLIC_BASE_URL must use https
- HUB_SESSION_SECRET must contain at least 32 characters"
@@ -107,11 +102,11 @@ describe("validateDeploymentPreflight", () => {
);
});
it("rejects a non-empty ANTHROPIC_API_KEY that would conflict with auth-token mode", () => {
it("rejects legacy process-global provider settings instead of silently ignoring them", () => {
expect(() =>
validateDeploymentPreflight(
input({ env: { ...VALID_ENV, ANTHROPIC_API_KEY: "conflicting-api-key" } }),
input({ env: { ...VALID_ENV, ANTHROPIC_AUTH_TOKEN: "global-secret" } }),
),
).toThrow("ANTHROPIC_API_KEY must be present and empty");
).toThrow("ANTHROPIC_AUTH_TOKEN must not be set");
});
});
+7 -4
View File
@@ -212,10 +212,13 @@ function mockSettings(): RuntimeSettings {
async provider(providerId) {
return {
id: providerId,
baseUrl: "https://example.invalid",
authToken: "test-token",
anthropicApiKey: "",
sdkEnv: {},
async openAgentLease() {
return {
sdkEnv: {},
sensitiveValues: [],
async close() {},
};
},
};
},
async modelRegistry() {
+156
View File
@@ -0,0 +1,156 @@
import { createServer } from "node:http";
import { once } from "node:events";
import { afterEach, describe, expect, it } from "vitest";
import { openProviderProxyLease, type AgentProviderLease } from "../../src/connections/providerProxy.js";
const leases: AgentProviderLease[] = [];
const upstreamServers: ReturnType<typeof createServer>[] = [];
afterEach(async () => {
await Promise.all(leases.splice(0).map((lease) => lease.close()));
await Promise.all(upstreamServers.splice(0).map(async (server) => {
server.closeAllConnections();
if (server.listening) {
server.close();
await once(server, "close");
}
}));
});
describe("run-scoped provider proxy", () => {
it("keeps the Organization provider credential out of the Agent environment", async () => {
const observed: Array<{ authorization: string | undefined; apiKey: string | undefined; body: string }> = [];
const upstream = createServer((request, response) => {
const chunks: Buffer[] = [];
request.on("data", (chunk: Buffer) => chunks.push(chunk));
request.on("end", () => {
observed.push({
authorization: request.headers.authorization,
apiKey: header(request.headers["x-api-key"]),
body: Buffer.concat(chunks).toString("utf8"),
});
response.writeHead(200, { "content-type": "application/json" });
response.end(JSON.stringify({ ok: true }));
});
});
upstreamServers.push(upstream);
upstream.listen(0, "127.0.0.1");
await once(upstream, "listening");
const address = upstream.address();
if (address === null || typeof address === "string") throw new Error("expected upstream TCP address");
const lease = await openProviderProxyLease({
baseUrl: `http://127.0.0.1:${address.port}/api`,
authToken: "customer-provider-auth-token",
anthropicApiKey: "customer-provider-api-key",
});
leases.push(lease);
const serializedAgentEnv = JSON.stringify(lease.sdkEnv);
expect(serializedAgentEnv).not.toContain("customer-provider-auth-token");
expect(serializedAgentEnv).not.toContain("customer-provider-api-key");
expect(serializedAgentEnv).not.toContain(String(address.port));
expect(lease.sdkEnv).toMatchObject({
ANTHROPIC_BASE_URL: expect.stringMatching(/^http:\/\/127\.0\.0\.1:\d+$/),
ANTHROPIC_AUTH_TOKEN: expect.any(String),
ANTHROPIC_API_KEY: "",
});
const response = await fetch(`${lease.sdkEnv.ANTHROPIC_BASE_URL}/v1/messages`, {
method: "POST",
headers: {
authorization: `Bearer ${lease.sdkEnv.ANTHROPIC_AUTH_TOKEN}`,
"content-type": "application/json",
"anthropic-version": "2023-06-01",
},
body: JSON.stringify({ model: "test" }),
});
expect(response.status).toBe(200);
await expect(response.json()).resolves.toEqual({ ok: true });
expect(observed).toEqual([{
authorization: "Bearer customer-provider-auth-token",
apiKey: "customer-provider-api-key",
body: JSON.stringify({ model: "test" }),
}]);
});
it("rejects requests without the run capability before contacting upstream", async () => {
let upstreamRequests = 0;
const diagnostics: unknown[] = [];
const upstream = createServer((_request, response) => {
upstreamRequests += 1;
response.end("unexpected");
});
upstreamServers.push(upstream);
upstream.listen(0, "127.0.0.1");
await once(upstream, "listening");
const address = upstream.address();
if (address === null || typeof address === "string") throw new Error("expected upstream TCP address");
const lease = await openProviderProxyLease(
{
baseUrl: `http://127.0.0.1:${address.port}`,
authToken: "customer-secret",
anthropicApiKey: "",
},
{ onDiagnostic: (diagnostic) => diagnostics.push(diagnostic) },
);
leases.push(lease);
const response = await fetch(`${lease.sdkEnv.ANTHROPIC_BASE_URL}/v1/messages`, {
method: "POST",
body: "{}",
});
expect(response.status).toBe(401);
expect(upstreamRequests).toBe(0);
expect(diagnostics).toEqual([{ code: "provider_proxy_unauthorized", category: "authorization" }]);
});
it("does not forward provider credentials across an upstream redirect", async () => {
let redirectedRequests = 0;
const diagnostics: unknown[] = [];
const redirectTarget = createServer((_request, response) => {
redirectedRequests += 1;
response.end("leaked");
});
upstreamServers.push(redirectTarget);
redirectTarget.listen(0, "127.0.0.1");
await once(redirectTarget, "listening");
const targetAddress = redirectTarget.address();
if (targetAddress === null || typeof targetAddress === "string") throw new Error("expected redirect target address");
const upstream = createServer((_request, response) => {
response.writeHead(307, { location: `http://127.0.0.1:${targetAddress.port}/capture` });
response.end();
});
upstreamServers.push(upstream);
upstream.listen(0, "127.0.0.1");
await once(upstream, "listening");
const upstreamAddress = upstream.address();
if (upstreamAddress === null || typeof upstreamAddress === "string") throw new Error("expected upstream address");
const lease = await openProviderProxyLease(
{
baseUrl: `http://127.0.0.1:${upstreamAddress.port}`,
authToken: "customer-secret",
anthropicApiKey: "",
},
{ onDiagnostic: (diagnostic) => diagnostics.push(diagnostic) },
);
leases.push(lease);
const response = await fetch(`${lease.sdkEnv.ANTHROPIC_BASE_URL}/v1/messages`, {
headers: { authorization: `Bearer ${lease.sdkEnv.ANTHROPIC_AUTH_TOKEN}` },
redirect: "manual",
});
expect(response.status).toBe(502);
await expect(response.text()).resolves.toBe("provider redirect refused");
expect(redirectedRequests).toBe(0);
expect(diagnostics).toEqual([{ code: "provider_proxy_redirect_refused", category: "redirect" }]);
});
});
function header(value: string | string[] | undefined): string | undefined {
return Array.isArray(value) ? value[0] : value;
}
+128
View File
@@ -0,0 +1,128 @@
import { createServer } from "node:http";
import { once } from "node:events";
import { afterEach, describe, expect, it } from "vitest";
import { ProviderReadinessError, probeOpenRouterCredential } from "../../src/connections/providerReadiness.js";
const servers: ReturnType<typeof createServer>[] = [];
afterEach(async () => {
await Promise.all(servers.splice(0).map(async (server) => {
server.closeAllConnections();
if (server.listening) {
server.close();
await once(server, "close");
}
}));
});
describe("provider credential readiness", () => {
it("authenticates the OpenRouter key endpoint before activation", async () => {
const requests: Array<{ url: string | undefined; authorization: string | undefined }> = [];
const server = createServer((request, response) => {
requests.push({ url: request.url, authorization: request.headers.authorization });
response.writeHead(200, { "content-type": "application/json" });
response.end('{"data":{"label":"test"}}');
});
servers.push(server);
server.listen(0, "127.0.0.1");
await once(server, "listening");
const address = server.address();
if (address === null || typeof address === "string") throw new Error("expected TCP address");
await expect(probeOpenRouterCredential({
providerId: "openrouter",
baseUrl: `http://127.0.0.1:${address.port}/api`,
authToken: "readiness-secret",
anthropicApiKey: "",
})).resolves.toBeUndefined();
expect(requests).toEqual([{
url: "/api/v1/key",
authorization: "Bearer readiness-secret",
}]);
});
it("fails closed on rejected credentials without exposing them in the error", async () => {
const server = createServer((_request, response) => {
response.writeHead(401, { "content-type": "application/json" });
response.end('{"error":"token rejected"}');
});
servers.push(server);
server.listen(0, "127.0.0.1");
await once(server, "listening");
const address = server.address();
if (address === null || typeof address === "string") throw new Error("expected TCP address");
let message = "";
try {
await probeOpenRouterCredential({
providerId: "openrouter",
baseUrl: `http://127.0.0.1:${address.port}`,
authToken: "never-return-readiness-secret",
anthropicApiKey: "",
});
} catch (error) {
message = error instanceof Error ? error.message : String(error);
}
expect(message).toBe("provider credential readiness check failed: status 401");
expect(message).not.toContain("never-return-readiness-secret");
});
it("does not follow redirects with the provider credential", async () => {
let redirected = 0;
const target = createServer((_request, response) => {
redirected += 1;
response.end("leaked");
});
servers.push(target);
target.listen(0, "127.0.0.1");
await once(target, "listening");
const targetAddress = target.address();
if (targetAddress === null || typeof targetAddress === "string") throw new Error("expected target address");
const provider = createServer((_request, response) => {
response.writeHead(307, { location: `http://127.0.0.1:${targetAddress.port}/capture` });
response.end();
});
servers.push(provider);
provider.listen(0, "127.0.0.1");
await once(provider, "listening");
const providerAddress = provider.address();
if (providerAddress === null || typeof providerAddress === "string") throw new Error("expected provider address");
await expect(probeOpenRouterCredential({
providerId: "openrouter",
baseUrl: `http://127.0.0.1:${providerAddress.port}`,
authToken: "redirect-secret",
anthropicApiKey: "",
})).rejects.toThrow("status 307");
expect(redirected).toBe(0);
});
it("preserves a redacted network category for observability", async () => {
const server = createServer();
server.listen(0, "127.0.0.1");
await once(server, "listening");
const address = server.address();
if (address === null || typeof address === "string") throw new Error("expected provider address");
server.close();
await once(server, "close");
let failure: unknown;
try {
await probeOpenRouterCredential({
providerId: "openrouter",
baseUrl: `http://127.0.0.1:${address.port}`,
authToken: "network-secret",
anthropicApiKey: "",
});
} catch (error) {
failure = error;
}
expect(failure).toBeInstanceOf(ProviderReadinessError);
expect(failure).toMatchObject({
code: "provider_readiness_unreachable",
category: "connection",
message: "provider credential readiness check could not reach provider",
});
expect(JSON.stringify(failure)).not.toContain("network-secret");
});
});
+6 -6
View File
@@ -194,7 +194,7 @@ describe("runAgent", () => {
expect(result.costUsd).toBe(0.0042);
});
it("passes only provider and safe runtime env without mutating process env", async () => {
it("passes only the loopback provider proxy capability and safe runtime env without mutating process env", async () => {
process.env["DATABASE_URL"] = "postgresql://platform-secret";
process.env["FEISHU_APP_SECRET"] = "feishu-secret";
process.env["HUB_SESSION_SECRET"] = "session-secret";
@@ -205,9 +205,9 @@ describe("runAgent", () => {
model: undefined,
project: { projectId: "p", boundChatId: "c", workspaceRoot, workspaceDir: workspace },
systemPrompt: undefined,
providerEnv: {
ANTHROPIC_BASE_URL: "https://openrouter.ai/api",
ANTHROPIC_AUTH_TOKEN: "test-token",
providerProxyEnv: {
ANTHROPIC_BASE_URL: "http://127.0.0.1:43123",
ANTHROPIC_AUTH_TOKEN: "run-proxy-capability",
ANTHROPIC_API_KEY: "",
},
runId: "run-1",
@@ -219,8 +219,8 @@ describe("runAgent", () => {
expect(call).toMatchObject({
options: {
env: {
ANTHROPIC_BASE_URL: "https://openrouter.ai/api",
ANTHROPIC_AUTH_TOKEN: "test-token",
ANTHROPIC_BASE_URL: "http://127.0.0.1:43123",
ANTHROPIC_AUTH_TOKEN: "run-proxy-capability",
ANTHROPIC_API_KEY: "",
},
sandbox: {
+4 -32
View File
@@ -15,44 +15,16 @@ describe("runtime settings", () => {
expect((await settings.modelRegistry()).resolve(undefined, "draft")).toBe("z-ai/glm-4.7");
});
it("returns provider SDK env without requiring global process env mutation", async () => {
it("refuses process-global provider credentials even when they are present", async () => {
const settings = createEnvRuntimeSettings({
ANTHROPIC_BASE_URL: "https://example.test/api",
ANTHROPIC_AUTH_TOKEN: "openrouter-token",
ANTHROPIC_API_KEY: "explicit-api-key",
});
await expect(settings.provider("openrouter")).resolves.toMatchObject({
id: "openrouter",
baseUrl: "https://example.test/api",
authToken: "openrouter-token",
anthropicApiKey: "explicit-api-key",
sdkEnv: {
ANTHROPIC_BASE_URL: "https://example.test/api",
ANTHROPIC_AUTH_TOKEN: "openrouter-token",
ANTHROPIC_API_KEY: "explicit-api-key",
},
});
});
it("defaults Anthropic API key to empty for OpenRouter's Anthropic skin", async () => {
const settings = createEnvRuntimeSettings({
ANTHROPIC_AUTH_TOKEN: "openrouter-token",
});
await expect(settings.provider("openrouter")).resolves.toMatchObject({
baseUrl: "https://openrouter.ai/api",
anthropicApiKey: "",
sdkEnv: {
ANTHROPIC_API_KEY: "",
},
});
});
it("requires an auth token for the OpenRouter provider", async () => {
const settings = createEnvRuntimeSettings({});
await expect(settings.provider("openrouter")).rejects.toThrow("missing required runtime setting: ANTHROPIC_AUTH_TOKEN");
await expect(settings.provider("openrouter")).rejects.toThrow(
"process-global provider credentials are disabled",
);
});
it("honors HUB_AGENT_MAX_TURNS as a runtime run policy", async () => {
+188
View File
@@ -0,0 +1,188 @@
import { mkdtemp, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import {
LocalSecretEnvelope,
loadLocalSecretKeyring,
type SecretBinding,
} from "../../src/security/secretEnvelope.js";
const createdDirectories: string[] = [];
afterEach(async () => {
await Promise.all(createdDirectories.splice(0).map((directory) => rm(directory, { recursive: true, force: true })));
});
describe("local secret envelope", () => {
it("encrypts with a per-secret DEK and authenticates the complete binding", async () => {
const keyring = await keyringFile({ active: key("a"), previous: key("b") }, "active");
const secrets = new LocalSecretEnvelope(await loadLocalSecretKeyring({
NODE_ENV: "test",
HUB_SECRET_KEYRING_FILE: keyring,
}));
const binding = secretBinding();
const plaintext = {
schemaVersion: 1,
baseUrl: "https://provider.example/api",
authToken: "org-a-secret-token",
anthropicApiKey: "org-a-api-key",
};
const envelope = secrets.encryptJson(binding, plaintext);
expect(envelope).toMatchObject({
version: 1,
algorithm: "AES-256-GCM",
keyId: "active",
});
expect(JSON.stringify(envelope)).not.toContain(plaintext.authToken);
expect(envelope.wrappedDek.ciphertext).not.toBe(envelope.payload.ciphertext);
expect(secrets.decryptJson(binding, envelope)).toEqual(plaintext);
});
it.each([
["organization", { organizationId: "org-b" }],
["connection", { connectionId: "connection-b" }],
["version", { secretVersionId: "secret-version-b" }],
["purpose", { purpose: "feishu-application" }],
])("rejects ciphertext substituted across %s scope", async (_label, changed) => {
const keyring = await keyringFile({ active: key("a") }, "active");
const secrets = new LocalSecretEnvelope(await loadLocalSecretKeyring({
NODE_ENV: "test",
HUB_SECRET_KEYRING_FILE: keyring,
}));
const binding = secretBinding();
const envelope = secrets.encryptJson(binding, { token: "never-log-this-token" });
expect(() => secrets.decryptJson({ ...binding, ...changed }, envelope)).toThrow(
"secret envelope authentication failed",
);
});
it("fails closed for a missing KEK or corrupted ciphertext without including plaintext", async () => {
const encryptingKeyring = await keyringFile({ encrypting: key("a") }, "encrypting");
const decryptingKeyring = await keyringFile({ other: key("b") }, "other");
const encrypting = new LocalSecretEnvelope(await loadLocalSecretKeyring({
NODE_ENV: "test",
HUB_SECRET_KEYRING_FILE: encryptingKeyring,
}));
const decrypting = new LocalSecretEnvelope(await loadLocalSecretKeyring({
NODE_ENV: "test",
HUB_SECRET_KEYRING_FILE: decryptingKeyring,
}));
const binding = secretBinding();
const envelope = encrypting.encryptJson(binding, { token: "never-log-this-token" });
expect(() => decrypting.decryptJson(binding, envelope)).toThrow("secret envelope key is unavailable");
const corrupted = structuredClone(envelope);
corrupted.payload.ciphertext = flipFirstByte(corrupted.payload.ciphertext);
let message = "";
try {
encrypting.decryptJson(binding, corrupted);
} catch (error) {
message = error instanceof Error ? error.message : String(error);
}
expect(message).toBe("secret envelope authentication failed");
expect(message).not.toContain("never-log-this-token");
});
it("rewraps only the DEK when the active KEK rotates", async () => {
const firstFile = await keyringFile({ old: key("a") }, "old");
const rotatedFile = await keyringFile({ old: key("a"), current: key("c") }, "current");
const first = new LocalSecretEnvelope(await loadLocalSecretKeyring({
NODE_ENV: "test",
HUB_SECRET_KEYRING_FILE: firstFile,
}));
const rotated = new LocalSecretEnvelope(await loadLocalSecretKeyring({
NODE_ENV: "test",
HUB_SECRET_KEYRING_FILE: rotatedFile,
}));
const binding = secretBinding();
const envelope = first.encryptJson(binding, { token: "rotatable" });
const rewrapped = rotated.rewrap(binding, envelope);
expect(rewrapped.keyId).toBe("current");
expect(rewrapped.payload).toEqual(envelope.payload);
expect(rewrapped.wrappedDek).not.toEqual(envelope.wrappedDek);
expect(rotated.decryptJson(binding, rewrapped)).toEqual({ token: "rotatable" });
});
it("loads production keys only from the fixed systemd credential", async () => {
const credentialsDirectory = await temporaryDirectory();
await writeKeyring(path.join(credentialsDirectory, "cph-secret-keyring"), { active: key("a") }, "active");
await expect(loadLocalSecretKeyring({
NODE_ENV: "production",
CREDENTIALS_DIRECTORY: credentialsDirectory,
})).resolves.toMatchObject({ activeKeyId: "active" });
await expect(loadLocalSecretKeyring({
NODE_ENV: "production",
CREDENTIALS_DIRECTORY: credentialsDirectory,
HUB_SECRET_KEYRING_FILE: "/tmp/untrusted-keyring.json",
})).rejects.toThrow("production secret keyring must use the systemd credential");
});
it("rejects absent, malformed, or incomplete keyrings", async () => {
await expect(loadLocalSecretKeyring({ NODE_ENV: "test" })).rejects.toThrow(
"missing required secret keyring setting",
);
const directory = await temporaryDirectory();
const malformed = path.join(directory, "malformed.json");
await writeFile(malformed, "not json", "utf8");
await expect(loadLocalSecretKeyring({
NODE_ENV: "test",
HUB_SECRET_KEYRING_FILE: malformed,
})).rejects.toThrow("invalid local secret keyring");
const missingActive = await keyringFile({ old: key("a") }, "current");
await expect(loadLocalSecretKeyring({
NODE_ENV: "test",
HUB_SECRET_KEYRING_FILE: missingActive,
})).rejects.toThrow("active key is unavailable");
});
});
function secretBinding(): SecretBinding {
return {
purpose: "provider-connection",
organizationId: "org-a",
connectionId: "connection-a",
secretVersionId: "secret-version-a",
};
}
function key(character: string): string {
return Buffer.alloc(32, character).toString("base64");
}
async function keyringFile(keys: Readonly<Record<string, string>>, activeKeyId: string): Promise<string> {
const directory = await temporaryDirectory();
const file = path.join(directory, "keyring.json");
await writeKeyring(file, keys, activeKeyId);
return file;
}
async function temporaryDirectory(): Promise<string> {
const directory = await mkdtemp(path.join(tmpdir(), "cph-secret-envelope-"));
createdDirectories.push(directory);
return directory;
}
async function writeKeyring(
file: string,
keys: Readonly<Record<string, string>>,
activeKeyId: string,
): Promise<void> {
await writeFile(file, JSON.stringify({ version: 1, activeKeyId, keys }), { encoding: "utf8", mode: 0o600 });
}
function flipFirstByte(value: string): string {
const bytes = Buffer.from(value, "base64");
bytes[0] = (bytes[0] ?? 0) ^ 1;
return bytes.toString("base64");
}