Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write-only collections in MongoDB

I'm currently using MongoDB to record application logs, and while I'm quite happy with both the performance and with being able to dump arbitrary structured data into log records, I'm troubled by the mutability of log records once stored.

In a traditional database, I would structure the grants for my log tables such that the application user had INSERT and SELECT privileges, but not UPDATE or DELETE. Similarly, in CouchDB, I could write a update validator function that rejected all attempts to modify an existing document.

However, I've been unable to find a way to restrict operations on a MongoDB database or collection beyond the three access levels (no access, read-only, "god mode") documented in the security topic on the MongoDB wiki.

Has anyone else deployed MongoDB as a document store in a setting where immutability (or at least change tracking) for documents was a requirement? What tricks or techniques did you use to ensure that poorly-written or malicious application code could not modify or destroy existing log records? Do I need to wrap my MongoDB logging in a service layer that enforces the write-only policy, or can I use some combination of configuration, query hacking, and replication to ensure a consistent, audit-able record is maintained?

like image 565
rcoder Avatar asked Mar 08 '10 19:03

rcoder


People also ask

How do I create a collection in MongoDB?

MongoDB creates collections automatically when you insert some documents. For example: Insert a document named seomount into a collection named SSSIT. The operation will create the collection if the collection does not currently exist. If you want to see the inserted document, use the find() command.

How do I create a capped collection in MongoDB?

Create a Capped CollectionYou must create capped collections explicitly using the db. createCollection() method, which is a mongosh helper for the create command. When creating a capped collection you must specify the maximum size of the collection in bytes, which MongoDB will pre-allocate for the collection.

How do I select a collection in MongoDB?

In MongoDB, find() method is used to select documents in a collection and return a cursor to the selected documents. Cursor means a pointer that points to a document, when we use find() method it returns a pointer on the selected documents and returns one by one.

Can we lock collection in MongoDB?

MongoDB uses multi-granularity locking [1] that allows operations to lock at the global, database or collection level, and allows for individual storage engines to implement their own concurrency control below the collection level (e.g., at the document-level in WiredTiger).


2 Answers

I would say the best bet would be to wrap up the access to MongoDB in a service layer that enforces your specific contracts. We don't do much in the way of fine-grained access control because there are so many different cases that solving all of them correctly is tricky to get right. So for the most part it's up to the application layer to implement those kind of controls.

like image 159
mdirolf Avatar answered Oct 03 '22 20:10

mdirolf


To add a write only (on collection level) user to the MongoDB do the following.

Say you want to have a user that can only write (insert only) to a certain collection on a certain database.

Create a file createuser.js with following contents:

function createCollectionWriter(database, username, password, rolename, collection)
{
    db.getSiblingDB(database).createUser({
        user : username,
        pwd  : password,
        roles : [ ]
    });

    db.getSiblingDB(database).createRole({
        role  : rolename,
        privileges : [
        {
            resource : { db : database, "collection" : collection },
            actions  : [ "insert" ]
        }
        ],
        roles : []
    });

    db.getSiblingDB(database).grantRolesToUser(username, [ rolename ] );
}

And execute this from command-line

$ mongo --eval="load('createuser.js'); createCollectionWriter('yourdb', 'user1', 'pass1', 'rolename', 'col1')"

This creates a user with username user1 with password pass1 and this user has write only access to database's yourdb collection col1.

A side-effect of this is that role rolename is created. If you have existing user that should have a write only access to the same collection, grant role rolename to that existing user.

Feel free to use and modify the code provided above :).

like image 30
Developer Marius Žilėnas Avatar answered Oct 03 '22 19:10

Developer Marius Žilėnas