From e796e7f06d73a74a403000c53942d56cab91781b Mon Sep 17 00:00:00 2001 From: Michael Kret <88898367+michael-radency@users.noreply.github.com> Date: Wed, 10 Jan 2024 15:02:05 +0200 Subject: [PATCH] feat(MongoDB Node): Add support for TLS (#8266) --- .../credentials/MongoDb.credentials.ts | 62 +++++++++++++++++++ .../nodes/MongoDb/GenericFunctions.ts | 32 +++++++++- .../nodes-base/nodes/MongoDb/MongoDb.node.ts | 13 ++-- 3 files changed, 99 insertions(+), 8 deletions(-) diff --git a/packages/nodes-base/credentials/MongoDb.credentials.ts b/packages/nodes-base/credentials/MongoDb.credentials.ts index f018e67b59932..495e9ed5b83f2 100644 --- a/packages/nodes-base/credentials/MongoDb.credentials.ts +++ b/packages/nodes-base/credentials/MongoDb.credentials.ts @@ -96,5 +96,67 @@ export class MongoDb implements ICredentialType { }, default: 27017, }, + { + displayName: 'Use TLS', + name: 'tls', + type: 'boolean', + default: false, + }, + { + displayName: 'CA Certificate', + name: 'ca', + type: 'string', + typeOptions: { + password: true, + }, + displayOptions: { + show: { + tls: [true], + }, + }, + default: '', + }, + { + displayName: 'Public Client Certificate', + name: 'cert', + type: 'string', + typeOptions: { + password: true, + }, + displayOptions: { + show: { + tls: [true], + }, + }, + default: '', + }, + { + displayName: 'Private Client Key', + name: 'key', + type: 'string', + typeOptions: { + password: true, + }, + displayOptions: { + show: { + tls: [true], + }, + }, + default: '', + }, + { + displayName: 'Passphrase', + name: 'passphrase', + type: 'string', + typeOptions: { + password: true, + }, + displayOptions: { + show: { + tls: [true], + }, + }, + default: '', + }, ]; } diff --git a/packages/nodes-base/nodes/MongoDb/GenericFunctions.ts b/packages/nodes-base/nodes/MongoDb/GenericFunctions.ts index 1be13325373ad..3dc6be03abfa9 100644 --- a/packages/nodes-base/nodes/MongoDb/GenericFunctions.ts +++ b/packages/nodes-base/nodes/MongoDb/GenericFunctions.ts @@ -8,13 +8,16 @@ import { NodeOperationError } from 'n8n-workflow'; import get from 'lodash/get'; import set from 'lodash/set'; -import { ObjectId } from 'mongodb'; +import { MongoClient, ObjectId } from 'mongodb'; import type { IMongoCredentials, IMongoCredentialsType, IMongoParametricCredentials, } from './mongoDb.types'; +import { createSecureContext } from 'tls'; +import { formatPrivateKey } from '../../utils/utilities'; + /** * Standard way of building the MongoDB connection string, unless overridden with a provided string * @@ -140,3 +143,30 @@ export function stringifyObjectIDs(items: IDataObject[]) { } }); } + +export async function connectMongoClient(connectionString: string, credentials: IDataObject = {}) { + let client: MongoClient; + + if (credentials.tls) { + const ca = credentials.ca ? formatPrivateKey(credentials.ca as string) : undefined; + const cert = credentials.cert ? formatPrivateKey(credentials.cert as string) : undefined; + const key = credentials.key ? formatPrivateKey(credentials.key as string) : undefined; + const passphrase = (credentials.passphrase as string) || undefined; + + const secureContext = createSecureContext({ + ca, + cert, + key, + passphrase, + }); + + client = await MongoClient.connect(connectionString, { + tls: true, + secureContext, + }); + } else { + client = await MongoClient.connect(connectionString); + } + + return client; +} diff --git a/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts b/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts index 304abe6c38772..f506b26d5592f 100644 --- a/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts +++ b/packages/nodes-base/nodes/MongoDb/MongoDb.node.ts @@ -17,12 +17,13 @@ import type { UpdateOptions, Sort, } from 'mongodb'; -import { MongoClient, ObjectId } from 'mongodb'; +import { ObjectId } from 'mongodb'; import { generatePairedItemData } from '../../utils/utilities'; import { nodeProperties } from './MongoDbProperties'; import { buildParameterizedConnString, + connectMongoClient, prepareFields, prepareItems, stringifyObjectIDs, @@ -74,7 +75,7 @@ export class MongoDb implements INodeType { ); } - const client: MongoClient = await MongoClient.connect(connectionString); + const client = await connectMongoClient(connectionString, credentials); const { databases } = await client.db().admin().listDatabases(); @@ -100,12 +101,10 @@ export class MongoDb implements INodeType { }; async execute(this: IExecuteFunctions): Promise { - const { database, connectionString } = validateAndResolveMongoCredentials( - this, - await this.getCredentials('mongoDb'), - ); + const credentials = await this.getCredentials('mongoDb'); + const { database, connectionString } = validateAndResolveMongoCredentials(this, credentials); - const client: MongoClient = await MongoClient.connect(connectionString); + const client = await connectMongoClient(connectionString, credentials); const mdb = client.db(database);