This commit is contained in:
2026-09-03 11:28:30 +07:00 Unverified
parent 26c2d0f015
commit 82d0fe3e0d
93 changed files with 19237 additions and 1285 deletions
+471
View File
@@ -0,0 +1,471 @@
import { describe, expect, spyOn, test } from "bun:test";
import { cleanupExpiredSessions, createApp } from "../../server/app";
import { hashToken, MemoryAuthStore } from "../../server/auth";
import { MemoryAuditStore } from "../../server/audit-store";
import type { ManagementService } from "../../server/management";
import {
MemoryOperationStore,
MemoryWorkspaceLeaseProvider,
} from "../../server/operation-store";
import { MemoryWorkspaceStore } from "../../server/workspace-store";
function request(
path: string,
init: RequestInit = {},
token?: string,
): Request {
const headers = new Headers(init.headers);
if (token) headers.set("authorization", `Bearer ${token}`);
return new Request(`https://kuber.astrxl.dev${path}`, { ...init, headers });
}
describe("kuber API authentication", () => {
test("logs in, resolves identity, and revokes the session", async () => {
const store = new MemoryAuthStore();
await store.putUser({
username: "dmgnr",
passwordHash: "stored-hash",
roles: ["admin"],
});
const app = createApp({
store,
now: () => Date.parse("2026-09-02T00:00:00.000Z"),
verifyPassword: async (password, hash) =>
password === "correct" && hash === "stored-hash",
});
const login = await app(
request("/api/v2/login", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
username: "dmgnr",
password: "correct",
persistent: false,
}),
}),
);
expect(login.status).toBe(200);
const session = (await login.json()) as {
token: string;
expiresAt: string;
};
expect(session.expiresAt).toBe("2026-09-03T00:00:00.000Z");
const me = await app(request("/api/v2/me", {}, session.token));
expect(await me.json()).toEqual({ username: "dmgnr", roles: ["admin"] });
const logout = await app(
request("/api/v2/logout", { method: "POST" }, session.token),
);
expect(logout.status).toBe(204);
expect((await app(request("/api/v2/me", {}, session.token))).status).toBe(
401,
);
});
test("rejects invalid credentials and unauthenticated requests", async () => {
const store = new MemoryAuthStore();
await store.putUser({
username: "dmgnr",
passwordHash: "stored-hash",
roles: ["admin"],
});
const app = createApp({
store,
verifyPassword: async () => false,
});
const login = await app(
request("/api/v2/login", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ username: "dmgnr", password: "wrong" }),
}),
);
expect(login.status).toBe(401);
expect((await app(request("/api/v2/me"))).status).toBe(401);
});
test("provides an unauthenticated health endpoint", async () => {
const app = createApp({ store: new MemoryAuthStore() });
const response = await app(request("/api/v2/health"));
expect(response.status).toBe(200);
expect(await response.json()).toEqual({ status: "ok" });
});
test("provides an explicit expired-session startup cleanup helper", async () => {
const store = new MemoryAuthStore();
await store.putUser({
username: "user",
passwordHash: "hash",
roles: ["viewer"],
});
await store.putSession({
tokenHash: hashToken("expired"),
username: "user",
authVersion: 1,
expiresAt: "2026-09-01T00:00:00.000Z",
});
expect(
await cleanupExpiredSessions(
store,
Date.parse("2026-09-02T00:00:00.000Z"),
),
).toBe(1);
});
test("rate limits repeated failed logins", async () => {
const app = createApp({
store: new MemoryAuthStore(),
now: () => 0,
});
const login = () =>
app(
request("/api/v2/login", {
method: "POST",
body: JSON.stringify({ username: "missing", password: "wrong" }),
}),
);
for (let attempt = 0; attempt < 5; attempt += 1) {
expect((await login()).status).toBe(401);
}
const limited = await login();
expect(limited.status).toBe(429);
expect(limited.headers.get("retry-after")).toBe("300");
});
});
async function authenticatedStore(role: "viewer" | "operator" | "admin") {
const store = new MemoryAuthStore();
await store.putUser({ username: role, passwordHash: "hash", roles: [role] });
await store.putSession({
tokenHash: hashToken("token"),
username: role,
authVersion: 1,
expiresAt: "2030-01-01T00:00:00.000Z",
});
return store;
}
describe("kuber v2 HTTP routes", () => {
test("uses exact origins, request IDs, and problem+json errors", async () => {
const app = createApp({
store: new MemoryAuthStore(),
allowedOrigins: ["https://console.example"],
requestId: () => "generated-id",
});
const denied = await app(
request("/api/v2/health", {
headers: { origin: "https://console.example.evil" },
}),
);
expect(denied.status).toBe(403);
expect(denied.headers.get("content-type")).toContain(
"application/problem+json",
);
expect(denied.headers.get("x-request-id")).toBe("generated-id");
expect(await denied.json()).toMatchObject({
code: "ORIGIN_NOT_ALLOWED",
requestId: "generated-id",
});
const allowed = await app(
request("/api/v2/health", {
headers: {
origin: "https://console.example",
"x-request-id": "caller-id",
},
}),
);
expect(allowed.headers.get("access-control-allow-origin")).toBe(
"https://console.example",
);
expect(allowed.headers.get("x-request-id")).toBe("caller-id");
});
test("enforces capabilities and supports user CRUD with revocation", async () => {
const viewerStore = await authenticatedStore("viewer");
const viewerApp = createApp({ store: viewerStore });
expect(
(await viewerApp(request("/api/v2/users", {}, "token"))).status,
).toBe(403);
const store = await authenticatedStore("admin");
const auditStore = new MemoryAuditStore();
const app = createApp({
store,
auditStore,
hashPassword: async (password) => `hashed:${password}`,
});
const created = await app(
request(
"/api/v2/users",
{
method: "POST",
body: JSON.stringify({
username: "alice",
password: "secret",
roles: ["operator"],
}),
},
"token",
),
);
expect(created.status).toBe(201);
expect(await created.json()).toEqual({
username: "alice",
roles: ["operator"],
disabled: false,
});
expect((await store.getUser("alice"))?.passwordHash).toBe("hashed:secret");
const revoke = await app(
request(
"/api/v2/users/alice/sessions/revoke",
{ method: "POST" },
"token",
),
);
expect(revoke.status).toBe(200);
expect(await revoke.json()).toEqual({ username: "alice", revoked: 0 });
expect((await auditStore.list()).map((event) => event.spec.action)).toEqual(
["user.create", "sessions.revoke"],
);
});
test("provides workspace ETags and idempotent synchronous operations", async () => {
const store = await authenticatedStore("operator");
const workspaceStore = new MemoryWorkspaceStore({
uid: () => "workspace-uid",
now: () => new Date("2026-09-02T00:00:00.000Z"),
});
const operationStore = new MemoryOperationStore(
() => new Date("2026-09-02T00:00:00.000Z"),
() => "operation-uid",
);
let stops = 0;
const management = {
stop: async () => {
stops += 1;
return ["api"];
},
} as unknown as ManagementService;
const app = createApp({
store,
workspaceStore,
operationStore,
management,
});
const created = await app(
request(
"/api/v2/workspaces",
{
method: "POST",
body: JSON.stringify({
id: "demo",
source: { uri: "oci://example/demo", digest: "sha256:abc" },
}),
},
"token",
),
);
expect(created.status).toBe(201);
expect(created.headers.get("etag")).toBe('"1"');
const missingPrecondition = await app(
request(
"/api/v2/workspaces/demo",
{
method: "PUT",
body: JSON.stringify({
source: { uri: "oci://example/demo", digest: "sha256:def" },
}),
},
"token",
),
);
expect(missingPrecondition.status).toBe(428);
const stop = () =>
app(
request(
"/api/v2/workspaces/demo/lifecycle",
{
method: "POST",
headers: { "idempotency-key": "stop-once" },
body: JSON.stringify({ action: "stop", services: ["api"] }),
},
"token",
),
);
expect((await stop()).status).toBe(200);
expect((await stop()).status).toBe(200);
expect(stops).toBe(1);
expect(await operationStore.list("demo")).toHaveLength(1);
});
test("rejects JSON bodies over the configured limit", async () => {
const app = createApp({
store: await authenticatedStore("admin"),
workspaceStore: new MemoryWorkspaceStore(),
jsonBodyLimit: 32,
});
const result = await app(
request(
"/api/v2/workspaces",
{ method: "POST", body: JSON.stringify({ value: "x".repeat(64) }) },
"token",
),
);
expect(result.status).toBe(413);
expect(await result.json()).toMatchObject({ code: "BODY_TOO_LARGE" });
});
test("does not expose request internals or corrupt success when auditing fails", async () => {
const reported = spyOn(console, "error").mockImplementation(() => {});
const workspaceStore = new MemoryWorkspaceStore({
uid: () => "workspace-uid",
});
await workspaceStore.create({
id: "demo",
source: { uri: "oci://example/demo", digest: "sha256:abc" },
});
const operationStore = new MemoryOperationStore(
undefined,
() => "operation-uid",
);
const app = createApp({
store: await authenticatedStore("operator"),
workspaceStore,
operationStore,
management: { stop: async () => ["api"] } as unknown as ManagementService,
auditStore: {
append: async () => {
throw new Error("audit unavailable");
},
list: async () => [],
},
});
const result = await app(
request(
"/api/v2/workspaces/demo/lifecycle",
{
method: "POST",
headers: { "idempotency-key": "private-request" },
body: JSON.stringify({ action: "stop", password: "do-not-store" }),
},
"token",
),
);
expect(result.status).toBe(200);
const body = (await result.json()) as Record<string, any>;
expect(body.operation.spec).toEqual({
workspaceId: "demo",
action: "workspace.stop",
});
expect(body.operation.status.state).toBe("succeeded");
expect(reported).toHaveBeenCalledTimes(1);
reported.mockRestore();
expect(
await operationStore.get("operation-operation-uid"),
).not.toHaveProperty("spec.request");
});
test("fails and identifies operations that cannot acquire the workspace lease", async () => {
const workspaceStore = new MemoryWorkspaceStore({
uid: () => "workspace-uid",
});
await workspaceStore.create({
id: "demo",
source: { uri: "oci://example/demo", digest: "sha256:abc" },
});
const operationStore = new MemoryOperationStore(undefined, () => "blocked");
const leases = new MemoryWorkspaceLeaseProvider();
await leases.acquire("demo", "other");
const app = createApp({
store: await authenticatedStore("operator"),
workspaceStore,
operationStore,
leases,
management: { stop: async () => [] } as unknown as ManagementService,
});
const result = await app(
request(
"/api/v2/workspaces/demo/lifecycle",
{ method: "POST", body: JSON.stringify({ action: "stop" }) },
"token",
),
);
expect(result.status).toBe(409);
expect(await result.json()).toMatchObject({
code: "WORKSPACE_BUSY",
operationId: "operation-blocked",
});
expect((await operationStore.get("operation-blocked"))?.status.state).toBe(
"failed",
);
});
test("routes workspace adoption and keeps platform adoption admin-only", async () => {
const workspaceStore = new MemoryWorkspaceStore({
uid: () => "workspace-uid",
});
await workspaceStore.create({
id: "demo",
source: { uri: "oci://example/demo", digest: "sha256:abc" },
});
const adopted: string[] = [];
const adoption = {
adopt: async (workspaceId: string, workspaceUid: string) => {
adopted.push(`${workspaceId}:${workspaceUid}`);
return { workspaceId, workspaceUid, resourcesAdopted: 2 };
},
adoptPlatform: async (workspaceUid: string) => ({
workspaceId: "kuber-system",
workspaceUid,
resourcesAdopted: 1,
}),
};
const operatorApp = createApp({
store: await authenticatedStore("operator"),
workspaceStore,
adoption,
});
const regular = await operatorApp(
request("/api/v2/workspaces/demo/adopt", { method: "POST" }, "token"),
);
expect(regular.status).toBe(200);
expect(adopted).toEqual(["demo:workspace-uid"]);
expect(
(
await operatorApp(
request(
"/api/v2/platform/kuber-system/adopt",
{
method: "POST",
body: JSON.stringify({ workspaceUid: "platform" }),
},
"token",
),
)
).status,
).toBe(403);
const adminApp = createApp({
store: await authenticatedStore("admin"),
workspaceStore,
adoption,
});
const platform = await adminApp(
request(
"/api/v2/platform/kuber-system/adopt",
{ method: "POST", body: JSON.stringify({ workspaceUid: "platform" }) },
"token",
),
);
expect(platform.status).toBe(200);
});
});