summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/list_databases.cpp
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2018-10-10 19:46:46 +0000
committerSara Golemon <sara.golemon@mongodb.com>2018-10-11 20:27:14 +0000
commit02455d9de270cf612329425301478262cb30af1f (patch)
tree27d3e7f45a4139e4547d1bb4cbf9f0f3bf322557 /src/mongo/db/commands/list_databases.cpp
parent480af6017647716bd2d087c6d772ef44db47c4cc (diff)
downloadmongo-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.cpp31
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.