Thursday, September 15, 2016


Enable Authentication & Authorization on 

MongoDB Ops Manager


In this note, I will describe how to enable authentication and authorization on MongoDB Ops Manager cloud control env. 

My setup is as follows
3 node rerplicaset for Ops Manager Metadata Repository
3 node rerplicaset for Ops Manager Sync Store DB 
2 node for application servers
1 node for Backup Daemon 

At high level we need to do following. 

a. Create db user in rerplicaset with right roles.
b. Modify Ops manager config files with user details
c. Create key file on replicaset nodes and copy it on all nodes (assuming you are using single key file across all replica sets. If otherwise create multiple key files)
d. Modify mongod.conf file on all nodes of all replica sets and restart mongbdb in rolling fashion.


1.  create users on both replset(metadata and blockstore/syncstore)

db.createUser(
  {
    user: "opsmanager",
    pwd: "xxxxxxx",
    roles: [ { role: "root", db: "admin" } ]
  }
)
Make sure the data is replicated.

2. modify opsmanager config files with users details

#mongo.mongoUri=mongodb://username:password@memdb03.phx.aexp.com:27017,memdb02.phx.aexp.com:27017,memdb01.phx.aexp.com:27017

3. bounce all opsmanagers and backup daemon

pbrun /etc/init.d/mongodb-mms restart


Create key file on replicaset nodes -

1. create key file on replset , both

 openssl  rand -base64 755 > /etc/mongodb.key
 chown mongod:mongod /etc/mongodb.key
 chmod  400 /etc/mongodb.key

copy /etc/mongodb.key to all db instances in both repl set.

2.  modify mongb conf files for authrization and key file (secondary, secondary, primary)

 Go to the first secondary instance and change following in conf file. (Try to do it before hand for all replica sets, all nodes)

 security:
  authorization: enabled
  keyFile: /data/mongodb/pqmrsme001/mongodb.key
  
 bounce the mongodb instance and make sure its in sync with primary

 Go to second secondary perform the above change and then primary

 pbrun /etc/init.d/mongod restart


##After first/primary node restart

[root@lpdosput00250 ~]#  mongo --port 27017 --authenticationDatabase admin -u opsmanager -p xxxxxxx
MongoDB shell version: 3.2.1
MongoDB Enterprise rs0:RECOVERING> rs.status()
{
        "set" : "rs0",
        "date" : ISODate("2016-08-18T18:46:06.886Z"),
        "myState" : 3,
        "term" : NumberLong(141),
        "heartbeatIntervalMillis" : NumberLong(2000),
        "members" : [
                {
                        "_id" : 0,
                        "name" : "10.20.176.248:28017",
                        "health" : 1,
                        "state" : 3,
                        "stateStr" : "RECOVERING",    <-- Notice the change of state
                        "uptime" : 34,
                        "optime" : {
                                "ts" : Timestamp(1471545769, 1),
                                "t" : NumberLong(141)
                        },
                        "optimeDate" : ISODate("2016-08-18T18:42:49Z"),
                        "infoMessage" : "could not find member to sync from",
                        "configVersion" : 3,
                        "self" : true
                },
                {
                        "_id" : 1,
                        "name" : "10.20.176.248:28018",
                        "health" : 0,
                        "state" : 6,
                        "stateStr" : "(not reachable/healthy)", <-- Notice the change of state
                        "uptime" : 0,
                        "optime" : {
                                "ts" : Timestamp(0, 0),
                                "t" : NumberLong(-1)
                        },
                        "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
                        "lastHeartbeat" : ISODate("2016-08-18T18:46:03.207Z"),
                        "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
                        "pingMs" : NumberLong(0),
                        "authenticated" : false,
                        "configVersion" : -1
                },
                {
                        "_id" : 2,
                        "name" : "10.20.176.248:28019",
                        "health" : 0,
                        "state" : 6,
                        "stateStr" : "(not reachable/healthy)", <-- Notice the change of state
                        "uptime" : 0,
                        "optime" : {
                                "ts" : Timestamp(0, 0),
                                "t" : NumberLong(-1)
                        },
                        "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
                        "lastHeartbeat" : ISODate("2016-08-18T18:46:03.209Z"),
                        "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
                        "pingMs" : NumberLong(0),
                        "authenticated" : false,
                        "configVersion" : -1
                }
        ],
        "ok" : 1
}

##After Secondary node restart -

MongoDB Enterprise rs0:SECONDARY> rs.status()
{
        "set" : "rs0",
        "date" : ISODate("2016-08-18T18:47:27.806Z"),
        "myState" : 2,
        "term" : NumberLong(141),
        "heartbeatIntervalMillis" : NumberLong(2000),
        "members" : [
                {
                        "_id" : 0,
                        "name" : "10.20.176.248:28017",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "PRIMARY", <-- Notice the change of state
                        "uptime" : 10,
                        "optime" : {
                                "ts" : Timestamp(1471545769, 1),
                                "t" : NumberLong(141)
                        },
                        "optimeDate" : ISODate("2016-08-18T18:42:49Z"),
                        "lastHeartbeat" : ISODate("2016-08-18T18:47:27.724Z"),
                        "lastHeartbeatRecv" : ISODate("2016-08-18T18:47:24.382Z"),
                        "pingMs" : NumberLong(0),
                        "configVersion" : 3
                },
                {
                        "_id" : 1,
                        "name" : "10.20.176.248:28018",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY", <-- Notice the change of state
                        "uptime" : 10,
                        "optime" : {
                                "ts" : Timestamp(1471545769, 1),
                                "t" : NumberLong(141)
                        },
                        "optimeDate" : ISODate("2016-08-18T18:42:49Z"),
                        "infoMessage" : "could not find member to sync from",
                        "configVersion" : 3,
                        "self" : true
                },
                {
                        "_id" : 2,
                        "name" : "10.20.176.248:28019",
                        "health" : 0,
                        "state" : 6,
                        "stateStr" : "(not reachable/healthy)", <-- Notice the change of state
                        "uptime" : 0,
                        "optime" : {
                                "ts" : Timestamp(0, 0),
                                "t" : NumberLong(-1)
                        },
                        "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
                        "lastHeartbeat" : ISODate("2016-08-18T18:47:27.726Z"),
                        "lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
                        "pingMs" : NumberLong(0),
                        "authenticated" : false,
                        "configVersion" : -1
                }
        ],
        "ok" : 1
}


##After Secondary node restart -

MongoDB Enterprise rs0:SECONDARY> rs.status()
{
        "set" : "rs0",
        "date" : ISODate("2016-08-18T18:51:29.408Z"),
        "myState" : 2,
        "term" : NumberLong(143),
        "syncingTo" : "10.20.176.248:28018",
        "heartbeatIntervalMillis" : NumberLong(2000),
        "members" : [
                {
                        "_id" : 0,
                        "name" : "10.20.176.248:28017",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY", <-- Notice the change of state
                        "uptime" : 9,
                        "optime" : {
                                "ts" : Timestamp(1471546211, 1),
                                "t" : NumberLong(143)
                        },
                        "optimeDate" : ISODate("2016-08-18T18:50:11Z"),
                        "lastHeartbeat" : ISODate("2016-08-18T18:51:25.260Z"),
                        "lastHeartbeatRecv" : ISODate("2016-08-18T18:51:29.261Z"),
                        "pingMs" : NumberLong(0),
                        "electionTime" : Timestamp(0, 0),
                        "electionDate" : ISODate("1970-01-01T00:00:00Z"),
                        "configVersion" : 3
                },
                {
                        "_id" : 1,
                        "name" : "10.20.176.248:28018",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY", <-- Notice the change of state
                        "uptime" : 9,
                        "optime" : {
                                "ts" : Timestamp(1471546211, 1),
                                "t" : NumberLong(143)
                        },
                        "optimeDate" : ISODate("2016-08-18T18:50:11Z"),
                        "lastHeartbeat" : ISODate("2016-08-18T18:51:25.260Z"),
                        "lastHeartbeatRecv" : ISODate("2016-08-18T18:51:28.127Z"),
                        "pingMs" : NumberLong(0),
                        "syncingTo" : "10.20.176.248:28017",
                        "configVersion" : 3
                },
                {
                        "_id" : 2,
                        "name" : "10.20.176.248:28019",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY", <-- Notice the change of state
                        "uptime" : 10,
                        "optime" : {
                                "ts" : Timestamp(1471546211, 1),
                                "t" : NumberLong(143)
                        },
                        "optimeDate" : ISODate("2016-08-18T18:50:11Z"),
                        "syncingTo" : "10.20.176.248:28018",
                        "infoMessage" : "syncing from: 10.20.176.248:28018",
                        "configVersion" : 3,
                        "self" : true
                }
        ],
        "ok" : 1
}


After you make this change, one has to enable the password for oplog store database so that ops manager can login 
and write oplog from replica sets to oplog store database.

From OpsMgr:  Click 'Admin' in upper right, then the 'Backup' tab, then the 'Oplog Storage' sub-tab and fill in username and password fields.

Once that is done, restart the opsmanager and backup daemon servers.

If you miss the above, you will see following error on Ops manager system warnings.

com.xgen.svc.brs.web.res.BackupConfigurationResource.updateReplicaSetConfiguration(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,boolean,java.lang.String,java.util.List,java.lang.String,java.lang.String,java.lang.String) - msg: { "serverUsed" : "memdb05:27017" , "ok" : 0.0 , "errmsg" : "not authorized on 570d36d634fc72f8790f2e63 to execute command { createIndexes: \"oplog_pdmcl101\", indexes: [ { name: \"groupId_1_rsId_1_valid_1_end_1__id_1\", ns: \"570d36d634fc72f8790f2e63.oplog_pdmcl101\", background: true, key: { groupId: 1, rsId: 1, valid: 1, end: 1, _id: 1 } } ] }" , "code" : 13} com.mongodb.CommandFailureException { "serverUsed" : "memdb05:27017" , "ok" : 0.0 , "errmsg" : "not authorized on 570d36d634fc72f8790f2e63 to execute command { createIndexes: \"oplog_pdmcl101\", indexes: [ { name: \"groupId_1_rsId_1_valid_1_end_1__id_1\", ns: \"570d36d634fc72f8790f2e63.oplog_pdmcl101\", background: true, key: { groupId: 1, rsId: 1, valid: 1, end: 1, _id: 1 } } ] }" , "code" : 13} 

Also remember that if you have monitoring and backup agents running on backup daemon, they dont need bounce coz monitoring agent does not need to talk with Meta data DB as it check the target db status and ask the opsmanager to write details to Metadata DB.