mirror of https://github.com/mongodb/mongo
SERVER-78466: check whether the user has been already authenticated. (#37733)
Co-authored-by: Brad Cater <brad.cater@mongodb.com> GitOrigin-RevId: 9bf493d889221cecb88b65dbaef9530df8c6c5b7
This commit is contained in:
parent
b31ac5e6d1
commit
f44be441d4
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
* This test checks that consecutive authentication attempt on the same
|
||||
* ScopedDbCollection instance does not result in reauthentication warning on primary
|
||||
*
|
||||
* Previously we had a warning so this test will fail with any earlier version of the code
|
||||
*
|
||||
* @tags: [
|
||||
* requires_fcv_83
|
||||
* ]
|
||||
*/
|
||||
|
||||
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
||||
import {validateSessionsCollection} from "jstests/libs/sessions_collection.js";
|
||||
|
||||
// This test makes assertions about the number of sessions, which are not compatible with
|
||||
// implicit sessions.
|
||||
TestData.disableImplicitSessions = true;
|
||||
|
||||
const replTest = new ReplSetTest({
|
||||
name: "refresh",
|
||||
nodes: [
|
||||
{
|
||||
/* primary */
|
||||
},
|
||||
{/* secondary */ rsConfig: {priority: 0}},
|
||||
],
|
||||
keyFile: "jstests/libs/key1",
|
||||
nodeOptions: {
|
||||
setParameter: "connPoolMaxConnsPerHost=1",
|
||||
}, // global connection pool will contain only one connection
|
||||
});
|
||||
const nodes = replTest.startSet();
|
||||
|
||||
replTest.initiate();
|
||||
const kAdminUser = {
|
||||
name: "admin",
|
||||
pwd: "admin",
|
||||
};
|
||||
|
||||
const primary = replTest.getPrimary();
|
||||
// Create the admin user
|
||||
const adminDB = primary.getDB("admin");
|
||||
assert.commandWorked(adminDB.runCommand({createUser: kAdminUser.name, pwd: kAdminUser.pwd, roles: ["root"]}));
|
||||
assert.eq(1, adminDB.auth(kAdminUser.name, kAdminUser.pwd));
|
||||
|
||||
const primaryAdmin = primary.getDB("admin");
|
||||
|
||||
replTest.awaitReplication();
|
||||
const secondary = replTest.getSecondary();
|
||||
const secondaryAdmin = secondary.getDB("admin");
|
||||
assert.eq(1, secondaryAdmin.auth(kAdminUser.name, kAdminUser.pwd));
|
||||
|
||||
// Get the current value of the TTL index so that we can verify it's being properly applied.
|
||||
let res = assert.commandWorked(primary.adminCommand({getParameter: 1, localLogicalSessionTimeoutMinutes: 1}));
|
||||
|
||||
let timeoutMinutes = res.localLogicalSessionTimeoutMinutes;
|
||||
|
||||
{
|
||||
// Sessions collection doesn't yet exist on primary
|
||||
validateSessionsCollection(primary, false, false, timeoutMinutes);
|
||||
|
||||
replTest.awaitReplication();
|
||||
// Sessions collection doesn't yet exist on secondary
|
||||
validateSessionsCollection(secondary, false, false, timeoutMinutes);
|
||||
|
||||
assert.commandWorked(primaryAdmin.runCommand({refreshLogicalSessionCacheNow: 1}));
|
||||
// Created sessions collection
|
||||
validateSessionsCollection(primary, true, true, timeoutMinutes);
|
||||
}
|
||||
|
||||
{
|
||||
replTest.awaitReplication();
|
||||
// Refresh cache on secondary will authenticate a user with new ScopedDbCollection instance
|
||||
assert.commandWorked(secondaryAdmin.runCommand({refreshLogicalSessionCacheNow: 1}));
|
||||
// Another refresh on secondary will authenticate again on the same instance because we limited
|
||||
// connection pool to be of size 1
|
||||
assert.commandWorked(secondaryAdmin.runCommand({refreshLogicalSessionCacheNow: 1}));
|
||||
replTest.awaitReplication();
|
||||
}
|
||||
// Make sure that the fix worked and no warning logged on primary and secondary
|
||||
assert(
|
||||
checkLog.checkContainsWithCountJson(primary, 5626700, {}, 0, null, true),
|
||||
"Expecting not to find reauthentication warning in primary logs",
|
||||
);
|
||||
assert(
|
||||
checkLog.checkContainsWithCountJson(secondary, 5626700, {}, 0, null, true),
|
||||
"Expecting not to find reauthentication warning in primary logs",
|
||||
);
|
||||
|
||||
replTest.stopSet();
|
||||
|
|
@ -409,6 +409,7 @@ void DBClientBase::_auth(const BSONObj& params) {
|
|||
|
||||
HostAndPort remote(getServerAddress());
|
||||
auth::authenticateClient(params, remote, clientName, _makeAuthRunCommandHook()).get();
|
||||
_isClientAuthenticated.store(true);
|
||||
}
|
||||
|
||||
void DBClientBase::authenticateInternalUser(auth::StepDownBehavior stepDownBehavior) {
|
||||
|
|
@ -439,6 +440,7 @@ void DBClientBase::authenticateInternalUser(auth::StepDownBehavior stepDownBehav
|
|||
_makeAuthRunCommandHook(),
|
||||
authProvider)
|
||||
.get();
|
||||
_isClientAuthenticated.store(true);
|
||||
} catch (const DBException& e) {
|
||||
if (!serverGlobalParams.quiet.load()) {
|
||||
LOGV2(20117,
|
||||
|
|
@ -474,6 +476,7 @@ void DBClientBase::auth(const DatabaseName& dbname, StringData username, StringD
|
|||
|
||||
void DBClientBase::logout(const DatabaseName& dbName, BSONObj& info) {
|
||||
runCommand(dbName, BSON("logout" << 1), info);
|
||||
_isClientAuthenticated.store(false);
|
||||
}
|
||||
|
||||
bool DBClientBase::isPrimary(bool& isPrimary, BSONObj* info) {
|
||||
|
|
|
|||
|
|
@ -540,6 +540,9 @@ public:
|
|||
return find(std::move(findRequest), readPref, ExhaustMode::kOff);
|
||||
}
|
||||
|
||||
bool isAuthenticated() const {
|
||||
return _isClientAuthenticated.load();
|
||||
}
|
||||
/**
|
||||
* Issues a find command described by 'findRequest' and the given read preference. Rather than
|
||||
* returning a cursor to the caller, iterates the cursor under the hood and calls the provided
|
||||
|
|
@ -757,6 +760,8 @@ private:
|
|||
Timestamp _lastOperationTime;
|
||||
|
||||
ClientAPIVersionParameters _apiParameters;
|
||||
|
||||
AtomicWord<bool> _isClientAuthenticated = {false};
|
||||
}; // DBClientBase
|
||||
|
||||
BSONElement getErrField(const BSONObj& result);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "mongo/client/internal_auth.h"
|
||||
#include "mongo/client/read_preference.h"
|
||||
#include "mongo/client/remote_command_targeter_factory_impl.h"
|
||||
#include "mongo/db/auth/authorization_session.h"
|
||||
#include "mongo/db/dbdirectclient.h"
|
||||
#include "mongo/db/local_catalog/lock_manager/d_concurrency.h"
|
||||
#include "mongo/db/local_catalog/lock_manager/lock_manager_defs.h"
|
||||
|
|
@ -82,7 +83,7 @@ auto SessionsCollectionRS::_makePrimaryConnection(OperationContext* opCtx) {
|
|||
auto conn = std::make_unique<ScopedDbConnection>(res.toString());
|
||||
|
||||
// Make a connection to the primary, auth, then send
|
||||
if (auth::isInternalAuthSet()) {
|
||||
if (auth::isInternalAuthSet() && !conn->get()->isAuthenticated()) {
|
||||
conn->get()->authenticateInternalUser();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue