Closed rechvs closed 1 year ago
@rechvs now i had some time to look into this.. are you using https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo.spring with user and password set as in this test: https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo.spring/blob/main/src/test/java/de/flapdoodle/embed/mongo/spring/autoconfigure/EmbeddedMongoAutoConfigurationTest.java#L194 ?
Thank you for looking into this.
I’ve finally had time to set up an example project. To answer your question: no, I don’t use the Spring integration but rather setup everything manually (including role and user creation), so it’s very well possible that I’m screwing up there.
The project actually exemplifies three types of unexepected behavior (I’ve conflated the first and second one in my first comment, sorry about that):
com.mongodb.client.MongoDatabase::listCollectionNames
method (see Issue442Test::customRole)
This is the main concern of this issue.de.flapdoodle.reverse.TearDownException
at the end (see Issue442Test::readRole))@rechvs thanks.. i will have a look into this sample project..
I forgot to add this in my last comment: this is the offical documentation for the listCollections action.
@rechvs no problem..
@rechvs .. thanks for your example project.. one problem with this: as i try to reduce my dependency footprint i can shutdown a mongodb server simply by sending a binary stream of the shutdown command to an instance without using any driver.. UNTIL no auth is used .. that's why the shutdown fails if you set users with roles..
maybe i have a workaround for this.. i did some trickery in my spring adapter (call shutdown by driver, ignoring shutdown failure in teardown) .. but i hope i can solve this better then that.. stay tuned.
@rechvs i would like to use the testcode from your example as part of this project.. if this is ok? and would add an author line for this..
@rechvs as i understand this the readAnyDatabase can not be assigned to a new user https://www.mongodb.com/docs/manual/reference/built-in-roles/#readAnyDatabase
but i hope i can solve this better then that.. stay tuned.
:+1:
i would like to use the testcode from your example as part of this project.. if this is ok?
Sure, I’m glad I managed to cobble together something useful for this project. :slightly_smiling_face:
as i understand this the readAnyDatabase can not be assigned to a new user
Maybe you’re right: it seems that while users can be created on an arbitrary (non-admin) database, the readAnyDatabase role (like all all-database roles) only exists on the admin database. So if we want to eventually grant a user one of the all-database roles, we must create that user on the admin database? I added a commit to the example project that seems to verify this: the assertions of the readAnyDatabaseRole test now work, but the test throws a de.flapdoodle.reverse.TearDownException
at the end.
On the other hand, here the docs explicilty say (emphasis mine)
The database where you create the user (in this example,
test
) is that user's authentication database. Although the user authenticates to this database, the user can have roles in other databases. The user's authentication database does not limit the user's privileges.
But maybe I’m misunderstanding the roles in other dabatases part and it only means that users can have roles that grant access to other databases, while I initially thought it meant that users can have roles that are defined in other databases.
@rechvs in teardown i try to stop the mongodb by sending a shutdown command to the database, which does not work if auth==true .. i am working on this..
I think I found out what was wrong with my attempt to grant the readAnyDatabase role: when granting the role (either via createUser
or via grantRolesToUser
) you can specify the role as a document like this:
{ role: "<role>", db: "<database>" }
So if you want to grant the readAnyDatabase (which only exists on the admin database), you would specify the role like this (credit goes to @ydylla for pointing me in the right direction):
{"role": "readAnyDatabase", "db": "admin"}
I’ve adjusted the corresponding test in the example project accordingly. However, the test now fails with
com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='test-db-user', source='admin', password=
which I think is a flapdoodle issue.
@rechvs i will have to look into this change.. thanks for your efforts:)
@rechvs hmm... did you tried this directly on a mongodb? without this java-test-stuff? I am by far no expert on these issues...
No, not yet. I’ll verify the expected behavior against a normal MongoDB instance, but it might be a while until I have some time on my hands.
@rechvs no hurry:)
@rechvs .. any progress with that?
Sorry, not yet. I’m afraid I won’t have time for this before the end of February. :frowning_face: If keeping the issue open for a currently unknown time bothers you, feel free to close it. If it’s ok for you, I would reopen it as soon as I can work on it some more.
@rechvs .. no problem:) it stays open..
I’ve finally managed to verify that the behavior expected by me is actually the appropriate behavior.
I’ve attached a ZIP of shell scripts that’ll hopefully also help you in verifying the expected behavior (at least if you’re on Linux with systemd):
./mongodb-create-collections-without-auth
../mongodb-create-user-and-role-without-auth
./etc/mongod.conf
./stop-mongod-via-systemd; ./start-mongod-via-systemd
to restart your local MongoDB instance.Execute ./mongodb-list-collections-with-auth
.
This should return something like the following:
{
"cursor" : {
"id" : NumberLong(0),
"ns" : "issue-442-test-db.$cmd.listCollections",
"firstBatch" : [
{
"name" : "issue-442-test-coll-1",
"type" : "collection",
"options" : {
},
"info" : {
"readOnly" : false,
"uuid" : UUID("545ccde1-4362-4326-aeec-1798ecfb93d2")
},
"idIndex" : {
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
}
},
{
"name" : "issue-442-test-coll-2",
"type" : "collection",
"options" : {
},
"info" : {
"readOnly" : false,
"uuid" : UUID("70d8c260-b933-45dd-92bd-37d70578cf6d")
},
"idIndex" : {
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
}
}
]
},
"ok" : 1
}
@rechvs awesome .. so i can try to reproduce this.. :) thanks a lot..
@rechvs i could create a test from that .. https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo/blob/main/src/test/java/de/flapdoodle/embed/mongo/scenario/AccessControlAndListCollectionsActionTest.java .. now i can check which modification will break this:)
IMHO this should be possible in one go.. without a server restart.. but maybe not.
IMHO this should be possible in one go
I’m not sure. If I understand the procedure for SCRAM correctly, you have to start the instance without access control in order to be able to at least create the user admin (or whatever users you need for your test scenario), which you can then (when access control is enabled) use to create all other users. I don’t see a way around this. :frowning_face:
@rechvs .. i will try:) and then i have a test for that.. :) .. or a test that shows that it does not work..
@rechvs did update the test.. works in one go .. there are now to tests, hope it helps to spot the difference.. so i try to make this work in my spring adapter too:) thanks for your work and very helpful input:)
@rechvs after some fun with spring i could create this tests: https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo.spring/blob/main/src/test/java/de/flapdoodle/embed/mongo/spring/autoconfigure/AuthTest.java .. which now works with spring3.x, spring2.7.x and spring2.6.x .. i had to upgrade the mongodb drivers to make it work with spring2.7.x and spring2.6.x .. which was kind of surprise ..
.. and after all this i might wonder if the problem was a mongodb driver issue and not something we did wrong..
.. anyway. could remove a lot of code.. :) thanks for this inspiration:) i close this issue.. just reopen or create a new if still something is wrong.
Granting a user a role that includes the listCollections action (e.g., the readAnyDatabase role) does not actually allow that user to perform the listCollections command. Performing the command instead throws a MongoCommandException: