Karmatr0n

Programming and Infosec for fun!

MongoDB Replica Set Configuration with Authentication and Transactions Support

28 Feb 2023

I’ve been working on a Python project that requires MongoDB with transactions in recent months. The transactions feature is only available for replica sets and sharded clusters. So, the goal of this post is to provide a quick guide for configuring a development environment with authentication and transaction enabled, rather than a fully functional cluster configuration.

Prerequisites

Updating your system

1
$ sudo dnf update

Installing MongoDB

1
2
3
4
5
6
7
8
9
10
11
$ sudo vi /etc/yum.repos.d/mongodb.repo
[mongodb-org-6.0] 
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/9Server/mongodb-org/6.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-6.0.asc


$ sudo dnf install mongodb-org mongodb-mongosh
$ sudo systemctl start mongod

Creating the DB and adding user with the required roles

1
2
3
$ mongosh
> use <db_name>
> db.createUser({ user: <db_user>, pwd: <db_password>, roles: [{ role: 'dbOwner', db: <db_name> }] })

Adding the keyfile required for the Replica Set

1
2
3
4
$ sudo openssl rand -base64 768 >  /tmp/keyFile
$ sudo mv /tmp/keyFile /var/lib/mongo/
$ sudo chown mongod:mongod /var/lib/mongo/keyFile 
$ sudo chmod 600 /var/lib/mongo/keyFile

Configuring the replica set and authentication for MongoDB

1
2
3
4
5
6
7
8
9
10
11
12
13
$ sudo systemctl stop mongod
$ sudo vi /etc/mongod.conf

security:
  authorization: enabled
  keyFile: /var/lib/mongo/keyFile

replication:
  replSetName: "rs0"

$ sudo systemctl disable mongod
$ sudo systemctl enable mongod
$ sudo systemctl start mongod

Testing the database connection

1
$ mongosh 'mongodb://<db_user>:<db_password>@127.0.0.1:27017/<db_name>'

Initializing the replica set

Once connected into the database you can initialize the replica set and check the status.

1
2
rs.initiate()
rs.status()

Conclusion

After following the steps above you should have a MongoDB replica set with authentication and transactions enabled. Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );

employeesCollection = session.getDatabase("hr").employees;
eventsCollection = session.getDatabase("reporting").events;
session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );

try {
  employeesCollection.updateOne( { employee: 3 }, { $set: { status: "Inactive" } } );
  eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } );
} catch (error) {
  session.abortTransaction();
  throw error;
}

session.commitTransaction();
session.endSession();

References