UNPKG

@apolitical/server

Version:

Node.js module to encapsulate Apolitical's express server setup

78 lines (61 loc) 1.96 kB
'use strict'; module.exports = ({ secretManager, config, logger }) => { let client = null; const resolvedImpersonationTarget = config.GOOGLE_IMPERSONATE_SERVICE_ACCOUNT?.trim() || null; function isImpersonationEnabled() { return resolvedImpersonationTarget !== null; } function impersonationLogContext() { return resolvedImpersonationTarget ? { targetServiceAccount: resolvedImpersonationTarget } : {}; } function getClient() { if (!client) { if (isImpersonationEnabled()) { logger.info('[secrets] using impersonation', impersonationLogContext()); } client = new secretManager.SecretManagerServiceClient(); } return client; } async function loadSecrets(opts) { const { secrets } = opts; const projectId = opts.projectId ?? config.GOOGLE_CLOUD_PROJECT; if (!projectId) { throw new Error('Missing projectId for Secret Manager'); } if (!secrets || secrets.length === 0) { return; } const secretClient = getClient(); for (const spec of secrets) { const version = spec.version ?? 'latest'; const name = `projects/${projectId}/secrets/${spec.name}/versions/${version}`; try { const [resp] = await secretClient.accessSecretVersion({ name }); const payload = resp.payload?.data?.toString('utf8'); if (!payload) { throw new Error(`Empty payload for secret ${spec.name}`); } process.env[spec.envVar] = payload; logger.info('[secrets] loaded', { name: spec.name, envVar: spec.envVar, version, }); } catch (err) { throw new Error(`Failed to load secret "${spec.name}": ${err.message}`); } } } function getSecret(envVar) { const val = process.env[envVar]; if (!val) { throw new Error(`Secret "${envVar}" not loaded`); } return val; } return { loadSecrets, getSecret, }; };