Overview
When you're just starting out with MongoDB e.g. playing with it on your home PC, you don't need to worry about setting up database users etc, because authentication is disabled by default.
But once you start thinking about building an application with MongoDB, you'll probably need to think about which users should be able to read/write to which databases/collections. For example, ordinary users should probably only be able to read/write certain collections in a given database, while your application admin would need to be able to do things like create collections and create indexes etc in the application database.
Coming from an RDBMS background, I found MongoDB's user set-up a bit confusing, so I put together this post on how to set up a couple of users for an application database, where some users can only read/write in a specific database/collection. I hope this will help you to get started with MongoDB's approach to user permissions etc.
Remember that this is just a learning example, so don't rely on this for your production systems.
Make sure you refer to the MongoDB authentication guide for reliable and up-to-date advice on how to do this for real!
This example also relies on the localhost exception when enabling authentication and creating your first user, so make sure this is working on your server machine. You don't want to lock yourself out of your own database!
What we will do here
This post will show you how you can do the following:
- enable authentication on a local MongoDB server
- create a user administrator (you need to do this as soon as you enable authentication)
- create a DBA super-user who can do anything
- create an application-specific database
- create an admin user for the application database only
- create a couple of collections inside the application database
- create an application-specific user role with read/write permissions for specific collections only
- create an application-specific user with that role
- check that this user can only access the specified collections
That should be enough to get you started with MongoDB user authentication.
Databases
- admin: this is where you define privileges that apply to any database.
- myappdb: an application-specific database where you want to define local user privileges.
Roles
- root: can do anything.
- userAdminAnyDatabase: can manage users on any database.
- dbOwner: can manage the relevant DB (we use this in myappdb).
- myAppUserRole: has limited access to specific collections in in myappdb.
Users
- siteUserAdmin: this user can manage users across the MongoDB server.
- superuser: this user can do anything on any DB via the “root” role.
- myappowner: this user manages the “myappdb” database via the “dbOwner” role.
- bob: this user has the “myAppUserRole” role within “myappdb“ only.
Enable authentication on MongoDB server
- See http://docs.mongodb.org/manual/tutorial/enableauthentication/ for detailed instructions.
Modify configuration to enable authentication
This is based on a Ubuntu server (other platforms may have slightly different config files).
Stop MongoDB:
sudo service mongod stop
Edit /etc/mongod.conf (in Ubuntu) and set auth=true.
This is the simplest authentication method, but you can also set up SSH authentication via keyfiles, as described in the MongoDB documentation (see above).
Restart MongoDB:
sudo service mongod start
Create default user administrator (must connect via localhost)
Connect to MongoDB shell on the DB server (localhost):
mongo
Switch to admin DB and create the site user administrator:
use admin
db.createUser({
user: "siteUserAdmin",
pwd: "secret",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
})
Reconnect to MongoDB shell on (localhost) DB server with this user:
mongo -u siteUserAdmin -p secret --authenticationDatabase admin
Create a super-user
Log into the MongoDB shell as the site user administrator (as above).
Switch to admin DB and create a “root” user called “superuser”:
use admin
db.createUser(
{
user: "superuser",
pwd: "123456",
roles: [ "root" ]
}
)
Set up authentication for your application
Create an application database
Connect to MongoDB shell as the superuser (authenticated via admin DB)
mongo -u superuser -p 123456 --authenticationDatabase admin
Create your application database:
use myappdb
Create a DB owner for the application database
Make sure you are logged in as superuser and working in myappdb (see above).
Create the application owner called “myappowner” for this database:
db.createUser(
{ user: "myappowner",
pwd: "secret",
roles:["dbOwner"]})
Reconnect to MongoDB as the DB owner (authenticated via your application DB):
mongo -u myappowner -p secret --authenticationDatabase myappdb
Create collections in application database
Log in as application owner (see above) and switch to myappdb:
use myappdb
Create a collection that we will later define as readonly for ordinary users:
db.myappreadonly.insert({"Foo":"Bar"})
Check it worked:
db.myappreadonly.find()
{ "_id" : ObjectId("54b7a63850d47a6b57031616"), "Foo" : "Bar" }
Now create a readwrite collection:
db.myappreadwrite.insert({"Baz":"Bax"})
Check it worked:
db.myappreadwrite.find()
{ "_id" : ObjectId("54b7a67b50d47a6b57031617"), "Baz" : "Bax" }
Create an application-specific user role
Make sure you are logged in as application owner (see above) and using myappdb.
Now create a local user role on this DB, with appropriate access to the collections we
created above:
db.createRole({
role: "myAppUserRole",
privileges: [
{ resource: { db: "myappdb",collection:"myappreadonly"},
actions: ["find"]},
{ resource: { db: "myappdb", collection: "myappreadwrite"},
actions: ["find","update","insert"]}
], roles:[]})
Create a specific user with this role:
db.createUser(
{user:"bob",
pwd: "secret",
roles:["myAppUserRole"]})
Check your application user has correct permissions
Reconnect as this user and switch to myappdb:
mongo -u bob -p secret --authenticationDatabase myappdb
use myappdb
See if you can read the collections correctly
db.myappreadonly.find()
{ "_id" : ObjectId("54b7a63850d47a6b57031616"), "Foo" : "Bar" }
db.myappreadwrite.find()
{ "_id" : ObjectId("54b7a67b50d47a6b57031617"), "Baz" : "Bax" }
You should be able to insert into the readwrite collection:
db.myappreadwrite.insert({"bob":"allowed"})
WriteResult({ "nInserted" : 1 })
db.myappreadwrite.find()
{ "_id" : ObjectId("54b7a67b50d47a6b57031617"), "Baz" : "Bax" }
{ "_id" : ObjectId("54b7a98099923fa639b3c70f"), "bob" :
"allowed" }
You should not be able to insert into the readonly collection:
db.myappreadonly.insert({"bob":"not allowed"})
WriteResult({
" writeError " : {
"code" : 13,
"errmsg" : "not authorized on myappdb to execute
command { insert: \"myappreadonly\",
documents: [ { _id: ObjectId('54b7a97299923fa639b3c70e'),
bob: \"not allowed\" } ],
ordered: true }" }})
Check the application user cannot do anything else
e.g. cannot show all collections in myappdb:
show collections
20150115T11:49:29.040+0000 error: {
"$err" : "not authorized for query on
myappdb.system.namespaces",
"code" : 13} at src/mongo/shell/query.js:131
e.g. cannot create collections or insert data on another DB:
use test
switched to db test
db.bobcoll.insert({"bob":"bad"})
WriteResult({
"writeError" : {
"code" : 13,
"errmsg" : "not authorized on test to execute command
{ insert: \"bobcoll\", documents: [ { _id:
ObjectId('54b7aa6699923fa639b3c710'), bob: \"bad\" } ],
ordered: true }"
}
})
Conclusion
- Using these techniques, it should be possible to set up a simple set of users/roles to manage basic access to your database and application.
- MongoDB provides many more roles, e.g. for managing access to clusters, but these are beyond the scope of this simple introduction.
- See the MongoDB manual for comprehensive advice on security.
No comments:
Post a Comment