UNPKG

@naturalcycles/nodejs-lib

Version:
101 lines 3.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const fs = require("fs-extra"); const __1 = require(".."); let loaded = false; // it's wrapped to be able to pipe console.* to Stackdriver const getLog = () => __1.Debug('nc:nodejs-lib:secret'); const secretMap = {}; /** * Loads plaintext secrets from process.env, removes them, stores locally. * Make sure to call this function early on server startup, so secrets are removed from process.env * * Does NOT delete previous secrets from secretMap. */ function loadSecretsFromEnv() { require('dotenv').config(); // ensure .env is loaded const secrets = {}; Object.keys(process.env) .filter(k => k.toUpperCase().startsWith('SECRET_')) .forEach(k => { secrets[k.toUpperCase()] = process.env[k]; secretMap[k.toUpperCase()] = process.env[k]; delete process.env[k]; }); loaded = true; getLog()(`${Object.keys(secrets).length} secret(s) loaded from process.env: ${Object.keys(secrets).join(', ')}`); } exports.loadSecretsFromEnv = loadSecretsFromEnv; /** * Removes process.env.SECRET_* */ function removeSecretsFromEnv() { Object.keys(process.env) .filter(k => k.toUpperCase().startsWith('SECRET_')) .forEach(k => delete process.env[k]); } exports.removeSecretsFromEnv = removeSecretsFromEnv; /** * Does NOT delete previous secrets from secretMap. * * If SECRET_ENCRYPTION_KEY argument is passed - will decrypt the contents of the file first, before parsing it as JSON. */ function loadSecretsFromJsonFile(filePath, SECRET_ENCRYPTION_KEY) { if (!fs.existsSync(filePath)) { throw new Error(`loadSecretsFromPlainJsonFile() cannot load from path: ${filePath}`); } let secrets; if (SECRET_ENCRYPTION_KEY) { const buf = fs.readFileSync(filePath); const plain = __1.decryptRandomIVBuffer(buf, SECRET_ENCRYPTION_KEY).toString('utf8'); secrets = JSON.parse(plain); } else { secrets = fs.readJsonSync(filePath); } Object.entries(secrets).forEach(([k, v]) => (secretMap[k.toUpperCase()] = v)); loaded = true; getLog()(`${Object.keys(secrets).length} secret(s) loaded from ${filePath}: ${Object.keys(secrets) .map(s => s.toUpperCase()) .join(', ')}`); } exports.loadSecretsFromJsonFile = loadSecretsFromJsonFile; /** * json secrets are always base64'd */ function secret(k, json = false) { const v = secretOptional(k, json); if (!v) { throw new Error(`secret(${k.toUpperCase()}) not found!`); } return v; } exports.secret = secret; function secretOptional(k, json = false) { requireLoaded(); const v = secretMap[k.toUpperCase()]; return v && json ? JSON.parse(__1.base64ToString(v)) : v; } exports.secretOptional = secretOptional; function getSecretMap() { requireLoaded(); return secretMap; } exports.getSecretMap = getSecretMap; /** * REPLACES secretMap with new map. */ function setSecretMap(map) { Object.keys(secretMap).forEach(k => delete secretMap[k]); Object.entries(map).forEach(([k, v]) => (secretMap[k.toUpperCase()] = v)); getLog()(`setSecretMap set ${Object.keys(secretMap).length} secret(s): ${Object.keys(map) .map(s => s.toUpperCase()) .join(', ')}`); } exports.setSecretMap = setSecretMap; function requireLoaded() { if (!loaded) { throw new Error(`Secrets were not loaded! Call loadSecrets() before accessing secrets.`); } } //# sourceMappingURL=secret.util.js.map