admin管理员组文章数量:1299988
Context
In my current web application project, I set up a MongoDB database, including server administrator and project users, by means of a number of JavaScript files that are executed with the MongoDB shell.
I can't seem to find a way to handle root
or user passwords in a safe fashion:
Problem 1: create users
This is an examplary JavaScript file I use to create a superuser and a 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 do I go about not storing cleartext passwords in there ?!? The db.createUser(...)
docs explicitely state the cleartext password must be passed (except when using an external user database).
Seriously ?!?
Problem 2: use credentials
I found three ways to pass credentials when accessing the database (to e.g. run the database setup script); none of them works satisfactorily:
authenticating on the mand line
The mongo
executable takes corresponding arguments:
mongo --username project_admin \
--password def456 \
--authenticationDatabase project_db \
< "${path_to_db_build_script}"
Problem: The password is visible in e.g. ps
output. Not acceptable.
Passing --username project_admin
only fails with Error: Missing expected field "pwd"
.
Passing --username project_admin --password
makes mongo
query the password interactively which obviously prevents automatic script execution - and automatic is why this is a script in the first place...
authenticating using ~/.mongorc.js
Taken from this blog post:
db = connect("localhost:27017/project_db");
db.getSiblingDB("project_db").auth("project_admin", "def456");
This does work, but does not seem to provide a way to work with more than one user. There might be an approach to work with one .js
file per user and/or .js
file templates, but once there is any plexity involved there, those files should be under version control - and that brings us back to the same problem as for creating users.
authenticating using code
In theory, it should also be possible to use db.auth(...)
to authenticate within the script.
In practice, this just seems an epic fail to me:
This works, but stores credentials in code:
db.auth("project_admin", "def456")
This works using a JSON doc; also stores credentials in code:
db.auth({ user: "project_admin", pwd: "def456" })
db.auth(...)
does have a digestPassword
parameter which is largely undocumented, but the name suggests it is meant to indicate the password is passed in some encrypted / hashed / salted / whatever fashion.
This would allow storing the .js
scripts in version control with non-cleartext passwords; not ideal, but definitely better than cleartext. However, this simply does not work, i.e. fails with Error: Authentication failed.
For starters, I would assume setting digestPassword
to false
is appropriate when passing the password in cleartext; however, this fails (BUG #1 ?):
db.auth({ user: "project_admin", pwd: "def456", digestPassword: fails })
whereas this works (WTF ?!?):
db.auth({ user: "project_admin", pwd: "def456", digestPassword: true })
Setting the mechanism
to PLAIN
fails with Error: Missing expected field "mechanism"
, despite the field clearly being there (BUG #2 ?), no matter if digestPassword
is true
or false
:
db.auth({ user: "project_admin", pwd: "def456", digestPassword: true, mechanism: "PLAIN" })
Setting the mechanism
to the default SCRAM-SHA-1
seems to expose the same bug as above; this fails:
db.auth({ user: "project_admin", pwd: "def456", digestPassword: fails, mechanism: "SCRAM-SHA-1" })
whereas this works:
db.auth({ user: "project_admin", pwd: "def456", digestPassword: true, mechanism: "SCRAM-SHA-1" })
Encrypted / hashed / digested / whatever passwords can be obtained by starting the mongo
shell as root
, e.g.
mongo admin -u root -p abc123
and running 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 (?) from the output as password with digestPassword
true
or false
fails. Without looking into the sources, I can only assume that there is some sha1(password + salt)
relationship with the credentials
above, but there seems to be no documentation whatsoever and the presumed bugs my attempts so far have exposed do not exactly encourage pursuing this any further.
custom approach
There might be a way to run JavaScript in ~/.mongorc.js
that takes the current username (from where ?) and looks up the password from an external source. But why would I have to implement credentials management for a supposed database solution ?
Questions:
- How do people handle credentials when working with MongoDB ?
- My experience with MongoDB so far has been so abyssmally bad that, considering MongoDB is being sold for production purposes, it seems wise to first search for the cause on my side. Am I doing something fundamentally wrong ? Are my expectations unjustified ? Do MongoDB users not care about password safety ?
I would greatly appreciate if someone could share their approaches and experiences.
Context
In my current web application project, I set up a MongoDB database, including server administrator and project users, by means of a number of JavaScript files that are executed with the MongoDB shell.
I can't seem to find a way to handle root
or user passwords in a safe fashion:
Problem 1: create users
This is an examplary JavaScript file I use to create a superuser and a 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 do I go about not storing cleartext passwords in there ?!? The db.createUser(...)
docs explicitely state the cleartext password must be passed (except when using an external user database).
Seriously ?!?
Problem 2: use credentials
I found three ways to pass credentials when accessing the database (to e.g. run the database setup script); none of them works satisfactorily:
authenticating on the mand line
The mongo
executable takes corresponding arguments:
mongo --username project_admin \
--password def456 \
--authenticationDatabase project_db \
< "${path_to_db_build_script}"
Problem: The password is visible in e.g. ps
output. Not acceptable.
Passing --username project_admin
only fails with Error: Missing expected field "pwd"
.
Passing --username project_admin --password
makes mongo
query the password interactively which obviously prevents automatic script execution - and automatic is why this is a script in the first place...
authenticating using ~/.mongorc.js
Taken from this blog post:
db = connect("localhost:27017/project_db");
db.getSiblingDB("project_db").auth("project_admin", "def456");
This does work, but does not seem to provide a way to work with more than one user. There might be an approach to work with one .js
file per user and/or .js
file templates, but once there is any plexity involved there, those files should be under version control - and that brings us back to the same problem as for creating users.
authenticating using code
In theory, it should also be possible to use db.auth(...)
to authenticate within the script.
In practice, this just seems an epic fail to me:
This works, but stores credentials in code:
db.auth("project_admin", "def456")
This works using a JSON doc; also stores credentials in code:
db.auth({ user: "project_admin", pwd: "def456" })
db.auth(...)
does have a digestPassword
parameter which is largely undocumented, but the name suggests it is meant to indicate the password is passed in some encrypted / hashed / salted / whatever fashion.
This would allow storing the .js
scripts in version control with non-cleartext passwords; not ideal, but definitely better than cleartext. However, this simply does not work, i.e. fails with Error: Authentication failed.
For starters, I would assume setting digestPassword
to false
is appropriate when passing the password in cleartext; however, this fails (BUG #1 ?):
db.auth({ user: "project_admin", pwd: "def456", digestPassword: fails })
whereas this works (WTF ?!?):
db.auth({ user: "project_admin", pwd: "def456", digestPassword: true })
Setting the mechanism
to PLAIN
fails with Error: Missing expected field "mechanism"
, despite the field clearly being there (BUG #2 ?), no matter if digestPassword
is true
or false
:
db.auth({ user: "project_admin", pwd: "def456", digestPassword: true, mechanism: "PLAIN" })
Setting the mechanism
to the default SCRAM-SHA-1
seems to expose the same bug as above; this fails:
db.auth({ user: "project_admin", pwd: "def456", digestPassword: fails, mechanism: "SCRAM-SHA-1" })
whereas this works:
db.auth({ user: "project_admin", pwd: "def456", digestPassword: true, mechanism: "SCRAM-SHA-1" })
Encrypted / hashed / digested / whatever passwords can be obtained by starting the mongo
shell as root
, e.g.
mongo admin -u root -p abc123
and running 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 (?) from the output as password with digestPassword
true
or false
fails. Without looking into the sources, I can only assume that there is some sha1(password + salt)
relationship with the credentials
above, but there seems to be no documentation whatsoever and the presumed bugs my attempts so far have exposed do not exactly encourage pursuing this any further.
custom approach
There might be a way to run JavaScript in ~/.mongorc.js
that takes the current username (from where ?) and looks up the password from an external source. But why would I have to implement credentials management for a supposed database solution ?
Questions:
- How do people handle credentials when working with MongoDB ?
- My experience with MongoDB so far has been so abyssmally bad that, considering MongoDB is being sold for production purposes, it seems wise to first search for the cause on my side. Am I doing something fundamentally wrong ? Are my expectations unjustified ? Do MongoDB users not care about password safety ?
I would greatly appreciate if someone could share their approaches and experiences.
Share Improve this question asked Oct 6, 2016 at 10:39 sscssc 9,91310 gold badges69 silver badges99 bronze badges 3- Hi @ssc, did you managed to find a way? This is exactly what I am looking at the moment and can't find anything. – Lukino Commented Nov 9, 2018 at 9:27
- @Lukino: Nope, sorry. Due to this - and many, many other issues - I stopped trying to use MongoDB: I still have a feeling I'm misunderstanding something fundamentally, but AFAICT, the hype around MongoDB is not justified; at least it wasn't when I asked the question 2 years ago. – ssc Commented Nov 9, 2018 at 11:25
-
1
Well, I managed to hack it a little bit, so Mongo setup isn't totally insecure - mainly having passwords in cleartext... Basically you create a user
db.createUser(...)
using fake password and then you update his credentials to already hashed one in a waydb.system.users.updateOne({user: "user", {$set: {credentials: "..."}}})
. Not perfect way to do this, but works for me. This will make me less worried to have unencrypted password on gitlab/chef server (although for latter one there is an encrypted data bag, which I used till now, but I am trying to not to use it) – Lukino Commented Nov 9, 2018 at 11:53
3 Answers
Reset to default 3You could prepare your script in version control and assume a local file called password.file
with restricted read permissions containing the password in clear text.
You can then launch the script like this:
cat password.file | mongo -u <USERNAME> < myscript.js
This makes the Mongo shell read the password from stdin, and has the benefit of keeping the password out of version control and out of ps
output.
Probably a better solution is to use x509 certificates for the script, or moving to Kerberos for authentication.
How about using load
to load a file with the connect
mand:
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 in safety and excluded from version control.
I assume you are using node.js
so the basic approach would be to do an application side encryption i.e. encrypt in your app code the fields such as passwords before saving it to mongoDB.
how you do it ?
you can use a node.js package called bcrypt
.
To install bcrypt use the following mand: npm install bcrypt –save-dev.
Then you can write a function on Save operation which will encrypt the fields you want 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);
});
The other option you have is to configure some security at the Database level itself. well that's something huge so i cannot really summarize it here.
hope this link will be helpful for you : https://docs.mongodb./manual/security/
本文标签: javascriptMongoDB How to store credentials safelyStack Overflow
版权声明:本文标题:javascript - MongoDB: How to store credentials safely? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741652315a2390552.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论