UNPKG

@enspirit/emb

Version:

A replacement for our Makefile-for-monorepos

83 lines (82 loc) 3.08 kB
// Matches ${provider:path#key} patterns for secret providers // We're specifically looking for non-env providers (vault, aws, azure, etc.) const SECRET_REGEX = /\${(\w+):([\w/.]+(?:-[\w/.]+)*)(?:#([\w-]+))?(?::-[^}]*)?}/g; /** * Recursively find all secret references in an object. */ // eslint-disable-next-line max-params function findSecretsInValue(value, fieldPath, location, secretProviders, results) { if (typeof value === 'string') { // Find all secret references in the string let match; SECRET_REGEX.lastIndex = 0; // Reset regex state while ((match = SECRET_REGEX.exec(value)) !== null) { const [original, provider, pathWithKey, explicitKey] = match; // Only include registered secret providers if (!secretProviders.has(provider)) { continue; } // Parse path and key - key can be after # or part of path let path = pathWithKey; let key = explicitKey; // If no explicit key via #, check if path contains # if (!key && path.includes('#')) { const hashIndex = path.indexOf('#'); key = path.slice(hashIndex + 1); path = path.slice(0, hashIndex); } results.push({ provider, path, key, original, location: { ...location, field: fieldPath, }, }); } } else if (Array.isArray(value)) { value.forEach((item, index) => { findSecretsInValue(item, `${fieldPath}[${index}]`, location, secretProviders, results); }); } else if (value !== null && typeof value === 'object') { for (const [key, val] of Object.entries(value)) { const newPath = fieldPath ? `${fieldPath}.${key}` : key; findSecretsInValue(val, newPath, location, secretProviders, results); } } } /** * Discover all secret references in a configuration object. * * @param config - The configuration object to scan * @param location - Base location information * @param secretProviders - Set of registered secret provider names to look for * @returns Array of discovered secret references */ export function discoverSecrets(config, location = {}, secretProviders = new Set()) { const results = []; findSecretsInValue(config, '', location, secretProviders, results); return results; } export function aggregateSecrets(secrets) { const map = new Map(); for (const secret of secrets) { const id = `${secret.provider}:${secret.path}#${secret.key || ''}`; if (map.has(id)) { map.get(id).locations.push(secret.location); } else { map.set(id, { provider: secret.provider, path: secret.path, key: secret.key, locations: [secret.location], }); } } return [...map.values()]; }