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.