Tuesday, October 15, 2013

MongoDB single user account for multiple databases

Recently, I decided to move the MongoDB backend to an Amazon EC2 instance. Among other things, I needed to set up authentication and this post is about what I learned. While working through this, I didn't find any examples for syntax of the end to end scenario and in fact had to resort to some brute force trial and error - hopefully this post will remedy some of that.

I won't go into too many details about the mechanics of setting up EC2 instances and installing Mongo here though.

Scenario

My app has 6 databases (relatively small) and the NodeJS server runs on a different EC2 instance and accesses the databases over the network. I use MongooseJS to access the MongoDB server.

This translates into the following requirements (among others)

1. Enable authentication for the MongoDB instance.

2. Create user accounts to read-write and administer the databases. I could have chosen to create user accounts per database (relatively easy to setup) but that can be a chore to maintain. Instead I opted to use a single set of user accounts that have access to all the databases (so that password updates etc. are required only once per account)

Steps

The steps below assume a vanilla install of Mongodb that can be accessed without auth over the loopback interface(127.0.0.1). Lines prefixed by # are comments and should be no-ops in a shell if you copy paste but I haven't tested every shell.

  1. Create an admin user

mongo  # fire up the mongo client on the system with MongoDB installed
use admin #switch to the admin database
db.addUser( { user: "adminuser", pwd: "mypassword", roles: [ "userAdminAnyDatabase", "clusterAdmin", "readWriteAnyDatabase" , "dbAdminAnyDatabase" ] } )

Note: The roles give you all access to any database. This is a simplification, and you should scope the roles for each user before you enter production. Read more about roles here

  1. Create database users

Continuing from the previous step, add a database user who can access any database on the system.

db.addUser( { user: "dbuser", pwd: "mypassword", roles: [ "readWriteAnyDatabase" , "dbAdminAnyDatabase" ] } )


  1. Enable auth and network access

On the Ubuntu 12.04 install that I used this meant enabling the following lines (i.e. delete the leading '#') in /etc/mongodb.conf.

port = 27017
auth=true

  1. Setup connection in your app(Node/mongoose)

var myDB = mongoose.createConnection("mongodb://dbuser:mypassword@myipaddress:27017/myfirstdb" ,{auth:{authdb:"admin"}});

The createConnection string should look familiar for the most part. The section {auth:{authdb:"admin"}} is a set of options that tells the driver to authenticate the user (dbuser) against the admin  database instead of myfirstdb.

 You can find more on CreateConnection here

And you are off to the races.

Finer access granularity

In the example above a single user dbuser was given read write access to all databases in that MongoDB instance. In the example below we'll create a database (mydb) and provide access to the user (mydbuser) defined in the admin database. mydbuser  won't have any other access or admin rights to other databases unlike the previous example.


  1. Create the database user

mongo 127.0.0.1:27017/admin -u "adminuser" -p "mypassword"  # logs you in
use admin
db.addUser( { user: "mydbuser", pwd: "mypassword", roles: [ ] } )

Note: You can replace the 127.0.0.1 ip with a public IP and login from a remote system too.

  1. Create the database and assign the user readWrite and dbAdmin roles
Continuing from the previous step

use mydb
db.addUser( { user: "mydbuser", userSource: "admin" , roles: [ "readWrite" , "dbAdmin"] } )


And you now have a user mydbuser with only access rights to the database mydb. Similarly you might divvy out access other databases or other users or both.

One last tip. If you need to login from the mongo shell to access a certain database (while authenticating against admin) use this

mongo myipaddr:27017/mydb -u "mydbuser" -p "mypassword" --authenticationDatabase admin


No comments:

Post a Comment