Securing and navigating around xDB – Mongo and xDB part two

Peeking around

There are a number of options for navigating your way around Mongo. Depending on what you’re most comfortable with, you may prefer using command line tools and batch files or you may prefer GUI tools like RoboMongo, MongoChef or MongoVue. That said, for the more complex operations you’ll have to be comfortable with the command line tools unless you’re hosting with a third party.

The Mongo eco-system is based on a Javascript ‘shell’. This means that all functions, loops and the like follow the normal Javascript syntax rules. It also means that reading any custom functions and profile scripts should be easy for anyone who is familiar with Javascript for web development. Before we continue and look at some simple operations, its useful to repeat some Mongo definitions. Naturally these are all available on the Mongo documentation website so I’ll be brief:

  • Database – the same concept as in a relational product like Sql Server.
  • Collection – similar to a table but doesn’t have a schema
  • Document – a record in a collection.
  • Index – the same concept as in a relational product

When we want to insert data into Mongo, we create a new document and add it to a collection. Mongo also allows us to embed one document inside another which can be useful but does require some care when constructing queries and designing indexes. Once we have some documents, we can pull them out using queries (as you’d expect). These queries can have a bit of a ‘linq’ feel to them due to the use of the Javascript shell. Here’s an example:

use myusertable
db.users.find({"Country": "New Zealand"}).sort( { "Surname": 1, "Firstname": 1 } )

So lets put a Sitecore spin on this. If we look at the analytics database, we’ll see the following collections. Not too dissimilar to the Sql Server version though much of the related data is now present as direct values or embedded documents. This list may be different depending on whether you’ve used the migration tool or not. Plus I expect this list to change with future changes to the DMS.

  • AutomationRanges
  • AutomationStates
  • ClassificationsMap
  • Interactions

Creating reports is still done by SQL Server but this now acts as a ‘data aggregator’ by using what is termed fact tables. These tables are built/rebuilt by the user based on the raw Mongo data and then the reports built from there. There are quite a few tables here but that’s fine as we are aggregating data and this gives us a pretty solid separation of concerns. We can think of the raw user data as a high speed dump of user activity. We don’t really need too much relational work going in and we can optimise the environment for this particular task alone. Then the reporting database can aggregate this data in a variety of ways without being bound into one particular relational design.

 Protecting what we’ve got

It is possible to secure MongoDB in a number of different ways. The simplest is to use a username and password and store those in your database. Until then, your MongoDB server is running with a local exception. It will allow unauthenticated connections from the local machine. To setup security, we follow some simple steps (taken from the Mongo docs):

  1. First off we tell Mongo we want to have security
  2. Then we create our admin user who can do everything
  3. Then we create our database user who has restricted access

In some developer environments I’ve worked in, I’ve seen colleagues and clients use Sql Server with the ‘sa’ credentials. Needless to say this is a bad thing, the reasons of which I won’t go into. With that in mind, we won’t be skipping step 3 and will configure Sitecore to use the restricted user.

The MongoDB admin user

We can give our admin user any username but for consistency with Sql Server I’m using ‘sa’. I could use anything but I like to have a bit of similarity here since this is a multi-database environment. So the two snippets below add security to the configuration file and then setup the user. The user script should be run from the mongo shell.

   authorization: enabled

Paste the above into your configuration file. Please remember that YAML doesn’t use tabs so the indentation here is with spaces. If you use tabs, the config file will be invalid and Mongo won’t start. Now for the shell commands to create our administrator:

use admin
db.createUser({ user: "sa", pwd: "PASSWORD", roles: [ { role: "root", db: "admin" }]})

This creates the sa user in the admin database with the root role. We can test this by restarting Mongo with our config change and logging in via the Mongo shell:

use admin
db.auth("sa", "PASSWORD")

If authentication is successful, we should see the shell print ‘1’. If we want to create more users, we can use the same snippet as above but change the roles and databases accordingly. We should do this for Sitecore and so here’s a sample that I use:

use analytics
db.createUser({ user: "sitecore", pwd: "Testing1234;",  roles: [ { role: "readWrite", db: "analytics" }] })

use tracking-live
db.createUser({ user: "sitecore", pwd: "Testing1234;",  roles: [ { role: "readWrite", db: "tracking-live" }] })

use tracking-history
db.createUser({ user: "sitecore", pwd: "Testing1234;",  roles: [ { role: "readWrite", db: "tracking-history" }] })

To use this in the Sitecore, we adjust our connection strings as follows. Note that I’ve put a link to this format in the references so you can refer to it yourself.

   <add name="analytics" connectionString="mongodb://sitecore:Testing1234;@localhost/analytics" />
   <add name="" connectionString="mongodb://sitecore:Testing1234;@localhost/tracking-live" />
   <add name="tracking.history" connectionString="mongodb://sitecore:Testing1234;@localhost/tracking-history" />

Its worth noting that we create these users in each database and so we can have a different user for each if we wanted. In a live environment were we to use replica sets we would use keyfiles instead. But that’s a different topic!

Final thoughts

There’s a lot to security when it comes to Mongo. I’ve stuck with using the admin database here but we could well store all users in a separate database. That said, we really want to keep things simple while we are working in our developer environment.

In future posts we’ll look at bundling sitecore specific roles in Mongo as well. While not really necessary, its useful to understand how we can lock down our user depending on our developer and production scenarios.


The following references are worth looking at in relation to security:

  1. Built in roles
  2. Connection string format

One thought on “Securing and navigating around xDB – Mongo and xDB part two

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s