From de034526310639a4451f356b7a6ad0f01fb3fe51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Mon, 14 Apr 2025 16:58:22 +0200 Subject: [PATCH] fix(core): Fix missing encryption key check on workers (#14603) --- packages/cli/src/commands/worker.ts | 3 -- .../__tests__/instance-settings.test.ts | 20 +++++++++---- .../instance-settings/instance-settings.ts | 30 ++++++++++++------- .../worker-missing-encryption-key.error.ts | 0 4 files changed, 34 insertions(+), 19 deletions(-) rename packages/{cli/src/errors => core/src/instance-settings}/worker-missing-encryption-key.error.ts (100%) diff --git a/packages/cli/src/commands/worker.ts b/packages/cli/src/commands/worker.ts index 2fc69cb22ae..989a11a21c8 100644 --- a/packages/cli/src/commands/worker.ts +++ b/packages/cli/src/commands/worker.ts @@ -3,7 +3,6 @@ import { Flags, type Config } from '@oclif/core'; import config from '@/config'; import { N8N_VERSION, inTest } from '@/constants'; -import { WorkerMissingEncryptionKey } from '@/errors/worker-missing-encryption-key.error'; import { EventMessageGeneric } from '@/eventbus/event-message-classes/event-message-generic'; import { MessageEventBus } from '@/eventbus/message-event-bus/message-event-bus'; import { LogStreamingEventRelay } from '@/events/relays/log-streaming.event-relay'; @@ -58,8 +57,6 @@ export class Worker extends BaseCommand { } constructor(argv: string[], cmdConfig: Config) { - if (!process.env.N8N_ENCRYPTION_KEY) throw new WorkerMissingEncryptionKey(); - if (config.getEnv('executions.mode') !== 'queue') { config.set('executions.mode', 'queue'); } diff --git a/packages/core/src/instance-settings/__tests__/instance-settings.test.ts b/packages/core/src/instance-settings/__tests__/instance-settings.test.ts index b57ed99f092..c0473b90a90 100644 --- a/packages/core/src/instance-settings/__tests__/instance-settings.test.ts +++ b/packages/core/src/instance-settings/__tests__/instance-settings.test.ts @@ -2,18 +2,18 @@ import { mock } from 'jest-mock-extended'; jest.mock('node:fs', () => mock()); import * as fs from 'node:fs'; -import { InstanceSettings } from '@/instance-settings'; -import { InstanceSettingsConfig } from '@/instance-settings/instance-settings-config'; -import { Logger } from '@/logging/logger'; -import { mockInstance } from '@test/utils'; +import type { Logger } from '@/logging/logger'; + +import { InstanceSettings } from '../instance-settings'; +import { InstanceSettingsConfig } from '../instance-settings-config'; +import { WorkerMissingEncryptionKey } from '../worker-missing-encryption-key.error'; describe('InstanceSettings', () => { const userFolder = '/test'; - process.env.N8N_USER_FOLDER = userFolder; const settingsFile = `${userFolder}/.n8n/config`; const mockFs = mock(fs); - const logger = mockInstance(Logger); + const logger = mock(); const createInstanceSettings = (opts?: Partial) => new InstanceSettings( @@ -27,6 +27,9 @@ describe('InstanceSettings', () => { beforeEach(() => { jest.resetAllMocks(); mockFs.statSync.mockReturnValue({ mode: 0o600 } as fs.Stats); + + process.argv[2] = 'main'; + process.env = { N8N_USER_FOLDER: userFolder }; }); describe('If the settings file exists', () => { @@ -184,6 +187,11 @@ describe('InstanceSettings', () => { }, ); }); + + it("should throw on a worker process, if encryption key isn't set via env", () => { + process.argv[2] = 'worker'; + expect(() => createInstanceSettings()).toThrowError(WorkerMissingEncryptionKey); + }); }); describe('constructor', () => { diff --git a/packages/core/src/instance-settings/instance-settings.ts b/packages/core/src/instance-settings/instance-settings.ts index 5f8a68596b3..4d4e505c125 100644 --- a/packages/core/src/instance-settings/instance-settings.ts +++ b/packages/core/src/instance-settings/instance-settings.ts @@ -9,6 +9,7 @@ import { Memoized } from '@/decorators'; import { Logger } from '@/logging/logger'; import { InstanceSettingsConfig } from './instance-settings-config'; +import { WorkerMissingEncryptionKey } from './worker-missing-encryption-key.error'; const nanoid = customAlphabet(ALPHABET, 16); @@ -46,7 +47,7 @@ export class InstanceSettings { readonly enforceSettingsFilePermissions = this.loadEnforceSettingsFilePermissionsFlag(); - private settings = this.loadOrCreate(); + private settings: Settings; /** * Fixed ID of this n8n instance, for telemetry. @@ -54,7 +55,7 @@ export class InstanceSettings { * * @example '258fce876abf5ea60eb86a2e777e5e190ff8f3e36b5b37aafec6636c31d4d1f9' */ - readonly instanceId = this.generateInstanceId(); + readonly instanceId: string; readonly instanceType: InstanceType; @@ -68,6 +69,8 @@ export class InstanceSettings { : 'main'; this.hostId = `${this.instanceType}-${nanoid()}`; + this.settings = this.loadOrCreate(); + this.instanceId = this.generateInstanceId(); } /** @@ -177,6 +180,7 @@ export class InstanceSettings { * settings file with an auto-generated encryption key. */ private loadOrCreate(): Settings { + const encryptionKeyFromEnv = process.env.N8N_ENCRYPTION_KEY; if (existsSync(this.settingsFile)) { const content = readFileSync(this.settingsFile, 'utf8'); this.ensureSettingsFilePermissions(); @@ -189,7 +193,7 @@ export class InstanceSettings { const { encryptionKey, tunnelSubdomain } = settings; - if (process.env.N8N_ENCRYPTION_KEY && encryptionKey !== process.env.N8N_ENCRYPTION_KEY) { + if (encryptionKeyFromEnv && encryptionKey !== encryptionKeyFromEnv) { throw new ApplicationError( `Mismatching encryption keys. The encryption key in the settings file ${this.settingsFile} does not match the N8N_ENCRYPTION_KEY env var. Please make sure both keys match. More information: https://docs.n8n.io/hosting/environment-variables/configuration-methods/#encryption-key`, ); @@ -198,19 +202,25 @@ export class InstanceSettings { return { encryptionKey, tunnelSubdomain }; } + if (!encryptionKeyFromEnv) { + if (this.instanceType === 'worker') { + throw new WorkerMissingEncryptionKey(); + } + + if (!inTest) { + this.logger.info( + `No encryption key found - Auto-generating and saving to: ${this.settingsFile}`, + ); + } + } + mkdirSync(this.n8nFolder, { recursive: true }); - const encryptionKey = process.env.N8N_ENCRYPTION_KEY ?? randomBytes(24).toString('base64'); + const encryptionKey = encryptionKeyFromEnv ?? randomBytes(24).toString('base64'); const settings: Settings = { encryptionKey }; this.save(settings); - - if (!inTest && !process.env.N8N_ENCRYPTION_KEY) { - this.logger.info( - `No encryption key found - Auto-generated and saved to: ${this.settingsFile}`, - ); - } this.ensureSettingsFilePermissions(); return settings; diff --git a/packages/cli/src/errors/worker-missing-encryption-key.error.ts b/packages/core/src/instance-settings/worker-missing-encryption-key.error.ts similarity index 100% rename from packages/cli/src/errors/worker-missing-encryption-key.error.ts rename to packages/core/src/instance-settings/worker-missing-encryption-key.error.ts