CopyDisable

Thursday, 11 February 2016

MongoDB: enable access control

Enabling access control in MongoDB requires Authentication and Authorization. Authentication is the process of verifying the identity of a client. Authorization determines what a user can do once he/she is connected to the database.
To enable access control, we have to start MongoDB server with --auth or security.authorization configuration file setting.
For this example I am using mongodb config file:

image
Starting mongodb with access control:
image
Once mongodb started, we can connect to MongoDB server from localhost without any username/password and create our first user, this is called localhost exception.
Localhost Exception: With the localhost exception, after you enable access control, connect to the localhost interface and create the first user in the admin database. The first user must have privileges to create other users, such as a user with the userAdmin or userAdminAnyDatabase role.
Source: https://docs.mongodb.org/manual/core/security-users/#localhost-exception
Now we will connect to admin database of mongodb using mongo shell and create our first admin user.
root@ubuntutest:/mongodb# mongo admin
> db.createUser(
{
     user: "admino",
     pwd: "admin123",
     roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
}
)
image
After creating our first user, if we try to create another user, we will get exception:
image
We have to authenticate with the first user that we created and then we can create the next user.
> db.auth("admino","admin123")
Lets create a user who can only read data of any database in the MongoDB server. The readAnyDatabase is a special role on the admin database that grants privileges to a user to read any database.
image
Our user is created, now lets connect using this user to the callcenter database and read some data:
image
Oopss… login failed Disappointed smile???? What happened Confused smile???? We created the user with readAnyDatabase role, why the user is getting exception while connecting to callcenter database???
Well, when we created the user we gave the “db” name as “admin”, so while authenticating we have to authenticate the user against admin db, so we have to login as:
mongo callcenter -u pranabs -p "abc123" --authenticationDatabase "admin"
image

For testing I am creating one user pekay who can read/write in the callcenter database
> db.createUser(
... {
... user: "pekay",
... pwd: "pekay123",
... roles: [ { role: "readWrite", db: "callcenter" }]
... }
... )
Successfully added user: {
        "user" : "pekay",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "callcenter"
                }
        ]
}
User is created, now I will login with this user and update one record:
mongo callcenter -u pekay -p "pekay123"
> db.account.findOne()
{
        "_id" : ObjectId("56bc4ccfc0952e06f50b99ef"),
        "username" : "user1",
        "password" : "abc123"
}
> db.account.update({"username" : "user1"},{"username" : "user1","password" : "user123"})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.account.findOne()
{
        "_id" : ObjectId("56bc4ccfc0952e06f50b99ef"),
        "username" : "user1",
        "password" : "user123"
}

Now say I want some data from another database support, but pekay user has access only to callcenter database. To get data from support database I am using the pranabs account who has readAnyDatabase role:
image
Again I need to update a document in callcenter database, so I swiched to callcenter database:
image
Line1: > db
Line2: callcenter
Line3: > use admin
Line4: switched to db admin
Line5: > db.auth("pranabs", "abc123")
Line6: 1
Line7: > use support
Line8: switched to db support
Line9: > db.issues.findOne()
Line10: { "_id" : ObjectId("56bc5476d509294313459003"), "issueID" : 1 }
Line11: > use callcenter
Line12: switched to db callcenter
Line13: >  db.account.update({"username" : "user1"},{"username" : "user1","password" : "newpassword"})
Line14: WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
Line15: > db.account.findOne()
Line16: {
        "_id" : ObjectId("56bc4ccfc0952e06f50b99ef"),
        "username" : "user1",
        "password" : "newpassword"
}
Few steps back I have authenticated myself as pranabs user (in Line5), I have switched myself back to callcenter database (in Line11), but still I could update a document of callcenter database (in Line13). This should not happen as the user pranabs has only readAnyDatabase role, so this user should not be able to update a document. Why this happened Surprised smile????
Lets investigateJust kidding:
So get the connection status:
> db.runCommand({"connectionStatus": 1})
{
        "authInfo" : {
                "authenticatedUsers" : [
                        {
                                "user" : "pekay",
                                "db" : "callcenter"
                        },
                        {
                                "user" : "pranabs",
                                "db" : "admin"
                        }
                ],
                "authenticatedUserRoles" : [
                        {
                                "role" : "readWrite",
                                "db" : "callcenter"
                        },
                        {
                                "role" : "readAnyDatabase",
                                "db" : "admin"
                        }
                ]
        },
        "ok" : 1
}
Here we can see that our connection is authenticated for two users pekay and pranabs, so using this connection we can get all the permissions of pekay and pranabs users and we can do all the operations permitted to these two users. Each time we run the method db.auth from an existing connection, the user and roles are added to the list of authenticated users and roles for that connection.
Continuing the above example, now I will authenticate using another user with name support. After running the db.auth method, we can see the support user has been added to the authenticatedUsers list and roles of support user also added to the authenticatedUserRoles list.
image
So this was just a small introduction into MongoDB’s access control, for details you can always visit official MongoDB documents.