SERVER-122836: Emit source client address in Client::getRemote if connected to proxy unix socket (#49941)

GitOrigin-RevId: 93ab54812def6d33443f9389fbaa8de48c6f3792
This commit is contained in:
Joseph Prince 2026-03-27 08:18:58 -07:00 committed by MongoDB Bot
parent 91dad8fa94
commit f300452c07
5 changed files with 178 additions and 1 deletions

98
jstests/auth/auth_log.js Normal file
View File

@ -0,0 +1,98 @@
// Test that the client field in auth logs is emitting correctly.
import {ProxyProtocolServer} from "jstests/sharding/libs/proxy_protocol.js";
// Test that the auth logs include the `expectedClient`.
function testClientAttr(mongodRunner, db, expectedClient, connectionHealthLoggingOn) {
db.auth("admin", "pwd");
if (connectionHealthLoggingOn) {
assert.soon(
() =>
checkLog.checkContainsWithCountJson(
mongodRunner,
5286306,
{"client": expectedClient, "result": 0},
1,
null,
true,
),
"Did not find expected sourceClient in successful auth log",
);
} else {
assert.eq(
checkLog.checkContainsOnceJson(mongodRunner, 5286306, {}),
false,
"Expected not to find successful auth log entry",
);
}
db.logout();
db.auth("admin", "wrong");
if (connectionHealthLoggingOn) {
assert.soon(
() =>
checkLog.checkContainsWithCountJson(
mongodRunner,
5286307,
{"client": expectedClient, "result": 18},
1,
null,
true,
),
"Did not find expected sourceClient in failed auth log",
);
} else {
assert.eq(
checkLog.checkContainsOnceJson(mongodRunner, 5286307, {}),
false,
"Expected not to find failed auth log entry",
);
}
}
function runClientAttrTests(connectionHealthLoggingOn) {
// This test is not supported on windows since it uses the ProxyProtocolServer.
if (_isWindows()) {
return;
}
const ingressPort = allocatePort();
const prefix = `${MongoRunner.dataPath}${jsTestName()}`;
mkdir(prefix);
const mongod = MongoRunner.runMongod({
proxyUnixSocketPrefix: prefix,
unixSocketPrefix: prefix,
setParameter: {
enableDetailedConnectionHealthMetricLogLines: connectionHealthLoggingOn,
},
});
const unixSocketPath = `${prefix}/mongodb-${mongod.port}.sock`;
assert(fileExists(unixSocketPath), `Expected unix socket to exist: ${unixSocketPath}`);
const proxySocketPath = `${prefix}/proxy-mongodb-${mongod.port}.sock`;
assert(fileExists(proxySocketPath), `Expected proxy socket to exist: ${proxySocketPath}`);
let proxyServer = new ProxyProtocolServer(ingressPort, mongod.port, 2, {
egressUnixSocket: proxySocketPath,
});
proxyServer.setTLVs([{"type": 0x02, "value": "authority.example.com"}]);
proxyServer.start();
try {
mongod.getDB("admin").createUser({user: "admin", pwd: "pwd", roles: ["root"], mechanisms: ["SCRAM-SHA-256"]});
// Connection via standard unix socket should emit "anonymous unix socket:27017" as remote addr.
const unixConn = new Mongo(unixSocketPath);
const unixAdminDB = unixConn.getDB("admin");
testClientAttr(mongod, unixAdminDB, "anonymous unix socket:27017", connectionHealthLoggingOn);
// Connection via the proxy unix socket should emit the source ip address as remote addr.
const proxiedConn = new Mongo(`mongodb://127.0.0.1:${ingressPort}`);
testClientAttr(mongod, proxiedConn.getDB("admin"), /^127\.0\.0\.1:\d{1,5}$/, connectionHealthLoggingOn);
} finally {
MongoRunner.stopMongod(mongod);
proxyServer.stop();
}
}
runClientAttrTests(true);
runClientAttrTests(false);

View File

@ -93,6 +93,30 @@ export const testProxyProtocolReplicaSet = (ingressPort, egressPort, version, te
rs.stopSet();
};
export const testProxyProtocolReplicaSetWithProxyUnixSocket = (ingressPort, testFn) => {
const prefix = `${MongoRunner.dataPath}${jsTestName()}`;
mkdir(prefix);
const rs = new ReplSetTest({nodes: 1});
rs.startSet({proxyUnixSocketPrefix: prefix, unixSocketPrefix: prefix});
rs.initiate();
const unixSockPath = `${prefix}/proxy-mongodb-${rs.getPrimary().port}.sock`;
const proxy_server = new ProxyProtocolServer(
ingressPort,
"" /* egressPort (ignored) */,
2 /* proxy protocol version */,
{egressUnixSocket: unixSockPath},
);
proxy_server.setTLVs([{"type": 0x02, "value": "authority.example.com"}]);
proxy_server.start();
testFn(ingressPort, prefix, rs.getPrimary(), false);
proxy_server.stop();
rs.stopSet();
};
export const testProxyProtocolShardedCluster = (ingressPort, egressPort, version, testFn) => {
const proxy_server = new ProxyProtocolServer(ingressPort, egressPort, version);
proxy_server.start();
@ -108,3 +132,49 @@ export const testProxyProtocolShardedCluster = (ingressPort, egressPort, version
proxy_server.stop();
st.stop();
};
export const testProxyProtocolShardedClusterWithProxyUnixSocket = (ingressPort, testFn) => {
const prefix = `${MongoRunner.dataPath}${jsTestName()}`;
mkdir(prefix);
const st = new ShardingTest({
shards: 1,
mongos: 1,
mongosOptions: {proxyUnixSocketPrefix: prefix, unixSocketPrefix: prefix},
});
const unixSockPath = `${prefix}/proxy-mongodb-${st.s0.port}.sock`;
const proxy_server = new ProxyProtocolServer(
ingressPort,
"" /* egressPort (ignored) */,
2 /* proxy protocol version */,
{egressUnixSocket: unixSockPath},
);
proxy_server.setTLVs([{"type": 0x02, "value": "authority.example.com"}]);
proxy_server.start();
testFn(ingressPort, prefix, st.s, true);
proxy_server.stop();
st.stop();
};
// Verify that the "client metadata" log (id 51800) emits the remote attribute properly.
export const testClientMetadataLogOverUnixSocket = (ingressPort, unixSockPrefix, node, isRouter) => {
const kClientMetadataLogId = 51800;
const unixSockPath = `${unixSockPrefix}/mongodb-${node.port}.sock`;
const proxyUnixSockPath = `${unixSockPrefix}/proxy-mongodb-${node.port}.sock`;
// Connections via a unix domain socket should log "anonymous unix socket:27017" as remote attr.
const directConn = new Mongo(unixSockPath);
assert.neq(null, directConn, "Failed to connect directly to node");
assert.commandWorked(directConn.getDB("admin").runCommand({hello: 1}));
checkLog.containsJson(node, kClientMetadataLogId, {remote: "anonymous unix socket:27017"});
// Connections via the proxy unix domain socket should log the originating address reported in the proxy protocol header.
const lbParam = isRouter ? "/?loadBalanced=true" : "";
const proxiedConn = new Mongo(`mongodb://127.0.0.1:${ingressPort}${lbParam}`);
assert.neq(null, proxiedConn, "Failed to connect through proxy");
assert.commandWorked(proxiedConn.getDB("admin").runCommand({hello: 1}));
checkLog.containsJson(node, kClientMetadataLogId, {remote: /^127\.0\.0\.1:\d{1,5}$/});
};

View File

@ -13,6 +13,8 @@ import {
emptyMessageTest,
fuzzingTest,
testProxyProtocolReplicaSet,
testProxyProtocolReplicaSetWithProxyUnixSocket,
testClientMetadataLogOverUnixSocket,
} from "jstests/noPassthrough/libs/proxy_protocol_helpers.js";
import {ReplSetTest} from "jstests/libs/replsettest.js";
import {ProxyProtocolServer} from "jstests/sharding/libs/proxy_protocol.js";
@ -125,3 +127,5 @@ testProxyProtocolReplicaSet(ingressPort, egressPort, 2, emptyMessageTest);
testProxyProtocolReplicaSet(ingressPort, egressPort, 1, fuzzingTest);
testProxyProtocolReplicaSet(ingressPort, egressPort, 2, fuzzingTest);
testProxyProtocolReplicaSetWithProxyUnixSocket(ingressPort, testClientMetadataLogOverUnixSocket);

View File

@ -13,6 +13,8 @@ import {
emptyMessageTest,
fuzzingTest,
testProxyProtocolShardedCluster,
testProxyProtocolShardedClusterWithProxyUnixSocket,
testClientMetadataLogOverUnixSocket,
} from "jstests/noPassthrough/libs/proxy_protocol_helpers.js";
const ingressPort = allocatePort();
@ -23,3 +25,5 @@ testProxyProtocolShardedCluster(ingressPort, egressPort, 2, emptyMessageTest);
testProxyProtocolShardedCluster(ingressPort, egressPort, 1, fuzzingTest);
testProxyProtocolShardedCluster(ingressPort, egressPort, 2, fuzzingTest);
testProxyProtocolShardedClusterWithProxyUnixSocket(ingressPort, testClientMetadataLogOverUnixSocket);

View File

@ -163,7 +163,8 @@ public:
HostAndPort getRemote() const {
MONGO_verify(_session);
return _session->remote();
return _session->isConnectedToProxyUnixSocket() ? _session->getSourceRemoteEndpoint()
: _session->remote();
}
/**