Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Creating User Access Control in MongoDB

DZone's Guide to

Creating User Access Control in MongoDB

User-defined roles were introduced to MongoDB in version 2.6. See how to take advantage of this feature and introduce user access control into a MongoDB instance.

Free Resource

Whether you work in SQL Server Management Studio or Visual Studio, Redgate tools integrate with your existing infrastructure, enabling you to align DevOps for your applications with DevOps for your SQL Server databases. Discover true Database DevOps, brought to you in partnership with Redgate.

MongoDB provides user access on role-based controls. It provides many built-in roles to be assigned to users: most notably the read and readwrite roles. Sometimes, however, they are not as granular as we would like.

I recently had a chance to explore user-defined roles in MongoDB, which were introduced in version 2.6. In this blog post, I will go over the MongoDB user-defined roles and define some custom roles that you might find useful.

Create Roles

Creating a user-defined role in MongoDB is simple. You can use the createRole command to create a new role. The generic create role syntax is as follows.

{
   createRole: "<role name>",
   privileges: [{
      resource: { <resource> },
      actions: [ "<action>",] },
   ],
   roles: [
      { role: "<role>", db: "<database>" } | "<role>",],
   writeConcern: <write concern document>
}

Before running the createRole command, make sure that you switch to the database that you want to create the role in. Note that the roles will be defined only in the database where the role has been created. If you want to create a role that grants access to more than one database, then that needs to be created on the admin database.

Let's go over the major components of the createRole syntax.

Privileges

Permissions can be added to a user-defined role by adding a privilege. A privilege contains action and resource fields, which are discussed below.

Actions

Actions are a set of operations that are grouped together. For example, the insert action can both insert and create. Actions are as granular as MongoDB’s role-based access control gets. The privileges parameter can be used to add roles to Mongo actions. A privilege constitutes the actions along with the resource on which the action applies. The following adds actions find, insert, and update on database mydb.

privileges:
[
   {resource: {db: "mydb", collection: "" },
   actions: [ “find”,”insert”,”update” ] }
]

Resource

The resource document would specify the scope at which the actions would apply. The scope can be set at various granularities as follows.

  • Collection: The resource can be set to resource: {db: "<db-name>", collection: "<collection name>" } to grant the specified actions to just that particular collection.

  • Database: The resource can be set to a particular database by leaving the collection parameter empty. Resource string resource{db: "<db-name>", collection: "<collection name>" } sets the scope to the entire database.

  • Single collection across databases: The resource can be set to a particular collection using  resource: {db: ", collection: "<collection name>" } to grant permissions to the collection on all databases. This permission can only be added onto a role created on the admin database.

  • Multiple collections across databases: The resource can be set to all collections except the system collections across all databases by leaving both the db and collection parameters empty — resource: {db: "", collection: "" }. This resource, like the one above, can only be granted on a role created on to the admin database.

  • Cluster-wide resource: A cluster-wide resource can be specified by using resource: { cluster : true }. This cluster-wide resource can be used to specify the state of the system such as shutdown, replSetReconfig rather than to grant permissions on any particular document.

  • All resources: It’s not recommended to use this scope for other than extraordinary circumstances. {anyResource: true } can be used to set scope set to all resources.

Roles

Inbuilt roles can be added to a custom role, as well. When an inbuilt role is added by using the roles parameter roles :[], it adds the permissions of the inbuilt role to the custom role.

An example of the roles parameter is roles: [{ role: "read", db: " "}] .

Here, the custom role would inherit all the permissions of role read over the database defined. Let’s say a role is inherited onto a database db1. The custom role can either be created on the database db1 or on the admin database.

Write Concern

The write concern defines the level of acknowledgment requested from MongoDB. It can be used to control write acknowledgments from the database. A write concern is not required when creating a role. A write concern can include fields w, j, and wtimeout.

  • W can be used to state the number of instances the write has been propagated to.

  • J: Field j can be set to determine whether the write is written to the journal.

  • Wtimeout is used to set the time by which the write has to achieve write concern. The write concern might still be achieved after the error is thrown. If a wtimeout has not been set and the write concern cannot be achieved, the write will be blocked indefinitely.

Assigning Roles

Custom roles are database-specific. A role can only be assigned to a user in the same database.

Let’s say we created a role myrole on database db1. We can create a user on the database using the following commands.

Use db1

db.createUser({"user" : "<user>",pwd: "<password>","roles" : [{"role" : "myrole", "db" : "db1"}]})

For further information on user management, refer to uthis post on user management in MongoDB.

Custom Roles

Let’s go over some custom roles that might be useful.

User With Read, Insert, and Update Permissions on a Single DB

The inbuilt roles read and readWrite might sometimes feel like too many permissions or too little permissions. Let’s see how we can create a custom role granting just read, insert and write permissions.

We already know we need all read permissions, so we can add the inbuilt role “read” to our custom role. We would also need permissions to create and update documents. These can be added by adding privilege actions insert and update. If we want to give the user the ability to create indexes and create collections, we can add the privilege action createIndex and createCollection.

For the scope, let's assume I have a database named db1 on which I the above permissions. The create command would look something like this:

Use db1.
 
db.createRole(
 
{
 
createRole: "<role-name>",
 
privileges: [
 
{ resource: { db: "db1", collection: "" },
 
actions: [ "insert","update","createIndex", "createCollection" ] }
 
],
 
roles: [{ role: "read", db: "db1"}]
 
})

The above command would create a role with <role-name> in database db1. A user granted permission by the above role will not have the “remove” privilege action. Also, note that the methods db.collection.findAndModify(), db.collection.mapReduce(), and db.collection.aggregate() cannot be run in full as they require the remove privilege.

User With Only Read, Insert, and Update Permissions on All DBs

We can create a role on the admin database similar to the one above to grant read, create, and update privileges on all DBs. This role should be created on the admin DB and the subsequent user should also be created on the admin DB.

For this role, instead of using the standard read role, we can inherit permissions from the readAnyDatabase role. The role create would look something like this:

Use admin.
 
db.createRole(
 
{
 
createRole: "<role-name>",
 
privileges: [
 
{ resource: { db: "", collection: "" },
 
actions: [ "insert","update","createIndex", "createCollection" ] }
 
],
 
roles: [{ role: "readAnyDatabase", db: "admin"}]
 
})

Writer Roles With Write Concern

You could have a use case where write concern needs to be enforced. For this purpose, the write concern command can be added to a role. Adding writeConcern to a role would enforce it on all the users granted the role on the DB. Let's define a role with a write concern that enforces majority writes.

Use admin.
 
db.createRole(
 
{
 
createRole: "<role-name>",
 
privileges: [ ],
 
roles: [{ role: "readWriteAnyDatabase", db: "admin"}],
 
writeConcern: { w: “majority”, j: false, wtimeout: 300 }
 
})

That's it for this post!

It’s easier than you think to extend DevOps practices to SQL Server with Redgate tools. Discover how to introduce true Database DevOps, brought to you in partnership with Redgate

Topics:
database ,tutorial ,mongodb ,user access control ,role-based access

Published at DZone with permission of Neeraj Chinthireddy, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}