summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2018-02-14 15:36:10 -0500
committerSara Golemon <sara.golemon@mongodb.com>2018-02-24 16:15:33 -0500
commit0fcf0cf28aa4a5a5213d401645515c6a8a853505 (patch)
tree772f82d623eead26ba52cc9125d1a6332fc7307c
parent10c09477dd67543a417423254b1e7c4dd4f9d05c (diff)
downloadmongo-0fcf0cf28aa4a5a5213d401645515c6a8a853505.tar.gz
SERVER-32977 Make shell use SASL mechanism negotiation
-rw-r--r--jstests/auth/auth_mechanism_discovery.js43
-rw-r--r--src/mongo/shell/db.js37
2 files changed, 73 insertions, 7 deletions
diff --git a/jstests/auth/auth_mechanism_discovery.js b/jstests/auth/auth_mechanism_discovery.js
new file mode 100644
index 00000000000..e613adff8c3
--- /dev/null
+++ b/jstests/auth/auth_mechanism_discovery.js
@@ -0,0 +1,43 @@
+// Tests that a client will auto-discover a user's supported SASL mechanisms during auth().
+(function() {
+ "use strict";
+
+ function runTest(conn) {
+ const admin = conn.getDB("admin");
+ const test = conn.getDB("test");
+
+ admin.createUser({user: 'admin', pwd: 'pass', roles: jsTest.adminUserRoles});
+ assert(admin.auth('admin', 'pass'));
+
+ // Enable SCRAM-SHA-256.
+ assert.commandWorked(admin.runCommand({setFeatureCompatibilityVersion: "4.0"}));
+
+ function checkUser(username, mechanism) {
+ var createUser = {createUser: username, pwd: 'pwd', roles: []};
+ if (mechanism !== undefined) {
+ createUser.mechanisms = [mechanism];
+ } else {
+ // Create both variants, expect to prefer 256.
+ mechanism = 'SCRAM-SHA-256';
+ }
+ assert.commandWorked(test.runCommand(createUser));
+ assert.eq(test._getDefaultAuthenticationMechanism(username, test.getName()), mechanism);
+ assert(test.auth(username, 'pwd'));
+ test.logout();
+ }
+ checkUser('userSha1', 'SCRAM-SHA-1');
+ checkUser('userSha256', 'SCRAM-SHA-256');
+ checkUser('userAll');
+ }
+
+ // Test standalone.
+ const m = MongoRunner.runMongod({auth: ""});
+ runTest(m);
+ MongoRunner.stopMongod(m);
+
+ // Test sharded.
+ const st =
+ new ShardingTest({shards: 1, mongos: 1, config: 1, other: {keyFile: 'jstests/libs/key1'}});
+ runTest(st.s0);
+ st.stop();
+})();
diff --git a/src/mongo/shell/db.js b/src/mongo/shell/db.js
index ca0048c301a..4493b2a1192 100644
--- a/src/mongo/shell/db.js
+++ b/src/mongo/shell/db.js
@@ -544,9 +544,10 @@ var DB;
}
if (!mechanism) {
- mechanism = this._getDefaultAuthenticationMechanism();
+ mechanism = this._getDefaultAuthenticationMechanism(username, fromdb);
}
- assert(mechanism == "SCRAM-SHA-1" || mechanism == "MONGODB-CR");
+ assert(mechanism == "SCRAM-SHA-1" || mechanism == "SCRAM-SHA-256" ||
+ mechanism == "MONGODB-CR");
// Check for no auth or copying from localhost
if (!username || !password || fromhost == "") {
@@ -554,8 +555,8 @@ var DB;
{copydb: 1, fromhost: fromhost, fromdb: fromdb, todb: todb, slaveOk: slaveOk});
}
- // Use the copyDatabase native helper for SCRAM-SHA-1
- if (mechanism == "SCRAM-SHA-1") {
+ // Use the copyDatabase native helper for SCRAM-SHA-1/256
+ if (mechanism != "MONGODB-CR") {
// TODO SERVER-30886: Add session support for Mongo.prototype.copyDatabaseWithSCRAM().
return this.getMongo().copyDatabaseWithSCRAM(
fromdb, todb, fromhost, username, password, slaveOk);
@@ -1563,7 +1564,28 @@ var DB;
DB.prototype._defaultAuthenticationMechanism = null;
- DB.prototype._getDefaultAuthenticationMechanism = function() {
+ DB.prototype._getDefaultAuthenticationMechanism = function(username, database) {
+ if (username !== undefined) {
+ const userid = database + "." + username;
+ const result = this.runCommand({isMaster: 1, saslSupportedMechs: userid});
+ if (result.ok && (result.saslSupportedMechs !== undefined)) {
+ const mechs = result.saslSupportedMechs;
+ if (!Array.isArray(mechs)) {
+ throw Error("Server replied with invalid saslSupportedMechs response");
+ }
+ // Never include PLAIN in auto-negotiation.
+ const priority = ["GSSAPI", "SCRAM-SHA-256", "SCRAM-SHA-1"];
+ for (var i = 0; i < priority.length; ++i) {
+ if (mechs.includes(priority[i])) {
+ return priority[i];
+ }
+ }
+ }
+ // If isMaster doesn't support saslSupportedMechs,
+ // or if we couldn't agree on a mechanism,
+ // then fallthrough to configured default or SCRAM-SHA-1.
+ }
+
// Use the default auth mechanism if set on the command line.
if (this._defaultAuthenticationMechanism != null)
return this._defaultAuthenticationMechanism;
@@ -1586,8 +1608,9 @@ var DB;
"auth expects either (username, password) or ({ user: username, pwd: password })");
}
- if (params.mechanism === undefined)
- params.mechanism = this._getDefaultAuthenticationMechanism();
+ if (params.mechanism === undefined) {
+ params.mechanism = this._getDefaultAuthenticationMechanism(params.user, this.getName());
+ }
if (params.db !== undefined) {
throw Error("Do not override db field on db.auth(). Use getMongo().auth(), instead.");