MongoDB: How to store credentials safely?

Context

In my web application project, I created a MongoDB database, including the server administrator and project users, using several JavaScript files that run with the MongoDB shell.

I cannot find a way to handle root or user passwords correctly:

Problem 1: create users

This is an example JavaScript file that I use to create the superuser and project user:

 use admin db.createUser( { user: "root", pwd: "abc123", roles: [ { role: "root", db: "admin" }] }) use project_db db.createUser( { user: "project_admin", pwd: "def456", roles: [ { role: "dbOwner", db: "project_db" }] }) 

Obviously, this file is under version control. How can I not store passwords with clear text at all?!? The db.createUser(...) docs explicitly states that the cleartext password must be passed (unless an external user database is used).

Really?!?

Problem 2: using credentials

I found three ways to transfer credentials when accessing the database (for example, start the database setup script); none of them work satisfactorily:

command line authentication

The executable mongo accepts the appropriate arguments:

 mongo --username project_admin \ --password def456 \ --authenticationDatabase project_db \ < "${path_to_db_build_script}" 

Problem: password is displayed, for example. ps . Unacceptably. The --username project_admin transfer fails with the Error: Missing expected field "pwd" error.
Passing --username project_admin --password causes mongo request the password interactively, which obviously prevents the script from executing automatically - and automatically - this is why this is the script in the first place ...

authentication using ~/.mongorc.js

Taken from this blog post :

 db = connect("localhost:27017/project_db"); db.getSiblingDB("project_db").auth("project_admin", "def456"); 

This works, but does not seem to make it possible to work with multiple users. Perhaps there is an approach to working with one .js file for each user and / or .js file templates, but as soon as there is any complexity, these files should be versioned - and this brings us back to the same problem as for create users.

code authentication

In theory, it should also be possible to use db.auth(...) for authentication in a script.
In practice, it just seems to me epic:

This works, but saves the credentials in code:

 db.auth("project_admin", "def456") 

This works using a JSON document; also saves credentials in code:

 db.auth({ user: "project_admin", pwd: "def456" }) 

db.auth(...) has the digestPassword parameter, which is largely undocumented, but the name assumes that it is intended to indicate that the password is transmitted in some encrypted / hashed / salty / any form.

This would allow storing .js scripts in version control using non-cleartext passwords; not perfect, but definitely better than cleanliness. However, this simply does not work, that is, with the Error: Authentication failed. error Error: Authentication failed.

To begin with, I would suggest that setting digestPassword to false is appropriate when passing a password in clear text; however this fails (BUG # 1?):

 db.auth({ user: "project_admin", pwd: "def456", digestPassword: fails }) 

then how does it work (WTF?!?):

 db.auth({ user: "project_admin", pwd: "def456", digestPassword: true }) 

The installation of the mechanism in PLAIN ends with Error: Missing expected field "mechanism" , despite the fact that the field is clearly there (BUG # 2?), Regardless of whether digestPassword is true or false :

 db.auth({ user: "project_admin", pwd: "def456", digestPassword: true, mechanism: "PLAIN" }) 

Setting the mechanism to the default value of SCRAM-SHA-1 seems to detect the same error as above; this fails:

 db.auth({ user: "project_admin", pwd: "def456", digestPassword: fails, mechanism: "SCRAM-SHA-1" }) 

then how does it work:

 db.auth({ user: "project_admin", pwd: "def456", digestPassword: true, mechanism: "SCRAM-SHA-1" }) 

Encrypted / hashed / digested / any passwords can be obtained by running the mongo shell as root , for example.

 mongo admin -u root -p abc123 

and run db.system.users.find() , which returns something like this:

  ... { "_id": "project_db.project_admin", "user": "project_admin", "db": "project_db", "credentials": { "SCRAM-SHA-1": { "iterationCount": 10000, "salt": "WnKFmGs3BTbmkbUWi0RPnA==", "storedKey": "EEIMqBEMUUOpoR3i3pgKz0iRumI=", "serverKey": "HsSOxujNODlKcRiEdi1zkj83MRo=" } }, "roles": [ { "role": "dbOwner", "db": "project_db" }] } ... 

Using any of the three hashes (?) Exiting as a password with digestPassword true or false fails. Despite the sources, I can only assume that there is some sha1(password + salt) connection with the credentials above, but there seems to be no documentation, and the alleged errors that my attempts so far have not revealed do not quite encourage the pursuit of this further.

user approach

Perhaps there is a way to run JavaScript in ~/.mongorc.js , which takes the current username (where?) And looks for the password from an external source. But why do I need to implement credential management for the proposed database solution?

Questions:

  • How do people handle credentials when working with MongoDB?
  • My experience with MongoDB so far has been so terribly bad that, given that MongoDB is for sale for production purposes, it seems reasonable to look for a cause on my side first. Am I doing something fundamentally wrong? Are my expectations unfounded? MongoDB users don't care about password security?

I would really appreciate it if someone could share their approaches and experiences.

+9
source share
3 answers

How about using load to load a file with the connect command:

 touch conn.js chmod 600 conn.js vim conn.js # db = connect('localhost/mydb', 'myuser', 'pword'); vim myscript.js # load('conn.js') # db.coll.count() mongo --nodb < myscript.js 

This way you can have multiple connection files safe and excluded from version control.

0
source

You can prepare your script in the version control system and assume that a local file with the password.file with limited read permissions contains the password in clear text.

Then you can run the script as follows:

 cat password.file | mongo -u <USERNAME> < myscript.js 

This forces the Mongo shell to read the password from stdin and allows you to save the password outside of version control and ps output.

Perhaps the best solution would be to use x509 certificates for the script, or switch to Kerberos for authentication.

0
source

I assume you are using node.js

therefore, the main approach would be to make encryption on the application side, i.e. to encrypt the code in your application with fields such as passwords before storing it in mongoDB.

how do you do it

you can use the node.js package called bcrypt .

To install bcrypt, use the following command: npm install bcrypt –save-dev.

You can then write a function in a save operation that will encrypt the required fields before saving them to MongoDatabase.

 var mongoose = require('mongoose'); var bcrypt = require('bcrypt'); var SALT_WORK_FACTOR = 10; mongoose.connect('mongodb://localhost/project_db'); var db = mongoose.connection; db.on('error', function(err){ console.log('connection error', err); }); db.once('open', function(){ console.log('Connection to DB successful'); }); var Schema = mongoose.Schema; var userSchema= new Schema({ name:String, password:String }); var User = mongoose.model('User', userSchema); userSchema.pre('save', function(next){ var user = this; if (!user.isModified('password')) return next(); bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt){ if(err) return next(err); bcrypt.hash(user.password, salt, function(err, hash){ if(err) return next(err); user.password = hash; next(); }); }); }); var testSample = new User({ name: "admin", password: "password1234" }); testSample.save(function(err, data){ if(err) console.log(err); else console.log ('Sucess:' , data); }); 

Another option you have is to set up some security at the database level. it’s good that something is huge, so I can’t summarize it here.

I hope this link is useful to you: https://docs.mongodb.com/manual/security/

-3
source

Source: https://habr.com/ru/post/1257787/


All Articles