mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-29 14:45:24 +00:00
feat: convert secret-sources into a plugin (B20)
This commit is contained in:
1 parent
2ac7779eda
commit
f4f26a9b8b
72 files changed
+18843
-933
No files matched your search
@@ -1,46 +1,38 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
vi.mock("../../database/repositories/factory.js", () => ({
|
||||
createCurrentSecretSourceRepository: () => ({
|
||||
listVisibleToUser: async () => [],
|
||||
decryptToken: () => "",
|
||||
}),
|
||||
createCurrentSettingsRepository: () => ({ get: async () => null }),
|
||||
}));
|
||||
|
||||
const {
|
||||
clearExternalSecretCache,
|
||||
isSecretReference,
|
||||
resolveExternalSecretRefs,
|
||||
resolveSecretReference,
|
||||
} = await import("../../hosts/external-secrets.js");
|
||||
const { setSecretResolverOwnerSource, resetSecretResolverRegistryForTests } =
|
||||
await import("../../hosts/connect/secret-resolver-registry.js");
|
||||
|
||||
const source = {
|
||||
id: "src-1",
|
||||
userId: "alice",
|
||||
name: "1P",
|
||||
kind: "onepassword-connect",
|
||||
baseUrl: "https://connect.internal",
|
||||
token: "enc",
|
||||
shared: false,
|
||||
createdAt: "",
|
||||
updatedAt: "",
|
||||
};
|
||||
describe("isSecretReference", () => {
|
||||
it("recognises a scheme:// reference without confusing it with a secret", () => {
|
||||
expect(isSecretReference("op://v/i/f")).toBe(true);
|
||||
expect(isSecretReference(" op://v/i/f")).toBe(true);
|
||||
expect(isSecretReference("vault+https://x")).toBe(true);
|
||||
expect(isSecretReference("hunter2")).toBe(false);
|
||||
expect(isSecretReference(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("external secret references", () => {
|
||||
beforeEach(() => clearExternalSecretCache());
|
||||
|
||||
it("replaces references in the host's secret fields and leaves plain secrets alone", async () => {
|
||||
const resolver = vi.fn(async (_s, ref: string) => `resolved:${ref}`);
|
||||
const resolver = vi.fn(
|
||||
async (_userId: string, ref: string) => `resolved:${ref}`,
|
||||
);
|
||||
const host: Record<string, unknown> = {
|
||||
password: "op://Infra/box/password",
|
||||
key: "-----BEGIN OPENSSH PRIVATE KEY-----",
|
||||
sudoPassword: "op://Infra/box/sudo",
|
||||
username: "op://not-a-secret-field",
|
||||
};
|
||||
await resolveExternalSecretRefs(host, "alice", {
|
||||
resolver,
|
||||
pickSource: async () => source,
|
||||
});
|
||||
await resolveExternalSecretRefs(host, "alice", { resolver });
|
||||
expect(host.password).toBe("resolved:op://Infra/box/password");
|
||||
expect(host.sudoPassword).toBe("resolved:op://Infra/box/sudo");
|
||||
expect(host.key).toBe("-----BEGIN OPENSSH PRIVATE KEY-----");
|
||||
@@ -48,10 +40,10 @@ describe("external secret references", () => {
|
||||
expect(resolver).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("caches a resolved reference per source for a minute", async () => {
|
||||
it("caches a resolved reference per user for a minute", async () => {
|
||||
const resolver = vi.fn(async () => "s3cret");
|
||||
let clock = 1_000_000;
|
||||
const deps = { resolver, pickSource: async () => source, now: () => clock };
|
||||
const deps = { resolver, now: () => clock };
|
||||
await resolveSecretReference("alice", "op://v/i/f", deps);
|
||||
await resolveSecretReference("alice", "op://v/i/f", deps);
|
||||
expect(resolver).toHaveBeenCalledTimes(1);
|
||||
@@ -60,12 +52,26 @@ describe("external secret references", () => {
|
||||
expect(resolver).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("fails clearly when the user has no secret source", async () => {
|
||||
it("fails clearly when no plugin resolves the scheme", async () => {
|
||||
await expect(
|
||||
resolveSecretReference("bob", "op://v/i/f", {
|
||||
resolver: async () => "x",
|
||||
pickSource: async () => null,
|
||||
}),
|
||||
).rejects.toThrow(/no secret source/);
|
||||
resolveSecretReference("bob", "op://v/i/f", {}),
|
||||
).rejects.toThrow(/needs the .* plugin|no enabled plugin resolves/);
|
||||
});
|
||||
|
||||
it("names the plugin that would resolve a disabled scheme", async () => {
|
||||
setSecretResolverOwnerSource(() => [
|
||||
{
|
||||
scheme: "op",
|
||||
pluginId: "secret-sources",
|
||||
pluginName: "Secret Sources",
|
||||
},
|
||||
]);
|
||||
try {
|
||||
await expect(
|
||||
resolveSecretReference("bob", "op://v/i/f", {}),
|
||||
).rejects.toThrow("needs the Secret Sources plugin");
|
||||
} finally {
|
||||
resetSecretResolverRegistryForTests();
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user