Secure MongoDB Atlas: AuthN and AuthZ / Manage Database User Roles and Privileges
How do you ensure that each visitor only accesses the materials they're allowed to see?
That's where database user authorization comes in. It's the essential mechanism that controls who gets to view or modify data within your database, safeguarding against unauthorized access and protecting your data.
In this video, we'll focus on the data plane. We'll discuss database users and the roles they use to connect to a MongoDB cluster.
We'll cover three topics, understanding built in roles and privileges available for database users, creating a custom role, and assigning that role to a new database user. Before we begin, let's take a moment to recap what a database user is.
Database users interact directly with databases.
In MongoDB, a database user serves as a credential for authenticating to your cluster, acting as a unique entity with specific permissions that determine actions you can perform within the database.
In MongoDB, roles are essentially collections of privileges that grant users the ability to perform specific operations within the database.
And privileges define the actions a role permits, such as reading or writing data.
Database users have the flexibility to choose between built in roles, custom roles, or even a combination of both to suit your needs. Let's dive in and explore both options, starting with the built in roles of Atlas admin, read write any database, and read any database to get a better sense of their responsibilities.
The Atlas admin role includes privileges like performing administrative tasks across all databases within the cluster, managing shards, and configuring database settings.
The read write any database role, as its name suggests, allows users to perform read and write operations on any database within the cluster. Lastly, the read any database role permits users to read data from all databases, but doesn't allow any modifications.
But what if you need a more fine grained control over what a database user can access and do?
MongoDB's flexibility allows us to define precise privileges.
A custom role specifies the actions allowed for a role across multiple collections or databases, ensuring users have only the permissions they need.
Let's create our own custom role that can read one collection and insert into another collection.
For this, we'll use the Atlas admin API, which requires you to generate API keys prior to using it. You also have the option to use the UI or CLI for this task.
First, let's set our header information.
We'll specify the API version to ensure the response is compatible with our expectations.
Details can be found in the Atlas admin API documentation.
Additionally, we'll indicate the format of the data we're sending.
After that, we'll send a post request to the custom DB roles endpoint, providing the group ID for the Atlas project.
Next, we send along the data that contains the custom DB roles configuration.
Let's go over these fields at a high level before we get into the contents of each.
The data we send along includes the actions this role will be able to perform.
Actions translate to the specific privileges we want this role to have.
Next, we have the option to define whether this role inherits privileges from existing roles.
Inherited roles allow the new role to automatically include all the privileges of the specified roles.
This streamlines permissions management by building on already established sets of privileges.
Finally, we provide the name we want for the custom role. It's always a good idea to use descriptive names.
Now let's dive into the actions and inherited roles to get a better sense of how they work. Let's start with the actions field, which expects an array that includes the action we want this role to have.
Here, we're specifying two actions, find and insert.
We then define the resources these actions can be performed on. For the find action, we specify the sales collection in the catalog database.
For the insert action, we specify the return collection in the same database.
You may have noticed the cluster field.
If this is set to true, the collection and DB fields are ignored, so the action is enabled for the entire cluster.
We don't want to allow that for this custom role, so we set it to false and define the specific databases and collections for each action.
Lastly, we have the inherited roles field.
Here, if we want our custom role to inherit existing permissions, we supply a list of existing roles and the databases they should apply to for the custom role. We'll skip this for now since we don't want our custom role to inherit any other privileges.
With that complete, we can send a request which will create the custom database user role.
Now let's create a new database user that uses the custom role we just created. Just like earlier, we must provide our API key along with the required headers.
Next, we specify a post request to the database user's endpoint along with our group ID.
We also send the data that contains the configuration of our new database user.
The configuration for the new user must contain the database this user will authenticate on, the group ID, and since we'll be authenticating with SCRAM, we need to provide a password.
Depending on the authentication method you choose, the kind of information will vary. For your desired authentication method, check out the Atlas admin API documentation.
After that, we provide roles for our user.
Then, we specify the database our custom role is scoped to. In Atlas, all roles are scoped to the admin database, but this doesn't mean the role has access to the admin database.
Next, we provide the name of the role. And in our case, we're using the custom database role we created.
Next, we define the scope of the user by specifying which cluster the user has access to and the type.
Type refers to either the cluster, data lake, or stream for stream processing.
If left blank, the user will have access to all three. Since our user is limited to a few actions, we'll set the type to cluster. Finally, we provide the username that we want this database user to have. If successful, we will receive a response (HTTP) 201 confirming the creation of the database user.
Followed by the response code, we also receive a document with the user's information.
Now we can send this request, and the database user will be created with a custom database role. To test it, let's authenticate to our cluster with the new database user.
Remember, we assign a custom role to our database user, granting them read access to the sales collection and permission to insert items into the return collection.
Keep in mind, if you are using a different authentication method, this may look a little different.
Once we have successfully connected, switch to the catalog database.
Let's try inserting a test document into the sales collection to see what happens.
When we run the command, we receive an error. It's not often that getting an error is a good sign, but in this case, it is. The error is telling us that our database user is not authorized to perform an insert operation on the sales collection.
This is exactly what we wanted to happen since this user is only allowed to read from the sales and to insert into the returns collections.
This was just a small sample of the different roles and privileges available for database users. For a full list, make sure you check out the Atlas documentation.
Awesome work. We have given a database user the authorization to access specific resources in our Atlas cluster.
Let's take a moment to recap what we've learned.
We began by discussing the roles and privileges available to database users, highlighting the built in roles. Next, we created a custom role that grants specific privileges tailored to our needs for more precise access control.
Lastly, we walk through a code example demonstrating how to establish a custom role and create a new database user assigned to that role.
