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?
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.
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.
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.
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).
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.
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 :).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With