[SERVER-3301] Allow admin user to login to any database Created: 20/Jun/11  Updated: 10/Dec/14  Resolved: 08/May/14

Status: Closed
Project: Core Server
Component/s: Admin
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Minor - P4
Reporter: Ryan Nitz Assignee: Unassigned
Resolution: Done Votes: 4
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to DOCS-3370 Clarify that even though in 2.6 all u... Closed
Participants:

 Description   

Currently, in the shell if you created an admin user you need to login to the admin database first and then change databases.

For example, this fails for an admin account:

mongo -u test -p test localhost:27017/test

This succeeds for an admin account:

mongo -u test -p test localhost:27017/admin

MySQL will let you connect to any database from the shell (with auth). This becomes an issue when you'are executing scripts from the shell. Currently, you have to login to admin and then issue a change database.

This will/is confusing for users.



 Comments   
Comment by Spencer Brody (Inactive) [ 08/May/14 ]

It seems like there is some confusion here, let me see if I can help clarify the behavior.

In version 2.4, we added the authenticationDatabase option to the shell, which I believe addresses the initial issue from this ticket, as now if you want the shell to connect to the "test" database but authenticate to the "admin" db you can do that by specifying "--authenticationDatabase admin".

As to Rudi's question, while the system was changed to store user documents in the admin database, you are right that the core behavior is the same in that users are still scoped to specific databases, and you must specify the proper database when authenticating a user. The change in 2.6 was merely to centralize the storage of user information, not to change the fact that every user still has a "home" database they are associated with. You can think about the database component almost like a namespace, so user "bob" on the "test" database is a completely distinct user from user "bob" on the "foo" database, even though the user documents are all stored in the "admin" database. I filed DOCS-3370 to clarify this in our documentation.

Hopefully that helps clear things up. Please let us know if you have any further questions about this behavior.

Comment by Rudi Wijaya [ 07/May/14 ]

ceefour tag

Comment by Rudi Wijaya [ 07/May/14 ]

MongoDB 2.6.0 release notes (http://docs.mongodb.org/manual/release-notes/2.6/) mentioned:

Global user management, which stores all user and user-defined role data in the admin database and provides a new set of commands for managing users and roles.

According to the documentation it should be possible to login into any database just by creating the user in admin database. MongoDB behavior as of 2.6.1 seems to be similar to 2.4.x, i.e. it doesn't follow the 2.6 documentation.

With the following user in admin database:

{
        "_id" : "admin.bipporeg_dev",
        "user" : "bipporeg_dev",
        "db" : "admin",
        "roles" : [
                {
                        "role" : "userAdmin",
                        "db" : "demo_dev"
                },
                {
                        "role" : "dbAdmin",
                        "db" : "demo_dev"
                },
                {
                        "role" : "readWrite",
                        "db" : "demo_dev"
                }
        ]
}

mongo shell test case:

rudi@rudi ~ $ mongo -ubipporeg_dev -ppassword admin
MongoDB shell version: 2.6.1
connecting to: admin
Error while trying to show server startup warnings: not authorized on admin to execute command { getLog: "startupWarnings" }
> use demo_dev
switched to db demo_dev
> db.product.count()
126
> 
bye
 
rudi@rudi ~ $ mongo -ubipporeg_dev -ppassword demo_dev
MongoDB shell version: 2.6.1
connecting to: demo_dev
2014-05-07T00:46:31.570-0430 Error: 18 { ok: 0.0, errmsg: "auth failed", code: 18 } at src/mongo/shell/db.js:1210
exception: login failed

Java test case:

@Test
public void loginDirectlyToDatabase() throws UnknownHostException {
	MongoClient mongo = new MongoClient(new MongoClientURI("mongodb://bipporeg_dev:password@localhost/demo_dev"));
	System.out.println(mongo.getDB("demo_dev").getCollection("product").count());
}
 
@Test
public void loginViaAdmin() throws UnknownHostException {
	MongoClient mongo = new MongoClient(new MongoClientURI("mongodb://bipporeg_dev:password@localhost/admin"));
	System.out.println(mongo.getDB("demo_dev").getCollection("product").count());
}
 
@Test
public void loginViaNothing() throws UnknownHostException {
	MongoClient mongo = new MongoClient(new MongoClientURI("mongodb://bipporeg_dev:password@localhost/"));
	System.out.println(mongo.getDB("demo_dev").getCollection("product").count());
}

loginViaAdmin and (surprisingly) loginViaNothing succeeds, while loginDirectlyToDatabase fails with:

com.mongodb.CommandFailureException: { "serverUsed" : "localhost:27017" , "ok" : 0.0 , "errmsg" : "auth failed" , "code" : 18}
	at com.mongodb.CommandResult.getException(CommandResult.java:76)
	at com.mongodb.CommandResult.throwOnError(CommandResult.java:131)
	at com.mongodb.DBPort$NativeAuthenticator.authenticate(DBPort.java:658)
	at com.mongodb.DBPort.authenticate(DBPort.java:370)
	at com.mongodb.DBPort.checkAuth(DBPort.java:381)
	at com.mongodb.DBTCPConnector.innerCall(DBTCPConnector.java:299)
	at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:279)
	at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:84)
	at com.mongodb.DB.command(DB.java:317)
	at com.mongodb.DB.command(DB.java:296)
	at com.mongodb.DBCollection.getCount(DBCollection.java:1189)
	at com.mongodb.DBCollection.getCount(DBCollection.java:1154)
	at com.mongodb.DBCollection.getCount(DBCollection.java:1138)
	at com.mongodb.DBCollection.getCount(DBCollection.java:1107)
	at com.mongodb.DBCollection.count(DBCollection.java:1028)
	at org.soluvas.mongo.Apatest.loginDirectlyToDatabase(Apatest.java:25)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Comment by Rudi Wijaya [ 07/May/14 ]

This real behavior (tested with mongos 2.6.1) is contrary to MongoDB Manual (http://docs.mongodb.org/manual/core/authentication/) which says:

"MongoDB stores all user information, including credentials and authorization information, for a MongoDB instance in the system.users collection in the admin database."

The manual confirms that user information for a particular database needs not be stored in that database as well, but only in the admin database. However, in reality that's not the case.

Comment by Jake Justman [ 10/Apr/13 ]

I ran into this when trying to add users from the unix shell when trying to execute the below command.

mongo -u mms_agent -p testpass --eval "db.addUser('tim', 'tim')" fun

Comment by Ryan Nitz [ 20/Jun/11 ]

Just to clarify... if an admin logs in and the database isn't admin, the admin database auth credentials should be checked first (or of the auth fails... whichever works).

Generated at Thu Feb 08 03:02:40 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.