Daniel Watrous on Software Engineering

A Collection of Software Problems and Solutions

Posts tagged auth

Software Engineering

MongoDB Authentication Setup

Authentication in MongoDB provides ‘normal’, which is full read and write, or ‘readonly’ access at a database level. There are two scenarios when authentication comes into play: single server and multi-server. When using a single server, authentication can be enabled but adding --auth to the startup parameters.

When using a replicaset, sharded setup or combination, a key file must be provided and the --keyFile parameter used at startup. This enables each node to communicate with other nodes using a nonce scheme based on the keyFile. In this configuration, --auth is implied and the all MongoDB access then requires authentication.

The details below assume a replicaset configuration.

Creating a keyFile

The keyFile must be 1kB or less. It can be any text and for platform independence, any whitespace is ignored. On Linux, OpenSSL can be used to create a solid keyFile like this:

openssl rand -base64 258 > mongokey

At this point, the local file mongokey will contain something like this:

rMvhlWEIzktbhXN+rcTV43z2YKPGsd8YHNNuOVpZLW9bIPx1MaAeGTVullFVY4A5
B0zRpKLXcB347T/m278LK3BNBynB3mVpoe1pPmSYVjpBmo3LhsDKXywb8dU7UrBl
9bgh4NZfNaBcYykuoQsiloWNP5QtMquBymF2bh+1s+aJpvkq1FzAhsJvwcGeILBc
gnBOwZAsDXlE0M1hr0zvsulkyvFDgE2UcS+2tm4yZPKNDygA2HCcXqJypa9L2f1J
dC83SLNxbN4MkeE+NeY3ZE+LFUqTyvb827VhXfCX+S+TpD5h/otiS1GiQnTcBiSB
fYrMhLsOFPU9UYc705XDw48m

It’s important to choose a multiple of 3 (e.g. 258) so that not equal signs are added to the keyFile.

Installing keyFile

It’s important to protect this file from unauthorized access. One way to do this is to store it in a way that only the limited user mongod user has access. In my case I moved the file into a directory owned by the mongod user and set permissions restrictively.

mkdir /home/mongod
mv /home/watrous/mongokey /home/mongod/
chown -R mongod.mongod /home/mongod/
chmod -R 700 /home/mongod/

Update MongoDB configuration

With the keyFile in place and secure, I then updated the configuration file, /etc/mongo.conf, to include a reference to the keyFile by adding this line:

keyFile = /home/mongod/mongokey

MongoDB must then be restarted and will load up. After restarting you may notice chatter in the logs about failed authentication. These errors will go away as the same procedure is completed on remaining nodes and they have the keyFile available.

Establishing users

Once a keyFile has been installed as described above, MongoDB then requires authentication. Keep in mind that it is not necessary to add --auth as a startup parameter when using a keyFile.

Complete instructions for adding users can be found here: http://docs.mongodb.org/manual/tutorial/control-access-to-mongodb-with-authentication/.

I began by establishing an admin user. I did this by connecting to mongo locally on the primary node:

[watrous@system ~]$ mongo
MongoDB shell version: 2.0.6
connecting to: test
PRIMARY> use admin
switched to db admin
PRIMARY> db.addUser("admin", "bn%c@4fE0ns$!w4TFao$innIjOBKoPS*")
{
        "n" : 0,
        "lastOp" : NumberLong("5828987137181089793"),
        "connectionId" : 60,
        "err" : null,
        "ok" : 1
}
{
        "user" : "admin",
        "readOnly" : false,
        "pwd" : "f9d7f021d49ccc82b5186d16c664c652",
        "_id" : ObjectId("50e4b8eae0bdfc9063b69c32")
}
> db.auth("admin", "bn%c@4fE0ns$!w4TFao$innIjOBKoPS*")
1
PRIMARY> db.system.users.find()
{ "_id" : ObjectId("50e4b8eae0bdfc9063b69c32"), "user" : "admin", "readOnly" : false, "pwd" : "f9d7f021d49ccc82b5186d16c664c652" }

Next I established an account for a specific database. I created two accounts, one with normal access and the other with readonly access.

PRIMARY> use documents
switched to db documents
PRIMARY> db.addUser("documents_full", "*XE@D2x@nc8pfp9iKnA!!Fu!3mTd*HYY")
{
        "n" : 0,
        "lastOp" : NumberLong("5828988434261213185"),
        "connectionId" : 60,
        "err" : null,
        "ok" : 1
}
{
        "user" : "documents_full",
        "readOnly" : false,
        "pwd" : "3cd1cbaec406081b310d7f49b4284c2f",
        "_id" : ObjectId("50e4ba19e0bdfc9063b69c33")
}
PRIMARY> db.addUser("documents_readonly", "91h#Tv5prInoU%GZQDNF9AoAWN5HTEag", true)
{
        "n" : 0,
        "lastOp" : NumberLong("5828988696254218241"),
        "connectionId" : 60,
        "err" : null,
        "ok" : 1
}
{
        "user" : "documents_readonly",
        "readOnly" : true,
        "pwd" : "87cab9e7ce7a5c731b34b1a0737c2ae9",
        "_id" : ObjectId("50e4ba56e0bdfc9063b69c34")
}
PRIMARY> db.system.users.find()
{ "_id" : ObjectId("50e4ba19e0bdfc9063b69c33"), "user" : "documents_full", "readOnly" : false, "pwd" : "3cd1cbaec406081b310d7f49b4284c2f" }
{ "_id" : ObjectId("50e4ba56e0bdfc9063b69c34"), "user" : "documents_readonly", "readOnly" : true, "pwd" : "87cab9e7ce7a5c731b34b1a0737c2ae9" }

At this point I was able to verify authentication and access levels.