Address project-wide review (todo §3); fix JWKS_URL default → tokenizer signing key + read-only web mount, cap bootstrap restart, --no-deps for unit commands
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { test } from "node:test";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { loadConfig } from "./config.ts";
|
||||
|
||||
// Explicit secure-secret enforcement (no environment sniffing): secrets are the only
|
||||
@@ -18,11 +20,26 @@ test("loads dev defaults when the environment is empty", () => {
|
||||
assert.equal(c.kratosAdminUrl, "http://kratos:4434");
|
||||
assert.equal(c.ketoReadUrl, "http://keto:4466");
|
||||
assert.equal(c.ketoWriteUrl, "http://keto:4467");
|
||||
assert.match(c.jwksUrl, /jwks/);
|
||||
assert.match(c.cookieSecret, /dev-insecure/);
|
||||
assert.match(c.csrfSecret, /dev-insecure/);
|
||||
});
|
||||
|
||||
test("JWKS_URL defaults to the committed Kratos tokenizer signing key, not an http endpoint", () => {
|
||||
// The session JWT is signed by the tokenizer key (kratos.yml jwks_url); Kratos does NOT
|
||||
// republish it at /.well-known/jwks.json, so the §4 verifier reads that same file://.
|
||||
const url = new URL(loadConfig({}).jwksUrl);
|
||||
assert.equal(url.protocol, "file:");
|
||||
assert.match(url.pathname, /tokenizer\/jwks\.json$/);
|
||||
|
||||
// And that file is a real ES256 signing JWKS carrying a kid (what the verifier resolves by).
|
||||
const path = fileURLToPath(new URL("../ory/kratos/tokenizer/jwks.json", import.meta.url));
|
||||
const key = (JSON.parse(readFileSync(path, "utf8")) as { keys: { alg: string; kid: string; kty: string }[] }).keys[0];
|
||||
assert.ok(key, "tokenizer JWKS must have a key");
|
||||
assert.equal(key.alg, "ES256");
|
||||
assert.equal(key.kty, "EC");
|
||||
assert.ok(key.kid, "tokenizer JWKS key must carry a kid");
|
||||
});
|
||||
|
||||
test("parses explicit boolean toggles and rejects non-boolean values", () => {
|
||||
assert.equal(loadConfig({ CACHE_TEMPLATES: "true" }).cacheTemplates, true);
|
||||
assert.equal(loadConfig({ CACHE_TEMPLATES: "false" }).cacheTemplates, false);
|
||||
|
||||
@@ -68,7 +68,11 @@ export function loadConfig(env: Env = process.env): Config {
|
||||
cacheTemplates: readBool(env, "CACHE_TEMPLATES", false),
|
||||
cookieSecret: readSecret(env, "COOKIE_SECRET", "dev-insecure-cookie-secret", requireSecure),
|
||||
csrfSecret: readSecret(env, "CSRF_SECRET", "dev-insecure-csrf-secret", requireSecure),
|
||||
jwksUrl: readUrl(env, "JWKS_URL", "http://kratos:4433/.well-known/jwks.json"),
|
||||
// The session JWT is signed by the Kratos tokenizer key (kratos.yml jwks_url); the §4
|
||||
// verifier reads that same key. Kratos does not republish it over HTTP, so default to a
|
||||
// file:// of the tokenizer JWKS mounted into the web container (compose.yml) — not a
|
||||
// well-known endpoint. Prod overrides with a real key (README: JWT signing key & rotation).
|
||||
jwksUrl: readUrl(env, "JWKS_URL", "file:///etc/config/kratos/tokenizer/jwks.json"),
|
||||
ketoReadUrl: readUrl(env, "KETO_READ_URL", "http://keto:4466"),
|
||||
ketoWriteUrl: readUrl(env, "KETO_WRITE_URL", "http://keto:4467"),
|
||||
kratosAdminUrl: readUrl(env, "KRATOS_ADMIN_URL", "http://kratos:4434"),
|
||||
|
||||
Reference in New Issue
Block a user