SERVER-122836: Emit source client address in Client::getRemote if connected to proxy unix socket (#49941)
GitOrigin-RevId: 93ab54812def6d33443f9389fbaa8de48c6f3792
This commit is contained in:
parent
91dad8fa94
commit
f300452c07
98
jstests/auth/auth_log.js
Normal file
98
jstests/auth/auth_log.js
Normal 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);
|
||||
@ -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}$/});
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -163,7 +163,8 @@ public:
|
||||
|
||||
HostAndPort getRemote() const {
|
||||
MONGO_verify(_session);
|
||||
return _session->remote();
|
||||
return _session->isConnectedToProxyUnixSocket() ? _session->getSourceRemoteEndpoint()
|
||||
: _session->remote();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user