Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable authorizedDatabases & authorizedCollections for fetching metadata in MongoDB #14988

Merged
merged 2 commits into from
Dec 5, 2022

Conversation

huberty89
Copy link
Contributor

@huberty89 huberty89 commented Nov 10, 2022

Description

Enable authorizedDatabases & authorizedCollections for fetching metadata in MongoDB

Fixes

#1398

Release notes

( ) This is not user-visible or docs only and no release notes are required.
( ) Release notes are required, please propose a release note for me.
(x) Release notes are required, with the following suggested text:

# MongoDB
* Fix failure when an unauthorized exception happens while listing schemas or tables. ({issue}`1398`)

@huberty89
Copy link
Contributor Author

I need to update the docs

@huberty89 huberty89 force-pushed the huberty89/mongo-metadata-privileges branch from 0db337e to 0dfe3d0 Compare November 10, 2022 20:37
@huberty89
Copy link
Contributor Author

Looks like TestMetadataPrivilegesRequired test added by me is flaky - Docker container with MongoDB cannot starts successfully.
I will take a look on Monday.

@huberty89 huberty89 force-pushed the huberty89/mongo-metadata-privileges branch from 0dfe3d0 to 0c8ad0a Compare November 10, 2022 22:01
@@ -44,6 +44,7 @@
private Optional<String> connectionUrl = Optional.empty();
private List<ServerAddress> seeds = ImmutableList.of();
private List<MongoCredential> credentials = ImmutableList.of();
private boolean metadataPrivilegesRequired = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you share why we want to introduce a config property? Other connectors hide unauthorized databases and tables. Always enabling authorizedDatabasesOnly & authorizedCollections properties looks fine to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But older versions behave differently with this config enabled so unless we confirm that we don’t support older versions of Mongo (i.e 4.0) - enabling it by default might cause some issue. @huberty89 can you share how it works in the latest and older version ?

Copy link
Contributor Author

@huberty89 huberty89 Nov 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I also agree to not introduce new property.
In older version of MongoDB returned list of databases and collection was filtered out, in newer versions it's required to have specific privilege to list those. So this behavior has changed between versions only for authorizedDatabases=true and authorizedCollections=true


private static MongoServer setupMongoServer()
{
MongoServer server = new MongoServer("4.0.6", ImmutableMap.of(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MongoDB 4.0 already reached EOL on Apr 30. Let's use a new version. Upcoming FTE on MongoDB will upgrade the minimum supported version to 4.2.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I set version to 4.4.17 - it seams docker init flakiness (when I set root user and password via env) got fixed

Copy link
Member

@ebyhr ebyhr Nov 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it's still failing in my environment. It looks relating to testcontainers/testcontainers-java#4695

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like org.testcontainers.containers.MongoDBContainer contains a bug.

When I set MONGO_INITDB_ROOT_USERNAME and MONGO_INITDB_ROOT_PASSWORD this cause a restart MongoDB process.
At the same time db.runCommand( { isMaster: 1 } ).ismaster==false is executed inside Docker container in a loop (60 times) and during process restart this throw network error - that's the main issue.

I create AuthenticatedMongoServer which use GenericContainer directly. Default enabled replication is not needed in current scenario.

Copy link
Member

@skrzypo987 skrzypo987 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks ok, ping me for another round.

@@ -44,6 +44,7 @@
private Optional<String> connectionUrl = Optional.empty();
private List<ServerAddress> seeds = ImmutableList.of();
private List<MongoCredential> credentials = ImmutableList.of();
private boolean metadataPrivilegesRequired = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But older versions behave differently with this config enabled so unless we confirm that we don’t support older versions of Mongo (i.e 4.0) - enabling it by default might cause some issue. @huberty89 can you share how it works in the latest and older version ?

@huberty89 huberty89 force-pushed the huberty89/mongo-metadata-privileges branch from 0c8ad0a to 5e159c8 Compare November 16, 2022 14:15
@huberty89
Copy link
Contributor Author

@skrzypo987 @ebyhr @Praveen2112 I make an update, please take a look

@huberty89 huberty89 force-pushed the huberty89/mongo-metadata-privileges branch from 5e159c8 to 32b1889 Compare November 16, 2022 14:30
@huberty89 huberty89 changed the title Add property to set requirement of privileges for fetching metadata from MongoDB Enable authorizedDatabases & authorizedCollections for fetching metadata in MongoDB Nov 16, 2022
Copy link
Member

@ebyhr ebyhr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good except for the flaky container initialization & a minor comment.


private static void createTestRole(MongoDatabase database)
{
Double commandStatus = database.runCommand(new BsonDocument("createRole", new BsonString(TEST_ROLE))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use Document class to improve readability?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, I also try to improve readability by spiting it into few methods

Copy link
Member

@s2lomon s2lomon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please elaborate on why these changes are required in commit message. Right now it doesn't seem important and it is. In addition please describe what is the current behaviour etc.

if (schemaName.equals(remoteSchemaName.toLowerCase(ENGLISH))) {
return remoteSchemaName;
}
}
return schemaName;
}

private Iterable<String> listDatabaseNames()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead returning Iterable from here and later turning it to Stream through ImmutableList.of(listDatabaseNames()).stream(), please return Iterable from here, for example by Streams.stream(...).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the name of the method starts with list maybe just return a list?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discuss this offline, because listDatabaseNames is private I return now MongoIterable

@@ -178,7 +183,7 @@ public List<HostAddress> getAddresses()

public List<String> getAllSchemas()
{
return ImmutableList.copyOf(client.listDatabaseNames()).stream()
return ImmutableList.copyOf(listDatabaseNames()).stream()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please look below - change the return type of listDatabaseNames to make it simpler to read. I'm kind of lost on what is transformed into what.

MongoDatabase database = client.getDatabase(databaseName);
Document cursor = database.runCommand(new Document(AUTHORIZED_LIST_COLLECTIONS_COMMAND)).get("cursor", Document.class);

List<Document> firstBatch = cursor.get("firstBatch", List.class);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would there be another batch ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or a next batch ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked in a MongoDB Java driver source and by just creating 10,000 collections in MongoDB and by default MongoDB returns everything in a single response, so this implementation should be sufficient.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does MongoDB takes too long to create 10,000 collections ? Can we add it as a test to ensure that if the newer version returns in some batch we could handle the same ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Listing 10,000 collections took for me 1.14 second. Still agree a test for this case is a good idea, I will add it

{
assertThat(getQueryRunner().execute("SHOW TABLES FROM mongodb." + TEST_DATABASE)
.getOnlyColumnAsSet())
.containsExactly(TEST_COLLECTION.toLowerCase(Locale.ENGLISH));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a redundant conversion ? Can we use assertQuery where we could provide a result as VALUES ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaced

}
}

private static void createTestRole(MongoDatabase database)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to MongoServer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved into AuthenticatedMongoServer

Copy link
Member

@skrzypo987 skrzypo987 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm % minor comment and other's comments

if (schemaName.equals(remoteSchemaName.toLowerCase(ENGLISH))) {
return remoteSchemaName;
}
}
return schemaName;
}

private Iterable<String> listDatabaseNames()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the name of the method starts with list maybe just return a list?

@huberty89 huberty89 force-pushed the huberty89/mongo-metadata-privileges branch 2 times, most recently from 5857836 to 963b174 Compare November 22, 2022 13:06
@huberty89 huberty89 force-pushed the huberty89/mongo-metadata-privileges branch from 963b174 to 47fcc6b Compare December 4, 2022 22:35
Send `authorizedDatabases=true` parameter while listing databases/schemas
Send `authorizedCollections=true` parameter while listing collections/tables
Without those listing databases & collections require `listDatabases` & `listCollections`
actions.
@huberty89 huberty89 force-pushed the huberty89/mongo-metadata-privileges branch from 47fcc6b to 87bf835 Compare December 4, 2022 22:47
@huberty89
Copy link
Contributor Author

@Praveen2112 @skrzypo987 @ebyhr Please take a look if everything looks good and it's good to be merged, thanks

@ebyhr ebyhr merged commit a53d472 into trinodb:master Dec 5, 2022
@ebyhr
Copy link
Member

ebyhr commented Dec 5, 2022

Merged, thanks!

@findepi
Copy link
Member

findepi commented Jan 10, 2023

Follow up: #15652

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

6 participants