diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2018-10-10 19:46:46 +0000 |
---|---|---|
committer | Sara Golemon <sara.golemon@mongodb.com> | 2018-10-11 20:27:14 +0000 |
commit | 02455d9de270cf612329425301478262cb30af1f (patch) | |
tree | 27d3e7f45a4139e4547d1bb4cbf9f0f3bf322557 /src/mongo/db/commands/list_databases.cpp | |
parent | 480af6017647716bd2d087c6d772ef44db47c4cc (diff) | |
download | mongo-02455d9de270cf612329425301478262cb30af1f.tar.gz |
SERVER-37551 Add authorizedDatabases param to listDatabases command
Diffstat (limited to 'src/mongo/db/commands/list_databases.cpp')
-rw-r--r-- | src/mongo/db/commands/list_databases.cpp | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/src/mongo/db/commands/list_databases.cpp b/src/mongo/db/commands/list_databases.cpp index 59e29c5f600..62a09490f2e 100644 --- a/src/mongo/db/commands/list_databases.cpp +++ b/src/mongo/db/commands/list_databases.cpp @@ -92,10 +92,29 @@ public: BSONObjBuilder& result) final { IDLParserErrorContext ctx("listDatabases"); auto cmd = ListDatabasesCommand::parse(ctx, cmdObj); + auto* as = AuthorizationSession::get(opCtx->getClient()); + // {nameOnly: bool} - default false. const bool nameOnly = cmd.getNameOnly(); - // Parse the filter. + // {authorizedDatabases: bool} - Dynamic default based on permissions. + const bool authorizedDatabases = ([as](const boost::optional<bool>& authDB) { + const bool mayListAllDatabases = as->isAuthorizedForActionsOnResource( + ResourcePattern::forClusterResource(), ActionType::listDatabases); + + if (authDB) { + uassert(ErrorCodes::Unauthorized, + "Insufficient permissions to list all databases", + authDB.get() || mayListAllDatabases); + return authDB.get(); + } + + // By default, list all databases if we can, otherwise + // only those we're allowed to find on. + return !mayListAllDatabases; + })(cmd.getAuthorizedDatabases()); + + // {filter: matchExpression}. std::unique_ptr<MatchExpression> filter; if (auto filterObj = cmd.getFilter()) { // The collator is null because database metadata objects are compared using simple @@ -116,20 +135,12 @@ public: vector<BSONObj> dbInfos; - // If we have ActionType::listDatabases, - // then we don't need to test each record in the output. - // Otherwise, we'll test the database names as we enumerate them. - const auto as = AuthorizationSession::get(opCtx->getClient()); - const bool checkAuth = as && - !as->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(), - ActionType::listDatabases); - const bool filterNameOnly = filter && filter->getCategory() == MatchExpression::MatchCategory::kLeaf && filter->path() == kNameField; intmax_t totalSize = 0; for (const auto& dbname : dbNames) { - if (checkAuth && as && + if (authorizedDatabases && !as->isAuthorizedForActionsOnResource(ResourcePattern::forDatabaseName(dbname), ActionType::find)) { // We don't have listDatabases on the cluser or find on this database. |