Files
wireguard-ui/src/functions/backend/caddy/build-caddyfile.test.ts
T

154 lines
4.7 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import type {
BUN_SQLITE_WGUI_CLIENT_ROUTES,
BUN_SQLITE_WGUI_TLS_CERTIFICATES,
} from "@/db/types/db";
import buildCaddyfile from "./build-caddyfile";
const base = {
https_port: 8443,
http_port: 8081,
admin_socket: `/run/wgui-caddy/admin.sock`,
storage_dir: `/var/lib/wgui/caddy/data`,
};
const certificate = {
hostname: "media.example.com",
cert_path: "/var/lib/wgui/tls/media.example.com/fullchain.pem",
key_path: "/var/lib/wgui/tls/media.example.com/privkey.pem",
status: "active",
} as BUN_SQLITE_WGUI_TLS_CERTIFICATES;
function route(
values: Partial<BUN_SQLITE_WGUI_CLIENT_ROUTES>,
): BUN_SQLITE_WGUI_CLIENT_ROUTES {
return {
hostname: "media.example.com",
path_prefix: "/",
upstream_url: "http://10.5.0.20:8080",
enabled: 1,
...values,
};
}
describe("buildCaddyfile", () => {
test("uses a high port and never 80/443", () => {
const res = buildCaddyfile({ ...base, routes: [], certificates: [] });
expect(res.config).toContain("https_port 8443");
expect(res.config).toContain("http_port 8081");
expect(res.config).not.toContain("auto_https disable_redirects");
expect(res.config).not.toContain("https_port 443");
expect(res.config).not.toContain("http_port 80\n");
});
test("can disable automatic HTTPS redirects", () => {
const res = buildCaddyfile({
...base,
redirect: false,
routes: [],
certificates: [],
});
expect(res.config).toContain("auto_https disable_redirects");
});
test("orders longer prefixes before the catch-all", () => {
const res = buildCaddyfile({
...base,
certificates: [certificate],
routes: [
route({ name: "root", path_prefix: "/" }),
route({
name: "app",
path_prefix: "/app",
strip_prefix: 1,
upstream_url: "http://10.5.0.30:9000",
}),
],
});
const app_index = res.config?.indexOf("@route_1 {") || 0;
const root_index = res.config?.indexOf("handle {") || 0;
expect(app_index).toBeGreaterThan(0);
expect(root_index).toBeGreaterThan(app_index);
expect(res.config).toContain("path /app /app/*");
expect(res.config).toContain("uri strip_prefix /app");
});
test("skips routes without an active certificate", () => {
const res = buildCaddyfile({
...base,
certificates: [],
routes: [route({ name: "media" })],
});
expect(res.config).not.toContain("media.example.com {");
expect(res.warnings[0]).toContain("certificate");
});
test("scopes a route to its host's WireGuard subnet", () => {
const res = buildCaddyfile({
...base,
certificates: [certificate],
hosts: [{ id: 0, wg_ip_address: "10.5.0.1" }],
routes: [route({ host_id: 0, path_prefix: "/app" })],
});
expect(res.config).toContain("remote_ip 10.5.0.0/24");
});
test("appends route allowed_ips to the remote_ip matcher", () => {
const res = buildCaddyfile({
...base,
certificates: [certificate],
hosts: [{ id: 0, wg_ip_address: "10.5.0.1" }],
routes: [
route({
host_id: 0,
path_prefix: "/app",
allowed_ips: "203.0.113.0/24, 198.51.100.0/24",
}),
],
});
expect(res.config).toContain(
"remote_ip 10.5.0.0/24 127.0.0.1/32 ::1/128 203.0.113.0/24 198.51.100.0/24",
);
});
test("maps insecure upstream TLS to Caddy", () => {
const res = buildCaddyfile({
...base,
certificates: [certificate],
routes: [
route({
upstream_url: "https://10.5.0.20:8443",
upstream_tls_verify: 0,
}),
],
});
expect(res.config).toContain("tls_insecure_skip_verify");
});
test("allows a catch-all route with allowed_ips to have a matcher", () => {
const res = buildCaddyfile({
...base,
certificates: [certificate],
hosts: [{ id: 0, wg_ip_address: "10.5.0.1" }],
routes: [
route({
host_id: 0,
path_prefix: "/",
allowed_ips: "203.0.113.0/24",
}),
],
});
expect(res.config).toContain("@route_1 remote_ip");
expect(res.config).toContain("203.0.113.0/24");
});
});