summaryrefslogtreecommitdiff
path: root/src/mongo/db/auth
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/auth')
-rw-r--r--src/mongo/db/auth/SConscript27
-rw-r--r--src/mongo/db/auth/action_type.idl19
-rw-r--r--src/mongo/db/auth/auth_name.cpp9
-rw-r--r--src/mongo/db/auth/auth_name.h2
-rw-r--r--src/mongo/db/auth/auth_op_observer.h4
-rw-r--r--src/mongo/db/auth/authentication_session.cpp50
-rw-r--r--src/mongo/db/auth/authentication_session.h6
-rw-r--r--src/mongo/db/auth/authorization_manager_impl.cpp8
-rw-r--r--src/mongo/db/auth/authorization_session_impl.cpp14
-rw-r--r--src/mongo/db/auth/authorization_session_test.cpp117
-rw-r--r--src/mongo/db/auth/authorization_session_test_fixture.cpp88
-rw-r--r--src/mongo/db/auth/authorization_session_test_fixture.h87
-rw-r--r--src/mongo/db/auth/builtin_roles.cpp42
-rw-r--r--src/mongo/db/auth/builtin_roles_test.cpp1
-rw-r--r--src/mongo/db/auth/resource_pattern.h4
-rw-r--r--src/mongo/db/auth/sasl_commands.h2
-rw-r--r--src/mongo/db/auth/sasl_mechanism_registry.h10
-rw-r--r--src/mongo/db/auth/user.cpp6
18 files changed, 156 insertions, 340 deletions
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript
index b8639a62846..57af14b709d 100644
--- a/src/mongo/db/auth/SConscript
+++ b/src/mongo/db/auth/SConscript
@@ -82,7 +82,7 @@ env.Library(
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/audit',
'$BUILD_DIR/mongo/db/catalog/collection_options',
- '$BUILD_DIR/mongo/db/index/index_access_method',
+ '$BUILD_DIR/mongo/db/index/index_descriptor',
'$BUILD_DIR/mongo/db/op_observer',
'$BUILD_DIR/mongo/db/op_observer_util',
'$BUILD_DIR/mongo/db/repl/oplog_entry',
@@ -189,9 +189,9 @@ env.Library(
'$BUILD_DIR/mongo/base/secure_allocator',
'$BUILD_DIR/mongo/bson/util/bson_extract',
'$BUILD_DIR/mongo/db/common',
+ '$BUILD_DIR/mongo/db/curop',
'$BUILD_DIR/mongo/db/global_settings',
'$BUILD_DIR/mongo/db/namespace_string',
- '$BUILD_DIR/mongo/db/query/query_stats/query_stats',
'$BUILD_DIR/mongo/idl/feature_flag',
'$BUILD_DIR/mongo/util/concurrency/thread_pool',
'$BUILD_DIR/mongo/util/icu',
@@ -514,7 +514,7 @@ env.Library(
source=[
'ldap_operation_stats.cpp',
'ldap_cumulative_operation_stats.cpp',
- 'user_cache_acquisition_stats.cpp',
+ 'user_cache_acquisition_stats.cpp'
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/base',
@@ -522,22 +522,6 @@ env.Library(
],
)
-env.Library(
- target='authorization_session_test_fixture',
- source=[
- 'authorization_session_for_test.cpp',
- 'authorization_session_test_fixture.cpp',
- ],
- LIBDEPS=[
- '$BUILD_DIR/mongo/db/service_context_d_test_fixture',
- '$BUILD_DIR/mongo/transport/transport_layer_mock',
- 'auth',
- 'auth_impl_internal',
- 'authentication_restriction',
- 'authmocks',
- ],
-)
-
env.CppUnitTest(
target='db_auth_test',
source=[
@@ -547,6 +531,7 @@ env.CppUnitTest(
'authorization_contract_test.cpp',
'auth_op_observer_test.cpp',
'authorization_manager_test.cpp',
+ 'authorization_session_for_test.cpp',
'authorization_session_test.cpp',
'builtin_roles_test.cpp',
'privilege_parser_test.cpp',
@@ -569,12 +554,14 @@ env.CppUnitTest(
'$BUILD_DIR/mongo/db/service_context_d_test_fixture',
'$BUILD_DIR/mongo/db/service_context_test_fixture',
'$BUILD_DIR/mongo/transport/transport_layer_common',
+ '$BUILD_DIR/mongo/transport/transport_layer_mock',
'$BUILD_DIR/mongo/util/net/network',
'address_restriction',
+ 'auth',
+ 'auth_impl_internal',
'auth_op_observer',
'authentication_restriction',
'authmocks',
- 'authorization_session_test_fixture',
'saslauth',
'security_file',
'security_key',
diff --git a/src/mongo/db/auth/action_type.idl b/src/mongo/db/auth/action_type.idl
index 2c09bfca837..1d83378f275 100644
--- a/src/mongo/db/auth/action_type.idl
+++ b/src/mongo/db/auth/action_type.idl
@@ -45,7 +45,6 @@ enums:
values:
addShard : "addShard"
advanceClusterTime : "advanceClusterTime"
- allCollectionStats: "allCollectionStats"
anyAction : "anyAction" # Special ActionType that represents *all* actions
appendOplogNote : "appendOplogNote"
applicationMessage : "applicationMessage"
@@ -77,7 +76,6 @@ enums:
createDatabase : "createDatabase" # ID only
createIndex : "createIndex" # ID only
createRole : "createRole"
- createSearchIndexes : "createSearchIndexes"
createUser : "createUser"
dbCheck : "dbCheck"
dbHash : "dbHash"
@@ -88,7 +86,6 @@ enums:
dropConnections : "dropConnections"
dropDatabase : "dropDatabase"
dropIndex : "dropIndex"
- dropSearchIndex : "dropSearchIndex"
dropRole : "dropRole"
dropUser : "dropUser"
emptycapped : "emptycapped"
@@ -99,7 +96,6 @@ enums:
flushRouterConfig : "flushRouterConfig"
forceUUID : "forceUUID"
fsync : "fsync"
- fsyncUnlock: "fsyncUnlock"
getClusterParameter: "getClusterParameter"
getDatabaseVersion : "getDatabaseVersion"
getDefaultRWConcern : "getDefaultRWConcern"
@@ -129,7 +125,6 @@ enums:
listCursors : "listCursors"
listDatabases : "listDatabases"
listIndexes : "listIndexes"
- listSearchIndexes : "listSearchIndexes"
listSessions : "listSessions"
listShards : "listShards"
logRotate : "logRotate"
@@ -140,8 +135,6 @@ enums:
planCacheIndexFilter : "planCacheIndexFilter" # view/update index filters
planCacheRead : "planCacheRead" # view contents of plan cache
planCacheWrite : "planCacheWrite" # clear cache, drop cache entry, pin/unpin/shun plans
- queryStatsRead: "queryStatsRead" # view untransformed contents of queryStats store
- queryStatsReadTransformed: "queryStatsReadTransformed" # view transformed contents of queryStats store
refineCollectionShardKey : "refineCollectionShardKey"
reIndex : "reIndex"
remove : "remove"
@@ -170,11 +163,10 @@ enums:
setClusterParameter: "setClusterParameter"
setDefaultRWConcern : "setDefaultRWConcern"
setFeatureCompatibilityVersion : "setFeatureCompatibilityVersion"
- setFreeMonitoring : "setFreeMonitoring" # Removed (backwards compatibility)
+ setFreeMonitoring : "setFreeMonitoring"
setParameter : "setParameter"
setUserWriteBlockMode: "setUserWriteBlockMode"
shardCollection : "shardCollection" # ID only
- shardedDataDistribution : "shardedDataDistribution"
shardingState : "shardingState"
shutdown : "shutdown"
splitChunk : "splitChunk"
@@ -188,7 +180,6 @@ enums:
useUUID : "useUUID"
update : "update"
updateRole : "updateRole" # ID only
- updateSearchIndex : "updateSearchIndex"
updateUser : "updateUser" # ID only
validate : "validate"
viewRole : "viewRole"
@@ -236,13 +227,11 @@ enums:
- convertToCapped
- createCollection
- createIndex
- - createSearchIndexes
- dbCheck
- dbHash
- dbStats
- dropCollection
- dropIndex
- - dropSearchIndex
- exportCollection
- find
- importCollection
@@ -251,14 +240,12 @@ enums:
- killCursors
- listCollections
- listIndexes
- - listSearchIndexes
- planCacheRead
- reIndex
- remove
- renameCollection
- renameCollectionSameDB
- update
- - updateSearchIndex
- validate
# resource: { db: 'exact', collection: '' }
@@ -278,13 +265,11 @@ enums:
- convertToCapped
- createCollection
- createIndex
- - createSearchIndexes
- dbCheck
- dbHash
- dbStats
- dropCollection
- dropIndex
- - dropSearchIndex
- exportCollection
- find
- importCollection
@@ -293,14 +278,12 @@ enums:
- killCursors
- listCollections
- listIndexes
- - listSearchIndexes
- planCacheRead
- reIndex
- remove
- renameCollection
- renameCollectionSameDB
- update
- - updateSearchIndex
- validate
# Actions specific to the database match types.
diff --git a/src/mongo/db/auth/auth_name.cpp b/src/mongo/db/auth/auth_name.cpp
index 2c091c0f53e..4b8116b23e8 100644
--- a/src/mongo/db/auth/auth_name.cpp
+++ b/src/mongo/db/auth/auth_name.cpp
@@ -164,15 +164,6 @@ BSONObj AuthName<T>::toBSON(bool encodeTenant) const {
return bob.obj();
}
-template <typename T>
-std::size_t AuthName<T>::getBSONObjSize() const {
- return 4UL + // BSONObj size
- 1UL + T::kFieldName.size() + 1UL + // FieldName elem type, FieldName, terminating NULL.
- 4UL + getName().size() + 1UL + // Length of name data, name data, terminating NULL.
- 1UL + ("db"_sd).size() + 1UL + // DB field elem type, "db", terminating NULL.
- 4UL + getDB().size() + 1UL + // DB value length, DB value, terminating NULL.
- 1UL; // EOD marker.
-}
// Materialize the types we care about.
template class AuthName<RoleName>;
diff --git a/src/mongo/db/auth/auth_name.h b/src/mongo/db/auth/auth_name.h
index 20a5e279fcd..62fd1d6fa8e 100644
--- a/src/mongo/db/auth/auth_name.h
+++ b/src/mongo/db/auth/auth_name.h
@@ -91,8 +91,6 @@ public:
void appendToBSON(BSONObjBuilder* bob, bool encodeTenant = false) const;
BSONObj toBSON(bool encodeTenant = false) const;
- std::size_t getBSONObjSize() const;
-
/**
* Gets the name part of a AuthName.
*/
diff --git a/src/mongo/db/auth/auth_op_observer.h b/src/mongo/db/auth/auth_op_observer.h
index f0afcd2a860..c145ebc3371 100644
--- a/src/mongo/db/auth/auth_op_observer.h
+++ b/src/mongo/db/auth/auth_op_observer.h
@@ -206,10 +206,6 @@ public:
size_t numberOfPrePostImagesToWrite,
Date_t wallClockTime) final {}
- void onTransactionPrepareNonPrimary(OperationContext* opCtx,
- const std::vector<repl::OplogEntry>& statements,
- const repl::OpTime& prepareOpTime) final {}
-
void onTransactionAbort(OperationContext* opCtx,
boost::optional<OplogSlot> abortOplogEntryOpTime) final {}
diff --git a/src/mongo/db/auth/authentication_session.cpp b/src/mongo/db/auth/authentication_session.cpp
index 97ae7654d01..30d6f74fc31 100644
--- a/src/mongo/db/auth/authentication_session.cpp
+++ b/src/mongo/db/auth/authentication_session.cpp
@@ -40,35 +40,21 @@ namespace mongo {
namespace {
constexpr auto kDiagnosticLogLevel = 3;
-Status crossVerifyUserNames(const UserName& oldUser,
- const UserName& newUser,
- const bool isMechX509) noexcept {
+Status crossVerifyUserNames(const UserName& oldUser, const UserName& newUser) noexcept {
if (oldUser.empty()) {
return Status::OK();
}
- // There are some special cases around __system where a switch in the username is acceptable.
- if (oldUser.getUser() == "__system") {
- // If the new user is on $external and X.509 auth is being used, then any username is
- // allowed.
- if (newUser.getDB() == "$external" && isMechX509) {
- return Status::OK();
- }
- }
-
- // Allow a switch from an empty user on admin to __system@local if enableTestCommands is true.
- // This is needed for auth passthrough suites on mongos.
- if (getTestCommandsEnabled() && oldUser.getUser().empty() && oldUser.getDB() == "admin" &&
- newUser.getUser() == "__system" && newUser.getDB() == "local") {
- return Status::OK();
- }
+ if (!getTestCommandsEnabled()) {
+ // Authenticating the __system@local user to the admin database on mongos is required
+ // by the auth passthrough test suite, hence we forgive this set of errors in testing.
- // Barring special cases, both the database and the username must be the same.
- if (oldUser.getDB() != newUser.getDB()) {
- return {
- ErrorCodes::ProtocolError,
- str::stream() << "Attempt to switch database target during SASL authentication from "
- << oldUser << " to " << newUser};
+ if (oldUser.getDB() != newUser.getDB()) {
+ return {ErrorCodes::ProtocolError,
+ str::stream()
+ << "Attempt to switch database target during SASL authentication from "
+ << oldUser << " to " << newUser};
+ }
}
if (oldUser.getUser().empty() || newUser.getUser().empty()) {
@@ -215,9 +201,8 @@ void AuthenticationSession::setMechanismName(StringData mechanismName) {
}
}
-void AuthenticationSession::_verifyUserNameFromSaslSupportedMechanisms(const UserName& userName,
- const bool isMechX509) {
- if (auto status = crossVerifyUserNames(_ssmUserName, userName, isMechX509); !status.isOK()) {
+void AuthenticationSession::_verifyUserNameFromSaslSupportedMechanisms(const UserName& userName) {
+ if (auto status = crossVerifyUserNames(_ssmUserName, userName); !status.isOK()) {
LOGV2(5286202,
"Different user name was supplied to saslSupportedMechs",
"error"_attr = status);
@@ -239,20 +224,20 @@ void AuthenticationSession::setUserNameForSaslSupportedMechanisms(UserName userN
"Set user name for session",
"userName"_attr = userName,
"oldName"_attr = _userName);
- _verifyUserNameFromSaslSupportedMechanisms(userName, false /* isMechX509 */);
+ _verifyUserNameFromSaslSupportedMechanisms(userName);
_ssmUserName = userName;
}
-void AuthenticationSession::updateUserName(UserName userName, bool isMechX509) {
+void AuthenticationSession::updateUserName(UserName userName) {
LOGV2_DEBUG(5286203,
kDiagnosticLogLevel,
"Updating user name for session",
"userName"_attr = userName,
"oldName"_attr = _userName);
- _verifyUserNameFromSaslSupportedMechanisms(userName, isMechX509);
- uassertStatusOK(crossVerifyUserNames(_userName, userName, isMechX509));
+ _verifyUserNameFromSaslSupportedMechanisms(userName);
+ uassertStatusOK(crossVerifyUserNames(_userName, userName));
_userName = userName;
}
@@ -287,8 +272,7 @@ void AuthenticationSession::_finish() {
if (_mech->isClusterMember()) {
setAsClusterMember();
}
- updateUserName({_mech->getPrincipalName(), _mech->getAuthenticationDatabase()},
- _mechName == auth::kMechanismMongoX509);
+ updateUserName({_mech->getPrincipalName(), _mech->getAuthenticationDatabase()});
}
}
diff --git a/src/mongo/db/auth/authentication_session.h b/src/mongo/db/auth/authentication_session.h
index 09206ab8b21..0b95b4ed2fb 100644
--- a/src/mongo/db/auth/authentication_session.h
+++ b/src/mongo/db/auth/authentication_session.h
@@ -145,7 +145,7 @@ public:
* The database will be validated against the current database for this session.
*/
void updateDatabase(StringData database) {
- updateUserName(UserName("", database.toString()), false /* isMechX509 */);
+ updateUserName(UserName("", database.toString()));
}
/**
@@ -153,7 +153,7 @@ public:
*
* The user name will be validated against the current user name for this session.
*/
- void updateUserName(UserName userName, bool isMechX509);
+ void updateUserName(UserName userName);
/**
* Set the last user name used with `saslSupportedMechs` for this session.
@@ -235,7 +235,7 @@ private:
static boost::optional<AuthenticationSession>& _get(Client* client);
void _finish();
- void _verifyUserNameFromSaslSupportedMechanisms(const UserName& user, bool isMechX509);
+ void _verifyUserNameFromSaslSupportedMechanisms(const UserName& user);
Client* const _client;
diff --git a/src/mongo/db/auth/authorization_manager_impl.cpp b/src/mongo/db/auth/authorization_manager_impl.cpp
index 771abcf427b..93450c8b1f5 100644
--- a/src/mongo/db/auth/authorization_manager_impl.cpp
+++ b/src/mongo/db/auth/authorization_manager_impl.cpp
@@ -675,35 +675,35 @@ void AuthorizationManagerImpl::_pinnedUsersThreadRoutine() noexcept try {
void AuthorizationManagerImpl::invalidateUserByName(OperationContext* opCtx,
const UserName& userName) {
LOGV2_DEBUG(20235, 2, "Invalidating user", "user"_attr = userName);
+ _updateCacheGeneration();
_authSchemaVersionCache.invalidateAll();
// Invalidate the named User, assuming no externally provided roles. When roles are defined
// externally, there exists no user document which may become invalid.
_userCache.invalidateKey(UserRequest(userName, boost::none));
- _updateCacheGeneration();
}
void AuthorizationManagerImpl::invalidateUsersFromDB(OperationContext* opCtx, StringData dbname) {
LOGV2_DEBUG(20236, 2, "Invalidating all users from database", "database"_attr = dbname);
+ _updateCacheGeneration();
_authSchemaVersionCache.invalidateAll();
_userCache.invalidateKeyIf(
[&](const UserRequest& userRequest) { return userRequest.name.getDB() == dbname; });
- _updateCacheGeneration();
}
void AuthorizationManagerImpl::invalidateUsersByTenant(OperationContext* opCtx,
const TenantId& tenant) {
LOGV2_DEBUG(6323600, 2, "Invalidating tenant users", "tenant"_attr = tenant);
+ _updateCacheGeneration();
_authSchemaVersionCache.invalidateAll();
_userCache.invalidateKeyIf(
[&](const UserRequest& userRequest) { return userRequest.name.getTenant() == tenant; });
- _updateCacheGeneration();
}
void AuthorizationManagerImpl::invalidateUserCache(OperationContext* opCtx) {
LOGV2_DEBUG(20237, 2, "Invalidating user cache");
+ _updateCacheGeneration();
_authSchemaVersionCache.invalidateAll();
_userCache.invalidateAll();
- _updateCacheGeneration();
}
Status AuthorizationManagerImpl::refreshExternalUsers(OperationContext* opCtx) {
diff --git a/src/mongo/db/auth/authorization_session_impl.cpp b/src/mongo/db/auth/authorization_session_impl.cpp
index a657784f660..8c2be85d37c 100644
--- a/src/mongo/db/auth/authorization_session_impl.cpp
+++ b/src/mongo/db/auth/authorization_session_impl.cpp
@@ -715,6 +715,20 @@ void AuthorizationSessionImpl::_refreshUserInfoAsNeeded(OperationContext* opCtx)
auto swUser = authMan.reacquireUser(opCtx, currentUser);
if (!swUser.isOK()) {
auto& status = swUser.getStatus();
+ // If an external user is no longer in the cache and cannot be acquired from the cache's
+ // backing external service, it should be removed from _authenticatedUsers. This
+ // guarantees that no operations can be performed until the external authorization
+ // provider comes back up.
+ if (name.getDB() == "$external"_sd) {
+ removeUser(it++);
+ LOGV2(5914804,
+ "Removed external user from session cache of user information because of "
+ "error status",
+ "user"_attr = name,
+ "status"_attr = status);
+ continue; // No need to advance "it" in this case.
+ }
+
switch (status.code()) {
case ErrorCodes::UserNotFound: {
// User does not exist anymore; remove it from _authenticatedUsers.
diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp
index 237997f232e..4ecb9cca692 100644
--- a/src/mongo/db/auth/authorization_session_test.cpp
+++ b/src/mongo/db/auth/authorization_session_test.cpp
@@ -33,21 +33,115 @@
#include "mongo/base/status.h"
#include "mongo/bson/bson_depth.h"
+#include "mongo/crypto/mechanism_scram.h"
+#include "mongo/crypto/sha1_block.h"
+#include "mongo/crypto/sha256_block.h"
+#include "mongo/db/auth/action_type.h"
#include "mongo/db/auth/authorization_checks.h"
-#include "mongo/db/auth/authorization_session_test_fixture.h"
+#include "mongo/db/auth/authorization_manager_impl.h"
+#include "mongo/db/auth/authorization_session_for_test.h"
+#include "mongo/db/auth/authz_manager_external_state_mock.h"
+#include "mongo/db/auth/authz_session_external_state_mock.h"
+#include "mongo/db/auth/restriction_environment.h"
+#include "mongo/db/auth/sasl_options.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
+#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/pipeline/aggregation_request_helper.h"
+#include "mongo/db/service_context_test_fixture.h"
#include "mongo/idl/server_parameter_test_util.h"
#include "mongo/transport/session.h"
#include "mongo/transport/transport_layer_mock.h"
#include "mongo/unittest/unittest.h"
namespace mongo {
-
namespace {
-using AuthorizationSessionTest = AuthorizationSessionTestFixture;
+
+class FailureCapableAuthzManagerExternalStateMock : public AuthzManagerExternalStateMock {
+public:
+ FailureCapableAuthzManagerExternalStateMock() = default;
+ ~FailureCapableAuthzManagerExternalStateMock() = default;
+
+ void setFindsShouldFail(bool enable) {
+ _findsShouldFail = enable;
+ }
+
+ Status findOne(OperationContext* opCtx,
+ const NamespaceString& collectionName,
+ const BSONObj& query,
+ BSONObj* result) override {
+ if (_findsShouldFail && collectionName == AuthorizationManager::usersCollectionNamespace) {
+ return Status(ErrorCodes::UnknownError,
+ "findOne on admin.system.users set to fail in mock.");
+ }
+ return AuthzManagerExternalStateMock::findOne(opCtx, collectionName, query, result);
+ }
+
+private:
+ bool _findsShouldFail{false};
+};
+
+class AuthorizationSessionTest : public ScopedGlobalServiceContextForTest, public unittest::Test {
+public:
+ void setUp() {
+ _session = transportLayer.createSession();
+ _client = getServiceContext()->makeClient("testClient", _session);
+ RestrictionEnvironment::set(
+ _session, std::make_unique<RestrictionEnvironment>(SockAddr(), SockAddr()));
+ _opCtx = _client->makeOperationContext();
+ auto localManagerState = std::make_unique<FailureCapableAuthzManagerExternalStateMock>();
+ managerState = localManagerState.get();
+ managerState->setAuthzVersion(AuthorizationManager::schemaVersion26Final);
+ auto uniqueAuthzManager = std::make_unique<AuthorizationManagerImpl>(
+ getServiceContext(), std::move(localManagerState));
+ authzManager = uniqueAuthzManager.get();
+ AuthorizationManager::set(getServiceContext(), std::move(uniqueAuthzManager));
+ auto localSessionState = std::make_unique<AuthzSessionExternalStateMock>(authzManager);
+ sessionState = localSessionState.get();
+ authzSession = std::make_unique<AuthorizationSessionForTest>(
+ std::move(localSessionState),
+ AuthorizationSessionImpl::InstallMockForTestingOrAuthImpl{});
+ authzManager->setAuthEnabled(true);
+
+ credentials =
+ BSON("SCRAM-SHA-1" << scram::Secrets<SHA1Block>::generateCredentials(
+ "a", saslGlobalParams.scramSHA1IterationCount.load())
+ << "SCRAM-SHA-256"
+ << scram::Secrets<SHA256Block>::generateCredentials(
+ "a", saslGlobalParams.scramSHA256IterationCount.load()));
+ }
+
+ void tearDown() override {
+ authzSession->logoutAllDatabases(_client.get(), "Ending AuthorizationSessionTest");
+ }
+
+ Status createUser(const UserName& username, const std::vector<RoleName>& roles) {
+ BSONObjBuilder userDoc;
+ userDoc.append("_id", username.getUnambiguousName());
+ username.appendToBSON(&userDoc);
+ userDoc.append("credentials", credentials);
+
+ BSONArrayBuilder rolesBSON(userDoc.subarrayStart("roles"));
+ for (const auto& role : roles) {
+ role.serializeToBSON(&rolesBSON);
+ }
+ rolesBSON.doneFast();
+
+ return managerState->insertPrivilegeDocument(_opCtx.get(), userDoc.obj(), {});
+ }
+
+protected:
+ FailureCapableAuthzManagerExternalStateMock* managerState;
+ transport::TransportLayerMock transportLayer;
+ transport::SessionHandle _session;
+ ServiceContext::UniqueClient _client;
+ ServiceContext::UniqueOperationContext _opCtx;
+ AuthzSessionExternalStateMock* sessionState;
+ AuthorizationManager* authzManager;
+ std::unique_ptr<AuthorizationSessionForTest> authzSession;
+ BSONObj credentials;
+};
const NamespaceString testFooNss("test.foo");
const NamespaceString testBarNss("test.bar");
@@ -1432,22 +1526,5 @@ TEST_F(AuthorizationSessionTest, MayBypassWriteBlockingModeIsSetCorrectly) {
ASSERT_FALSE(authzSession->mayBypassWriteBlockingMode());
}
-TEST_F(AuthorizationSessionTest, InternalSystemClientsBypassValidateRestrictions) {
- // set up a direct client without transport session
- auto client = getServiceContext()->makeClient("directClient");
- // set Client user to be the internal __system user.
- authzSession->grantInternalAuthorization(client.get());
- auto opCtx = client->makeOperationContext();
-
- // invalidate the __system user to force the next request to validate restrictions
- (*internalSecurity.getUser())->invalidate();
-
- // should not fail even though client does not have a transport session
- authzSession->startRequest(opCtx.get());
-
- User* currentUser = authzSession->getSingleUser();
- ASSERT_OK(currentUser->validateRestrictions(opCtx.get()));
-}
-
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/auth/authorization_session_test_fixture.cpp b/src/mongo/db/auth/authorization_session_test_fixture.cpp
deleted file mode 100644
index 330837ee719..00000000000
--- a/src/mongo/db/auth/authorization_session_test_fixture.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * Copyright (C) 2023-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-
-#include "mongo/db/auth/authorization_session_test_fixture.h"
-
-#include <vector>
-
-#include "mongo/bson/bsonmisc.h"
-#include "mongo/bson/bsonobj.h"
-#include "mongo/bson/bsonobjbuilder.h"
-#include "mongo/crypto/mechanism_scram.h"
-#include "mongo/crypto/sha1_block.h"
-#include "mongo/crypto/sha256_block.h"
-#include "mongo/db/auth/action_type.h"
-#include "mongo/db/auth/restriction_environment.h"
-#include "mongo/db/auth/sasl_options.h"
-#include "mongo/db/namespace_string.h"
-namespace mongo {
-
-void AuthorizationSessionTestFixture::setUp() {
- _session = transportLayer.createSession();
- _client = getServiceContext()->makeClient("testClient", _session);
- RestrictionEnvironment::set(_session,
- std::make_unique<RestrictionEnvironment>(SockAddr(), SockAddr()));
- _opCtx = _client->makeOperationContext();
- auto localManagerState = std::make_unique<FailureCapableAuthzManagerExternalStateMock>();
- managerState = localManagerState.get();
- managerState->setAuthzVersion(AuthorizationManager::schemaVersion26Final);
- auto uniqueAuthzManager = std::make_unique<AuthorizationManagerImpl>(
- getServiceContext(), std::move(localManagerState));
- authzManager = uniqueAuthzManager.get();
- AuthorizationManager::set(getServiceContext(), std::move(uniqueAuthzManager));
- auto localSessionState = std::make_unique<AuthzSessionExternalStateMock>(authzManager);
- sessionState = localSessionState.get();
- authzSession = std::make_unique<AuthorizationSessionForTest>(
- std::move(localSessionState), AuthorizationSessionImpl::InstallMockForTestingOrAuthImpl{});
- authzManager->setAuthEnabled(true);
-
- credentials =
- BSON("SCRAM-SHA-1" << scram::Secrets<SHA1Block>::generateCredentials(
- "a", saslGlobalParams.scramSHA1IterationCount.load())
- << "SCRAM-SHA-256"
- << scram::Secrets<SHA256Block>::generateCredentials(
- "a", saslGlobalParams.scramSHA256IterationCount.load()));
-}
-
-Status AuthorizationSessionTestFixture::createUser(const UserName& username,
- const std::vector<RoleName>& roles) {
- BSONObjBuilder userDoc;
- userDoc.append("_id", username.getUnambiguousName());
- username.appendToBSON(&userDoc);
- userDoc.append("credentials", credentials);
-
- BSONArrayBuilder rolesBSON(userDoc.subarrayStart("roles"));
- for (const auto& role : roles) {
- role.serializeToBSON(&rolesBSON);
- }
- rolesBSON.doneFast();
-
- return managerState->insertPrivilegeDocument(_opCtx.get(), userDoc.obj(), {});
-}
-} // namespace mongo
diff --git a/src/mongo/db/auth/authorization_session_test_fixture.h b/src/mongo/db/auth/authorization_session_test_fixture.h
deleted file mode 100644
index 7e80999ca5f..00000000000
--- a/src/mongo/db/auth/authorization_session_test_fixture.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Copyright (C) 2023-present MongoDB, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the Server Side Public License, version 1,
- * as published by MongoDB, Inc.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Server Side Public License for more details.
- *
- * You should have received a copy of the Server Side Public License
- * along with this program. If not, see
- * <http://www.mongodb.com/licensing/server-side-public-license>.
- *
- * As a special exception, the copyright holders give permission to link the
- * code of portions of this program with the OpenSSL library under certain
- * conditions as described in each individual source file and distribute
- * linked combinations including the program with the OpenSSL library. You
- * must comply with the Server Side Public License in all respects for
- * all of the code used other than as permitted herein. If you modify file(s)
- * with this exception, you may extend this exception to your version of the
- * file(s), but you are not obligated to do so. If you do not wish to do so,
- * delete this exception statement from your version. If you delete this
- * exception statement from all source files in the program, then also delete
- * it in the license file.
- */
-#pragma once
-
-#include <vector>
-
-#include "mongo/db/auth/authorization_manager_impl.h"
-#include "mongo/db/auth/authorization_session_for_test.h"
-#include "mongo/db/auth/authz_manager_external_state_mock.h"
-#include "mongo/db/auth/authz_session_external_state_mock.h"
-#include "mongo/db/service_context_d_test_fixture.h"
-#include "mongo/transport/transport_layer_mock.h"
-
-namespace mongo {
-
-class FailureCapableAuthzManagerExternalStateMock : public AuthzManagerExternalStateMock {
-public:
- FailureCapableAuthzManagerExternalStateMock() = default;
- ~FailureCapableAuthzManagerExternalStateMock() = default;
-
- void setFindsShouldFail(bool enable) {
- _findsShouldFail = enable;
- }
-
- Status findOne(OperationContext* opCtx,
- const NamespaceString& collectionName,
- const BSONObj& query,
- BSONObj* result) override {
- if (_findsShouldFail && collectionName == AuthorizationManager::usersCollectionNamespace) {
- return Status(ErrorCodes::UnknownError,
- "findOne on admin.system.users set to fail in mock.");
- }
- return AuthzManagerExternalStateMock::findOne(opCtx, collectionName, query, result);
- }
-
-private:
- bool _findsShouldFail{false};
-};
-
-class AuthorizationSessionTestFixture : public ServiceContextMongoDTest {
-public:
- void setUp();
-
- void tearDown() override {
- authzSession->logoutAllDatabases(_client.get(), "Ending AuthorizationSessionTest");
- }
-
- Status createUser(const UserName& username, const std::vector<RoleName>& roles);
-
-protected:
- FailureCapableAuthzManagerExternalStateMock* managerState;
- transport::TransportLayerMock transportLayer;
- transport::SessionHandle _session;
- ServiceContext::UniqueClient _client;
- ServiceContext::UniqueOperationContext _opCtx;
- AuthzSessionExternalStateMock* sessionState;
- AuthorizationManager* authzManager;
- std::unique_ptr<AuthorizationSessionForTest> authzSession;
- BSONObj credentials;
-};
-} // namespace mongo
diff --git a/src/mongo/db/auth/builtin_roles.cpp b/src/mongo/db/auth/builtin_roles.cpp
index 9eddd117f80..2b0c63cb798 100644
--- a/src/mongo/db/auth/builtin_roles.cpp
+++ b/src/mongo/db/auth/builtin_roles.cpp
@@ -119,7 +119,6 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) {
<< ActionType::killCursors
<< ActionType::listCollections
<< ActionType::listIndexes
- << ActionType::listSearchIndexes
<< ActionType::planCacheRead;
// Read-write role
@@ -129,15 +128,12 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) {
<< ActionType::convertToCapped // db admin gets this also
<< ActionType::createCollection // db admin gets this also
<< ActionType::createIndex
- << ActionType::createSearchIndexes
<< ActionType::dropCollection
<< ActionType::dropIndex
- << ActionType::dropSearchIndex
<< ActionType::insert
<< ActionType::remove
<< ActionType::renameCollectionSameDB // db admin gets this also
- << ActionType::update
- << ActionType::updateSearchIndex;
+ << ActionType::update;
// User admin role
userAdminRoleActions
@@ -167,24 +163,21 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) {
<< ActionType::dropDatabase // clusterAdmin gets this also TODO(spencer): should
// readWriteAnyDatabase?
<< ActionType::dropIndex
- << ActionType::dropSearchIndex
<< ActionType::createIndex
- << ActionType::createSearchIndexes
<< ActionType::enableProfiler
<< ActionType::listCollections
<< ActionType::listIndexes
- << ActionType::listSearchIndexes
<< ActionType::planCacheIndexFilter
<< ActionType::planCacheRead
<< ActionType::planCacheWrite
<< ActionType::reIndex
<< ActionType::renameCollectionSameDB // read_write gets this also
<< ActionType::storageDetails
- << ActionType::updateSearchIndex
<< ActionType::validate;
// clusterMonitor role actions that target the cluster resource
clusterMonitorRoleClusterActions
+ << ActionType::checkFreeMonitoringStatus
<< ActionType::connPoolStats
<< ActionType::getCmdLineOpts
<< ActionType::getDefaultRWConcern // clusterManager gets this also
@@ -203,11 +196,7 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) {
<< ActionType::top
<< ActionType::useUUID
<< ActionType::inprog
- << ActionType::shardingState
- << ActionType::allCollectionStats
- << ActionType::shardedDataDistribution
- << ActionType::queryStatsRead
- << ActionType::queryStatsReadTransformed;
+ << ActionType::shardingState;
// clusterMonitor role actions that target a database (or collection) resource
clusterMonitorRoleDatabaseActions
@@ -264,6 +253,7 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) {
<< ActionType::runTenantMigration
<< ActionType::setDefaultRWConcern
<< ActionType::setFeatureCompatibilityVersion
+ << ActionType::setFreeMonitoring
<< ActionType::setClusterParameter
<< ActionType::getClusterParameter;
@@ -376,8 +366,7 @@ void addUserAdminAnyDbPrivileges(PrivilegeVector* privileges) {
ActionSet readRoleAndIndexActions;
readRoleAndIndexActions += readRoleActions;
- readRoleAndIndexActions << ActionType::createIndex << ActionType::dropIndex
- << ActionType::createSearchIndexes << ActionType::dropSearchIndex;
+ readRoleAndIndexActions << ActionType::createIndex << ActionType::dropIndex;
Privilege::addPrivilegeToPrivilegeVector(
privileges, Privilege(ResourcePattern::forCollectionName("system.users"), readRoleActions));
@@ -433,11 +422,6 @@ void addClusterMonitorPrivileges(PrivilegeVector* privileges) {
Privilege(ResourcePattern::forDatabaseName("config"), clusterMonitorRoleDatabaseActions));
Privilege::addPrivilegeToPrivilegeVector(
privileges,
- Privilege(ResourcePattern::forExactNamespace(NamespaceString("config", "system.sessions")),
- clusterMonitorRoleDatabaseActions));
-
- Privilege::addPrivilegeToPrivilegeVector(
- privileges,
Privilege(ResourcePattern::forDatabaseName("local"), clusterMonitorRoleDatabaseActions));
addReadOnlyDbPrivileges(privileges, "config");
addReadOnlyDbPrivileges(privileges, "local");
@@ -535,8 +519,6 @@ void addQueryableBackupPrivileges(PrivilegeVector* privileges) {
Privilege::addPrivilegeToPrivilegeVector(
privileges, Privilege(ResourcePattern::forAnyResource(), ActionType::listIndexes));
Privilege::addPrivilegeToPrivilegeVector(
- privileges, Privilege(ResourcePattern::forAnyResource(), ActionType::listSearchIndexes));
- Privilege::addPrivilegeToPrivilegeVector(
privileges, Privilege(ResourcePattern::forAnySystemBuckets(), ActionType::find));
ActionSet clusterActions;
@@ -617,9 +599,7 @@ void addRestorePrivileges(PrivilegeVector* privileges) {
ActionSet actions;
actions << ActionType::bypassDocumentValidation << ActionType::collMod
<< ActionType::convertToCapped << ActionType::createCollection
- << ActionType::createIndex << ActionType::dropCollection
- << ActionType::createSearchIndexes << ActionType::updateSearchIndex
- << ActionType::insert;
+ << ActionType::createIndex << ActionType::dropCollection << ActionType::insert;
Privilege::addPrivilegeToPrivilegeVector(
privileges, Privilege(ResourcePattern::forAnyNormalResource(), actions));
@@ -696,11 +676,6 @@ void addRestorePrivileges(PrivilegeVector* privileges) {
Privilege(
ResourcePattern::forExactNamespace(AuthorizationManager::rolesCollectionNamespace),
ActionType::createIndex));
- Privilege::addPrivilegeToPrivilegeVector(
- privileges,
- Privilege(
- ResourcePattern::forExactNamespace(AuthorizationManager::rolesCollectionNamespace),
- ActionType::createSearchIndexes));
Privilege::addPrivilegeToPrivilegeVector(
privileges,
@@ -712,12 +687,7 @@ void addRestorePrivileges(PrivilegeVector* privileges) {
// Need to be able to set and bypass write blocking mode for C2C replication
ActionType::bypassWriteBlockingMode,
ActionType::setUserWriteBlockMode,
- // Needed for `mongorestore --preserveUUID`
- ActionType::applyOps,
}));
- Privilege::addPrivilegeToPrivilegeVector(
- privileges,
- Privilege(ResourcePattern::forCollectionName("system.views"), ActionType::dropCollection));
}
void addRootRolePrivileges(PrivilegeVector* privileges) {
diff --git a/src/mongo/db/auth/builtin_roles_test.cpp b/src/mongo/db/auth/builtin_roles_test.cpp
index ebf87660db7..15b5aa932fd 100644
--- a/src/mongo/db/auth/builtin_roles_test.cpp
+++ b/src/mongo/db/auth/builtin_roles_test.cpp
@@ -108,7 +108,6 @@ TEST(BuiltinRoles, addPrivilegesForBuiltinRole) {
ActionType::killCursors,
ActionType::listCollections,
ActionType::listIndexes,
- ActionType::listSearchIndexes,
ActionType::planCacheRead,
});
const auto adminDB = ResourcePattern::forDatabaseName("admin");
diff --git a/src/mongo/db/auth/resource_pattern.h b/src/mongo/db/auth/resource_pattern.h
index 67c00c9878b..5b4a952b886 100644
--- a/src/mongo/db/auth/resource_pattern.h
+++ b/src/mongo/db/auth/resource_pattern.h
@@ -130,9 +130,7 @@ public:
*/
static ResourcePattern forExactSystemBucketsCollection(StringData dbName,
StringData collectionName) {
- uassert(ErrorCodes::InvalidNamespace,
- "Invalid namespace '{}.system.buckets.{}'"_format(dbName, collectionName),
- !collectionName.startsWith("system.buckets."));
+ invariant(!collectionName.startsWith("system.buckets."));
return ResourcePattern(MatchTypeEnum::kMatchExactSystemBucketResource,
NamespaceString(dbName, collectionName));
}
diff --git a/src/mongo/db/auth/sasl_commands.h b/src/mongo/db/auth/sasl_commands.h
index 57dcb585794..054756745e6 100644
--- a/src/mongo/db/auth/sasl_commands.h
+++ b/src/mongo/db/auth/sasl_commands.h
@@ -36,7 +36,7 @@ namespace mongo {
class OperationContext;
/**
- * Handle hello: { speculativeAuthenticate: {...} }
+ * Handle isMaster: { speculativeAuthenticate: {...} }
*/
void doSpeculativeSaslStart(OperationContext* opCtx,
const BSONObj& sourceObj,
diff --git a/src/mongo/db/auth/sasl_mechanism_registry.h b/src/mongo/db/auth/sasl_mechanism_registry.h
index 921ae18ce3a..06b0850125b 100644
--- a/src/mongo/db/auth/sasl_mechanism_registry.h
+++ b/src/mongo/db/auth/sasl_mechanism_registry.h
@@ -104,12 +104,12 @@ public:
virtual SecurityPropertySet properties() const = 0;
/**
- * This returns a number that represents the "amount" of security provided by this mechanism to
- * determine the order in which it is offered to clients in the "hello" saslSupportedMechs
- * response.
+ * This returns a number that represents the "amount" of security provided by this mechanism
+ * to determine the order in which it is offered to clients in the isMaster
+ * saslSupportedMechs response.
*
- * The value of securityLevel is arbitrary so long as the more secure mechanisms return a higher
- * value than the less secure mechanisms.
+ * The value of securityLevel is arbitrary so long as the more secure mechanisms return a
+ * higher value than the less secure mechanisms.
*
* For example, SCRAM-SHA-256 > SCRAM-SHA-1 > PLAIN
*/
diff --git a/src/mongo/db/auth/user.cpp b/src/mongo/db/auth/user.cpp
index dba96b1f474..a418cfb8eb2 100644
--- a/src/mongo/db/auth/user.cpp
+++ b/src/mongo/db/auth/user.cpp
@@ -179,12 +179,6 @@ void User::setIndirectRestrictions(RestrictionDocuments restrictions) & {
}
Status User::validateRestrictions(OperationContext* opCtx) const {
- if (!opCtx->getClient()->session()) {
- // If Client has no transport session, it must be internal system connection
- invariant(opCtx->getClient()->isFromSystemConnection());
- return Status::OK();
- }
-
const auto& env = RestrictionEnvironment::get(*(opCtx->getClient()));
auto status = _restrictions.validate(env);
if (!status.isOK()) {