mirror of
https://github.com/tale/headplane.git
synced 2026-08-21 02:06:37 +00:00
feat: switch to a generalized api key config
This commit is contained in:
@@ -9,9 +9,9 @@ import { deprecatedField } from "./utils";
|
||||
|
||||
export const pathSupportedKeys = [
|
||||
"server.cookie_secret",
|
||||
"headscale.api_key",
|
||||
"oidc.client_secret",
|
||||
"oidc.headscale_api_key",
|
||||
"integration.agent.pre_authkey",
|
||||
] as const;
|
||||
|
||||
const serverConfig = type({
|
||||
@@ -45,6 +45,7 @@ const headscaleConfig = type({
|
||||
public_url: type("string.url")
|
||||
.pipe((v) => (v.endsWith("/") ? v.slice(0, -1) : v))
|
||||
.optional(),
|
||||
api_key: "string?",
|
||||
config_path: "string.lower?",
|
||||
config_strict: "boolean = true",
|
||||
dns_records_path: "string.lower?",
|
||||
@@ -58,6 +59,7 @@ const partialHeadscaleConfig = type({
|
||||
public_url: type("string.url")
|
||||
.pipe((v) => (v.endsWith("/") ? v.slice(0, -1) : v))
|
||||
.optional(),
|
||||
api_key: "string?",
|
||||
config_path: "string.lower?",
|
||||
config_strict: "boolean?",
|
||||
dns_records_path: "string.lower?",
|
||||
@@ -69,7 +71,12 @@ const oidcConfig = type({
|
||||
issuer: "string.url",
|
||||
client_id: "string",
|
||||
client_secret: "string",
|
||||
headscale_api_key: "string",
|
||||
headscale_api_key: type("string")
|
||||
.pipe((value, ctx) => {
|
||||
log.warn("config", "%s is deprecated, use headscale.api_key instead", ctx.propString);
|
||||
return value;
|
||||
})
|
||||
.optional(),
|
||||
use_pkce: "boolean = false",
|
||||
redirect_uri: type("string.url")
|
||||
.pipe((value, ctx) => {
|
||||
@@ -128,21 +135,21 @@ const partialOidcConfig = type({
|
||||
const agentConfig = type({
|
||||
enabled: "boolean",
|
||||
host_name: 'string = "headplane-agent"',
|
||||
pre_authkey: "string",
|
||||
cache_ttl: "number.integer = 180000",
|
||||
cache_path: 'string = "/var/lib/headplane/agent_cache.json"',
|
||||
executable_path: 'string = "/usr/libexec/headplane/agent"',
|
||||
work_dir: 'string = "/var/lib/headplane/agent"',
|
||||
pre_authkey: type("unknown").narrow(deprecatedField()).optional(),
|
||||
cache_path: type("unknown").narrow(deprecatedField()).optional(),
|
||||
});
|
||||
|
||||
const partialAgentConfig = type({
|
||||
enabled: "boolean?",
|
||||
host_name: "string?",
|
||||
pre_authkey: "string?",
|
||||
cache_ttl: "number.integer?",
|
||||
cache_path: "string?",
|
||||
executable_path: "string?",
|
||||
work_dir: "string?",
|
||||
pre_authkey: type("unknown").narrow(deprecatedField()).optional(),
|
||||
cache_path: type("unknown").narrow(deprecatedField()).optional(),
|
||||
});
|
||||
|
||||
const integrationConfig = type({
|
||||
|
||||
+27
-6
@@ -11,7 +11,7 @@ import { createDbClient } from "./db/client.server";
|
||||
import { createHeadscaleInterface } from "./headscale/api";
|
||||
import { loadHeadscaleConfig } from "./headscale/config-loader";
|
||||
import { createLiveStore, nodesResource, usersResource } from "./headscale/live-store";
|
||||
import { createHeadplaneAgent } from "./hp-agent";
|
||||
import { createAgentManager } from "./hp-agent";
|
||||
import { createAuthService } from "./web/auth";
|
||||
|
||||
declare global {
|
||||
@@ -36,10 +36,31 @@ try {
|
||||
}
|
||||
|
||||
const db = await createDbClient(join(config.server.data_path, "hp_persist.db"));
|
||||
const agents = await createHeadplaneAgent(config.integration?.agent, config.headscale.url, db);
|
||||
|
||||
const hsApi = await createHeadscaleInterface(config.headscale.url, config.headscale.tls_cert_path);
|
||||
|
||||
// Resolve the Headscale API key: headscale.api_key takes precedence,
|
||||
// falling back to the deprecated oidc.headscale_api_key for compatibility.
|
||||
const headscaleApiKey = config.headscale.api_key ?? config.oidc?.headscale_api_key;
|
||||
|
||||
const agents = headscaleApiKey
|
||||
? await createAgentManager(
|
||||
config.integration?.agent,
|
||||
config.headscale.url,
|
||||
headscaleApiKey,
|
||||
(user, ephemeral, reusable, expiration, aclTags) =>
|
||||
hsApi
|
||||
.getRuntimeClient(headscaleApiKey)
|
||||
.createPreAuthKey(user, ephemeral, reusable, expiration, aclTags),
|
||||
() => hsApi.getRuntimeClient(headscaleApiKey).getUsers(),
|
||||
db,
|
||||
)
|
||||
: (() => {
|
||||
if (config.integration?.agent?.enabled) {
|
||||
log.warn("agent", "Agent is enabled but no headscale.api_key is configured");
|
||||
}
|
||||
return undefined;
|
||||
})();
|
||||
|
||||
// We also use this file to load anything needed by the react router code.
|
||||
// These are usually per-request things that we need access to, like the
|
||||
// helper that can issue and revoke cookies.
|
||||
@@ -80,13 +101,13 @@ const appLoadContext = {
|
||||
agents,
|
||||
integration: await loadIntegration(config.integration),
|
||||
oidc:
|
||||
config.oidc && config.oidc.enabled !== false
|
||||
config.oidc && config.oidc.enabled !== false && headscaleApiKey
|
||||
? {
|
||||
apiKey: config.oidc.headscale_api_key,
|
||||
apiKey: headscaleApiKey,
|
||||
connector: createLazyOidcConnector(
|
||||
config.server.base_url,
|
||||
config.oidc,
|
||||
hsApi.getRuntimeClient(config.oidc.headscale_api_key),
|
||||
hsApi.getRuntimeClient(headscaleApiKey),
|
||||
),
|
||||
}
|
||||
: undefined,
|
||||
|
||||
Reference in New Issue
Block a user