Securing MongoDB Instances

DZone 's Guide to

Securing MongoDB Instances

MongoDB can be secured via native certification and LDAP. Learn how to do it right here!

· Security Zone ·
Free Resource

Authentication is one of the most important features of a database, and MongoDB supports it in different ways. Although it allows you to work without any authentication, the best practice is to enable authentication and give users only the permissions they need.

Instances without authentication allow all users to perform all the operations they feel like, and that is not safe at all.

Native Authentication

The MongoDB community version features more than one authentication method: SCRAM-SHA-1, MONGODB-CR, and x.509 Certificate Authentication. The current default method is SCRAM-SHA-1. The version prior to 3.0 used to have MONGODB-CR as its default method.

Percona Server for MongoDB also offers LDAP authentication free of charge where this feature is only available in the MongoDB enterprise version.

SCRAM-SHA-1 and MONGODB-CR check whether the user/password exists against a specific database and use challenge response authentication to verify user’s authenticity.

The x.509 authentication is based on certificates. It does not run challenge response algorithms. This method instead validates a certificate to prove client’s authenticity. It depends on a certificate authority and each client must have a valid certificate.

LDAP Authentication

The LDAP authentication uses an external LDAP server to authenticate the user by using authsasld in Linux. LDAP is commonly used to manage users in a network. There are advantages and disadvantages when using LDAP. One advantage is that it centralizes users. However, it depends on network connectivity to check user credentials and sasld tries to help with caching but it does have limitations. Please see further details here.

There are two different internal authentication methods for replica-set and shadings, where instances need to prove that they are expected members of the deployment. The first method is using a shared keyfile for all instances, and the second one is using a different x.509 certificate for each instance. It is important to know x.509 forces proper SSL coverage or replication while a key will not, but we will cover this topic in a different blog post.

Authorization and Roles

Once authenticated, users must be allowed to perform commands against the instance/replica-set/sharding. There are a few built-in roles that are able to cover almost all the user cases, and creating a user defined role is possible.
The current built-in roles are:

read readWrite dbAdmin dbOwner userAdmin clusterAdmin clusterManager clusterMonitor hostManager backup/restore readAnyDatabase readWriteAnyDatabase userAdminAnyDatabase dbAdminAnyDatabase root and many more…

There is also the __system role, which is solely used for internal purposes.

Customer User and Role by Example

This shows how to both enable MongoDB authentication and create a user-defined role, where the user will only be able to read a specific collection. We are using tarballs for testing only. To perform a production installation please follow our docs.

  1. Download Percona Server MongoDB:
    >wget https://www.percona.com/downloads/percona-server-mongodb-3.2/percona-server-mongodb-3.2.10-3.0/binary/tarball/percona-server-mongodb-3.2.10-3.0-trusty-x86_64.tar.gz >tar -xvzf percona-server-mongodb-3.2.10-3.0-trusty-x86_64.tar.gz >mv percona-server-mongodb-3.2.10-3.0/ perc-mongodb >cd perc-mongodb/ >mkdir bin/data
  2. Start the service with authentication:
    cd bin ./mongod --dbpath data --smallfiles --logpath data/mongod.log --fork --auth
  3. Create root/admin user: We are able to create the first user without authentication. The next users must be created by an authenticated user.
    > use admin > db.createUser({user : 'administrator', 
      pwd : '123', roles : ['root'] }) > 
      Successfully added user: { "user" : "administrator", "roles" : [ "root" ] }
  4. Login with the just created credentials:
    >mongo --authenticationDatabase admin -u administrator -p
  5. Create database and collection:
    > use percona > db.simple_collection.insert({ random_number : Math.random()}) >
      db.secure_collection.insert({ name : 'John', 
        annual_wage : NumberLong(130000.00), target_bonus : NumberLong(15000.00)})
  6. Create a user that can read all the collections in the Percona database:
    db.createUser( {     
      user: "app_read",     
      pwd: "123456",     
      roles: [ { role: "read", db: "percona" }]}) 
    // testing 
      ./mongo --authenticationDatabase admin -u app_read -p 
      MongoDB shell version: 3.2.10-3.0 Enter password: connecting to: test > 
        use percona switched to db percona > show collections foo secure_collection
          > db.employee_dependents.find()     
        { "_id" : ObjectId("583c5afe38c4be98b24e86e6"),
          "emp_id" : DBRef(‘employees’,’583c5bea38c4be98b24e86e8’} > 
          { "_id" : ObjectId("583c5bea38c4be98b24e86e8"),
            "name" : "John", "annual_wage" : NumberLong(130000), 
              "target_bonus" : NumberLong(15000) }
  7. Now we see that this user can read not only the simple_collection but also the secury_collection. We don’t want users to read the secury_collection, so we are going to create a user-defined role.
    > db.createRole( {     
      role : 'readOnly_nonPrivilegedCollections',     
      roles : [],     
      privileges: [       {          
        resource: {            
          db: "percona",            
          collection: "foo"          },          
        actions: [ "find"] }     ] });
  8. Assign created role to the user:
    db.createUser( {      
      user: "app_non_secure",      
        pwd: "123456",     
          roles: [ { 
            role: "readOnly_nonPrivilegedCollections", 
              db: 'admin' }] })
  9. Test access:
    ./mongo --authenticationDatabase admin -u app_non_secure -p > db.foo.find()     
    { "_id" : ObjectId("583c5afe38c4be98b24e86e6"), 
      "random_number" : 0.2878080930921183 } > db.secure_collection.find() 
      Error: error: {     
        "ok" : 0,     
          "errmsg" : 
        "not authorized on percona to execute command { 
          find: "secure_collection", filter: {} }",     "code" : 13 
database, mongodb, nosql, security

Published at DZone with permission of Adamo Tonete , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}