Jun 062012
 

There are many occasions where you get locked out of a Mongo DB database. It could be that the admin password is unknown, or that the only admin user that exists is “read-only” (something that Mongo permits you to do). Fortunately, it’s fairly straightforward to remove the admin database safely and recreate the admin user.

Mongo DB has an idiomatic, not to mention pragmatic approach to user authorization. Access to the database is simplified, and not particular granular, with the idea that access control should be passed more to the connecting application itself. Thus, the default access control is to have no users at all. You need to create an “admin” user account if you want one. Nothing, however enforces this.

One creates an admin user by creating a user on the “admin” database, after logging in to Mongo:

  # mongo localhost
MongoDB shell version: 2.0.2
connecting to: localhost/test
  > use admin
switched to db admin
  >  db.addUser("admin","Password")

And that’s it.

Once this user exists, then every time you login to the database, you need to authenticate, like this:

  # mongo localhost
MongoDB shell version: 2.0.2
connecting to: localhost/test
  > use admin
switched to db admin
  mongo> db.auth("admin","Password")

Failure to authenticate will allow you your connection, but no access to any data. Once again, it’s the fact of the existence of the admin user which enforces access control, as well as the following option in the Mongo DB config file:

  auth=true

Solution

This solution will focus on removal of the admin user in a replica set, because it’s slightly more complicated, and slightly more interesting. If you’re just running a single node, the procedure is considerably easier. Just ignore the cluster steps.

Stop all Mongo processes running in the replica set. These will probably be running with the command line or config file option of “replSet”. Check by running “ps” or checking the /etc/mongod.conf file.

When no Mongo replicas are running, perform the following procedure on each node in turn. You’ll need to bring the Mongo process up at one point, but it is vital that only one replica is running at any one time, otherwise the configuration will get resynchronised from another node, and you don’t want that. You want it changed.

On each node

Change to the mongo directory where the data files reside, possibly /var/lib/mongo but specified in the configuration file by the dbPath parameter.

  # cd /var/lib/mongo

Move the admin.* files somewhere else to back them up.

  # mv admin.* /tmp

It’s that simple. Deleting these datafiles will have removed the admin credentials from the database.

Start the mongo replica daemon on this single node. Depending on your distribution and how it’s configured, it’s probably something like this:

  # /etc/init.d/mongod start
  # mongo localhost
MongoDB shell version: 2.0.2
connecting to: localhost/test
  > use admin
switched to db admin
  > db.addUser("admin","password")

At this point, the admin datafiles should have been recreated. Check that the credentials work:

  > db.auth("admin","password")
1

If this returns the numeral “1”, then the login is successful. However, if this is a cluster, the node you’re on may have been marked as stale. To check and fix:

  > db.system.users.find()
error: { "$err" : "not master and slaveok=false", "code" : 13435 }
  > rs.slaveOk()
not master and slaveok=false

The rs.slaveOk() command will allow you to query normally from the secondary:

  SECONDARY> db.system.users.find()
{ "_id" : ObjectId("4fc4972525a7b704e9a3a09e"), "user" : "admin", "readOnly" : false, "pwd" : "2f1bffb1d28a2cca21679103652b1040" }

Now stop mongo, and repeat the above procedure on the other nodes:

  # /etc/init.d/mongod stop

When you have updated the admin password on all mongod replicas, restart all nodes in the replica set.

Now, you should find that all nodes have admin user accounts, and that you can use these to authenticate against each one.


Matt Parsons is a freelance Linux specialist who has designed, built and supported Unix and Linux systems in the finance, telecommunications and media industries.

He lives and works in London.

  6 Responses to “Mongo DB: forcing removal of the admin user”

  1. Thank you so much. This was very helpful.

  2. Do you mean to say # mv admin.* /tmp
    rather than # mv /admin.* /tmp?

    • I do indeed. Thanks very much for spotting that. That was a pretty silly typo. I’ve updated the post now.

  3. Thanks!

  4. In a sharded cluster environment (current build is 2.4.8 at the time of this writing) and using a keyFile on all instances/nodes (which inplies authentication), the admin.* files are hosted in the dbpath on the config server(s). After stopping ALL the mongos and mongod processes, move the admin.* files out of the dbpath location on EACH config server.
    Make sure you are NOT using the startup parameter enableLocalhostAuthBypass=0
    Then proceed with your normal processes startup routine: config servers first; mongod (replSets) next; then mongos processes. Because this is a sharded cluster, and the admin db is hosted on the config servers instead of the data repositories themselves, you only need to create one (1) admin account once.

    To do so, connect to your local system where one of your mongos processes is running and connect to your mongos process using the mongo client console
    mongo --host 127.0.0.1 --port your_mongos_port
    substituting your actual mongos port number. You should then be at a mongos prompt.
    mongos>
    At your mongos prompt, change to the admin db, then add your admin account.
    Note: MongoDB version 2.4 introduced new parameters and syntax to the db.addUser command.
    mongos> use admin
    mongos> db.addUser( { user:"YourNewAdminAccount", pwd:"YourNewPassword", roles: [ "dbAdminAnyDatabase","clusterAdmin" ] } )

    You should get a response of something like the following, and, your cursor will have changed
    {
    "user" : "YourNewAdminAccount",
    "pwd" : "YourNewPassword",
    "roles" : [
    "userAdminAnyDatabase",
    "clusterAdmin"
    ],
    "_id" : ObjectId("hexadecimal_ObjectId")
    }
    >

    because at least one account exists and authentication was/is enabled.
    The reason for the additional role of clusterAdmin is to avoid errors in the future if the account is used to drop a database from a cluster.
    You must now authenticate using your new credentials:
    > db.auth("YourNewAdminAccount","YourNewPassword")
    You should receive a 1 as a response and be returned to your mongos prompt:
    1
    mongos>

    You may now exit your mongos console connection as your new admin account has been created.

    • Question about the line
      “After stopping ALL the mongos and mongod processes…”

      Do you need to stop all of the mongod processes or just the ones that are config servers?

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>