How to update user-defined roles in MongoDB 3.0 in a sharding environment? - mongodb

I'm using MMS to manage my a typical sharding cluster with just one shard (at the moment): 3 mongod for shard000 (2 servers + 1 arbiter) + 1 config server + 2 mongos instances.
Auth is enabled and it's working well. I've added a user-defined role in the MMS admin console, and I can see it in mongo shell.
db.system.roles.findOne()
{
"_id" : "admin.myrole",
"role" : "myrole",
"db" : "admin",
"privileges" : [
{
"resource" : {
"db" : "",
"collection" : ""
},
"actions" : [
"changeCustomData",
"changePassword",
...
I want to change it to AnyAction on AnyResource (as doEval action requires). So, I'm trying to execute this:
db.runCommand({ "updateRole": "myrole", "privileges": [ { resource: { anyResource: true}, actions: [ "anyAction" ] } ] }); db.system.roles.findOne()`
and for one second, I get the result I want:
{
"_id" : "admin.myrole",
"role" : "myrole",
"db" : "admin",
"privileges" : [
{
"resource" : {
"anyResource" : true
},
"actions" : [
"anyAction"
]
}
],
"roles" : [ ]
}
But, about two seconds later:
the role got restored:
configsvr> db.system.roles.findOne()
{
"_id" : "admin.myrole",
"role" : "myrole",
"db" : "admin",
"privileges" : [
{
"resource" : {
"db" : "",
"collection" : ""
},
"actions" : [
"changeCustomData",
"changePassword",
...
and I don't know "who" is restoring it.
I've tried the above commands from the PRIMARY and from CONFIG server in admin database.
How can I get the role stored?
P.S: I know that "eval" is deprecated in 3.0, but what I'm asking is the reason I can't update the role.

Related

How to disallow a mongoDB user to update dataset?

I've created an user xyz with "read" permissions an a given Databases:
{
"_id" : "admin.xyz",
"userId" : UUID("12345trntr4-3465465465771-4d6nre9-96rnc51-96rntrndfb33affebe"),
"user" : "user01",
"db" : "admin",
"credentials" : {
"SCRAM-SHA-1" : {
"iterationCount" : 10000,
"salt" : "08154711",
"storedKey" : "raunuqfiagnuiraed132c4=",
"serverKey" : "LH89uhiearnuiae323cj3k="
},
"SCRAM-SHA-256" : {
"iterationCount" : 15000,
"salt" : "nuqfgiaeh98hepQFGHdmnudtrianefqX1Ag==",
"storedKey" : "nDuqfgiaeh98hepQFGHdmnudtrianefqmaM=",
"serverKey" : "zNuqfgiaeh98hepQFGHdmnudtrianefqDI="
}
},
"roles" : [
{
"role" : "read",
"db" : "myDatabase01"
},
{
"role" : "read",
"db" : "myDatabase02"
}
]
}
And in fact, if I connect with a DB-Client, and try to enter new Dataset it is denied.
BUT, it is still possible to EDIT an existing entry.
Question
How to I archive to have a user, who has read-only permission, but is not allowed to update (or change anything at all) in the Database?
Can you check whether user1 has some edit role(s) in the DB itself (not in admin DB)?
e.g. by running
use myDatabase01;
db.getUser("user1");
use myDatabase02;
db.getUser("user1");
A possible readWrite role defined on the specific DB (not in admin DB) might explain the weird situation that you are experiencing.

Why does dropping the last collection drop the database as well

I am trying to delete a collection from database using script file (.js).
My js file is a below
db1 = db.getSiblingDB('Books');
db1.TestBook.drop();
and executing like below
mongo localhost:27017 "d:/test.js"
When my database has multiple collection it is deleting that collection means "TestBook".
But if I try to deleted the last collection it is deleting the database as well.
Can anyone suggest what I am doing wrong.
This appears to be how MongoDB works:
MongoDB Enterprise > db.foo.insert({a:1})
WriteResult({ "nInserted" : 1 })
MongoDB Enterprise > db.getSiblingDB('admin').runCommand({listDatabases:1})
{
"databases" : [
{
"name" : "admin",
"sizeOnDisk" : NumberLong(8192),
"empty" : false
},
{
"name" : "config",
"sizeOnDisk" : NumberLong(12288),
"empty" : false
},
{
"name" : "local",
"sizeOnDisk" : NumberLong(8192),
"empty" : false
},
{
"name" : "test",
"sizeOnDisk" : NumberLong(8192),
"empty" : false
}
],
"totalSize" : NumberLong(36864),
"totalSizeMb" : NumberLong(0),
"ok" : 1
}
MongoDB Enterprise > db.foo.drop()
true
MongoDB Enterprise > db.getSiblingDB('admin').runCommand({listDatabases:1})
{
"databases" : [
{
"name" : "admin",
"sizeOnDisk" : NumberLong(8192),
"empty" : false
},
{
"name" : "config",
"sizeOnDisk" : NumberLong(12288),
"empty" : false
},
{
"name" : "local",
"sizeOnDisk" : NumberLong(8192),
"empty" : false
}
],
"totalSize" : NumberLong(28672),
"totalSizeMb" : NumberLong(0),
"ok" : 1
}
However, it appears that the database retains at least some of the configured state for the dropped database. For example, if you enable sharding on a database, then drop the last collection, then try to enable sharding on a new collection in that database, sharding on the collection will be enabled which requires the sharding to have already been enabled on the database.
Dropping collections does change the list of returned databases, which could be problematic for applications. You can report this as an issue via https://jira.mongodb.org/browse/server if you like.

mongodb user can login without any authentication

When you first install mongodb, there is no root user. You simply start mongo with (if on mac osx) "mongod --dbpath='/usr/local/var/mongodb'", and then run mongo in the shell and it will connect you without any authentication.
I create the admin user in the admin database:
> db
admin
> db.createUser({
"user" : "test1",
"pwd" : "test1",
"roles" : [ { "role" : "userAdminAnyDatabase", "db" : "admin" } ]
})
> db.getUsers()
[
{
"_id" : "admin.test1",
"user" : "test1",
"db" : "admin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
],
"mechanisms" : [
"SCRAM-SHA-1",
"SCRAM-SHA-256"
]
}
]
Now I connect to mongo shell as admin user:
> db
admin
> db.runCommand({connectionStatus : 1})
{
"authInfo" : {
"authenticatedUsers" : [
{
"user" : "test1",
"db" : "admin"
}
],
"authenticatedUserRoles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
},
"ok" : 1
}
I start mongod with access control:
$ sudo mongod --auth --port 27017 --dbpath=.
Password:
2020-04-16T20:28:40.656-0400 I CONTROL [main] Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'
2020-04-16T20:28:40.672-0400 I CONTROL [initandlisten] MongoDB starting : pid=8441 port=27017 dbpath=. 64-bit
I even turned on security:
$ cd /usr/local/etc/
$ vim mongod.conf
security:
authorization: "enabled"
Yet I can simply login with just "mongo":
$ mongo admin
MongoDB shell version v4.0.4
connecting to: mongodb://127.0.0.1:27017/admin
Implicit session: session { "id" : UUID("95879725-00ed-4cee-bd43-8ba093df1e19") }
MongoDB server version: 4.0.4
> db.runCommand({connectionStatus : 1})
{
"authInfo" : {
"authenticatedUsers" : [ ],
"authenticatedUserRoles" : [ ]
},
"ok" : 1
}
This is wild. What else must I do? Unless there is some type of automatic login when logged into the ip the server is running on?
Some commands do not require authentication. Try reading or writing to a collection.
Authentication itself is performed via a sequence of commands (you can read about those here) therefore some of the commands must by necessity not require authentication.
Some commands return different responses based on whether a connection is authenticated. For example, try {ismaster:1} with and without authentication.

cannot authenticate with new user in mongo

> use failsafereports;
> db.createUser({ user : 'readonly', pwd: 'readonly', roles : ['read']})
Successfully added user: { "user" : "readonly", "roles" : [ "read" ] }
> show users;
{
"_id" : "failsafereports.readonly",
"user" : "readonly",
"db" : "failsafereports",
"roles" : [
{
"role" : "read",
"db" : "failsafereports"
}
]
}
> db.auth('readonly','readonly')
Error: 18 { ok: 0.0, errmsg: "auth failed", code: 18 }
0
I am creating a new user.
It shows when I use show users
But when I try to auth, it fails.
any ideas?
I've read around the internet about this problem occurring from the command line, but couldn't find one that happens from mongo shell.

How do you change MongoDB user permissions?

For instance, if I have this user:
> db.system.users.find()
{ "user" : "testAdmin", "pwd" : "[some hash]", "roles" : [ "clusterAdmin" ], "otherDBRoles" : { "TestDB" : [ "readWrite" ] } }
And I want to give that user the dbAdmin permissions on the TestDB database, I can remove the user record then add it back with the new permissions:
> db.system.users.remove({"user":"testAdmin"})
> db.addUser( { user: "testAdmin",
pwd: "[whatever]",
roles: [ "clusterAdmin" ],
otherDBRoles: { TestDB: [ "readWrite", "dbAdmin" ] } } )
But that seems hacky and error-prone.
And I can update the table record itself:
> db.system.users.update({"user":"testAdmin"}, {$set:{ otherDBRoles: { TestDB: [ "readWrite", "dbAdmin" ] }}})
But I'm not sure if that really creates the correct permissions - it looks fine but it may be subtly wrong.
Is there a better way to do this?
If you want to just update Role of User. You can do in the following way
db.updateUser( "userName",
{
roles : [
{ role : "dbAdmin", db : "dbName" },
{ role : "readWrite", db : "dbName" }
]
}
)
Note:- This will override only roles for that user.
See array update operators.
> db.users.findOne()
{
"_id" : ObjectId("51e3e2e16a847147f7ccdf7d"),
"user" : "testAdmin",
"pwd" : "[some hash]",
"roles" : [
"clusterAdmin"
],
"otherDBRoles" : {
"TestDB" : [
"readWrite"
]
}
}
> db.users.update({"user" : "testAdmin"}, {$addToSet: {'otherDBRoles.TestDB': 'dbAdmin'}}, false, false)
> db.users.findOne()
{
"_id" : ObjectId("51e3e2e16a847147f7ccdf7d"),
"user" : "testAdmin"
"pwd" : "[some hash]",
"roles" : [
"clusterAdmin"
],
"otherDBRoles" : {
"TestDB" : [
"readWrite",
"dbAdmin"
]
},
}
Update:
MongoDB checks permission on every access. If you see operator db.changeUserPassword:
> db.changeUserPassword
function (username, password) {
var hashedPassword = _hashPassword(username, password);
db.system.users.update({user : username, userSource : null}, {$set : {pwd : hashedPassword}});
var err = db.getLastError();
if (err) {
throw "Changing password failed: " + err;
}
}
You will see — operator changes user's document.
See also system.users Privilege Documents and Delegated Credentials for MongoDB Authentication