SERVER-116025 Track egress in authCounter

Co-authored-by: Jenny Guo <jenny.guo@mongodb.com>
GitOrigin-RevId: 182579220566d8228563ebcc8a22575e7a0f53c9
This commit is contained in:
Gabriel Marks 2026-02-26 15:29:33 -05:00 committed by MongoDB Bot
parent a5917eb29c
commit 464a87d5b5
19 changed files with 508 additions and 253 deletions

View File

@ -27,16 +27,24 @@ admin.logout();
function assertStats() {
// Need to be authenticated to run serverStatus.
assert(admin.auth("admin", "pwd"));
++expected["SCRAM-SHA-256"].authenticate.successful;
++expected["SCRAM-SHA-256"].authenticate.received;
++expected["SCRAM-SHA-256"].ingress.authenticate.successful;
++expected["SCRAM-SHA-256"].ingress.authenticate.total;
const mechStats = assert.commandWorked(admin.runCommand({serverStatus: 1})).security.authentication.mechanisms;
Object.keys(expected).forEach(function (mech) {
try {
assert.eq(mechStats[mech].authenticate.received, expected[mech].authenticate.received);
assert.eq(mechStats[mech].authenticate.successful, expected[mech].authenticate.successful);
assert.eq(mechStats[mech].clusterAuthenticate.received, expected[mech].clusterAuthenticate.received);
assert.eq(mechStats[mech].clusterAuthenticate.successful, expected[mech].clusterAuthenticate.successful);
assert.eq(mechStats[mech].ingress.authenticate.total, expected[mech].ingress.authenticate.total);
assert.eq(mechStats[mech].ingress.authenticate.successful, expected[mech].ingress.authenticate.successful);
assert.eq(
mechStats[mech].ingress.clusterAuthenticate.total,
expected[mech].ingress.clusterAuthenticate.total,
);
assert.eq(
mechStats[mech].ingress.clusterAuthenticate.successful,
expected[mech].ingress.clusterAuthenticate.successful,
);
assert.eq(mechStats[mech].egress.authenticate.total, expected[mech].egress.authenticate.total);
assert.eq(mechStats[mech].egress.authenticate.successful, expected[mech].egress.authenticate.successful);
} catch (e) {
print("Mechanism: " + mech);
print("mechStats: " + tojson(mechStats));
@ -51,14 +59,14 @@ function assertStats() {
function assertSuccess(creds, mech, db = test) {
assert.eq(db.auth(creds), true);
db.logout();
++expected[mech].authenticate.received;
++expected[mech].authenticate.successful;
++expected[mech].ingress.authenticate.total;
++expected[mech].ingress.authenticate.successful;
assertStats();
}
function assertFailure(creds, mech, db = test) {
assert.eq(db.auth(creds), false);
++expected[mech].authenticate.received;
++expected[mech].ingress.authenticate.total;
assertStats();
}
@ -69,10 +77,10 @@ function assertSuccessInternal() {
authutil.asCluster(replTest.nodes, keyfile, () => true),
true,
);
++expected[mech].authenticate.received;
++expected[mech].authenticate.successful;
++expected[mech].clusterAuthenticate.received;
++expected[mech].clusterAuthenticate.successful;
++expected[mech].ingress.authenticate.total;
++expected[mech].ingress.authenticate.successful;
++expected[mech].ingress.clusterAuthenticate.total;
++expected[mech].ingress.clusterAuthenticate.successful;
// we have to re-auth as admin to get stats, which are validated at the end of assertSuccess
assertSuccess({user: "admin", pwd: "pwd"}, "SCRAM-SHA-256", admin);
}
@ -84,8 +92,8 @@ function assertFailureInternal() {
const mech = "SCRAM-SHA-256";
// If asCluster fails, it explodes.
assert.throws(authutil.asCluster, [replTest.nodes, badKeyfile, () => true]);
++expected[mech].authenticate.received;
++expected[mech].clusterAuthenticate.received;
++expected[mech].ingress.authenticate.total;
++expected[mech].ingress.clusterAuthenticate.total;
// we have to re-auth as admin to get stats, which are validated at the end of assertSuccess
assertSuccess({user: "admin", pwd: "pwd"}, "SCRAM-SHA-256", admin);
assertStats();

View File

@ -12,7 +12,7 @@ function authnSuccessIncrementsServerStatusTotalAuthTime(mongodRunner) {
admin.auth("admin", "pwd");
const expected = assert.commandWorked(admin.runCommand({serverStatus: 1})).security.authentication
.totalAuthenticationTimeMicros;
.totalIngressAuthenticationTimeMicros;
assert.gte(expected, 0);
@ -21,7 +21,7 @@ function authnSuccessIncrementsServerStatusTotalAuthTime(mongodRunner) {
admin.auth("admin", "pwd");
const nextExpected = assert.commandWorked(admin.runCommand({serverStatus: 1})).security.authentication
.totalAuthenticationTimeMicros;
.totalIngressAuthenticationTimeMicros;
assert.gt(nextExpected, expected);
@ -38,14 +38,14 @@ function authnFailureIncrementsServerStatusTotalAuthTime(mongodRunner) {
// Count the number of authentications performed during setup
const expected = assert.commandWorked(admin.runCommand({serverStatus: 1})).security.authentication
.totalAuthenticationTimeMicros;
.totalIngressAuthenticationTimeMicros;
assert.gte(expected, 0);
admin.auth("admin", "wrong");
const nextExpected = assert.commandWorked(admin.runCommand({serverStatus: 1})).security.authentication
.totalAuthenticationTimeMicros;
.totalIngressAuthenticationTimeMicros;
assert.gt(nextExpected, expected);

View File

@ -1,6 +1,6 @@
/**
* Tests that client-side SASL authentication using SCRAM-SHA-256 produces the expected connection
* health log lines.
* health log lines and increments the auth counter as expected.
*/
import {ShardingTest} from "jstests/libs/shardingtest.js";
@ -19,69 +19,153 @@ const st = new ShardingTest({
},
});
// Make admin user so we can fetch server status
const admin = st.s.getDB("admin");
admin.createUser({
user: "root",
pwd: "pass",
roles: ["root"],
});
assert.eq(1, admin.auth("root", "pass"), "Authentication for root user failed");
jsTest.log.info("Check secondary config servers for authentication logs");
st.configRS.getSecondaries().forEach((conn) => {
// Get per-mech auth counter stats from serverStatus
const admin = conn.getDB("admin");
assert.soon(() => admin.auth("root", "pass"), "Authentication for root user failed on " + conn.host);
const stats = assert.commandWorked(admin.runCommand({serverStatus: 1})).security.authentication;
jsTest.log.info("Authn stats: " + tojson(stats));
assert.gt(stats.totalEgressAuthenticationTimeMicros, 0);
const mechStats = stats.mechanisms;
let egressAuthSuccesses, egressSpecAuthSuccesses;
// We should see egress SCRAM-SHA-256 auths and speculative auths, and no other egress auths
for (const [mech, stats] of Object.entries(mechStats)) {
if (mech === "SCRAM-SHA-256") {
egressAuthSuccesses = stats.egress.authenticate.successful;
egressSpecAuthSuccesses = stats.egress.speculativeAuthenticate.successful;
assert.gte(
egressAuthSuccesses,
1,
"Expected at least one egress SCRAM-SHA-256 authenticate success on " + conn.host,
);
assert.gte(
egressSpecAuthSuccesses,
1,
"Expected at least one egress SCRAM-SHA-256 speculativeAuthenticate success on " + conn.host,
);
assert.eq(
egressAuthSuccesses,
stats.egress.authenticate.total,
"SCRAM-SHA-256 egress authenticate successful count should equal total on " + conn.host,
);
assert.eq(
egressSpecAuthSuccesses,
stats.egress.speculativeAuthenticate.total,
"SCRAM-SHA-256 egress speculativeAuthenticate successful count should equal total on " + conn.host,
);
} else {
assert.eq(
stats.egress.authenticate.total,
0,
"Mechanism " + mech + " should have no egress authenticate attempts on " + conn.host,
);
assert.eq(
stats.egress.speculativeAuthenticate.total,
0,
"Mechanism " + mech + " should have no egress speculativeAuthenticate attempts on " + conn.host,
);
assert.eq(
stats.ingress.authenticate.total,
0,
"Mechanism " + mech + " should have no ingress authenticate attempts on " + conn.host,
);
assert.eq(
stats.ingress.speculativeAuthenticate.total,
0,
"Mechanism " + mech + " should have no ingress speculativeAuthenticate attempts on " + conn.host,
);
assert.eq(
stats.ingress.clusterAuthenticate.total,
0,
"Mechanism " + mech + " should have no ingress clusterAuthenticate attempts on " + conn.host,
);
}
}
// Check that egress speculative/normal auths are all logged, and that the counts match those
// returned by serverStatus.
// getLog pulls a maximum of 1024 entries, which is sometimes not enough to find intra-cluster
// auth logs because startup is noisy. Instead, we search the log file directly.
assert.soon(
() =>
checkLog.checkContainsWithAtLeastCountJson(
conn.fullOptions.logFile,
kClientSaslSpeculativeSuccessLogId,
{
"username": "__system",
"targetDatabase": "local",
"mechanism": "SCRAM-SHA-256",
"result": 0,
"metrics": {
"conversation_duration": {
// Speculative auth doesn't record steps
"summary": {},
},
},
const specSuccessMessages = checkLog.getFilteredLogMessages(
conn.fullOptions.logFile,
kClientSaslSpeculativeSuccessLogId,
{
"username": "__system",
"targetDatabase": "local",
"mechanism": "SCRAM-SHA-256",
"result": 0,
"metrics": {
"conversation_duration": {
// Speculative auth doesn't record steps
"summary": {},
},
1 /* expectedCount */,
null /* severity */,
true /* isRelaxed */,
),
},
},
null /* severity */,
true /* isRelaxed */,
);
assert.gte(
specSuccessMessages.length,
1,
`Did not find SASL speculative success log for __system@local on secondary config server ${conn.host}`,
);
assert.soon(
() =>
checkLog.checkContainsWithAtLeastCountJson(
conn.fullOptions.logFile,
kClientSaslSuccessLogId,
{
"username": "__system",
"targetDatabase": "local",
"mechanism": "SCRAM-SHA-256",
"result": 0,
"metrics": {
"conversation_duration": {
"summary": {
// Validate that SCRAM-SHA-256 has 3 steps
"0": {
"step": 1,
"step_total": 3,
},
"1": {
"step": 2,
"step_total": 3,
},
"2": {
"step": 3,
"step_total": 3,
},
},
const successMessages = checkLog.getFilteredLogMessages(
conn.fullOptions.logFile,
kClientSaslSuccessLogId,
{
"username": "__system",
"targetDatabase": "local",
"mechanism": "SCRAM-SHA-256",
"result": 0,
"metrics": {
"conversation_duration": {
"summary": {
// Validate that SCRAM-SHA-256 has 3 steps
"0": {
"step": 1,
"step_total": 3,
},
"1": {
"step": 2,
"step_total": 3,
},
"2": {
"step": 3,
"step_total": 3,
},
},
},
1 /* expectedCount */,
null /* severity */,
true /* isRelaxed */,
),
},
},
null /* severity */,
true /* isRelaxed */,
);
assert.gte(
successMessages.length,
1,
`Did not find SASL success log for __system@local on secondary config server ${conn.host}`,
);
assert.lte(
Math.abs(egressAuthSuccesses - (specSuccessMessages.length + successMessages.length)),
2,
"Egress auth success count should be roughly sum of speculative and normal auth log messages on " + conn.host,
);
assert.lte(
Math.abs(egressSpecAuthSuccesses - specSuccessMessages.length),
2,
"Egress speculative auth success count should be roughly speculative success log message count on " + conn.host,
);
});
st.stop();

View File

@ -4,10 +4,11 @@
import {ReplSetTest} from "jstests/libs/replsettest.js";
const kAuthenticationSuccessfulLogId = 5286306;
const kAuthenticationFailedLogId = 5286307;
const kIngressAuthenticationSuccessfulLogId = 5286306;
const kIngressAuthenticationFailedLogId = 5286307;
const kEgressSpeculativeAuthenticationSuccessfulLogId = 10748710;
function countAuthInLog(conn) {
function countIngressAuthInLog(conn) {
let logCounts = {speculative: 0, cluster: 0, speculativeCluster: 0};
cat(conn.fullOptions.logFile)
@ -16,7 +17,7 @@ function countAuthInLog(conn) {
.forEach((line) => {
// Iterate through the log and verify our auth.
const entry = JSON.parse(line);
if (entry.id === kAuthenticationSuccessfulLogId) {
if (entry.id === kIngressAuthenticationSuccessfulLogId) {
// Successful auth.
if (entry.attr.isSpeculative) {
logCounts.speculative += 1;
@ -27,7 +28,7 @@ function countAuthInLog(conn) {
if (entry.attr.isSpeculative && entry.attr.isClusterMember) {
logCounts.speculativeCluster += 1;
}
} else if (entry.id === kAuthenticationFailedLogId) {
} else if (entry.id === kIngressAuthenticationFailedLogId) {
// Authentication can fail legitimately because the secondary abandons the connection
// during shutdown - if we do encounter an authentication failure in the log, make sure
// that it is only of this type, fail anything else
@ -42,6 +43,24 @@ function countAuthInLog(conn) {
return logCounts;
}
function countEgressAuthInLog(conn) {
let speculateLogCount = 0;
cat(conn.fullOptions.logFile)
.trim()
.split("\n")
.forEach((line) => {
const entry = JSON.parse(line);
if (entry.id === kEgressSpeculativeAuthenticationSuccessfulLogId) {
// Successful speculative auth.
speculateLogCount += 1;
}
});
print(`Found ${speculateLogCount} log entries for egress speculative authentication`);
return speculateLogCount;
}
const rst = new ReplSetTest({
nodes: 1,
nodeOptions: {
@ -82,15 +101,18 @@ assert(initialMechStats["SCRAM-SHA-256"] !== undefined);
// because we authenticated as `admin` using the shell helpers.
// Because of the simple cluster topology, we should have no intracluster authentication attempts.
Object.keys(initialMechStats).forEach(function (mech) {
const specStats = initialMechStats[mech].speculativeAuthenticate;
const clusterStats = initialMechStats[mech].clusterAuthenticate;
const specIngressStats = initialMechStats[mech].ingress.speculativeAuthenticate;
const specEgressStats = initialMechStats[mech].egress.speculativeAuthenticate;
const clusterStats = initialMechStats[mech].ingress.clusterAuthenticate;
// No speculation has occured
assert.eq(specStats.received, 0);
assert.eq(specIngressStats.total, 0);
assert.eq(specEgressStats.total, 0);
// Statistics should be consistent for all mechanisms
assert.eq(specStats.received, specStats.successful);
assert.eq(clusterStats.received, clusterStats.successful);
assert.eq(specIngressStats.total, specIngressStats.successful);
assert.eq(specEgressStats.total, specEgressStats.successful);
assert.eq(clusterStats.total, clusterStats.successful);
});
{
@ -113,32 +135,54 @@ Object.keys(initialMechStats).forEach(function (mech) {
}
{
// Speculative and cluster auth counts should align with the authentication
// events in the server log.
let ingressLogCounts = countIngressAuthInLog(admin.getMongo());
let egressSpecLogCount = countEgressAuthInLog(admin.getMongo());
// Capture new statistics, and assert that they're consistent.
let newMechStats = getMechStats(admin);
printjson(newMechStats);
// Speculative and cluster statistics should be incremented by intracluster auth.
assert.gt(
newMechStats["SCRAM-SHA-256"].speculativeAuthenticate.successful,
initialMechStats["SCRAM-SHA-256"].speculativeAuthenticate.successful,
newMechStats["SCRAM-SHA-256"].ingress.speculativeAuthenticate.successful,
initialMechStats["SCRAM-SHA-256"].ingress.speculativeAuthenticate.successful,
);
assert.gt(
newMechStats["SCRAM-SHA-256"].clusterAuthenticate.successful,
initialMechStats["SCRAM-SHA-256"].clusterAuthenticate.successful,
newMechStats["SCRAM-SHA-256"].egress.speculativeAuthenticate.successful,
initialMechStats["SCRAM-SHA-256"].egress.speculativeAuthenticate.successful,
);
assert.gt(
newMechStats["SCRAM-SHA-256"].ingress.clusterAuthenticate.successful,
initialMechStats["SCRAM-SHA-256"].ingress.clusterAuthenticate.successful,
);
assert.gt(
newMechStats["SCRAM-SHA-256"].egress.authenticate.successful,
initialMechStats["SCRAM-SHA-256"].egress.authenticate.successful,
);
// Speculative and cluster auth counts should align with the authentication
// events in the server log.
let logCounts = countAuthInLog(admin.getMongo());
// Assert that the number of authentication logs is roughly equal to what the stats report. We are not strict with this because of the inevitable race between when we read the log and when we get server stats.
assert.lte(
Math.abs(
ingressLogCounts.speculative -
(newMechStats["SCRAM-SHA-256"].ingress.speculativeAuthenticate.successful -
initialMechStats["SCRAM-SHA-256"].ingress.speculativeAuthenticate.successful),
),
2,
);
assert.eq(
logCounts.speculative,
newMechStats["SCRAM-SHA-256"].speculativeAuthenticate.successful -
initialMechStats["SCRAM-SHA-256"].speculativeAuthenticate.successful,
assert.lte(
Math.abs(
egressSpecLogCount -
(newMechStats["SCRAM-SHA-256"].egress.speculativeAuthenticate.successful -
initialMechStats["SCRAM-SHA-256"].egress.speculativeAuthenticate.successful),
),
2,
);
assert.gt(
logCounts.speculativeCluster,
ingressLogCounts.speculativeCluster,
0,
"Expected to observe at least one speculative cluster authentication attempt",
);
@ -148,8 +192,8 @@ Object.keys(initialMechStats).forEach(function (mech) {
const kClusterCountRetryIntervalMS = 5 * 1000;
assert.retry(
function () {
const logCount = logCounts.cluster;
const mechStatCount = newMechStats["SCRAM-SHA-256"].clusterAuthenticate.successful;
const logCount = ingressLogCounts.cluster;
const mechStatCount = newMechStats["SCRAM-SHA-256"].ingress.clusterAuthenticate.successful;
if (logCount == mechStatCount) {
return true;
}
@ -159,7 +203,7 @@ Object.keys(initialMechStats).forEach(function (mech) {
// Repoll values for a retry.
jsTest.log("Cluster counts mismatched: " + logCount + " != " + mechStatCount);
newMechStats = getMechStats(admin);
logCounts = countAuthInLog(admin.getMongo());
ingressLogCounts = countIngressAuthInLog(admin.getMongo());
return false;
},
"Cluster counts never stabilized",

View File

@ -29,19 +29,19 @@ function test(uri, incrMech, isClusterAuth = false) {
const inc = mech === incrMech ? 1 : 0;
const clusterInc = mech === incrMech && isClusterAuth ? 1 : 0;
const specBefore = lastStats[mech].speculativeAuthenticate;
const specAfter = stats[mech].speculativeAuthenticate;
assert.eq(specAfter.received, specBefore.received + inc);
const specBefore = lastStats[mech].ingress.speculativeAuthenticate;
const specAfter = stats[mech].ingress.speculativeAuthenticate;
assert.eq(specAfter.total, specBefore.total + inc);
assert.eq(specAfter.successful, specBefore.successful + inc);
const clusterBefore = lastStats[mech].clusterAuthenticate;
const clusterAfter = stats[mech].clusterAuthenticate;
assert.eq(clusterAfter.received, clusterBefore.received + clusterInc);
const clusterBefore = lastStats[mech].ingress.clusterAuthenticate;
const clusterAfter = stats[mech].ingress.clusterAuthenticate;
assert.eq(clusterAfter.total, clusterBefore.total + clusterInc);
assert.eq(clusterAfter.successful, clusterBefore.successful + clusterInc);
const allBefore = lastStats[mech].authenticate;
const allAfter = stats[mech].authenticate;
assert.eq(allAfter.received, allBefore.received + inc);
const allBefore = lastStats[mech].ingress.authenticate;
const allAfter = stats[mech].ingress.authenticate;
assert.eq(allAfter.total, allBefore.total + inc);
assert.eq(allAfter.successful, allBefore.successful + inc);
});
} catch (e) {

View File

@ -25,8 +25,8 @@ function assertStats(cb) {
// No speculative auth attempts yet.
assertStats(function (mechStats) {
Object.keys(mechStats).forEach(function (mech) {
const stats = mechStats[mech].speculativeAuthenticate;
assert.eq(stats.received, 0);
const stats = mechStats[mech].ingress.speculativeAuthenticate;
assert.eq(stats.total, 0);
assert.eq(stats.successful, 0);
});
});
@ -34,18 +34,18 @@ assertStats(function (mechStats) {
// No "intra-cluster" auth attempts yet.
assertStats(function (mechStats) {
Object.keys(mechStats).forEach(function (mech) {
const stats = mechStats[mech].clusterAuthenticate;
assert.eq(stats.received, 0);
const stats = mechStats[mech].ingress.clusterAuthenticate;
assert.eq(stats.total, 0);
assert.eq(stats.successful, 0);
});
});
function expectN(mechStats, mech, N1, M1, N2 = 0, M2 = 0) {
const specStats = mechStats[mech].speculativeAuthenticate;
const clusterStats = mechStats[mech].clusterAuthenticate;
assert.eq(N1, specStats.received);
const specStats = mechStats[mech].ingress.speculativeAuthenticate;
const clusterStats = mechStats[mech].ingress.clusterAuthenticate;
assert.eq(N1, specStats.total);
assert.eq(M1, specStats.successful);
assert.eq(N2, clusterStats.received);
assert.eq(N2, clusterStats.total);
assert.eq(M2, clusterStats.successful);
}

View File

@ -34,10 +34,10 @@ function assertStats() {
const mechStats = asAdmin({serverStatus: 1}).security.authentication.mechanisms[x509];
try {
assert.eq(mechStats.authenticate.received, expected.authenticate.received);
assert.eq(mechStats.authenticate.successful, expected.authenticate.successful);
assert.eq(mechStats.clusterAuthenticate.received, expected.clusterAuthenticate.received);
assert.eq(mechStats.clusterAuthenticate.successful, expected.clusterAuthenticate.successful);
assert.eq(mechStats.ingress.authenticate.total, expected.ingress.authenticate.total);
assert.eq(mechStats.ingress.authenticate.successful, expected.ingress.authenticate.successful);
assert.eq(mechStats.ingress.clusterAuthenticate.total, expected.ingress.clusterAuthenticate.total);
assert.eq(mechStats.ingress.clusterAuthenticate.successful, expected.ingress.clusterAuthenticate.successful);
} catch (e) {
print("mechStats: " + tojson(mechStats));
print("expected: " + tojson(expected));
@ -48,14 +48,14 @@ function assertStats() {
function assertSuccess(creds) {
assert.eq(external.auth(creds), true);
external.logout();
++expected.authenticate.received;
++expected.authenticate.successful;
++expected.ingress.authenticate.total;
++expected.ingress.authenticate.successful;
assertStats();
}
function assertFailure(creds) {
assert.eq(external.auth(creds), false);
++expected.authenticate.received;
++expected.ingress.authenticate.total;
assertStats();
}
@ -79,10 +79,10 @@ function assertSuccessInternal() {
),
0,
);
++expected.authenticate.received;
++expected.authenticate.successful;
++expected.clusterAuthenticate.received;
++expected.clusterAuthenticate.successful;
++expected.ingress.authenticate.total;
++expected.ingress.authenticate.successful;
++expected.ingress.clusterAuthenticate.total;
++expected.ingress.clusterAuthenticate.successful;
assertStats();
}

View File

@ -54,8 +54,8 @@ function assertStats(cb) {
// No speculative auth attempts yet.
assertStats(function (mechStats) {
Object.keys(mechStats).forEach(function (mech) {
const stats = mechStats[mech].speculativeAuthenticate;
assert.eq(stats.received, 0);
const stats = mechStats[mech].ingress.speculativeAuthenticate;
assert.eq(stats.total, 0);
assert.eq(stats.successful, 0);
});
});
@ -64,34 +64,34 @@ assertStats(function (mechStats) {
const baseURI = "mongodb://localhost:" + mongod.port + "/admin";
test(baseURI + "?authMechanism=MONGODB-X509");
assertStats(function (mechStats) {
const stats = mechStats["MONGODB-X509"].speculativeAuthenticate;
assert.eq(stats.received, 1);
const stats = mechStats["MONGODB-X509"].ingress.speculativeAuthenticate;
assert.eq(stats.total, 1);
assert.eq(stats.successful, 1);
});
// Connect without speculation and still have 1/1 result.
test(baseURI);
assertStats(function (mechStats) {
const stats = mechStats["MONGODB-X509"].speculativeAuthenticate;
assert.eq(stats.received, 1);
const stats = mechStats["MONGODB-X509"].ingress.speculativeAuthenticate;
assert.eq(stats.total, 1);
assert.eq(stats.successful, 1);
});
// We haven't done any cluster auth yet, so clusterAuthenticate counts should be 0
assertStats(function (mechStats) {
const stats = mechStats["MONGODB-X509"].clusterAuthenticate;
assert.eq(stats.received, 0);
const stats = mechStats["MONGODB-X509"].ingress.clusterAuthenticate;
assert.eq(stats.total, 0);
assert.eq(stats.successful, 0);
});
// Connect intra-cluster with speculation.
testInternal(baseURI + "?authMechanism=MONGODB-X509");
assertStats(function (mechStats) {
const specStats = mechStats["MONGODB-X509"].speculativeAuthenticate;
const clusterStats = mechStats["MONGODB-X509"].clusterAuthenticate;
assert.eq(specStats.received, 2);
const specStats = mechStats["MONGODB-X509"].ingress.speculativeAuthenticate;
const clusterStats = mechStats["MONGODB-X509"].ingress.clusterAuthenticate;
assert.eq(specStats.total, 2);
assert.eq(specStats.successful, 2);
assert.eq(clusterStats.received, 1);
assert.eq(clusterStats.total, 1);
assert.eq(clusterStats.successful, 1);
});

View File

@ -1,6 +1,6 @@
/**
* Tests that client-side SASL authentication using X.509 produces the expected connection health
* log lines.
* log lines and increments the auth counter as expected.
*/
import {ShardingTest} from "jstests/libs/shardingtest.js";
@ -33,30 +33,91 @@ const st = new ShardingTest({
jsTest.log.info("Check secondary config servers for authentication logs");
st.configRS.getSecondaries().forEach((conn) => {
const external = conn.getDB("$external");
assert.eq(
1,
external.auth({
mechanism: "MONGODB-X509",
}),
`X.509 auth failed on secondary ${conn.host} before running serverStatus`,
);
const stats = assert.commandWorked(external.runCommand({serverStatus: 1})).security.authentication;
jsTest.log.info("Authn stats: " + tojson(stats));
assert.gt(stats.totalEgressAuthenticationTimeMicros, 0);
const mechStats = stats.mechanisms;
let egressAuthSuccesses;
// We should see egress MONGODB-X509 auths and speculative auths, and no other egress auths
for (const [mech, stats] of Object.entries(mechStats)) {
if (mech === "MONGODB-X509") {
egressAuthSuccesses = stats.egress.authenticate.successful;
assert.gte(
egressAuthSuccesses,
1,
"Expected at least one egress MONGODB-X509 authenticate success on " + conn.host,
);
assert.eq(
egressAuthSuccesses,
stats.egress.authenticate.total,
"MONGODB-X509 egress authenticate successful count should equal total on " + conn.host,
);
assert.eq(
stats.egress.speculativeAuthenticate.total,
0,
"Expected no MONGODB-X509 speculativeAuthenticate attempts on " + conn.host,
);
} else {
assert.eq(
stats.egress.authenticate.total,
0,
"Mechanism " + mech + " should have no egress authenticate attempts on " + conn.host,
);
assert.eq(
stats.egress.speculativeAuthenticate.total,
0,
"Mechanism " + mech + " should have no egress speculativeAuthenticate attempts on " + conn.host,
);
assert.eq(
stats.ingress.authenticate.total,
0,
"Mechanism " + mech + " should have no ingress authenticate attempts on " + conn.host,
);
assert.eq(
stats.ingress.speculativeAuthenticate.total,
0,
"Mechanism " + mech + " should have no ingress speculativeAuthenticate attempts on " + conn.host,
);
assert.eq(
stats.ingress.clusterAuthenticate.total,
0,
"Mechanism " + mech + " should have no ingress clusterAuthenticate attempts on " + conn.host,
);
}
}
// getLog pulls a maximum of 1024 entries, which is sometimes not enough to find intra-cluster
// auth logs because startup is noisy. Instead, we search the log file directly.
assert.soon(
() =>
checkLog.checkContainsWithAtLeastCountJson(
conn.fullOptions.logFile,
kClientSaslX509SuccessLogId,
{
"subjectName": "CN=clustertest,OU=Kernel,O=MongoDB,L=New York City,ST=New York,C=US",
"targetDatabase": "$external",
"mechanism": "MONGODB-X509",
"result": 0,
"metrics": {
"conversation_duration": {
// X.509 auth has one step, so we don't collect step-by-step metrics.
"summary": {},
},
},
const successMessages = checkLog.getFilteredLogMessages(
conn.fullOptions.logFile,
kClientSaslX509SuccessLogId,
{
"subjectName": "CN=clustertest,OU=Kernel,O=MongoDB,L=New York City,ST=New York,C=US",
"targetDatabase": "$external",
"mechanism": "MONGODB-X509",
"result": 0,
"metrics": {
"conversation_duration": {
// X.509 auth has one step, so we don't collect step-by-step metrics.
"summary": {},
},
1 /* expectedCount */,
null /* severity */,
true /* isRelaxed */,
),
`Did not find SASL success log on secondary config server ${conn.host}`,
},
},
null /* severity */,
true /* isRelaxed */,
);
assert.lte(
Math.abs(successMessages.length - egressAuthSuccesses),
2,
"X.509 success log message count should be roughly egress auth success count on " + conn.host,
);
});

View File

@ -51,19 +51,19 @@ assert(initialMechStats["MONGODB-X509"] !== undefined);
// because we authenticated as `admin` using the shell helpers with SCRAM.
// Because of the simple cluster topology, we should have no intracluster authentication attempts.
Object.keys(initialMechStats).forEach(function (mech) {
const specStats = initialMechStats[mech].speculativeAuthenticate;
const clusterStats = initialMechStats[mech].clusterAuthenticate;
const specStats = initialMechStats[mech].ingress.speculativeAuthenticate;
const clusterStats = initialMechStats[mech].ingress.clusterAuthenticate;
if (mech === "MONGODB-X509") {
assert.eq(clusterStats.received, 1);
assert.eq(clusterStats.total, 1);
}
// No speculation has occured
assert.eq(specStats.received, 0);
assert.eq(specStats.total, 0);
// Statistics should be consistent for all mechanisms
assert.eq(specStats.received, specStats.successful);
assert.eq(clusterStats.received, clusterStats.successful);
assert.eq(specStats.total, specStats.successful);
assert.eq(clusterStats.total, clusterStats.successful);
});
{
@ -88,22 +88,22 @@ Object.keys(initialMechStats).forEach(function (mech) {
const newMechStats = getMechStats(admin);
printjson(newMechStats);
assert.eq(
newMechStats["MONGODB-X509"].speculativeAuthenticate.received,
newMechStats["MONGODB-X509"].speculativeAuthenticate.successful,
newMechStats["MONGODB-X509"].ingress.speculativeAuthenticate.total,
newMechStats["MONGODB-X509"].ingress.speculativeAuthenticate.successful,
);
assert.eq(
newMechStats["MONGODB-X509"].clusterAuthenticate.received,
newMechStats["MONGODB-X509"].clusterAuthenticate.successful,
newMechStats["MONGODB-X509"].ingress.clusterAuthenticate.total,
newMechStats["MONGODB-X509"].ingress.clusterAuthenticate.successful,
);
// Speculative and cluster statistics should be incremented by intracluster auth.
assert.gt(
newMechStats["MONGODB-X509"].speculativeAuthenticate.received,
initialMechStats["MONGODB-X509"].speculativeAuthenticate.successful,
newMechStats["MONGODB-X509"].ingress.speculativeAuthenticate.total,
initialMechStats["MONGODB-X509"].ingress.speculativeAuthenticate.successful,
);
assert.gt(
newMechStats["MONGODB-X509"].clusterAuthenticate.received,
initialMechStats["MONGODB-X509"].clusterAuthenticate.successful,
newMechStats["MONGODB-X509"].ingress.clusterAuthenticate.total,
initialMechStats["MONGODB-X509"].ingress.clusterAuthenticate.successful,
);
}

View File

@ -79,21 +79,21 @@ const authStats = assert.commandWorked(admin.runCommand({serverStatus: 1})).secu
jsTest.log("Authenticated stats: " + tojson(authStats));
// Got and succeeded an additional speculation.
const initSpec = initialStats.speculativeAuthenticate;
const authSpec = authStats.speculativeAuthenticate;
assert.eq(authSpec.received, initSpec.received + 2);
const initSpec = initialStats.ingress.speculativeAuthenticate;
const authSpec = authStats.ingress.speculativeAuthenticate;
assert.eq(authSpec.total, initSpec.total + 2);
assert.eq(authSpec.successful, initSpec.successful + 2);
// Got and succeeded an additional auth.
const initAuth = initialStats.authenticate;
const authAuth = authStats.authenticate;
assert.eq(authAuth.received, initAuth.received + 2);
const initAuth = initialStats.ingress.authenticate;
const authAuth = authStats.ingress.authenticate;
assert.eq(authAuth.total, initAuth.total + 2);
assert.eq(authAuth.successful, initAuth.successful + 2);
// Got and succeeded intra-cluster auth.
const initCluster = initialStats.clusterAuthenticate;
const authCluster = authStats.clusterAuthenticate;
assert.eq(authCluster.received, initCluster.received + 1);
const initCluster = initialStats.ingress.clusterAuthenticate;
const authCluster = authStats.ingress.clusterAuthenticate;
assert.eq(authCluster.total, initCluster.total + 1);
assert.eq(authCluster.successful, initCluster.successful + 1);
/////////////////////////////////////////////////////////////////////////////

View File

@ -48,6 +48,7 @@
#include "mongo/db/auth/user.h"
#include "mongo/db/connection_health_metrics_parameter_gen.h"
#include "mongo/db/server_options.h"
#include "mongo/db/stats/counters.h"
#include "mongo/db/wire_version.h"
#include "mongo/executor/remote_command_request.h"
#include "mongo/executor/remote_command_response.h"
@ -70,6 +71,14 @@
namespace mongo {
namespace auth {
const std::vector<std::string> kAllMechanisms{std::string(kMechanismMongoX509),
std::string(kMechanismSaslPlain),
std::string(kMechanismGSSAPI),
std::string(kMechanismScramSha1),
std::string(kMechanismScramSha256),
std::string(kMechanismMongoAWS),
std::string(kMechanismMongoOIDC)};
using executor::RemoteCommandRequest;
using AuthRequest = StatusWith<RemoteCommandRequest>;
@ -150,7 +159,11 @@ Future<void> authX509(RunCommandHook runCommand,
}
auto targetDb = std::move(swTargetDb.getValue());
auto argsBlock = std::make_tuple(hostname, params, std::string(clientName), targetDb);
auto mechCounter = authCounter.getMechanismCounter(kMechanismMongoX509);
mechCounter.incAuthenticateSent();
auto argsBlock =
std::make_tuple(hostname, params, std::string(clientName), targetDb, mechCounter);
auto sharedBlock = std::make_shared<decltype(argsBlock)>(std::move(argsBlock));
auto metricsRecorder = std::make_shared<AuthMetricsRecorder>();
@ -160,8 +173,9 @@ Future<void> authX509(RunCommandHook runCommand,
// into a Future<void>
return runCommand(swAuthRequest.getValue())
.then([metricsRecorder, sharedBlock](const BSONObj& obj) {
auto [hostname, params, clientName, targetDb] = *sharedBlock.get();
BSONObj metrics = metricsRecorder->captureEgress();
auto [hostname, params, clientName, targetDb, mechCounter] = *sharedBlock.get();
mechCounter.incEgressAuthenticateSuccessful();
if (gEnableDetailedConnectionHealthMetricLogLines.load()) {
LOGV2(10748708,
"Authentication to remote host succeeded using MONGODB-X509",
@ -175,8 +189,8 @@ Future<void> authX509(RunCommandHook runCommand,
}
})
.onError([metricsRecorder, sharedBlock](const Status& status) {
auto [hostname, params, clientName, targetDb] = *sharedBlock.get();
BSONObj metrics = metricsRecorder->captureEgress();
auto [hostname, params, clientName, targetDb, _] = *sharedBlock.get();
if (gEnableDetailedConnectionHealthMetricLogLines.load()) {
LOGV2(10748707,
"Authentication to remote host failed using MONGODB-X509",
@ -377,6 +391,11 @@ StatusWith<std::shared_ptr<SaslClientSession>> _speculateSaslStart(
}
std::string payload;
auto mechCounter = authCounter.getMechanismCounter(mechanism);
mechCounter.incAuthenticateSent();
mechCounter.incSpeculativeAuthenticateSent();
AuthMetricsRecorder metricsRecorder;
status = session->step("", &payload);
if (!status.isOK()) {
@ -395,6 +414,8 @@ StatusWith<std::shared_ptr<SaslClientSession>> _speculateSaslStart(
}
return status;
}
mechCounter.incEgressAuthenticateSuccessful();
mechCounter.incEgressSpeculativeAuthenticateSuccessful();
auto metrics = metricsRecorder.captureEgress();
if (gEnableDetailedConnectionHealthMetricLogLines.load()) {
LOGV2(10748710,

View File

@ -71,6 +71,7 @@ constexpr auto kMechanismScramSha1 = "SCRAM-SHA-1"_sd;
constexpr auto kMechanismScramSha256 = "SCRAM-SHA-256"_sd;
constexpr auto kMechanismMongoAWS = "MONGODB-AWS"_sd;
constexpr auto kMechanismMongoOIDC = "MONGODB-OIDC"_sd;
extern const std::vector<std::string> kAllMechanisms;
constexpr auto kInternalAuthFallbackMechanism = kMechanismScramSha1;
constexpr auto kSaslSupportedMechanisms = "saslSupportedMechs"_sd;

View File

@ -53,6 +53,7 @@
#include "mongo/db/auth/sasl_command_constants.h"
#include "mongo/db/connection_health_metrics_parameter_gen.h"
#include "mongo/db/database_name.h"
#include "mongo/db/stats/counters.h"
#include "mongo/executor/remote_command_request.h"
#include "mongo/executor/remote_command_response.h"
#include "mongo/logv2/log.h"
@ -343,7 +344,11 @@ Future<void> saslClientAuthenticateImpl(auth::RunCommandHook runCommand,
BSONObj inputObj = BSON(saslCommandPayloadFieldName << "");
auto argsBlock = std::make_tuple(hostname, saslParameters, username, targetDatabase, mechanism);
auto mechCounter = authCounter.getMechanismCounter(mechanism);
mechCounter.incAuthenticateSent();
auto argsBlock =
std::make_tuple(hostname, saslParameters, username, targetDatabase, mechanism, mechCounter);
auto sharedBlock = std::make_shared<decltype(argsBlock)>(std::move(argsBlock));
session->metrics()->restart();
@ -351,9 +356,9 @@ Future<void> saslClientAuthenticateImpl(auth::RunCommandHook runCommand,
return asyncSaslConversation(
runCommand, session, saslFirstCommandPrefix, inputObj, targetDatabase, saslLogLevel)
.onError([session, sharedBlock](Status status) {
auto [hostname, saslParameters, username, targetDatabase, mechanism] =
*sharedBlock.get();
BSONObj metrics = session->metrics()->captureEgress();
auto [hostname, saslParameters, username, targetDatabase, mechanism, _] =
*sharedBlock.get();
if (gEnableDetailedConnectionHealthMetricLogLines.load()) {
LOGV2(10748700,
"Authentication to remote host failed using SASL",
@ -369,9 +374,10 @@ Future<void> saslClientAuthenticateImpl(auth::RunCommandHook runCommand,
return status;
})
.then([session, sharedBlock]() {
auto [hostname, saslParameters, username, targetDatabase, mechanism] =
*sharedBlock.get();
BSONObj metrics = session->metrics()->captureEgress();
auto [hostname, saslParameters, username, targetDatabase, mechanism, mechCounter] =
*sharedBlock.get();
mechCounter.incEgressAuthenticateSuccessful();
if (gEnableDetailedConnectionHealthMetricLogLines.load()) {
LOGV2(10748701,
"Authentication to remote host succeeded using SASL",

View File

@ -41,7 +41,7 @@ void AuthMetricsRecorder::appendMetric(const BSONObj& metric) {
BSONObj AuthMetricsRecorder::captureIngress() {
Duration<std::micro> _duration = _timer.elapsed();
authCounter.incAuthenticationCumulativeTime(_duration.count());
authCounter.incIngressAuthenticationCumulativeTime(_duration.count());
return BSON("conversation_duration"
<< BSON("micros" << _duration.count() << "summary" << _appendedMetrics.done()));
@ -50,7 +50,7 @@ BSONObj AuthMetricsRecorder::captureIngress() {
BSONObj AuthMetricsRecorder::captureEgress() {
Duration<std::micro> _duration = _timer.elapsed();
// TODO SERVER-116025: Increment the egress version of authCounter
authCounter.incEgressAuthenticationCumulativeTime(_duration.count());
return BSON("conversation_duration"
<< BSON("micros" << _duration.count() << "summary" << _appendedMetrics.done()));

View File

@ -329,12 +329,12 @@ void AuthenticationSession::_finish() {
void AuthenticationSession::markSuccessful() {
_finish();
_mechCounter->incAuthenticateSuccessful();
_mechCounter->incIngressAuthenticateSuccessful();
if (_isClusterMember) {
_mechCounter->incClusterAuthenticateSuccessful();
}
if (_isSpeculative) {
_mechCounter->incSpeculativeAuthenticateSuccessful();
_mechCounter->incIngressSpeculativeAuthenticateSuccessful();
}
auto event =

View File

@ -236,32 +236,52 @@ void AuthCounter::incSaslSupportedMechanismsReceived() {
_saslSupportedMechanismsReceived.fetchAndAddRelaxed(1);
}
void AuthCounter::incAuthenticationCumulativeTime(long long micros) {
_authenticationCumulativeMicros.fetchAndAddRelaxed(micros);
void AuthCounter::incIngressAuthenticationCumulativeTime(long long micros) {
_ingressAuthenticationCumulativeMicros.fetchAndAddRelaxed(micros);
}
void AuthCounter::incEgressAuthenticationCumulativeTime(long long micros) {
_egressAuthenticationCumulativeMicros.fetchAndAddRelaxed(micros);
}
void AuthCounter::MechanismCounterHandle::incSpeculativeAuthenticateSent() {
_data->egress.speculativeAuthenticate.total.fetchAndAddRelaxed(1);
}
void AuthCounter::MechanismCounterHandle::incSpeculativeAuthenticateReceived() {
_data->speculativeAuthenticate.received.fetchAndAddRelaxed(1);
_data->ingress.speculativeAuthenticate.total.fetchAndAddRelaxed(1);
}
void AuthCounter::MechanismCounterHandle::incSpeculativeAuthenticateSuccessful() {
_data->speculativeAuthenticate.successful.fetchAndAddRelaxed(1);
void AuthCounter::MechanismCounterHandle::incIngressSpeculativeAuthenticateSuccessful() {
_data->ingress.speculativeAuthenticate.successful.fetchAndAddRelaxed(1);
}
void AuthCounter::MechanismCounterHandle::incEgressSpeculativeAuthenticateSuccessful() {
_data->egress.speculativeAuthenticate.successful.fetchAndAddRelaxed(1);
}
void AuthCounter::MechanismCounterHandle::incAuthenticateSent() {
_data->egress.authenticate.total.fetchAndAddRelaxed(1);
}
void AuthCounter::MechanismCounterHandle::incAuthenticateReceived() {
_data->authenticate.received.fetchAndAddRelaxed(1);
_data->ingress.authenticate.total.fetchAndAddRelaxed(1);
}
void AuthCounter::MechanismCounterHandle::incAuthenticateSuccessful() {
_data->authenticate.successful.fetchAndAddRelaxed(1);
void AuthCounter::MechanismCounterHandle::incIngressAuthenticateSuccessful() {
_data->ingress.authenticate.successful.fetchAndAddRelaxed(1);
}
void AuthCounter::MechanismCounterHandle::incEgressAuthenticateSuccessful() {
_data->egress.authenticate.successful.fetchAndAddRelaxed(1);
}
void AuthCounter::MechanismCounterHandle::incClusterAuthenticateReceived() {
_data->clusterAuthenticate.received.fetchAndAddRelaxed(1);
_data->ingress.clusterAuthenticate.total.fetchAndAddRelaxed(1);
}
void AuthCounter::MechanismCounterHandle::incClusterAuthenticateSuccessful() {
_data->clusterAuthenticate.successful.fetchAndAddRelaxed(1);
_data->ingress.clusterAuthenticate.successful.fetchAndAddRelaxed(1);
}
auto AuthCounter::getMechanismCounter(StringData mechanism) -> MechanismCounterHandle {
@ -274,17 +294,28 @@ auto AuthCounter::getMechanismCounter(StringData mechanism) -> MechanismCounterH
return MechanismCounterHandle(&data);
}
void AuthCounter::SuccessCounter::appendAsSubobj(BSONObjBuilder& bob, StringData fieldName) const {
BSONObjBuilder subBob(bob.subobjStart(fieldName));
subBob.append("total", total.load());
subBob.append("successful", successful.load());
subBob.done();
}
/**
* authentication: {
* "mechanisms": {
* "SCRAM-SHA-256": {
* "speculativeAuthenticate": { received: ###, successful: ### },
* "authenticate": { received: ###, successful: ### },
* },
* "MONGODB-X509": {
* "speculativeAuthenticate": { received: ###, successful: ### },
* "authenticate": { received: ###, successful: ### },
* "ingress": {
* "speculativeAuthenticate": { total: ###, successful: ### },
* "clusterAuthenticate": { total: ###, successful: ### },
* "authenticate": { total: ###, successful: ### },
* },
* "egress": {
* "speculativeAuthenticate": { total: ###, successful: ### },
* "authenticate": { total: ###, successful: ### },
* },
* },
* ...
* },
* }
*/
@ -297,43 +328,29 @@ void AuthCounter::append(BSONObjBuilder* b) {
for (const auto& it : _mechanisms) {
BSONObjBuilder mechBuilder(mechsBuilder.subobjStart(it.first));
{
const auto received = it.second.speculativeAuthenticate.received.load();
const auto successful = it.second.speculativeAuthenticate.successful.load();
BSONObjBuilder ingressBuilder(mechBuilder.subobjStart("ingress"));
it.second.ingress.speculativeAuthenticate.appendAsSubobj(ingressBuilder,
auth::kSpeculativeAuthenticate);
it.second.ingress.clusterAuthenticate.appendAsSubobj(ingressBuilder,
auth::kClusterAuthenticate);
it.second.ingress.authenticate.appendAsSubobj(ingressBuilder, auth::kAuthenticateCommand);
ingressBuilder.done();
BSONObjBuilder specAuthBuilder(mechBuilder.subobjStart(auth::kSpeculativeAuthenticate));
specAuthBuilder.append("received", received);
specAuthBuilder.append("successful", successful);
specAuthBuilder.done();
}
{
const auto received = it.second.clusterAuthenticate.received.load();
const auto successful = it.second.clusterAuthenticate.successful.load();
BSONObjBuilder clusterAuthBuilder(mechBuilder.subobjStart(auth::kClusterAuthenticate));
clusterAuthBuilder.append("received", received);
clusterAuthBuilder.append("successful", successful);
clusterAuthBuilder.done();
}
{
const auto received = it.second.authenticate.received.load();
const auto successful = it.second.authenticate.successful.load();
BSONObjBuilder authBuilder(mechBuilder.subobjStart(auth::kAuthenticateCommand));
authBuilder.append("received", received);
authBuilder.append("successful", successful);
authBuilder.done();
}
BSONObjBuilder egressBuilder(mechBuilder.subobjStart("egress"));
it.second.egress.speculativeAuthenticate.appendAsSubobj(egressBuilder,
auth::kSpeculativeAuthenticate);
it.second.egress.authenticate.appendAsSubobj(egressBuilder, auth::kAuthenticateCommand);
egressBuilder.done();
mechBuilder.done();
}
mechsBuilder.done();
const auto totalAuthenticationTimeMicros = _authenticationCumulativeMicros.load();
b->append("totalAuthenticationTimeMicros", totalAuthenticationTimeMicros);
const auto totalIngressAuthenticationTimeMicros = _ingressAuthenticationCumulativeMicros.load();
b->append("totalIngressAuthenticationTimeMicros", totalIngressAuthenticationTimeMicros);
const auto totalEgressAuthenticationTimeMicros = _egressAuthenticationCumulativeMicros.load();
b->append("totalEgressAuthenticationTimeMicros", totalEgressAuthenticationTimeMicros);
}
OpCounters& serviceOpCounters(ClusterRole role) {

View File

@ -278,11 +278,15 @@ public:
public:
MechanismCounterHandle(MechanismData* data) : _data(data) {}
void incSpeculativeAuthenticateSent();
void incSpeculativeAuthenticateReceived();
void incSpeculativeAuthenticateSuccessful();
void incIngressSpeculativeAuthenticateSuccessful();
void incEgressSpeculativeAuthenticateSuccessful();
void incAuthenticateSent();
void incAuthenticateReceived();
void incAuthenticateSuccessful();
void incIngressAuthenticateSuccessful();
void incEgressAuthenticateSuccessful();
void incClusterAuthenticateReceived();
void incClusterAuthenticateSuccessful();
@ -295,31 +299,36 @@ public:
void incSaslSupportedMechanismsReceived();
void incAuthenticationCumulativeTime(long long micros);
void incIngressAuthenticationCumulativeTime(long long micros);
void incEgressAuthenticationCumulativeTime(long long micros);
void append(BSONObjBuilder*);
void initializeMechanismMap(const std::vector<std::string>&);
private:
struct SuccessCounter {
AtomicWord<long long> total;
AtomicWord<long long> successful;
void appendAsSubobj(BSONObjBuilder& bob, StringData fieldName) const;
};
struct MechanismData {
struct {
AtomicWord<long long> received;
AtomicWord<long long> successful;
} speculativeAuthenticate;
SuccessCounter speculativeAuthenticate;
SuccessCounter authenticate;
SuccessCounter clusterAuthenticate;
} ingress;
struct {
AtomicWord<long long> received;
AtomicWord<long long> successful;
} authenticate;
struct {
AtomicWord<long long> received;
AtomicWord<long long> successful;
} clusterAuthenticate;
SuccessCounter speculativeAuthenticate;
SuccessCounter authenticate;
} egress;
};
using MechanismMap = std::map<std::string, MechanismData>;
AtomicWord<long long> _saslSupportedMechanismsReceived;
AtomicWord<long long> _authenticationCumulativeMicros;
AtomicWord<long long> _ingressAuthenticationCumulativeMicros;
AtomicWord<long long> _egressAuthenticationCumulativeMicros;
// Mechanism maps are initialized at startup to contain all
// mechanisms known to authenticationMechanisms setParam.
// After that they are kept to a fixed size.

View File

@ -37,10 +37,12 @@
#include "mongo/bson/bsonobjbuilder.h"
#include "mongo/bson/util/builder.h"
#include "mongo/bson/util/builder_fwd.h"
#include "mongo/client/authenticate.h"
#include "mongo/client/client_api_version_parameters_gen.h"
#include "mongo/client/mongo_uri.h"
#include "mongo/config.h" // IWYU pragma: keep
#include "mongo/db/auth/sasl_command_constants.h"
#include "mongo/db/auth/sasl_options.h"
#include "mongo/db/server_options.h"
#include "mongo/db/server_parameter.h"
#include "mongo/db/tenant_id.h"
@ -357,6 +359,8 @@ Status storeMongoShellOptions(const moe::Environment& params,
}
}
saslGlobalParams.authenticationMechanisms = auth::kAllMechanisms;
return Status::OK();
}