MongoDB replica set authentication guide

MongoDB replica set authentication guide

Share Everywhere

Table of contents

1. Create replica set

Launch EC2 instance & install mongoDB

You have to launch at least 3 EC2 instances. Make sure those 3 instances can connect to each other (set up ssh key, ssh config and check security groups). Use ansibe playbook (role XX.mongodb) to install mongoDB

Create mongoDB replica set

  1. In the first instance:
mongo

When mongo shell appear, run:

rs.status()
rs.initiate()

MongoDB will make the current EC2 instance become PRIMARY

  1. Add members to the replica set:
rs.add( { host: "ip-172-31-37-61.ap-northeast-1.compute.internal:27017" } )
rs.add( { host: "ip-172-31-44-98.ap-northeast-1.compute.internal:27017" } )
  1. Try to connect to the replica set:
mongo --host mongo-002
mongo --host mongo-003

Note that mongo-002 and mongo-003 is the DNS of the 2 private-IP instances: 172.31.37.61 and 172.31.44.98 (you can set alias in /etc/hosts)

If success ⇒ OK!

You can log in to mongo shell and see the status of the replica set. Example of result of rs.status() command:

rsCMS:PRIMARY> rs.status()
{
        "set" : "rsCMS",
        "date" : ISODate("2021-07-19T10:35:35.903Z"),
        "myState" : 1,
        "term" : NumberLong(3),
        "syncingTo" : "",
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "heartbeatIntervalMillis" : NumberLong(2000),
        "optimes" : {
                "lastCommittedOpTime" : {
                        "ts" : Timestamp(1626690933, 1),
                        "t" : NumberLong(3)
                },
                "readConcernMajorityOpTime" : {
                        "ts" : Timestamp(1626690933, 1),
                        "t" : NumberLong(3)
                },
                "appliedOpTime" : {
                        "ts" : Timestamp(1626690933, 1),
                        "t" : NumberLong(3)
                },
                "durableOpTime" : {
                        "ts" : Timestamp(1626690933, 1),
                        "t" : NumberLong(3)
                }
        },
        "lastStableCheckpointTimestamp" : Timestamp(1626690893, 1),
        "electionCandidateMetrics" : {
                "lastElectionReason" : "electionTimeout",
                "lastElectionDate" : ISODate("2021-07-19T09:52:53.446Z"),
                "electionTerm" : NumberLong(3),
                "lastCommittedOpTimeAtElection" : {
                        "ts" : Timestamp(0, 0),
                        "t" : NumberLong(-1)
                },
                "lastSeenOpTimeAtElection" : {
                        "ts" : Timestamp(1626685293, 1),
                        "t" : NumberLong(2)
                },
                "numVotesNeeded" : 2,
                "priorityAtElection" : 1,
                "electionTimeoutMillis" : NumberLong(10000),
                "numCatchUpOps" : NumberLong(0),
                "newTermStartDate" : ISODate("2021-07-19T09:52:53.452Z"),
                "wMajorityWriteAvailabilityDate" : ISODate("2021-07-19T09:52:54.774Z")
        },
        "members" : [
                {
                        "_id" : 0,
                        "name" : "ip-172-31-43-145.ap-northeast-1.compute.internal:27017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "uptime" : 2795,
                        "optime" : {
                                "ts" : Timestamp(1626690933, 1),
                                "t" : NumberLong(3)
                        },
                        "optimeDate" : ISODate("2021-07-19T10:35:33Z"),
                        "syncingTo" : "",
                        "syncSourceHost" : "",
                        "syncSourceId" : -1,
                        "infoMessage" : "",
                        "electionTime" : Timestamp(1626688373, 1),
                        "electionDate" : ISODate("2021-07-19T09:52:53Z"),
                        "configVersion" : 5,
                        "self" : true,
                        "lastHeartbeatMessage" : ""
                },
                {
                        "_id" : 1,
                        "name" : "ip-172-31-44-98.ap-northeast-1.compute.internal:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 2416,
                        "optime" : {
                                "ts" : Timestamp(1626690933, 1),
                                "t" : NumberLong(3)
                        },
                        "optimeDurable" : {
                                "ts" : Timestamp(1626690933, 1),
                                "t" : NumberLong(3)
                        },
                        "optimeDate" : ISODate("2021-07-19T10:35:33Z"),
                        "optimeDurableDate" : ISODate("2021-07-19T10:35:33Z"),
                        "lastHeartbeat" : ISODate("2021-07-19T10:35:34.142Z"),
                        "lastHeartbeatRecv" : ISODate("2021-07-19T10:35:34.742Z"),
                        "pingMs" : NumberLong(0),
                        "lastHeartbeatMessage" : "",
                        "syncingTo" : "ip-172-31-37-61.ap-northeast-1.compute.internal:27017",
                        "syncSourceHost" : "ip-172-31-37-61.ap-northeast-1.compute.internal:27017",
                        "syncSourceId" : 2,
                        "infoMessage" : "",
                        "configVersion" : 5
                },
                {
                        "_id" : 2,
                        "name" : "ip-172-31-37-61.ap-northeast-1.compute.internal:27017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "uptime" : 2570,
                        "optime" : {
                                "ts" : Timestamp(1626690933, 1),
                                "t" : NumberLong(3)
                        },
                        "optimeDurable" : {
                                "ts" : Timestamp(1626690933, 1),
                                "t" : NumberLong(3)
                        },
                        "optimeDate" : ISODate("2021-07-19T10:35:33Z"),
                        "optimeDurableDate" : ISODate("2021-07-19T10:35:33Z"),
                        "lastHeartbeat" : ISODate("2021-07-19T10:35:34.142Z"),
                        "lastHeartbeatRecv" : ISODate("2021-07-19T10:35:35.483Z"),
                        "pingMs" : NumberLong(0),
                        "lastHeartbeatMessage" : "",
                        "syncingTo" : "ip-172-31-43-145.ap-northeast-1.compute.internal:27017",
                        "syncSourceHost" : "ip-172-31-43-145.ap-northeast-1.compute.internal:27017",
                        "syncSourceId" : 0,
                        "infoMessage" : "",
                        "configVersion" : 5
                }
        ],
        "ok" : 1,
        "operationTime" : Timestamp(1626690933, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1626690933, 1),
                "signature" : {
                        "hash" : BinData(0,"hzd0+nqjoPVXbOcLPn1wM0sZiJM="),
                        "keyId" : NumberLong("6986536417509769219")
                }
        }
}
rsCMS:PRIMARY>

  1. Insert some sample data:
db.products.insert( { item: "card", qty: 15 } )

2. Create replica set authentication

1. Create keyfile:

cd /srv/
sudo mkdir mongodb
openssl rand -base64 756 > /srv/mongodb/keyfile
chmod 400 /srv/mongodb/keyfile
sudo chown mongod /srv/mongodb/keyfile

Note: You have to copy the keyfile that you have generated to each replica set member (also have to chmod 400 and chown mongod on member servers)

  1. Run ansible copy toi /nfs/

2. Create superuser:

Note: You have to stand on the Primary server to do this!

You have to create user root before you enable access control for the replica set. To create other users, you have to log into user root!

Log in to the mongo shell

mongo

and run:

admin = db.getSiblingDB("admin")
admin.createUser(
  {
    user: "root",
    pwd: "root",
    roles: [ { role: 'root', db: 'admin' } ]
  }
)

3. Shutdown all the members of the replica set:

  • SSH to the MongoDB servers
  • Run: sudo systemctl stop mongod

4. Modify the /etc/mongod.conf file:

You have to add security.keyFile option to the replica set:

# mongod.conf

# for documentation of all options, see:
#   <http://docs.mongodb.org/manual/reference/configuration-options/>

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

# Where and how to store data.
storage:
  dbPath: /var/lib/mongo
  journal:
    enabled: true
#  engine:
#  mmapv1:
#  wiredTiger:

# how the process runs
processManagement:
  fork: true  # fork and run in background
  pidFilePath: /var/run/mongodb/mongod.pid  # location of pidfile
  timeZoneInfo: /usr/share/zoneinfo

# network interfaces
net:
  port: 27017
#  bindIp: 127.0.0.1  # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.
  bindIp: 0.0.0.0

#security:
security:
   authorization: enabled
   keyFile: /srv/mongodb/keyfile

#operationProfiling:

replication:
  replSetName: "rsCMS"

#sharding:

## Enterprise-Only Options

#auditLog:

#snmp:

5. Start mongod again:

SSH to your mongodb servers and run:

sudo systemctl start mongod

6. Log into the mongo shell with root user:

You now can log into mongoDB using root user:

mongo -u "root" -p  --authenticationDatabase "admin"

Note: With users that authenticationDatabase is admin, –authenticationDatabase “admin” is optional

3. Create users:

1. Create user same as root but can not access to config and local:

admin = db.getSiblingDB("admin")
admin.createUser(
  {
    user: "adminrw",
    pwd: "adminrw",
    roles: [ { role: "readWriteAnyDatabase", db: "admin" } ]
  }
)

2. Create DB read only user (but can not read config and local db):

admin = db.getSiblingDB("admin")
admin.createUser(
  {
    user: "read",
    pwd: "read",
    roles: [ { role: "readAnyDatabase", db: "admin" } ]
  }
)

3. Create Database – level access control user:

use testDB1
db.createUser(
  {
    user: "admin1",
    pwd: "admin1",
    roles: [ { role: "readWrite", db: "testDB1" } ]
  }
)

When log in:

mongo -u "admin1" -p  --authenticationDatabase "testDB1"

Note: –authenticationDatabase “testDB1” is neccessary. If you do not specify ⇒ can not authenticate.

4. Create collection – level access control user:

  1. Create user – defined role:
use admin
db.createRole(
   {
     role: "manageOpRole", 
     privileges: [
       { resource: { db: "test", collection: "products" }, actions: [ "find", "update", "insert" ] },
	   { resource: { db: "testDB1", collection: "user" }, actions: [ "find", "update" ] },
	   { resource: { db: "testDB2", collection: "" }, actions: [ "listCollections" ] }
     ],
     roles: []
   }
)
  1. Create user and attach role:
admin = db.getSiblingDB("admin")
admin.createUser(
  {
    user: "cadmin2",
    pwd: "cadmin2",
    roles: [ { role: "manageOpRole", db: "admin" } ]
  }
)

4. Testing

Note: In our case, mongo-003 is primary and 001, 002 are secondaries.

Case 1: Log in to mongo shell and do not provide any authentication data ⇒ Can not find db information

MongoDB replica set authentication guide
MongoDB replica set authentication guide

Even in the case that you know that there are dbs that exist:

MongoDB replica set authentication guide
MongoDB replica set authentication guide

You can not interact with dbs

Case 2: Log into mongo shell, provide wrong authentication data:

  • Wrong password:
MongoDB replica set authentication guide
  • Wrong username:
MongoDB replica set authentication guide

Case 3: Log into mongo shell with correct authentication data:

MongoDB replica set authentication guide

Log into mongo shell with correct authentication data on secondaries:

MongoDB replica set authentication guideMongoDB replica set authentication guide

Case 4: Read Write any database but not config and local:

  • When log into by root user:
Create collection – level access control:
  • Log in by root user in secondaries:
Create collection – level access control:Log into by adminrw user:
  • Log into by adminrw user:
Create collection – level access control:

Case 5: Read only but can not read local and config DB: (log in to by read user)

Create collection – level access control:

Case 6: Access control for only one DB only: (Log into by admin1 user)

  • If connect to wrong DB:
Create collection – level access control:
  • Connect to right DB:
Create collection – level access control:

Case 7: Create collection – level access control:

Create collection – level access control:

 

Bạn thấy bài viết này như thế nào?
0 reactions

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
Image CAPTCHA
Enter the characters shown in the image.

Bài viết liên quan

Microservices Roadmap

Microservices Roadmap

- Kafka, RabbitMQ, Amazon SQS: Efficient and reliable message brokers for seamless communication between microservices.
The Data Analyst Roadmap

The Data Analyst Roadmap

**Database Knowledge**: Gain proficiency in working with databases like MySQL, PostgreSQL, or MongoDB.
Architectural patterns in software design

Architectural patterns in software design

Choose the architecture that aligns with your application's unique needs and goals. Each pattern offers a tailored approach to elevate your software system!
Exploring the Technological Marvel Behind Netflix

Exploring the Technological Marvel Behind Netflix

Ever wondered about the tech wizardry that powers your binge-watching adventures on Netflix?
Data engineers need to be proficient in at least one programming language

Roadmap to become a Data Engineer in 2024

Data engineers need to be proficient in at least one programming language