feat(auth): integrate authentication with installation lifecycle
This commit is contained in:
@@ -169,7 +169,7 @@ test("the session boundary exposes only exact health and authentication protocol
|
||||
expect((await app.inject({ method: "GET", url: "/auth/configured" })).statusCode).toBe(401);
|
||||
});
|
||||
|
||||
test("the session boundary retains the exact loopback tht maintenance identity in configured auth modes", async () => {
|
||||
test("loopback maintenance headers can never mint an administrator in configured auth modes", async () => {
|
||||
const app = Fastify();
|
||||
app.addHook("preHandler", authenticateSession({ mode: "local" }));
|
||||
app.get("/private", async (request) => getPrincipal(request));
|
||||
@@ -183,8 +183,8 @@ test("the session boundary retains the exact loopback tht maintenance identity i
|
||||
|
||||
for (const method of ["GET", "POST"] as const) {
|
||||
const response = await app.inject({ method, url: "/private", headers, remoteAddress: "127.0.0.1" });
|
||||
expect(response.statusCode).toBe(200);
|
||||
expect(response.json()).toMatchObject({ issuer: "tht", subject: "tht-maintenance", isAdmin: true });
|
||||
expect(response.statusCode).toBe(503);
|
||||
expect(response.body).not.toContain("tht-maintenance");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { chmodSync, mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { formatStartupFailure } from "../src/startup-error.js";
|
||||
|
||||
@@ -25,4 +29,34 @@ describe("formatStartupFailure", () => {
|
||||
expect(formatted).not.toContain(leaked);
|
||||
}
|
||||
});
|
||||
|
||||
it("sanitizes synchronous configuration failures from the real server subprocess", () => {
|
||||
const root = mkdtempSync(join(tmpdir(), "thothii-startup-secret-"));
|
||||
const secret = "startup-password-do-not-log";
|
||||
const authDirectory = join(root, `auth-${secret}`);
|
||||
mkdirSync(authDirectory, { mode: 0o700 });
|
||||
const authFile = join(authDirectory, "auth.yaml");
|
||||
writeFileSync(authFile, `version: 1\nmode: local\npassword: ${secret}\n`, { mode: 0o600 });
|
||||
chmodSync(authDirectory, 0o700);
|
||||
const entrypoint = resolve(process.cwd(), "src/server.ts");
|
||||
|
||||
const result = spawnSync(process.execPath, ["--import", "tsx", entrypoint], {
|
||||
cwd: process.cwd(),
|
||||
encoding: "utf8",
|
||||
timeout: 15_000,
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_ENV: "test",
|
||||
THT_AUTH_CONFIG_FILE: authFile,
|
||||
THT_AUTH_STATE_ROOT: join(root, "auth-state"),
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.status).toBe(1);
|
||||
expect(result.stdout).toBe("");
|
||||
expect(result.stderr.trim()).toBe("backend startup failed: auth_config_invalid");
|
||||
expect(`${result.stdout}${result.stderr}`).not.toContain(secret);
|
||||
expect(`${result.stdout}${result.stderr}`).not.toContain(authDirectory);
|
||||
expect(`${result.stdout}${result.stderr}`).not.toContain("server.ts");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user