146 lines
4.4 KiB
TypeScript
146 lines
4.4 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import type { KubernetesObjectApi } from "@kubernetes/client-node";
|
|
import { KubernetesTrustStore } from "../../server/kubernetes-state";
|
|
import { MemoryTrustStore } from "../../server/trust-store";
|
|
|
|
type ConfigMap = {
|
|
apiVersion: string;
|
|
kind: string;
|
|
metadata: {
|
|
name: string;
|
|
namespace?: string;
|
|
labels?: Record<string, string>;
|
|
};
|
|
data?: Record<string, string>;
|
|
};
|
|
|
|
class FakeObjects {
|
|
readonly maps = new Map<string, ConfigMap>();
|
|
readonly selectors: string[] = [];
|
|
|
|
async create(value: ConfigMap): Promise<void> {
|
|
this.maps.set(value.metadata.name, structuredClone(value));
|
|
}
|
|
|
|
async read(value: ConfigMap): Promise<ConfigMap> {
|
|
const found = this.maps.get(value.metadata.name);
|
|
if (!found) throw { code: 404 };
|
|
return structuredClone(found);
|
|
}
|
|
|
|
async delete(value: ConfigMap): Promise<void> {
|
|
if (!this.maps.delete(value.metadata.name)) throw { code: 404 };
|
|
}
|
|
|
|
async list(
|
|
_apiVersion: string,
|
|
_kind: string,
|
|
_namespace?: string,
|
|
_pretty?: string,
|
|
_exact?: boolean,
|
|
_exportValue?: boolean,
|
|
_fieldSelector?: string,
|
|
labelSelector?: string,
|
|
): Promise<{ items: ConfigMap[] }> {
|
|
this.selectors.push(labelSelector ?? "");
|
|
const labels = Object.fromEntries(
|
|
(labelSelector ?? "")
|
|
.split(",")
|
|
.filter(Boolean)
|
|
.map((part) => part.split("=")),
|
|
);
|
|
return {
|
|
items: [...this.maps.values()].filter((item) =>
|
|
Object.entries(labels).every(
|
|
([key, value]) => item.metadata.labels?.[key] === value,
|
|
),
|
|
),
|
|
};
|
|
}
|
|
}
|
|
|
|
describe("namespace trust store", () => {
|
|
test("rejects invalid namespace and fingerprint", async () => {
|
|
const store = new MemoryTrustStore();
|
|
await expect(store.grant("Demo", "a".repeat(64))).rejects.toThrow();
|
|
await expect(store.grant("a".repeat(64), "a".repeat(64))).rejects.toThrow();
|
|
await expect(store.grant("demo", "bad")).rejects.toThrow();
|
|
});
|
|
|
|
test("requires explicit registration for each CWD fingerprint", async () => {
|
|
const store = new MemoryTrustStore();
|
|
const first = "a".repeat(64);
|
|
const second = "b".repeat(64);
|
|
await store.grant("demo", first);
|
|
expect(await store.has("demo", first)).toBe(true);
|
|
expect(await store.has("demo", second)).toBe(false);
|
|
await store.grant("demo", second);
|
|
expect(await store.list("demo")).toEqual([first, second]);
|
|
expect(await store.revoke("demo", first)).toBe(true);
|
|
expect(await store.has("demo", first)).toBe(false);
|
|
});
|
|
|
|
test("persists valid ConfigMap records and ignores malformed payloads", async () => {
|
|
const objects = new FakeObjects();
|
|
const store = new KubernetesTrustStore(
|
|
objects as unknown as KubernetesObjectApi,
|
|
);
|
|
const fingerprint = "a".repeat(64);
|
|
|
|
await store.grant("demo", fingerprint);
|
|
const [record] = [...objects.maps.values()];
|
|
expect(record).toMatchObject({
|
|
apiVersion: "v1",
|
|
kind: "ConfigMap",
|
|
metadata: {
|
|
namespace: "kuber-system",
|
|
labels: {
|
|
"kuber.astrxl.dev/type": "trust",
|
|
"kuber.astrxl.dev/workspace": "demo",
|
|
},
|
|
},
|
|
data: { payload: JSON.stringify({ project: "demo", fingerprint }) },
|
|
});
|
|
expect(record?.metadata.name).toMatch(/^trust-[a-f0-9]{48}$/);
|
|
expect(await store.list("demo")).toEqual([fingerprint]);
|
|
expect(objects.selectors).toContain(
|
|
"kuber.astrxl.dev/type=trust,kuber.astrxl.dev/workspace=demo",
|
|
);
|
|
|
|
objects.maps.set("trust-malformed", {
|
|
apiVersion: "v1",
|
|
kind: "ConfigMap",
|
|
metadata: {
|
|
name: "trust-malformed",
|
|
labels: {
|
|
"kuber.astrxl.dev/type": "trust",
|
|
"kuber.astrxl.dev/workspace": "demo",
|
|
},
|
|
},
|
|
data: { payload: "not-json" },
|
|
});
|
|
objects.maps.set("trust-wrong-project", {
|
|
apiVersion: "v1",
|
|
kind: "ConfigMap",
|
|
metadata: {
|
|
name: "trust-wrong-project",
|
|
labels: {
|
|
"kuber.astrxl.dev/type": "trust",
|
|
"kuber.astrxl.dev/workspace": "demo",
|
|
},
|
|
},
|
|
data: {
|
|
payload: JSON.stringify({
|
|
project: "other",
|
|
fingerprint: "b".repeat(64),
|
|
}),
|
|
},
|
|
});
|
|
expect(await store.list("demo")).toEqual([fingerprint]);
|
|
|
|
expect(await store.revoke("demo", fingerprint)).toBe(true);
|
|
expect(await store.has("demo", fingerprint)).toBe(false);
|
|
expect(await store.revoke("demo", fingerprint)).toBe(false);
|
|
});
|
|
});
|