From 5c86cc8def1b2b3221f8da565b0bd45f972c1774 Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Wed, 11 Dec 2024 11:11:10 +0100 Subject: [PATCH] update CNR --- CHANGES_NEXT_RELEASE | 3 +- lib/model/dbConn.js | 139 +++++++++++++++++++++++++------------------ package.json | 2 +- 3 files changed, 85 insertions(+), 59 deletions(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index f2bd912..e44ed29 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -2,4 +2,5 @@ - Deprecated: /iot/services API routes - Upgrade body-parser dep from 1.19.0 to 1.20.3 - Upgrade express from 4.19.2 to 4.20.0 -- Upgrade mongoose dep from 5.13.20 to 5.13.22 +- Upgrade mongodb devdep from 4.17.1 to 4.17.2 +- Upgrade mongoose dep from 5.13.22 to 8.4.4 (solving vulnerability CVE-2024-53900) (#351) diff --git a/lib/model/dbConn.js b/lib/model/dbConn.js index 99c696a..658d848 100644 --- a/lib/model/dbConn.js +++ b/lib/model/dbConn.js @@ -29,9 +29,10 @@ const mongoose = require('mongoose'); const config = require('../utils/commonConfig'); const constants = require('../utils/constants'); +const iotagentLib = require('iotagent-node-lib'); const errors = require('../errors'); const DEFAULT_DB_NAME = 'iotagent-manager'; -//let defaultDb; +let defaultDb; mongoose.Promise = global.Promise; // not including this causes DeprecationWarning @@ -40,87 +41,95 @@ function loadModels() { require('./Configuration').load(); } -// Delay function for nodejs16 -function delay(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - /** * Creates a new connection to the Mongo DB. * * @this Reference to the dbConn module itself. */ function init(logger, host, db, port, username, password, options, callback) { - let credentials = ''; + let url; let retries = 0; let lastError; - if (username && password) { - credentials = `${username}:${password}@`; + const maxRetries = config.getConfig().mongodb?.retries || constants.DEFAULT_MONGODB_RETRIES; + + function addPort(item) { + return `${item}:${port}`; } - const hosts = host - .split(',') - .map((item) => `${item}:${port}`) - .join(','); - let url = `mongodb://${credentials}${hosts}/${db}`; + url = 'mongodb://'; - if (options.replicaSet) { - url += `?replicaSet=${options.replicaSet.rs_name}`; + if (options.auth) { + url += `${encodeURIComponent(options.auth.user)}:${encodeURIComponent(options.auth.password)}@`; + } + + const hosts = host.split(',').map(addPort).join(','); + url += `${hosts}/${db}`; + + if (options.extraArgs) { + const query = new URLSearchParams(options.extraArgs).toString(); + if (query) { + url += `?${query}`; + } + delete options.extraArgs; } - const maxRetries = config.getConfig().mongodb?.retries || constants.DEFAULT_MONGODB_RETRIES; - const retryTime = config.getConfig().mongodb?.retryTime || constants.DEFAULT_MONGODB_RETRY_TIME; - // /* eslint-disable no-await-in-loop */ - // for (let attempt = 1; attempt <= maxRetries; attempt++) { - // try { - // logger.info(`Attempt ${attempt}: Connecting to MongoDB at ${url}`); - // mongoose.connect(url, options); - // //logger.info('Successfully connected to MongoDB.'); - - // // Register events - // mongoose.connection.on('error', (err) => logger.error('Mongo Driver error:', err)); - // mongoose.connection.on('connected', () => logger.debug('Mongo Driver connected')); - // mongoose.connection.on('disconnected', () => logger.debug('Mongo Driver disconnected')); - // mongoose.connection.on('reconnectFailed', () => { - // logger.error('MONGODB-004: MongoDB connection was lost'); - // process.exit(1); - // }); - // //module.exports.db = defaultDb; - // loadModels(); - // break; // End loop if connection was OK - // } catch (error) { - // logger.error(`Attempt ${attempt} failed: ${error}`); - // if (attempt < maxRetries) { - // logger.info(`Retrying in ${retryTime} seconds...`); - // delay(retryTime * 1000); - // } else { - // throw new Error(`MONGODB-002: Connection failed after ${maxRetries} attempts.`); - // } - // } - // } - // /* eslint-enable no-await-in-loop */ function connectionAttempt(callback) { - logger.info(context, `Attempting to connect to MongoDB at ${url}. Attempt ${retries + 1}`); + logger.info(`Attempting to connect to MongoDB at ${url}. Attempt ${retries + 1}`); mongoose .connect(url, options) .then(() => { - //defaultDb = connection.connection; defaultDb = mongoose.connection; - logger.info(context, 'Successfully connected to MongoDB.'); + logger.info('Successfully connected to MongoDB.'); loadModels(); + defaultDb.on('error', function (error) { + logger.error('Mongo Driver error: %j', error); + lastError = error; + iotagentLib.alarms.raise(iotagentLib.constants.MONGO_ALARM, error); + }); + /* eslint-disable-next-line no-unused-vars */ + defaultDb.on('connecting', function (error) { + logger.debug('Mongo Driver connecting'); + }); + defaultDb.on('connected', function () { + logger.debug('Mongo Driver connected'); + }); + defaultDb.on('reconnected', function () { + logger.debug('Mongo Driver reconnected'); + }); + defaultDb.on('disconnected', function () { + logger.debug('Mongo Driver disconnected'); + }); + defaultDb.on('reconnectFailed', function () { + logger.error('MONGODB-004: MongoDB connection was lost'); + process.exit(1); + }); + defaultDb.on('disconnecting', function () { + logger.debug('Mongo Driver disconnecting'); + }); + defaultDb.on('open', function () { + logger.debug('Mongo Driver open'); + }); + defaultDb.on('close', function () { + logger.debug('Mongo Driver close'); + }); callback(); }) .catch((err) => { - logger.error(context, `MONGODB-001: Error trying to connect to MongoDB: ${err}`); - //lastError = err; + logger.error(`MONGODB-001: Error trying to connect to MongoDB: ${err}`); + lastError = err; retries++; if (retries < maxRetries) { - //const retryTime = config.getConfig().mongodb?.retryTime || constants.DEFAULT_MONGODB_RETRY_TIME; - logger.info(context, `Retrying in ${retryTime} seconds...`); + const retryTime = config.getConfig().mongodb?.retryTime || constants.DEFAULT_MONGODB_RETRY_TIME; + logger.info(`Retrying in ${retryTime} seconds...`); setTimeout(() => connectionAttempt(callback), retryTime * 1000); } else { - logger.error(context, `MONGODB-002: Failed to connect after ${maxRetries} attempts.`); + logger.error( + context, + 'MONGODB-002: Error to connect found after %d attempts: %s', + retries, + lastError + ); callback(err); } }); @@ -138,7 +147,23 @@ function configureDb(logger, callback) { const dbName = currentConfig.mongodb.db || DEFAULT_DB_NAME; const port = currentConfig.mongodb.port || 27017; - const options = currentConfig.mongodb.replicaSet ? { replicaSet: currentConfig.mongodb.replicaSet } : {}; + const options = {}; + + if (currentConfig.mongodb.replicaSet) options.replicaSet = currentConfig.mongodb.replicaSet; + if (currentConfig.mongodb.ssl) options.ssl = currentConfig.mongodb.ssl; + if (currentConfig.mongodb.extraArgs) options.extraArgs = currentConfig.mongodb.extraArgs; + if (currentConfig.mongodb.user && currentConfig.mongodb.password) { + options.auth = { + user: currentConfig.mongodb.user, + password: currentConfig.mongodb.password + }; + if (currentConfig.mongodb.authSource) { + options.extraArgs = { + ...options.extraArgs, + authSource: currentConfig.mongodb.authSource + }; + } + } init( logger, @@ -153,5 +178,5 @@ function configureDb(logger, callback) { } exports.configureDb = configureDb; -//exports.db = defaultDb; +exports.db = defaultDb; exports.DEFAULT_DB_NAME = DEFAULT_DB_NAME; diff --git a/package.json b/package.json index 2cdd52b..0c2bca3 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "husky": "~4.2.5", "lint-staged": "~10.2.11", "mocha": "8.0.1", - "mongodb": "4.17.0", + "mongodb": "4.17.2", "nock": "13.0.3", "nyc": "~15.1.0", "prettier": "~2.0.5",