0

As a veteran web developer - I get connection strings.

I've seen them inside WordPress wp-config.php files, I've seen them in many a ASP.NET app.config file. I know how to go into a MySQL installation and create a userName@<specific-host> and grant them all-privileges (or a subset) so that the web application can then use that credential to connect.

I know how to go into the Security section of MS SQL Server and set up an integrated user or a SQL-only login user.. etc..

Can someone use any of the above technologies to draw an analogy and help me better understand how to create a user in MongoDB (yes, I can google that) on a particular database that has 'all privileges' and then what the resulting connection string ought to look like?

When I'm in the mongo shell, is there not a default block of JSON, with well known roles.. appropriate for a web application that I should pass into a db.createUser() call? I can't seem to find this where I've been looking.


EDIT In addition to implementing Markus Mahlberg's beautiful answer below - I found I was getting an authentication error which required this S.O. fix, moving the auth version from 5 back down to 3 and this required that I recreate my admin user with role:"root" before proceeding.

Community
  • 1
  • 1
bkwdesign
  • 1,953
  • 2
  • 28
  • 50

1 Answers1

3

Introduction

Ok, first things first, it has to be said.

MongoDB is not

  • the cooler, newer and shinier MySQL. It is different, in every major aspect
  • suitable for thinking in analogies to product X (even couchdb). In fact, if you do so, this will get you well into trouble sooner or later.
  • to be taken lightly. You need to read the documentation. Thoroughly. And again.

You really have to stop thinking in terms of "How do I do X like I did in technology Y in technology Z?"

When it comes to data modeling in MongoDB for example, this attitude will cause some pains in the neck to you, some easy to correct (like overembeding), some very, very hard (like choosing a wrong shard key).

Disclaimer Changing security settings may render your instance and/or cluster inaccessible. Proceed with extreme caution and only if you are absolutely positively sure you understood what you are doing.

I will assume that we are talking of a standalone MongoDB instance or a replica set. If you have a sharded cluster, stop reading and ask your DBA – or get one.

Step 0: Read the security docs

Really. I mean it. Sudo read the docs! ;) They are well written, thorough and helpful.

You need to understand what you are doing, hence reading the docs is step 0.

Step 1: Create the administrative user

To have your administrative user ready when you enable the authentication feature, you need to set it up, first.

  1. Connect to your mongodb instance
  2. Change to the admindatabase

    use admin
    
  3. Create the administrative user

    db.createUser({
        user: "funkyNameForUserAdminSinceThereIsNoConvention",
        pwd: "changeMePlease:Loremipsumdolorsitamet,consecteturt",
        roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
    })
    

Note that this user only has the permission to manage other users. The user does not have any other permission. If you need other permissions: add according users with the respective roles after finishing step 4.

Step 2: Enable authentication

Probably the most controversial default setting in MongoDB is that authentication is not enabled by default, which lead to quite some data exposed to the public by... less professional people.

To enable authentication, you need to configure your instance accordingly. Here comes a problem: there are two configuration file formats available: the legacy format and YAML. You ave to find out which one your installation uses and make the change according to the details below.

In legacy format

Add the line

auth=true

to your mongod.conf

In YAML format

Add

security:
    authorization: enabled

to your mongod.conf (indentation matters!).

Step 3: Restart your MongoDB instance

Not much to say here, since I do not know your OS, but I am sure you know how to to this

Step 4: Create a user account

In MongoDB, any user can be stored in (almost) any database. So a user with access to "foo" might well be stored in database "bar". The reason for this is that while a user's primary database might be "bar", he might as well be granted access to db "foo" and this way there is no need for duplicate user entries. The user requesting access to "foo" would do so by setting the --authenticationDatabase flag for the shell client:

mongo [host[:port]/]foo --authenticationDatabase bar -u funkyUser -p

We do so now accordingly with our newly created admin user:

mongo [host[:port]/]bar --authenticationDatabase admin \ 
-u funkyNameForUserAdminSinceThereIsNoConvention -p

We should be now in the database "bar" for which we want to create a user with the readWrite role for "foo" and "bar", as per the example above.

db.createUser({
  user: "funkyUser",
  pwd: "changeMePlease:Loremipsumdolorsitamet,consecteturt",
  roles: [
    {role: "readWrite", db:"foo"},
    {role: "readWrite", db:"bar"}
  ]
})

Done!

You should now be able to log in as "funkyUser" and read and change both "foo" and "bar" according to the needs of a web application.

Markus W Mahlberg
  • 19,711
  • 6
  • 65
  • 89
  • alright! Now that's a concise explanation that I hadn't found anywhere else - I had successfully made my way through your steps 1, 2 & 3 already (and parts of step 0) - but, wasn't finding a step 4. Your Intro is quite true in a number of ways, Mongo is a different animal in almost every way to any RDBMS and I soon realized I was wrong to try to mentally map X with Y.. – bkwdesign Jan 22 '16 at 14:53
  • however.. a web app and a persistence store are well known concepts. Mongo DB IS a persistence store, even if it's a weird one. And web apps *should* connect to their persistence mechanisms in a secure way, and your elusive Step 4 - so well put - sounds EXACTLY LIKE security and role management in MS SQL Server.. the MS SQL Server has "logins" at the "server" level (server here, **not** meaning Win 2008 R2 box, but server meaning the MS SQL Server installed on the box). Logins have default databases, but, you can bring those logins into other databases as-needed. So.. an analogy lurks – bkwdesign Jan 22 '16 at 14:55
  • One more beef re: "How do I do X like I did in technology Y in technology Z?" - my goal was to do X (secure connect web app on server1 to a db on server2) .. MySQL and MongoDB can both run on Ubuntu so I just saw it all as 'Technology Y'.. but, I guess you can make an argument that the LAMP stack and the MEAN stack are quite different... but.. really.. for my scenario - I don't think my mental model was so off... and at a high level, experience told me.. "this is a major concern that needs solving." – bkwdesign Jan 22 '16 at 15:15
  • 1
    No beef, just a warning. I saw quite a few people fail miserably because of that state of mind. Most "Mongo? Meh." blog posts are made by those who failed this way. But you are wrong. There is no such thing as server-wide logins. All users are tied to a DB, although this may grant additional privileges. Small difference with big effect: delete the database where the user is stored, and he is simply gone... ;) – Markus W Mahlberg Jan 22 '16 at 15:48