From 41f616ad687f991321e98f9283a8781870d0eaa1 Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Wed, 15 Oct 2025 16:01:01 +0200 Subject: [PATCH 1/5] fix mongodb config for for auth --- lib/model/dbConn.js | 59 ++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/lib/model/dbConn.js b/lib/model/dbConn.js index a434d5605..48f9aac64 100644 --- a/lib/model/dbConn.js +++ b/lib/model/dbConn.js @@ -49,34 +49,41 @@ function loadModels() { * * @this Reference to the dbConn module itself. */ - -function init(host, db, port, options, callback) { +function init(host, db, port, mongoConfig, options, callback) { let url; let retries = 0; let lastError; - const maxRetries = config.getConfig().mongodb?.retries || constants.DEFAULT_MONGODB_RETRIES; + const maxRetries = mongoConfig.retries || constants.DEFAULT_MONGODB_RETRIES; function addPort(item) { return `${item}:${port}`; } - url = 'mongodb://'; + // Build URL for connection + const hosts = host.split(',').map(addPort).join(','); + let authPart = ''; - if (options.auth) { - url += `${encodeURIComponent(options.auth.user)}:${encodeURIComponent(options.auth.password)}@`; + if (mongoConfig.user && mongoConfig.password) { + authPart = `${encodeURIComponent(mongoConfig.user)}:${encodeURIComponent(mongoConfig.password)}@`; } - const hosts = host.split(',').map(addPort).join(','); - url += `${hosts}/${db}`; + url = `mongodb://${authPart}${hosts}/${db}`; - if (options.extraArgs) { - const query = new URLSearchParams(options.extraArgs).toString(); - if (query) { - url += `?${query}`; - } - delete options.extraArgs; + // Extra params (authSource, replicaSet, ssl ) + const extraArgs = { + authSource: mongoConfig.authSource, + ...options.extraArgs + }; + + const query = new URLSearchParams(Object.entries(extraArgs).filter(([_, v]) => v !== undefined)).toString(); + + if (query) { + url += `?${query}`; } + // Delete extraArgs for mongoose.connect + delete options.extraArgs; + function connectionAttempt(callback) { logger.info(context, `Attempting to connect to MongoDB at ${url}. Attempt ${retries + 1}`); @@ -91,8 +98,7 @@ function init(host, db, port, options, callback) { lastError = error; alarms.raise(constants.MONGO_ALARM, error); }); - /* eslint-disable-next-line no-unused-vars */ - defaultDb.on('connecting', function (error) { + defaultDb.on('connecting', function () { logger.debug(context, 'Mongo Driver connecting'); }); defaultDb.on('connected', function () { @@ -117,6 +123,7 @@ function init(host, db, port, options, callback) { defaultDb.on('close', function () { logger.debug(context, 'Mongo Driver close'); }); + callback(); }) .catch((err) => { @@ -124,7 +131,7 @@ function init(host, db, port, options, callback) { lastError = err; retries++; if (retries < maxRetries) { - const retryTime = config.getConfig().mongodb?.retryTime || constants.DEFAULT_MONGODB_RETRY_TIME; + const retryTime = mongoConfig.retryTime || constants.DEFAULT_MONGODB_RETRY_TIME; logger.info(context, `Retrying in ${retryTime} seconds...`); setTimeout(() => connectionAttempt(callback), retryTime * 1000); } else { @@ -144,6 +151,7 @@ function init(host, db, port, options, callback) { function configureDb(callback) { const currentConfig = config.getConfig(); + if (currentConfig.deviceRegistry?.type === 'mongodb') { if (!currentConfig.mongodb?.host) { logger.fatal(context, 'MONGODB-003: No host found for MongoDB driver.'); @@ -151,26 +159,21 @@ function configureDb(callback) { } else { const dbName = currentConfig.mongodb.db || DEFAULT_DB_NAME; const port = currentConfig.mongodb.port || 27017; + 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 }; - if (currentConfig.mongodb.authSource) { - options.extraArgs = { - ...options.extraArgs, - authSource: currentConfig.mongodb.authSource - }; - } } - init(currentConfig.mongodb.host, dbName, port, options, callback); + init(currentConfig.mongodb.host, dbName, port, currentConfig.mongodb, options, callback); } } else { callback(); From ae46c49e6161208e5bb9a8fb068d5026b72ae00a Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Wed, 15 Oct 2025 16:17:48 +0200 Subject: [PATCH 2/5] update test --- .../mongodb/mongodb-connectionoptions-test.js | 78 ++++++++----------- 1 file changed, 33 insertions(+), 45 deletions(-) diff --git a/test/unit/mongodb/mongodb-connectionoptions-test.js b/test/unit/mongodb/mongodb-connectionoptions-test.js index 51cb163ca..d2ec5a53a 100644 --- a/test/unit/mongodb/mongodb-connectionoptions-test.js +++ b/test/unit/mongodb/mongodb-connectionoptions-test.js @@ -30,6 +30,7 @@ const config = require('../../../lib/commonConfig'); const mongoose = require('mongoose'); const sinon = require('sinon'); const should = require('should'); + const iotAgentConfig = { logLevel: 'FATAL', contextBroker: { @@ -50,6 +51,7 @@ const iotAgentConfig = { providerUrl: 'http://smartgondor.com', deviceRegistrationDuration: 'P1M' }; + let oldConfig; describe('dbConn.configureDb', function () { @@ -66,7 +68,7 @@ describe('dbConn.configureDb', function () { } }); - describe('When set mongodb options, it should call mongoose.createCOnnection by using below params', function () { + describe('When set mongodb options, it should call mongoose.connect using expected params', function () { const tests = [ { mongodb: { @@ -74,8 +76,7 @@ describe('dbConn.configureDb', function () { }, expected: { url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME, - options: { - } + options: {} } }, { @@ -85,8 +86,7 @@ describe('dbConn.configureDb', function () { }, expected: { url: 'mongodb://example.com:98765/' + dbConn.DEFAULT_DB_NAME, - options: { - } + options: {} } }, { @@ -96,8 +96,7 @@ describe('dbConn.configureDb', function () { }, expected: { url: 'mongodb://example.com:27017/examples', - options: { - } + options: {} } }, { @@ -119,8 +118,7 @@ describe('dbConn.configureDb', function () { }, expected: { url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME, - options: { - } + options: {} } }, { @@ -130,8 +128,7 @@ describe('dbConn.configureDb', function () { }, expected: { url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME, - options: { - } + options: {} } }, { @@ -142,12 +139,7 @@ describe('dbConn.configureDb', function () { }, expected: { url: 'mongodb://user01:pass01@example.com:27017/' + dbConn.DEFAULT_DB_NAME, - options: { - auth: { - user: 'user01', - password: 'pass01' - } - } + options: {} } }, { @@ -156,9 +148,8 @@ describe('dbConn.configureDb', function () { authSource: 'admin' }, expected: { - url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME, - options: { - } + url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME + '?authSource=admin', + options: {} } }, { @@ -174,11 +165,7 @@ describe('dbConn.configureDb', function () { expected: { url: 'mongodb://user01:pass01@example.com:98765/examples?authSource=admin', options: { - replicaSet: 'rs0', - auth: { - user: 'user01', - password: 'pass01' - } + replicaSet: 'rs0' } } }, @@ -203,8 +190,7 @@ describe('dbConn.configureDb', function () { }, expected: { url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME + '?retryWrites=true', - options: { - } + options: {} } }, { @@ -220,8 +206,7 @@ describe('dbConn.configureDb', function () { 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME + '?retryWrites=true&readPreference=nearest', - options: { - } + options: {} } }, { @@ -231,8 +216,7 @@ describe('dbConn.configureDb', function () { }, expected: { url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME, - options: { - } + options: {} } }, { @@ -242,8 +226,7 @@ describe('dbConn.configureDb', function () { }, expected: { url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME, - options: { - } + options: {} } }, { @@ -253,8 +236,7 @@ describe('dbConn.configureDb', function () { }, expected: { url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME, - options: { - } + options: {} } }, { @@ -275,18 +257,17 @@ describe('dbConn.configureDb', function () { unknownparam: 'unknown' }, expected: { - url: 'mongodb://user01:pass01@example.com:98765/examples?retryWrites=true&readPreference=nearest&w=majority&authSource=admin', + url: + 'mongodb://user01:pass01@example.com:98765/examples?' + + 'authSource=admin&retryWrites=true&readPreference=nearest&w=majority', options: { replicaSet: 'rs0', - auth: { - user: 'user01', - password: 'pass01' - }, ssl: true } } } ]; + tests.forEach(function (params) { it( 'mongodb options = ' + @@ -298,15 +279,18 @@ describe('dbConn.configureDb', function () { const cfg = Object.assign({}, iotAgentConfig, { mongodb: params.mongodb }); + stub = sinon.stub(mongoose, 'connect').callsFake(function (url, options, fn) { url.should.be.equal(params.expected.url); options.should.be.eql(params.expected.options); done(); }); + config.setConfig(cfg); + dbConn.configureDb(function (error) { if (error) { - should.fail(); + should.fail('configureDb returned an unexpected error'); } }); } @@ -314,7 +298,7 @@ describe('dbConn.configureDb', function () { }); }); - describe('When no mongodb options or "host" is empty, it should returns an error callback', function () { + describe('When no mongodb options or "host" is empty, it should return an error callback', function () { const tests = [ { mongodb: undefined @@ -328,18 +312,22 @@ describe('dbConn.configureDb', function () { } } ]; + tests.forEach(function (params) { it('mongodb options = ' + JSON.stringify(params.mongodb), function (done) { const cfg = Object.assign({}, iotAgentConfig, { mongodb: params.mongodb }); - stub = sinon.stub(mongoose, 'connect').callsFake(function (url, options, fn) { - should.fail(); + + stub = sinon.stub(mongoose, 'connect').callsFake(() => { + should.fail('mongoose.connect should not be called'); }); + config.setConfig(cfg); + dbConn.configureDb(function (error) { if (!error) { - should.fail(); + should.fail('Expected error when MongoDB host is missing'); } done(); }); From b80beefffbae702d16bd8f58c04fdf62fe7bd0ef Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Wed, 15 Oct 2025 16:43:30 +0200 Subject: [PATCH 3/5] fix linter --- lib/model/dbConn.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model/dbConn.js b/lib/model/dbConn.js index 48f9aac64..a8932a5bb 100644 --- a/lib/model/dbConn.js +++ b/lib/model/dbConn.js @@ -75,7 +75,7 @@ function init(host, db, port, mongoConfig, options, callback) { ...options.extraArgs }; - const query = new URLSearchParams(Object.entries(extraArgs).filter(([_, v]) => v !== undefined)).toString(); + const query = new URLSearchParams(Object.entries(extraArgs).filter(([, v]) => v !== undefined)).toString(); if (query) { url += `?${query}`; From 86a9a8d8545ef772f94a15a64566d1fba76234e1 Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Thu, 16 Oct 2025 10:24:36 +0200 Subject: [PATCH 4/5] update CNR --- CHANGES_NEXT_RELEASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 8b1378917..09042c1e6 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1 +1 @@ - +- FIX mongodb auth configuration (#1741) From ad861b0e799b9b1befb3d61d500385d8aed71aa8 Mon Sep 17 00:00:00 2001 From: Alvaro Vega Date: Thu, 16 Oct 2025 10:57:30 +0200 Subject: [PATCH 5/5] Update MongoDB auth configuration note --- CHANGES_NEXT_RELEASE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 09042c1e6..e757d1f1b 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1 +1 @@ -- FIX mongodb auth configuration (#1741) +- FIX: do not pass auth options to mongoose init, because is redundant (#1741)