@uns-kit/core
Version:
Core utilities and runtime building blocks for UNS-based realtime transformers.
368 lines • 14.9 kB
JavaScript
import fs from "node:fs/promises";
import os from "node:os";
import { isSecretPlaceholder, } from "./secret-placeholders.js";
import { isHostPlaceholder, } from "./host-placeholders.js";
const INFISICAL_TOKEN_FILE = "/run/secrets/infisical_token";
const INFISICAL_PROJECT_ID_FILE = "/run/secrets/infisical_project_id";
const INFISICAL_SITE_URL_FILE = "/run/secrets/infisical_site_url";
const INFISICAL_TOKEN_FILE_ALT = "/var/lib/uns/secrets/infisical_token";
const INFISICAL_PROJECT_ID_FILE_ALT = "/var/lib/uns/secrets/infisical_project_id";
const INFISICAL_SITE_URL_FILE_ALT = "/var/lib/uns/secrets/infisical_site_url";
const envCache = new Map();
const infisicalCache = new Map();
async function readSecretFile(filePath) {
try {
const content = await fs.readFile(filePath, "utf8");
const trimmed = content.trim();
return trimmed.length > 0 ? trimmed : undefined;
}
catch (error) {
if (error.code === "ENOENT") {
return undefined;
}
throw new Error(`Failed to read Infisical secret file '${filePath}': ${error instanceof Error ? error.message : String(error)}`, { cause: error });
}
}
async function resolveInfisicalToken(options) {
const candidate = options?.token ??
process.env["INFISICAL_TOKEN"] ??
process.env["INFISICAL_PERSONAL_TOKEN"] ??
(await readSecretFile(INFISICAL_TOKEN_FILE)) ??
(await readSecretFile(INFISICAL_TOKEN_FILE_ALT));
return candidate?.trim() || undefined;
}
async function resolveInfisicalSiteUrl(options) {
const candidate = options?.siteUrl ??
process.env["INFISICAL_SITE_URL"] ??
(await readSecretFile(INFISICAL_SITE_URL_FILE)) ??
(await readSecretFile(INFISICAL_SITE_URL_FILE_ALT));
return candidate?.trim() || undefined;
}
async function resolveInfisicalProjectId(options) {
const candidate = options?.projectId ??
process.env["INFISICAL_PROJECT_ID"] ??
(await readSecretFile(INFISICAL_PROJECT_ID_FILE)) ??
(await readSecretFile(INFISICAL_PROJECT_ID_FILE_ALT));
return candidate?.trim() || undefined;
}
const structuredCloneFallback = (value) => typeof structuredClone === "function"
? structuredClone(value)
: JSON.parse(JSON.stringify(value));
export async function resolveConfigSecrets(config, options = {}) {
const working = structuredCloneFallback(config);
await resolveNode(working, options);
return working;
}
export function clearSecretResolverCaches() {
envCache.clear();
infisicalCache.clear();
defaultInfisicalFetcherCache.clear();
}
export async function resolveInfisicalConfig(options) {
const [token, projectId, siteUrl] = await Promise.all([
resolveInfisicalToken(options),
resolveInfisicalProjectId(options),
resolveInfisicalSiteUrl(options),
]);
return { token, projectId, siteUrl };
}
async function resolveNode(node, options) {
if (isSecretPlaceholder(node)) {
return resolveSecretValue(node, options);
}
if (isHostPlaceholder(node)) {
return resolveHostValue(node, options.hosts);
}
if (Array.isArray(node)) {
const resolvedArray = await Promise.all(node.map(item => resolveNode(item, options)));
return resolvedArray;
}
if (node && typeof node === "object") {
const obj = node;
for (const key of Object.keys(obj)) {
const current = obj[key];
if (isSecretPlaceholder(current)) {
const resolved = await resolveSecretValue(current, options);
if (resolved === undefined) {
delete obj[key];
}
else {
obj[key] = resolved;
}
continue;
}
if (isHostPlaceholder(current)) {
const resolved = await resolveHostValue(current, options.hosts);
if (resolved === undefined) {
delete obj[key];
}
else {
obj[key] = resolved;
}
continue;
}
const resolvedChild = await resolveNode(current, options);
obj[key] = resolvedChild;
}
return obj;
}
return node;
}
async function resolveSecretValue(placeholder, options) {
switch (placeholder.provider) {
case "env":
return resolveEnvSecret(placeholder, options);
case "infisical":
return resolveInfisicalSecret(placeholder, options);
default:
// Exhaustive check to guard future provider additions.
return assertNeverProvider(placeholder);
}
}
function assertNeverProvider(x) {
throw new Error(`Unsupported secret provider: ${JSON.stringify(x)}`);
}
async function resolveHostValue(placeholder, options) {
const effectiveOptions = options ?? {};
switch (placeholder.provider) {
case "inline":
return placeholder.value;
case "external": {
const envMap = effectiveOptions.env ?? process.env;
let resolved = await maybeResolveExternal(placeholder.key, effectiveOptions.resolveExternal);
if (resolved === undefined) {
resolved = effectiveOptions.externalHosts?.[placeholder.key];
}
if (resolved === undefined) {
resolved = envMap?.[placeholder.key];
}
if (resolved === undefined) {
if (placeholder.default !== undefined) {
return placeholder.default;
}
if (placeholder.optional) {
return undefined;
}
effectiveOptions.onMissingHost?.(placeholder);
throw new Error(`External host '${placeholder.key}' could not be resolved.`);
}
return resolved;
}
case "system":
return resolveSystemHost(placeholder, effectiveOptions);
default:
return assertNeverHostProvider(placeholder);
}
}
async function maybeResolveExternal(key, resolver) {
if (!resolver) {
return undefined;
}
try {
return await resolver(key);
}
catch (error) {
throw new Error(`Failed to resolve external host '${key}' via custom resolver: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
}
}
function assertNeverHostProvider(x) {
throw new Error(`Unsupported host provider: ${JSON.stringify(x)}`);
}
function resolveSystemHost(placeholder, options) {
const getInterfaces = options.networkInterfaces ?? os.networkInterfaces;
const interfaces = getInterfaces();
const family = placeholder.family ?? "IPv4";
const targetName = placeholder.interfaceName;
const interfaceEntries = targetName
? [[targetName, interfaces[targetName]]]
: Object.entries(interfaces);
for (const [, ifaceList] of interfaceEntries) {
if (!ifaceList) {
continue;
}
for (const iface of ifaceList) {
if (iface &&
iface.family === family &&
iface.internal !== true &&
typeof iface.address === "string" &&
iface.address.length > 0) {
return iface.address;
}
}
if (targetName) {
break;
}
}
if (placeholder.default !== undefined) {
return placeholder.default;
}
if (placeholder.optional) {
return undefined;
}
options.onMissingHost?.(placeholder);
const targetDescription = targetName ? `interface '${targetName}'` : "available interfaces";
throw new Error(`System host lookup failed for ${targetDescription} (family ${family}).`);
}
function resolveEnvSecret(placeholder, options) {
const envMap = options.env ?? process.env;
const cacheKey = placeholder.key;
if (envCache.has(cacheKey)) {
return envCache.get(cacheKey) ?? undefined;
}
const value = envMap[cacheKey];
if (value === undefined || value === null) {
if (placeholder.default !== undefined) {
envCache.set(cacheKey, placeholder.default);
return placeholder.default;
}
if (placeholder.optional) {
envCache.set(cacheKey, undefined);
return undefined;
}
options.onMissingSecret?.(placeholder, "env");
throw new Error(`Required environment variable '${cacheKey}' is not set.`);
}
envCache.set(cacheKey, value);
return value;
}
async function resolveInfisicalSecret(placeholder, options) {
const infisicalOptions = options.infisical;
const fetcher = await getInfisicalFetcher(infisicalOptions);
const environment = placeholder.environment ?? infisicalOptions?.environment ?? process.env["INFISICAL_ENVIRONMENT"];
const projectId = placeholder.projectId ?? (await resolveInfisicalProjectId(infisicalOptions));
const type = infisicalOptions?.type ?? "shared";
const cacheKey = JSON.stringify({
path: placeholder.path,
key: placeholder.key,
environment,
projectId,
type,
});
const useCache = infisicalOptions?.cache !== false;
const cached = useCache ? infisicalCache.get(cacheKey) : undefined;
if (!fetcher) {
if (cached) {
console.warn(`Infisical fetcher unavailable; using cached secret for ${placeholder.path}:${placeholder.key}.`);
return cached;
}
const fallback = placeholder.default !== undefined
? placeholder.default
: placeholder.optional
? undefined
: undefined;
console.warn(`Infisical fetcher unavailable; returning ${fallback === undefined ? "undefined" : "default"} for ${placeholder.path}:${placeholder.key}.`);
if (fallback === undefined && !placeholder.optional) {
options.onMissingSecret?.(placeholder, "infisical");
}
return fallback;
}
if (!environment) {
throw new Error(`Infisical secret '${placeholder.path}:${placeholder.key}' is missing an environment. ` +
"Set it on the placeholder, pass SecretResolverOptions.infisical.environment, or define INFISICAL_ENVIRONMENT.");
}
if (!projectId) {
throw new Error(`Infisical secret '${placeholder.path}:${placeholder.key}' is missing a project id. ` +
"Set it on the placeholder, pass SecretResolverOptions.infisical.projectId, define INFISICAL_PROJECT_ID, " +
"or provide /run/secrets/infisical_project_id (also /var/lib/uns/secrets/infisical_project_id).");
}
if (cached) {
return cached ?? undefined;
}
const fetchPromise = fetcher({
path: placeholder.path,
key: placeholder.key,
environment,
projectId,
type,
}).then(secret => {
if (secret === undefined || secret === null) {
if (placeholder.default !== undefined) {
return placeholder.default;
}
if (placeholder.optional) {
return undefined;
}
options.onMissingSecret?.(placeholder, "infisical");
throw new Error(`Secret '${placeholder.path}:${placeholder.key}' not found in Infisical.`);
}
return secret;
}).catch(error => {
if (cached) {
console.warn(`Infisical fetch failed (${error instanceof Error ? error.message : String(error)}); using cached secret for ${placeholder.path}:${placeholder.key}.`);
return cached;
}
const fallback = placeholder.default !== undefined
? placeholder.default
: placeholder.optional
? undefined
: undefined;
console.warn(`Infisical fetch failed (${error instanceof Error ? error.message : String(error)}); returning ${fallback === undefined ? "undefined" : "default"} for ${placeholder.path}:${placeholder.key}.`);
if (fallback === undefined && !placeholder.optional) {
options.onMissingSecret?.(placeholder, "infisical");
throw new Error(`Failed to fetch Infisical secret ${placeholder.path}:${placeholder.key}: ${error instanceof Error ? error.message : String(error)}`);
}
return fallback;
});
const guardedPromise = fetchPromise.then(value => value, error => {
if (useCache) {
infisicalCache.delete(cacheKey);
}
throw error;
});
if (useCache) {
infisicalCache.set(cacheKey, guardedPromise);
}
return guardedPromise;
}
async function getInfisicalFetcher(options) {
const effectiveOptions = options ?? {};
if (effectiveOptions.fetchSecret) {
return effectiveOptions.fetchSecret;
}
const token = await resolveInfisicalToken(effectiveOptions);
if (!token) {
return undefined;
}
const siteUrl = await resolveInfisicalSiteUrl(effectiveOptions);
const cacheKey = `${token}::${siteUrl ?? ""}`;
if (!defaultInfisicalFetcherCache.has(cacheKey)) {
defaultInfisicalFetcherCache.set(cacheKey, createDefaultInfisicalFetcher(token, siteUrl));
}
const baseFetcher = await defaultInfisicalFetcherCache.get(cacheKey);
return baseFetcher;
}
const defaultInfisicalFetcherCache = new Map();
async function createDefaultInfisicalFetcher(token, siteUrl) {
try {
const sdkModule = await import("@infisical/sdk");
const { InfisicalSDK, SecretType } = sdkModule;
if (!InfisicalSDK) {
throw new Error("@infisical/sdk does not export InfisicalSDK");
}
const sdkInstance = new InfisicalSDK({ siteUrl: siteUrl ?? "" });
const authenticatedSdk = sdkInstance.auth().accessToken(token);
return async ({ path, key, environment, projectId, type = "shared" }) => {
if (!environment) {
throw new Error(`Infisical secret '${path}:${key}' is missing an environment.`);
}
if (!projectId) {
throw new Error(`Infisical secret '${path}:${key}' is missing a project id.`);
}
const secret = await authenticatedSdk
.secrets()
.getSecret({
secretName: key,
secretPath: path,
environment,
projectId,
viewSecretValue: true,
type: type === "personal" ? SecretType.Personal : SecretType.Shared,
});
return secret?.secretValue ?? undefined;
};
}
catch (error) {
throw new Error("Failed to initialize @infisical/sdk. Install the package or provide SecretResolverOptions.infisical.fetchSecret.", { cause: error });
}
}
//# sourceMappingURL=secret-resolver.js.map