/** * Load secrets from Vault HTTP API * Writes secrets to .env.infisical file for sourcing */ import { writeFileSync } from "fs"; const VAULT_ADDR = process.env.VAULT_ADDR; const VAULT_TOKEN = process.env.VAULT_TOKEN; const VAULT_KV_MOUNT = process.env.VAULT_KV_MOUNT || "secret"; const VAULT_SHARED_PATH = process.env.VAULT_SHARED_PATH; const VAULT_PROJECT_PATH = process.env.VAULT_PROJECT_PATH; if (!VAULT_ADDR || !VAULT_TOKEN) { process.stderr.write("Missing required Vault environment variables (VAULT_ADDR, VAULT_TOKEN)\n"); process.exit(1); } process.stderr.write(`Loading secrets from Vault...\n`); const envLines = []; async function loadPath(path, sourceName) { if (!path) return; const url = `${VAULT_ADDR.replace(/\/$/, "")}/v1/${VAULT_KV_MOUNT}/data/${path}`; const response = await fetch(url, { headers: { "X-Vault-Token": VAULT_TOKEN }, }); if (!response.ok) { throw new Error(`Failed to load Vault path ${VAULT_KV_MOUNT}/${path}: ${response.status}`); } const json = await response.json(); const secrets = json?.data?.data || {}; const keys = Object.keys(secrets); for (const [key, value] of Object.entries(secrets)) { const escapedValue = String(value).replace(/'/g, "'\\''"); envLines.push(`export ${key}='${escapedValue}'`); } process.stderr.write(` ${sourceName}: ${keys.length} secrets loaded from ${VAULT_KV_MOUNT}/${path}\n`); } await loadPath(VAULT_SHARED_PATH, "shared"); await loadPath(VAULT_PROJECT_PATH, "project"); writeFileSync(".env.infisical", envLines.join("\n")); process.stderr.write("Secrets written to .env.infisical\n");