mongo/jstests/auth/init_replicated_fast_count.js
Parker Felix 27c039d8a9 SERVER-123367 Handle auth for new fastcount oplog entries (#52165)
GitOrigin-RevId: 34e5de0398f32b7597239bddd98f8cedb652c93e
2026-04-20 20:55:32 +00:00

114 lines
4.0 KiB
JavaScript

/*
* Auth test for the initReplicatedFastcount command wrapped in an applyOps command, running against
* a standalone mongod and a replica set.
* @tags: [
* featureFlagReplicatedFastCount,
* requires_replication,
* requires_fcv_90
* ]
*/
import {ReplSetTest} from "jstests/libs/replsettest.js";
// Auth-test the initReplicatedFastCount oplog command, when executed inside an applyOps command.
export function runTest(mongod) {
const admin = mongod.getDB("admin");
admin.createUser({user: "admin", pwd: "pass", roles: jsTest.adminUserRoles});
assert(admin.auth("admin", "pass"));
// Create roles with database-level permissions for test1 and test2.
["test1", "test2"].forEach((dbName) => {
admin.createRole({
role: `${dbName}_insert`,
privileges: [
// applyOps privilege is needed to send a initReplicatedFastCount command.
{resource: {cluster: true}, actions: ["applyOps"]},
{resource: {db: dbName, collection: ""}, actions: ["insert"]},
],
roles: [],
});
});
// user1 has privileges on test1.
admin.createUser({
user: "user1",
pwd: "pass",
roles: ["test1_insert"],
});
// user2 has privileges on test2.
admin.createUser({
user: "user2",
pwd: "pass",
roles: ["test2_insert"],
});
// user3 has no privileges.
admin.createUser({
user: "user3",
pwd: "pass",
roles: [],
});
// user4 is a __system user with privileges on the admin database.
admin.createUser({
user: "user4",
pwd: "pass",
roles: ["__system"],
});
admin.logout();
const runAuthTest = function ({user, dbName, expectedError}) {
admin.auth(user, "pass");
const db = admin.getSiblingDB(dbName);
// Run initReplicatedFastCount command as part of an applyOps command. This is necessary
// because there is no user-facing initReplicatedFastCount command in the server.
const applyOpsCmd = {
applyOps: [
{
op: "c",
ns: `${dbName}.$cmd`,
o: {
"initReplicatedFastCount": 1,
},
// Don't need an o2 since the op will be rejected.
},
],
};
if (expectedError) {
assert.commandFailedWithCode(db.runCommand(applyOpsCmd), [expectedError]);
} else {
assert.commandWorked(db.runCommand(applyOpsCmd));
}
admin.logout();
};
// user1 and user2 have applyOps privilege (from their roles), so the applyOps auth check
// passes. The initReplicatedFastCount command is not a registered command, so
// CommandHelpers::findCommand returns null and we get FailedToParse regardless of which
// database the op targets.
runAuthTest({user: "user1", dbName: "test1", expectedError: ErrorCodes.FailedToParse});
runAuthTest({user: "user1", dbName: "test2", expectedError: ErrorCodes.FailedToParse});
runAuthTest({user: "user2", dbName: "test1", expectedError: ErrorCodes.FailedToParse});
runAuthTest({user: "user2", dbName: "test2", expectedError: ErrorCodes.FailedToParse});
// user3 has no privileges -> Unauthorized (fails the applyOps cluster-level check).
runAuthTest({user: "user3", dbName: "test1", expectedError: ErrorCodes.Unauthorized});
runAuthTest({user: "user3", dbName: "test2", expectedError: ErrorCodes.Unauthorized});
// user4 (__system) has all privileges -> FailedToParse on admin.
runAuthTest({user: "user4", dbName: "admin", expectedError: ErrorCodes.FailedToParse});
}
const mongod = MongoRunner.runMongod({auth: ""});
runTest(mongod);
MongoRunner.stopMongod(mongod);
const replTest = new ReplSetTest({name: jsTestName(), nodes: 2, keyFile: "jstests/libs/key1"});
replTest.startSet();
replTest.initiate();
runTest(replTest.getPrimary());
replTest.stopSet();