UNPKG

n8n

Version:

n8n Workflow Automation Tool

366 lines 15.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExternalSecretsManager = void 0; const settings_repository_1 = require("../databases/repositories/settings.repository"); const n8n_core_1 = require("n8n-core"); const typedi_1 = __importStar(require("typedi")); const Logger_1 = require("../Logger"); const n8n_workflow_1 = require("n8n-workflow"); const constants_1 = require("./constants"); const License_1 = require("../License"); const event_service_1 = require("../events/event.service"); const externalSecretsHelper_ee_1 = require("./externalSecretsHelper.ee"); const ExternalSecretsProviders_ee_1 = require("./ExternalSecretsProviders.ee"); const orchestration_service_1 = require("../services/orchestration.service"); let ExternalSecretsManager = class ExternalSecretsManager { constructor(logger, settingsRepo, license, secretsProviders, cipher, eventService) { this.logger = logger; this.settingsRepo = settingsRepo; this.license = license; this.secretsProviders = secretsProviders; this.cipher = cipher; this.eventService = eventService; this.providers = {}; this.cachedSettings = {}; this.initialized = false; this.initRetryTimeouts = {}; } async init() { if (!this.initialized) { if (!this.initializingPromise) { this.initializingPromise = new Promise(async (resolve) => { await this.internalInit(); this.initialized = true; resolve(); this.initializingPromise = undefined; this.updateInterval = setInterval(async () => await this.updateSecrets(), (0, externalSecretsHelper_ee_1.updateIntervalTime)()); }); } return await this.initializingPromise; } } shutdown() { clearInterval(this.updateInterval); Object.values(this.providers).forEach((p) => { void p.disconnect().catch(() => { }); }); Object.values(this.initRetryTimeouts).forEach((v) => clearTimeout(v)); } async reloadAllProviders(backoff) { this.logger.debug('Reloading all external secrets providers'); const providers = this.getProviderNames(); if (!providers) { return; } for (const provider of providers) { await this.reloadProvider(provider, backoff); } } async broadcastReloadExternalSecretsProviders() { await typedi_1.default.get(orchestration_service_1.OrchestrationService).publish('reloadExternalSecretsProviders'); } decryptSecretsSettings(value) { const decryptedData = this.cipher.decrypt(value); try { return (0, n8n_workflow_1.jsonParse)(decryptedData); } catch (e) { throw new n8n_workflow_1.ApplicationError('External Secrets Settings could not be decrypted. The likely reason is that a different "encryptionKey" was used to encrypt the data.'); } } async getDecryptedSettings(settingsRepo) { const encryptedSettings = await settingsRepo.getEncryptedSecretsProviderSettings(); if (encryptedSettings === null) { return null; } return this.decryptSecretsSettings(encryptedSettings); } async internalInit() { const settings = await this.getDecryptedSettings(this.settingsRepo); if (!settings) { return; } const providers = (await Promise.allSettled(Object.entries(settings).map(async ([name, providerSettings]) => await this.initProvider(name, providerSettings)))).map((i) => (i.status === 'rejected' ? null : i.value)); this.providers = Object.fromEntries(providers.filter((p) => p !== null).map((s) => [s.name, s])); this.cachedSettings = settings; await this.updateSecrets(); } async initProvider(name, providerSettings, currentBackoff = constants_1.EXTERNAL_SECRETS_INITIAL_BACKOFF) { const providerClass = this.secretsProviders.getProvider(name); if (!providerClass) { return null; } const provider = new providerClass(); try { await provider.init(providerSettings); } catch (e) { this.logger.error(`Error initializing secrets provider ${provider.displayName} (${provider.name}).`); this.retryInitWithBackoff(name, currentBackoff); return provider; } try { if (providerSettings.connected) { await provider.connect(); } } catch (e) { try { await provider.disconnect(); } catch { } this.logger.error(`Error initializing secrets provider ${provider.displayName} (${provider.name}).`); this.retryInitWithBackoff(name, currentBackoff); return provider; } return provider; } retryInitWithBackoff(name, currentBackoff) { if (name in this.initRetryTimeouts) { clearTimeout(this.initRetryTimeouts[name]); delete this.initRetryTimeouts[name]; } this.initRetryTimeouts[name] = setTimeout(() => { delete this.initRetryTimeouts[name]; if (this.providers[name] && this.providers[name].state !== 'error') { return; } void this.reloadProvider(name, Math.min(currentBackoff * 2, constants_1.EXTERNAL_SECRETS_MAX_BACKOFF)); }, currentBackoff); } async updateSecrets() { if (!this.license.isExternalSecretsEnabled()) { return; } await Promise.allSettled(Object.entries(this.providers).map(async ([k, p]) => { try { if (this.cachedSettings[k].connected && p.state === 'connected') { await p.update(); } } catch { this.logger.error(`Error updating secrets provider ${p.displayName} (${p.name}).`); } })); } getProvider(provider) { return this.providers[provider]; } hasProvider(provider) { return provider in this.providers; } getProviderNames() { return Object.keys(this.providers); } getSecret(provider, name) { var _a; return (_a = this.getProvider(provider)) === null || _a === void 0 ? void 0 : _a.getSecret(name); } hasSecret(provider, name) { var _a, _b; return (_b = (_a = this.getProvider(provider)) === null || _a === void 0 ? void 0 : _a.hasSecret(name)) !== null && _b !== void 0 ? _b : false; } getSecretNames(provider) { var _a; return (_a = this.getProvider(provider)) === null || _a === void 0 ? void 0 : _a.getSecretNames(); } getAllSecretNames() { return Object.fromEntries(Object.keys(this.providers).map((provider) => { var _a; return [ provider, (_a = this.getSecretNames(provider)) !== null && _a !== void 0 ? _a : [], ]; })); } getProvidersWithSettings() { return Object.entries(this.secretsProviders.getAllProviders()).map(([k, c]) => { var _a, _b; return ({ provider: (_a = this.getProvider(k)) !== null && _a !== void 0 ? _a : new c(), settings: (_b = this.cachedSettings[k]) !== null && _b !== void 0 ? _b : {}, }); }); } getProviderWithSettings(provider) { var _a, _b; const providerConstructor = this.secretsProviders.getProvider(provider); if (!providerConstructor) { return undefined; } return { provider: (_a = this.getProvider(provider)) !== null && _a !== void 0 ? _a : new providerConstructor(), settings: (_b = this.cachedSettings[provider]) !== null && _b !== void 0 ? _b : {}, }; } async reloadProvider(provider, backoff = constants_1.EXTERNAL_SECRETS_INITIAL_BACKOFF) { if (provider in this.providers) { await this.providers[provider].disconnect(); delete this.providers[provider]; } const newProvider = await this.initProvider(provider, this.cachedSettings[provider], backoff); if (newProvider) { this.providers[provider] = newProvider; } } async setProviderSettings(provider, data, userId) { var _a, _b, _c, _d; let isNewProvider = false; let settings = await this.getDecryptedSettings(this.settingsRepo); if (!settings) { settings = {}; } if (!(provider in settings)) { isNewProvider = true; } settings[provider] = { connected: (_b = (_a = settings[provider]) === null || _a === void 0 ? void 0 : _a.connected) !== null && _b !== void 0 ? _b : false, connectedAt: (_d = (_c = settings[provider]) === null || _c === void 0 ? void 0 : _c.connectedAt) !== null && _d !== void 0 ? _d : new Date(), settings: data, }; await this.saveAndSetSettings(settings, this.settingsRepo); this.cachedSettings = settings; await this.reloadProvider(provider); await this.broadcastReloadExternalSecretsProviders(); void this.trackProviderSave(provider, isNewProvider, userId); } async setProviderConnected(provider, connected) { var _a, _b, _c, _d; let settings = await this.getDecryptedSettings(this.settingsRepo); if (!settings) { settings = {}; } settings[provider] = { connected, connectedAt: connected ? new Date() : (_b = (_a = settings[provider]) === null || _a === void 0 ? void 0 : _a.connectedAt) !== null && _b !== void 0 ? _b : null, settings: (_d = (_c = settings[provider]) === null || _c === void 0 ? void 0 : _c.settings) !== null && _d !== void 0 ? _d : {}, }; await this.saveAndSetSettings(settings, this.settingsRepo); this.cachedSettings = settings; await this.reloadProvider(provider); await this.updateSecrets(); await this.broadcastReloadExternalSecretsProviders(); } async trackProviderSave(vaultType, isNew, userId) { var _a, _b; let testResult; try { testResult = await ((_a = this.getProvider(vaultType)) === null || _a === void 0 ? void 0 : _a.test()); } catch { } this.eventService.emit('external-secrets-provider-settings-saved', { userId, vaultType, isNew, isValid: (_b = testResult === null || testResult === void 0 ? void 0 : testResult[0]) !== null && _b !== void 0 ? _b : false, errorMessage: testResult === null || testResult === void 0 ? void 0 : testResult[1], }); } encryptSecretsSettings(settings) { return this.cipher.encrypt(settings); } async saveAndSetSettings(settings, settingsRepo) { const encryptedSettings = this.encryptSecretsSettings(settings); await settingsRepo.saveEncryptedSecretsProviderSettings(encryptedSettings); } async testProviderSettings(provider, data) { var _a; let testProvider = null; try { testProvider = await this.initProvider(provider, { connected: true, connectedAt: new Date(), settings: data, }); if (!testProvider) { return { success: false, testState: 'error', }; } const [success, error] = await testProvider.test(); let testState = 'error'; if (success && ((_a = this.cachedSettings[provider]) === null || _a === void 0 ? void 0 : _a.connected)) { testState = 'connected'; } else if (success) { testState = 'tested'; } return { success, testState, error, }; } catch { return { success: false, testState: 'error', }; } finally { if (testProvider) { await testProvider.disconnect(); } } } async updateProvider(provider) { if (!this.license.isExternalSecretsEnabled()) { return false; } if (!this.providers[provider] || this.providers[provider].state !== 'connected') { return false; } try { await this.providers[provider].update(); await this.broadcastReloadExternalSecretsProviders(); return true; } catch { return false; } } }; exports.ExternalSecretsManager = ExternalSecretsManager; exports.ExternalSecretsManager = ExternalSecretsManager = __decorate([ (0, typedi_1.Service)(), __metadata("design:paramtypes", [Logger_1.Logger, settings_repository_1.SettingsRepository, License_1.License, ExternalSecretsProviders_ee_1.ExternalSecretsProviders, n8n_core_1.Cipher, event_service_1.EventService]) ], ExternalSecretsManager); //# sourceMappingURL=ExternalSecretsManager.ee.js.map