Connecting to MongoDB - Command 'createIndexes' requires authentication (Maybe Agenda.js related?) - node.js

As I'm introducing authentication for my MongoDB instance in Docker, I ran into problems which are probably related to the way agenda.js tries to connect to MongoDB, as the connection string invokes successful logs for mongoose connecting to the DB, therefore I assume the string should be valid.
Everything worked until I changed the connection string to use authentication. I verified the users are properly created in the database and also tried variations of the connection string and deleting/installing node modules.
Following output I get upon running docker-compose up:
server | /server/node_modules/agenda/node_modules/mongodb/lib/utils.js:133
server | throw err;
server | ^
server |
server | MongoError: command createIndexes requires authentication
server | at Connection.<anonymous> (/server/node_modules/agenda/node_modules/mongodb/lib/core/connection/pool.js:466:61)
server | at Connection.emit (events.js:314:20)
server | at processMessage (/server/node_modules/agenda/node_modules/mongodb/lib/core/connection/connection.js:384:10)
server | at Socket.<anonymous> (/server/node_modules/agenda/node_modules/mongodb/lib/core/connection/connection.js:553:15)
server | at Socket.emit (events.js:314:20)
server | at addChunk (_stream_readable.js:297:12)
server | at readableAddChunk (_stream_readable.js:272:9)
server | at Socket.Readable.push (_stream_readable.js:213:10)
server | at TCP.onStreamRead (internal/stream_base_commons.js:188:23)
server | Emitted 'error' event on Agenda instance at:
server | at /server/node_modules/agenda/lib/agenda/db-init.js:23:14
server | at /server/node_modules/agenda/node_modules/mongodb/lib/operations/execute_operation.js:76:14
server | at /server/node_modules/agenda/node_modules/mongodb/lib/operations/execute_operation.js:63:27
server | at ClientSession.endSession (/server/node_modules/agenda/node_modules/mongodb/lib/core/sessions.js:135:41)
server | at executeCallback (/server/node_modules/agenda/node_modules/mongodb/lib/operations/execute_operation.js:59:17)
server | at handleCallback (/server/node_modules/agenda/node_modules/mongodb/lib/utils.js:129:55)
server | at /server/node_modules/agenda/node_modules/mongodb/lib/operations/create_index.js:85:14
server | at handleCallback (/server/node_modules/agenda/node_modules/mongodb/lib/utils.js:129:55)
server | at /server/node_modules/agenda/node_modules/mongodb/lib/operations/command.js:113:23
server | at /server/node_modules/agenda/node_modules/mongodb/lib/core/connection/pool.js:420:18
server | at processTicksAndRejections (internal/process/task_queues.js:79:11) {
server | ok: 0,
server | errmsg: 'command createIndexes requires authentication',
server | code: 13,
server | codeName: 'Unauthorized',
server | [Symbol(mongoErrorContextSymbol)]: {}
server | }
package.json
"dependencies": {
"agenda": "^4.1.2",
"axios": "^0.21.1",
"bcryptjs": "^2.4.3",
"body-parser": "latest",
"express": "^4.17.1",
"infinite-timeout": "^0.1.0",
"jsonwebtoken": "^8.5.1",
"method-override": "^3.0.0",
"mongoose": "^5.12.4",
"mosca": "^2.8.3",
"passport": "^0.4.1",
"passport-jwt": "^4.0.0",
"websocket": "^1.0.34",
"webstorm": "^1.0.0",
"ws": "latest"
},
"devDependencies": {
"#shelf/jest-mongodb": "^1.1.3",
"#types/express": "^4.17.1",
"cors": "^2.8.5",
"jest": "^24.9.0"
},
"engines": {
"node": "12.x"
}
docker-compose.yml
version: "3.8"
services:
server:
container_name: server
build: .
restart: unless-stopped
ports:
- "9000:9000"
- "1883:1883"
links:
- mongo
networks:
- app-network
command: npm start
mongo:
container_name: mongo
image: mongo:4.4.4
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=superSafePassword
ports:
- "27317:27017"
volumes:
- dbdata:/data/db
- "./init.js/:/docker-entrypoint-initdb.d/init.js:ro"
restart: unless-stopped
networks:
- app-network
command: mongod
networks:
app-network:
driver: bridge
volumes:
dbdata:
node_modules:
Script to create users init.js
db = db.getSiblingDB("dbName");
db.createUser(
{
user: "dbUser",
pwd: "dbPassword",
roles: [
{
role: "readWrite",
db: "dbName"
}
]
}
);
Connection string
// mongo refers to the docker container
connectionString : 'mongodb://dbUser:dbPassword#mongo:27317/dbName',
How I initialize agenda:
class mScheduler {
constructor() {
if(typeof mScheduler.instance === 'object')
return mScheduler.instance;
this.agenda = new Agenda({ db: {address: config.connectionString, collection: 'agendaJobs', options: { useNewUrlParser: true }}, processEvery: '2 seconds', maxConcurrency : MAX_CONC});
process.on('SIGTERM', this.endJobs);
process.on('SIGINT', this.endJobs);
setImmediate(async ()=> await this.agenda.start());
mScheduler.instance = this;
return this;
}
someOtherMethods()
}
module.exports = new mScheduler();

try this
workaround these deprecation warnings with Mongoose provided options
const connectionOptions = {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
autoIndex: false
};
this.agenda = new Agenda({ db: {address: config.connectionString, collection: 'agendaJobs', options: connectionOptions}, processEvery: '2 seconds', maxConcurrency : MAX_CONC});

Related

Digital ocean mongo DB docker compose thorws "MongoServerError: Authentication failed."

Wrapping up a docker tutorial. When it comes to docker containers on my laptop, it works fine no Mongo DB issue.
But ever since I put it on digital ocean(Ubuntu 20.04 LTS x64, 2GB memory, 10GB disk) the issue occured below:
MongoServerError: Authentication failed.
at Connection.onMessage (/app/node_modules/mongodb/lib/cmap/connection.js:207:30)
at MessageStream.<anonymous> (/app/node_modules/mongodb/lib/cmap/connection.js:60:60)
at MessageStream.emit (node:events:513:28)
at processIncomingData (/app/node_modules/mongodb/lib/cmap/message_stream.js:132:20)
at MessageStream._write (/app/node_modules/mongodb/lib/cmap/message_stream.js:33:9)
at writeOrBuffer (node:internal/streams/writable:392:12)
at _write (node:internal/streams/writable:333:10)
at Writable.write (node:internal/streams/writable:337:10)
at Socket.ondata (node:internal/streams/readable:766:22)
at Socket.emit (node:events:513:28) {
ok: 0,
code: 18,
codeName: 'AuthenticationFailed',
connectionGeneration: 0,
[Symbol(errorLabels)]: Set(2) { 'HandshakeError', 'ResetPool' }
codes:
package.json
"dependencies": {
"bcryptjs": "^2.4.3",
"connect-redis": "^6.1.3",
"cors": "^2.8.5",
"express": "^4.18.2",
"express-session": "^1.17.3",
"mongoose": "^6.7.2",
"redis": "^4.5.0"
},
index.js
const {
MONGO_USER,
MONGO_PASSWORD,
MONGO_IP,
MONGO_PORT,
REDIS_URL,
REDIS_PORT,
SESSION_SECRET,
} = require("./config/config");
let redisClient = redis.createClient({
legacyMode: true,
socket: {
host: REDIS_URL,
port: REDIS_PORT,
},
});
redisClient
.connect()
.then(() => console.log("redis connected"))
.catch((e) => console.error("redis error", e));
const postRouter = require("./routes/postRoutes");
const userRouter = require("./routes/userRoutes");
const app = express();
const connectWithRetry = () => {
mongoose
.connect(
`mongodb://${MONGO_USER}:${MONGO_PASSWORD}#${MONGO_IP}:${MONGO_PORT}/?authSource=admin`
)
.then(() => console.log("successfully connected to DB"))
.catch((e) => {
console.error(e);
setTimeout(connectWithRetry, 5000);
});
};
connectWithRetry();
app.enable("trust proxy");
app.use(cors({}));
...
docker-compose.yml
version: "3"
services:
nginx:
image: nginx:stable-alpine
ports:
- "3000:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- node-app
node-app:
build: .
environment:
- PORT=3000
depends_on:
- mongo
mongo:
image: mongo
environment:
- MONGO_INITDB_ROOT_USERNAME=snap
- MONGO_INITDB_ROOT_PASSWORD=mypassword
volumes:
- mongo-db:/data/db
redis:
image: redis
volumes:
mongo-db:
docker-compose.prod.yml
version: "3"
services:
nginx:
ports:
- "80:80"
node-app:
build:
context: .
args:
NODE_ENV: production
environment:
- NODE_ENV=production
- MONGO_USER=${MONGO_USER}
- MONGO_PASSWORD=${MONGO_PASSWORD}
- SESSION_SECRET=${SESSION_SECRET}
command: node index.js
mongo:
environment:
- MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD}
The environment variables stored in .env file which located in the root directory of Ubuntu droplet. I tried hard coding the mongo uri instead of using environment variables but got the same result so pretty sure it may not be a cause.
Here's a log of db users below:
use admin
switched to db admin
admin> db.system.users.find()
[
{
_id: 'admin.snap',
userId: new UUID("4e79e245-894e-4d9a-9d76-802c970d9129"),
user: 'snap',
db: 'admin',
...
},
roles: [ { role: 'root', db: 'admin' } ]
},
{
_id: 'admin.admin',
userId: new UUID("0a8a471e-0e70-4e1c-b9ed-d99ede9ad0bd"),
user: 'admin',
db: 'admin',
...
},
roles: [ { role: 'root', db: 'admin' } ]
},
{
_id: 'test.snap',
userId: new UUID("4282b24f-9b15-4956-865f-ef9b206a499d"),
user: 'snap',
db: 'test',
...
roles: [ { role: 'readWrite', db: 'test' } ]
}
]
Thanks for your help.

How can I get the MongoDB Atlas cloud database to cooperate and connect to my Nodejs/Express app?

I'm getting a 'MongoServerSelectionError' while attempting to connect to the Atlas MongoDB cloud database. I've been working on this researching and trying different things to connect to the database but so far I've found no solution that works. I'm almost embarrased to say how long I've been working on this trying to find a solution to this problem. I've been racking my brain and searching SO, the MongoDB Community and the internet for days to no avail. The crazy part about it is that it was working at one time and now it isn't. So it seems something has changed on MongoDB's side. (see this post where someone else had the same problem and it mysteriously fixed itself: https://www.mongodb.com/community/forums/t/cannot-connect-to-mongodb-on-atlats/126634
I'd hate to abandon MongoDB Atlas altogether for another cloud-based DB development solution, especially after putting in so much time and effort finding a solution, but I'm fresh out of ideas.
Here is what I've tried:
Whitelisted my IP address and added the 'access from anywhere' device IP access to the Network Access: Whitelisting seems to be the most popular solution for most people, but didn't work for me. Also, 0.0.0.0/0 IP whitelisting is a security risk.
Made sure that MongoDB is running as service in the Windows processes.
Created an outbound rule for MongoDB in the Windows Firewall for ports 27015-27017:
Tried using the appropriate MongoDB Atlas connection strings for MongoDB Compass and the Mongosh CLI.
Here is the stacktrace:
[nodemon] starting `node app.js`
Server running in development mode on port 8001
TopologyDescription {
type: 'ReplicaSetNoPrimary',
servers: Map(3) {
'cluster0-shard-00-01.nrx14.mongodb.net:27017' => ServerDescription {
_hostAddress: new HostAddress('cluster0-shard-00-01.nrx14.mongodb.net:27017'),
address: 'cluster0-shard-00-01.nrx14.mongodb.net:27017',
type: 'Unknown',
hosts: [],
passives: [],
arbiters: [],
tags: {},
minWireVersion: 0,
maxWireVersion: 0,
roundTripTime: -1,
lastUpdateTime: 434689931,
lastWriteDate: 0,
error: [MongoNetworkError]
},
'cluster0-shard-00-02.nrx14.mongodb.net:27017' => ServerDescription {
_hostAddress: new HostAddress('cluster0-shard-00-02.nrx14.mongodb.net:27017'),
address: 'cluster0-shard-00-02.nrx14.mongodb.net:27017',
type: 'Unknown',
hosts: [],
passives: [],
arbiters: [],
tags: {},
minWireVersion: 0,
maxWireVersion: 0,
roundTripTime: -1,
lastUpdateTime: 434689992,
lastWriteDate: 0,
error: [MongoNetworkError]
},
'cluster0-shard-00-00.nrx14.mongodb.net:27017' => ServerDescription {
_hostAddress: new HostAddress('cluster0-shard-00-00.nrx14.mongodb.net:27017'),
address: 'cluster0-shard-00-00.nrx14.mongodb.net:27017',
type: 'Unknown',
hosts: [],
passives: [],
arbiters: [],
tags: {},
minWireVersion: 0,
maxWireVersion: 0,
roundTripTime: -1,
lastUpdateTime: 434689997,
lastWriteDate: 0,
error: [MongoNetworkError]
}
},
stale: false,
compatible: true,
heartbeatFrequencyMS: 10000,
localThresholdMS: 15,
setName: 'atlas-ru0p0t-shard-0',
logicalSessionTimeoutMinutes: undefined
}
[nodemon] app crashed - waiting for file changes before starting...
Here are the pertinent files:
package.json:
{
"name": "y",
"version": "1.0.0",
"description":
"main": "index.js",
"scripts": {
"start": "cross-env NODE_ENV=production node app",
"dev": "cross-env NODE_ENV=development nodemon app"
},
"author": "",
"license": "ISC",
"dependencies": {
"connect-mongo": "^4.6.0",
"cross-env": "^7.0.3",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"express-handlebars": "^6.0.6",
"express-session": "^1.17.3",
"mongoose": "^6.4.6",
"morgan": "^1.10.0",
"passport": "^0.6.0",
"passport-google-oauth20": "^2.0.0"
},
"devDependencies": {
"nodemon": "^2.0.19"
}
}
app.js
const express = require("express");
const dotenv = require("dotenv");
const connectDB = require('./config/db')
// Load config
dotenv.config({ path: './config/config.env'})
connectDB()
const app = express();
const PORT = process.env.PORT || 8001
app.listen(PORT, () =>
console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT} `)
)
db.js
const mongoose = require('mongoose')
const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI, {
// These params are no longer supported in Mongoose version 6
// useNewUrlParser: true,
// useUnifiedTopology: true,
})
console.log(`MongoDB Connected: ${conn.connection.host}`)
} catch (err) {
console.error(err.reason)
process.exit(1)
}
}
module.exports = connectDB
config.env
PORT=8888
MONGO_URI=mongodb+srv://Username1:Password1234#cluster0.nrx14.mongodb.net/myDatabase?retryWrites=true&w=majority
After numerous troubleshooting steps, I used my cell phone to tether to my computer to see if the issue was my ISP gateway. I was able to connect with no problems connecting with my phone. At that point, I knew it was an ISP issue. To connect using your ISP's internet, you have to open port 27017 on your gateway device. Search 'port forwarding' for your particular ISP to add port 27017 to the list of available ports. It's not open by default for some ISPs like mine. Good coding!

MongoClient cannot connect to mongo in another Docker container

I am currently trying to deploy my app with docker but I have some problem with mongodb.
My app is not succeeding to connect to mongodb in another container.
Here is my docker-compose.yml file:
version: "3.7"
services:
mqtt_broker:
build:
context: .
dockerfile: Dockerfile
container_name: mqtt_broker
ports:
- "4040:4040"
links:
- mqtt_db:mqtt_db
depends_on:
- mqtt_db
mqtt_db:
build:
context: ./mongo
dockerfile: Dockerfile
container_name: mqtt_db
ports:
- "27017:27017"
Here is the Dockerfile for the mongo container:
FROM mongo:latest
COPY init_docker.js /docker-entrypoint-initdb.d/
CMD mongod --replSet "rs0" --bind_ip_all
Here is how I connect to mongo in the app container:
const client = new MongoClient(config.get("dbURL"));
const mongo = await client.connect();
const db = client.db(config.get("dbName"));
with the configuration file:
{
"cors": {
"origin": "*"
},
"clientPort": 4040,
"mqttPort": 1883,
"dbURL": "mongodb://mqtt_db:27017",
"dbName": "mqtt_proxy"
}
Here the error I get with the mongo node client:
MongoServerSelectionError: Server selection timed out after 30000 ms
at Timeout._onTimeout (/broker/node_modules/mongodb/lib/sdam/topology.js:305:38)
at listOnTimeout (node:internal/timers:559:17)
at processTimers (node:internal/timers:502:7) {
reason: TopologyDescription {
type: 'Unknown',
servers: Map(1) {
'mqtt_db:27017' => ServerDescription {
_hostAddress: HostAddress { isIPv6: false, host: 'mqtt_db', port: 27017 },
address: 'mqtt_db:27017',
type: 'RSGhost',
hosts: [],
passives: [],
arbiters: [],
tags: {},
minWireVersion: 0,
maxWireVersion: 13,
roundTripTime: 35.24000000000001,
lastUpdateTime: 13896371,
lastWriteDate: 0,
topologyVersion: {
processId: ObjectId { [Symbol(id)]: [Buffer [Uint8Array]] },
counter: 0
},
logicalSessionTimeoutMinutes: 30
}
},
stale: false,
compatible: true,
heartbeatFrequencyMS: 10000,
localThresholdMS: 15,
commonWireVersion: 13,
logicalSessionTimeoutMinutes: undefined
},
code: undefined,
[Symbol(errorLabels)]: Set(0) {}
}
I can actually ping mqtt_db, the ip is resolved, but I don't see it in /etc/hosts.
I also tried to add networks in my docker-compose but it translated mqtt_db in localhost and it does not work.
Here is the repo of my project: https://gitlab.com/mqtt-broker-sniffer/sniffer
EDIT
I had to specify ?directConnection=true when I was connecting to the db.
Crédit: https://stackoverflow.com/a/70204195/19127936
const client = new MongoClient(
`${config.get("dbURL")}/${config.get("dbName")}?directConnection=true`
);
this.client = await client.connect();
this.db = client.db(config.get("dbName"));

Hapi catbox not able to connect to redis server

First of all, I would like to say that I'm new to Hapi so don't judge me hard.
I am following this tutorial trying to set up server-side caching based on Redis using catbox and catbox-redis npm packages, and I get the following error:
{
reason: Error: Connection is closed.
at Redis.connectionCloseHandler (/home/yuriy/dev/sources/all/hapi-getting-started/node_modules/ioredis/built/redis/index.js:305:24)
at Object.onceWrapper (events.js:300:26)
at Redis.emit (events.js:210:5)
at processTicksAndRejections (internal/process/task_queues.js:75:11)
}
As you can see it says that error is in ioredis (v4.14.1 according to package-lock.json) package which is dependency of catbox-redis.
I have Redis server running locally.
username#my-computer:~$ redis-cli -v
redis-cli 4.0.9
username#my-computer:~$ redis-cli
127.0.0.1:6379> ping
PONG
Here is my package.json:
{
"name": "hapi-getting-started",
"version": "1.0.0",
"description": "",
"main": "src/index.ts",
"scripts": {
"build": "rimraf dist && tsc",
"start": "rimraf dist && tsc && node dist/index.js",
"dev": "tsc -w | nodemon dist/index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"#hapi/catbox": "^10.2.3",
"#hapi/catbox-redis": "^5.0.5",
"#hapi/hapi": "^18.4.0",
"rimraf": "^3.0.0",
"typescript": "^3.7.2"
},
"devDependencies": {
"#types/hapi__catbox": "^10.2.2",
"#types/hapi__catbox-redis": "^5.0.0",
"#types/hapi__hapi": "^18.2.6",
"#types/node": "^12.12.14",
"nodemon": "^2.0.1"
}
}
And here is my src/index.ts:
const Hapi = require('#hapi/hapi');
const CatboxRedis = require('#hapi/catbox-redis');
console.log(`Running environment ${process.env.NODE_ENV || 'dev'}`);
// Catch uncaught exceptions
process.on('uncaughtException', (error: Error) => {
console.error(`uncaughtException ${error.message}`);
console.error({ reason });
});
// Catch unhandled rejected promises
process.on('unhandledRejection', (reason: any) => {
console.error(`unhandledRejection ${reason}`);
console.error({ error });
});
const init = async () => {
const server = Hapi.server({
host: 'localhost',
port: 8000,
cache: {
name: 'redis-cache',
provider: {
constructor: CatboxRedis,
options: {
partition: 'my_cached_data',
tls: {},
},
},
},
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
init();
Any ideas what I am doing wrong? I've spent a lot of time on this issue so any help would be very appreciated.
Okay, it appears that there is an issue in Hapi official docs on caching (Server-side Caching section). The solution was very simple but not obvious: I just removed tls: {},.
const server = Hapi.server({
host: 'localhost',
port: 8000,
cache: {
name: 'redis-cache',
provider: {
constructor: CatboxRedis,
options: {
partition: 'my_cached_data',
// tls: {}, <-- Here is a problem, remove this line
},
},
},
});
This is ioredis config params. From catbox-redis docs:
tls - an object representing TLS config options for ioredis.
You can find more details in ioredis docs.

NodeJS Sequelize throw new errors.AssertionError({ error connection

I'm trying to connect to a postgre(heroku) with the sequelize.
But the sequelize returns an error when starting my application
Help me us.
Error message returned when you run the command "node app.js":
$ node app.js
assert.js:42
throw new errors.AssertionError({
^
AssertionError [ERR_ASSERTION]: false == true
at Object.exports.connect (_tls_wrap.js:1036:3)
at Socket.<anonymous> (C:\DaniloNote\Pessoal\Projetos-Testes\Node8AndSequelize\node_modules\pg\lib\connection.js:94:23)
at Object.onceWrapper (events.js:315:30)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at Socket.Readable.push (_stream_readable.js:208:10)
at TCP.onread (net.js:607:20)
My file package.json
{
"name": "teste",
"description": "teste",
"author": "danilo <danilovex#gmail.com>",
"version": "0.1.0",
"engines": {
"node": "8.11.1"
},
"dependencies": {
"pg": "^7.4.2",
"pg-hstore": "^2.3.2",
"sequelize": "^4.37.7"
}
}
My file app.js
const Sequelize = require('sequelize');
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'host',
dialect: 'postgres',
dialectOptions: {
ssl: true
},
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
});
sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
This error happened when I updated my package to version 8 of the node.
Tks.

Resources