summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2022-02-24 16:24:43 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-02-28 23:25:56 +0000
commit7584bddbd31e6d803ffd950e134390e97ba25f84 (patch)
treead0fe35171ff78b1776475826f70a60c363555e6
parent71d70bf5ebba88a8f51a20d660cb4d9c6532f35c (diff)
downloadmongo-7584bddbd31e6d803ffd950e134390e97ba25f84.tar.gz
SERVER-63968 Prohibit ennumeration of builtin roles on $external database
(cherry picked from commit 59df956365a44cc63e2d3c55d1734ee960891a8b)
-rw-r--r--jstests/core/builtin_roles_external.js47
-rw-r--r--src/mongo/db/auth/builtin_roles.cpp18
-rw-r--r--src/mongo/db/namespace_string.h3
3 files changed, 64 insertions, 4 deletions
diff --git a/jstests/core/builtin_roles_external.js b/jstests/core/builtin_roles_external.js
new file mode 100644
index 00000000000..f2b9263cd5d
--- /dev/null
+++ b/jstests/core/builtin_roles_external.js
@@ -0,0 +1,47 @@
+/**
+ * Attempting to enumerate roles on the $external database should return an empty set.
+ * @tags: [requires_fcv_60,tenant_migration_incompatible]
+ */
+(function() {
+"use strict";
+
+function assertBuiltinRoles(dbname, shouldHaveRoles) {
+ const allRoles = assert
+ .commandWorked(db.getSiblingDB(dbname).runCommand(
+ {rolesInfo: 1, showBuiltinRoles: 1, showPrivileges: 1}))
+ .roles;
+ jsTest.log(dbname + ' roles: ' + tojson(allRoles));
+
+ const builtinRoles = allRoles.filter((r) => r.isBuiltin);
+ if (shouldHaveRoles) {
+ assert.gt(builtinRoles.length, 0, dbname + ' should have builtin roles, but none returned');
+
+ function assertRole(role, expect = true) {
+ const filtered = builtinRoles.filter((r) => r.role === role);
+ if (expect) {
+ assert.gt(
+ filtered.length, 0, dbname + ' should have role ' + role + ' but does not');
+ } else {
+ assert.eq(
+ filtered.length,
+ 0,
+ dbname + ' should have not role ' + role + ' but does: ' + tojson(filtered));
+ }
+ }
+
+ assertRole('read');
+ assertRole('readWrite');
+ assertRole('readWriteAnyDatabase', dbname === 'admin');
+ assertRole('hostManager', dbname === 'admin');
+ } else {
+ assert.eq(builtinRoles.length,
+ 0,
+ dbname + ' should not have builtin roles, found: ' + tojson(builtinRoles));
+ }
+}
+
+assertBuiltinRoles('admin', true);
+assertBuiltinRoles('test', true);
+assertBuiltinRoles('$external', false);
+assertBuiltinRoles('$test', true);
+}());
diff --git a/src/mongo/db/auth/builtin_roles.cpp b/src/mongo/db/auth/builtin_roles.cpp
index 7faee09e529..cf56506ca60 100644
--- a/src/mongo/db/auth/builtin_roles.cpp
+++ b/src/mongo/db/auth/builtin_roles.cpp
@@ -768,9 +768,21 @@ const std::map<StringData, BuiltinRoleDefinition> kBuiltinRoles({
{BUILTIN_ROLE_INTERNAL, {true, addInternalRolePrivileges}},
});
+// $external is a virtual database used for X509, LDAP,
+// and other authentication mechanisms and not used for storage.
+// Therefore, granting privileges on this database does not make sense.
+bool isValidDB(StringData dbname) {
+ return NamespaceString::validDBName(dbname, NamespaceString::DollarInDbNameBehavior::Allow) &&
+ (dbname != NamespaceString::kExternalDb);
+}
+
} // namespace
stdx::unordered_set<RoleName> auth::getBuiltinRoleNamesForDB(StringData dbname) {
+ if (!isValidDB(dbname)) {
+ return {};
+ }
+
const bool isAdmin = dbname == ADMIN_DBNAME;
stdx::unordered_set<RoleName> roleNames;
@@ -786,8 +798,7 @@ bool auth::addPrivilegesForBuiltinRole(const RoleName& roleName, PrivilegeVector
auto role = roleName.getRole();
auto dbname = roleName.getDB();
- if (!NamespaceString::validDBName(dbname, NamespaceString::DollarInDbNameBehavior::Allow) ||
- dbname == "$external") {
+ if (!isValidDB(dbname)) {
return false;
}
@@ -814,8 +825,7 @@ void auth::generateUniversalPrivileges(PrivilegeVector* privileges) {
bool auth::isBuiltinRole(const RoleName& role) {
auto dbname = role.getDB();
- if (!NamespaceString::validDBName(dbname, NamespaceString::DollarInDbNameBehavior::Allow) ||
- dbname == "$external") {
+ if (!isValidDB(dbname)) {
return false;
}
diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h
index ff7b93a983a..cb90a3dde39 100644
--- a/src/mongo/db/namespace_string.h
+++ b/src/mongo/db/namespace_string.h
@@ -68,6 +68,9 @@ public:
// Namespace for the sharding config database
static constexpr StringData kConfigDb = "config"_sd;
+ // The $external database used by X.509, LDAP, etc...
+ static constexpr StringData kExternalDb = "$external"_sd;
+
// Name for the system views collection
static constexpr StringData kSystemDotViewsCollectionName = "system.views"_sd;