diff --git a/jstests/auth/logs_include_client_info.js b/jstests/auth/logs_include_client_info.js new file mode 100644 index 00000000000..5e793100686 --- /dev/null +++ b/jstests/auth/logs_include_client_info.js @@ -0,0 +1,29 @@ +// This test just checks that the success/failure messages for authentication include the IP +// address of the client attempting to authenticate. + +(function() { + const conn = MongoRunner.runMongod({auth: ""}); + const admin = conn.getDB("admin"); + + admin.createUser({ + user: "root", + pwd: "root", + roles: ["root"], + }); + + assert(admin.auth("root", "root")); + + const failConn = new Mongo(conn.host); + failConn.getDB("admin").auth("root", "toot"); + + const log = assert.commandWorked(admin.runCommand({getLog: "global"})).log; + + const successRegex = + /Successfully authenticated as principal root on admin from client (?:\d{1,3}\.){3}\d{1,3}:\d+/; + const failRegex = + /SASL SCRAM-SHA-\d+ authentication failed for root on admin from client (?:\d{1,3}\.){3}\d{1,3}:\d+/; + + assert(log.some((line) => successRegex.test(line))); + assert(log.some((line) => failRegex.test(line))); + MongoRunner.stopMongod(conn); +})(); diff --git a/jstests/ssl/x509_client.js b/jstests/ssl/x509_client.js index d834cb46cea..32ade720a53 100644 --- a/jstests/ssl/x509_client.js +++ b/jstests/ssl/x509_client.js @@ -44,7 +44,8 @@ function authAndTest(mongo) { user: CLIENT_USER, roles: [ {'role': 'userAdminAnyDatabase', 'db': 'admin'}, - {'role': 'readWriteAnyDatabase', 'db': 'admin'} + {'role': 'readWriteAnyDatabase', 'db': 'admin'}, + {'role': 'clusterMonitor', 'db': 'admin'}, ] }); @@ -70,6 +71,14 @@ function authAndTest(mongo) { assert(external.runCommand({authenticate: 1, mechanism: 'MONGODB-X509'}).ok, "runCommand authentication with valid client cert and no user field failed"); + // Check that there's a "Successfully authenticated" message that includes the client IP + const log = + assert.commandWorked(external.getSiblingDB("admin").runCommand({getLog: "global"})).log; + const successRegex = new RegExp(`Successfully authenticated as principal ${CLIENT_USER} on ` + + `\\$external from client (?:\\d{1,3}\\.){3}\\d{1,3}:\\d+`); + + assert(log.some((line) => successRegex.test(line))); + // Check that we can add a user and read data test.createUser( {user: "test", pwd: "test", roles: [{'role': 'readWriteAnyDatabase', 'db': 'admin'}]}); diff --git a/src/mongo/db/auth/sasl_commands.cpp b/src/mongo/db/auth/sasl_commands.cpp index 176353c6a54..1218f37f4b8 100644 --- a/src/mongo/db/auth/sasl_commands.cpp +++ b/src/mongo/db/auth/sasl_commands.cpp @@ -210,7 +210,8 @@ Status doSaslStep(OperationContext* opCtx, if (!serverGlobalParams.quiet.load()) { log() << "Successfully authenticated as principal " << mechanism.getPrincipalName() - << " on " << mechanism.getAuthenticationDatabase(); + << " on " << mechanism.getAuthenticationDatabase() << " from client " + << opCtx->getClient()->session()->remote(); } } return Status::OK(); diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp index 7666955b122..1808f7022ea 100644 --- a/src/mongo/db/commands/authentication_commands.cpp +++ b/src/mongo/db/commands/authentication_commands.cpp @@ -285,8 +285,7 @@ bool CmdAuthenticate::run(OperationContext* opCtx, if (!status.isOK()) { if (!serverGlobalParams.quiet.load()) { auto const client = opCtx->getClient(); - log() << "Failed to authenticate " << user - << (client->hasRemote() ? (" from client " + client->getRemote().toString()) : "") + log() << "Failed to authenticate " << user << " from client " << client->getRemote() << " with mechanism " << mechanism << ": " << status; } sleepmillis(saslGlobalParams.authFailedDelay.load()); @@ -299,6 +298,12 @@ bool CmdAuthenticate::run(OperationContext* opCtx, } return false; } + + if (!serverGlobalParams.quiet.load()) { + log() << "Successfully authenticated as principal " << user.getUser() << " on " + << user.getDB() << " from client " << opCtx->getClient()->session()->remote(); + } + result.append("dbname", user.getDB()); result.append("user", user.getUser()); return true;