diff --git a/config/sub2rank.yaml b/config/sub2rank.yaml index 17ee494..3c93246 100644 --- a/config/sub2rank.yaml +++ b/config/sub2rank.yaml @@ -109,8 +109,7 @@ runtime: mode: http baseUrl: http://sub2rank.platform-infra-development.svc.cluster.local:8080 adminToken: - sourceRef: platform-infra/apistate.env - sourceKey: APISTATE_API_KEY + envKey: APISTATE_API_KEY native-api: mode: http baseUrl: http://127.0.0.1:8080 diff --git a/src/admin-http-client.ts b/src/admin-http-client.ts index dc4a466..7983af8 100644 --- a/src/admin-http-client.ts +++ b/src/admin-http-client.ts @@ -5,7 +5,13 @@ export class AdminHttpClient { private readonly token: string; constructor(private readonly config: AppConfig, private readonly target: HttpCliTarget) { - this.token = readSecret(config, target.adminToken); + if ("envKey" in target.adminToken) { + const value = process.env[target.adminToken.envKey]; + if (!value) throw new Error(`HTTP CLI target requires env ${target.adminToken.envKey}`); + this.token = value; + } else { + this.token = readSecret(config, target.adminToken); + } } private async request(path: string, init: RequestInit = {}, timeoutMs = this.config.sub2api.requestTimeoutMs): Promise { diff --git a/src/config.ts b/src/config.ts index 9557044..3a65f90 100644 --- a/src/config.ts +++ b/src/config.ts @@ -10,6 +10,10 @@ export interface SecretRef { sourceKey: string; } +export interface EnvSecretRef { + envKey: string; +} + export interface AppConfig { apiVersion: string; kind: string; @@ -87,7 +91,7 @@ export interface EmbeddedCliTarget { export interface HttpCliTarget { mode: "http"; baseUrl: string; - adminToken: SecretRef; + adminToken: SecretRef | EnvSecretRef; } export interface ServerTarget { @@ -175,6 +179,15 @@ function secretRef(value: unknown, path: string): SecretRef { return { sourceRef: stringValue(raw, "sourceRef", path), sourceKey: stringValue(raw, "sourceKey", path) }; } +function cliTokenRef(value: unknown, path: string): SecretRef | EnvSecretRef { + const raw = object(value, path); + if (typeof raw.envKey === "string") { + if (raw.sourceRef !== undefined || raw.sourceKey !== undefined) throw new Error(`${path} must use either envKey or sourceRef/sourceKey`); + return { envKey: stringValue(raw, "envKey", path) }; + } + return secretRef(raw, path); +} + function nativeFile(parent: ObjectValue, key: string, path: string): string { const value = stringValue(parent, key, path); if (value.includes("/") || value.includes("\\") || value === "." || value === "..") throw new Error(`${path}.${key} must be a filename`); @@ -219,7 +232,7 @@ export function loadConfig(path: string): AppConfig { monitorWorkDir: stringValue(target, "monitorWorkDir", `runtime.cliTargets.${id}`), temporalTaskQueue: stringValue(target, "temporalTaskQueue", `runtime.cliTargets.${id}`), }; - else if (mode === "http") cliTargets[id] = { mode, baseUrl: stringValue(target, "baseUrl", `runtime.cliTargets.${id}`), adminToken: secretRef(target.adminToken, `runtime.cliTargets.${id}.adminToken`) }; + else if (mode === "http") cliTargets[id] = { mode, baseUrl: stringValue(target, "baseUrl", `runtime.cliTargets.${id}`), adminToken: cliTokenRef(target.adminToken, `runtime.cliTargets.${id}.adminToken`) }; else throw new Error(`runtime.cliTargets.${id}.mode must be embedded or http`); } const serverTargets: Record = {};