summaryrefslogtreecommitdiff
path: root/jstests
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2019-12-04 17:12:10 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-02-12 19:16:45 +0000
commit812c8338f496da3f43174330e37f07f0aad442d3 (patch)
tree80baa88c0eb7aec60fe1d199b27308deae87d49c /jstests
parent37d1ef0d02582ac95a2adf835a341e0ead12abb3 (diff)
downloadmongo-812c8338f496da3f43174330e37f07f0aad442d3.tar.gz
SERVER-44858 Implement speculative sasl auth
create mode 100644 jstests/auth/speculative-auth-replset.js create mode 100644 jstests/auth/speculative-sasl-start.js create mode 100644 jstests/ssl/speculative-auth-replset.js create mode 100644 jstests/ssl/speculative-authenticate.js create mode 100644 src/mongo/db/auth/sasl_commands.h create mode 100644 src/mongo/db/s/balancer/core_options_stub.cpp
Diffstat (limited to 'jstests')
-rw-r--r--jstests/auth/mongoURIAuth.js4
-rw-r--r--jstests/auth/speculative-auth-replset.js58
-rw-r--r--jstests/auth/speculative-sasl-start.js96
-rw-r--r--jstests/ssl/speculative-auth-replset.js51
-rw-r--r--jstests/ssl/speculative-authenticate.js68
5 files changed, 275 insertions, 2 deletions
diff --git a/jstests/auth/mongoURIAuth.js b/jstests/auth/mongoURIAuth.js
index 7688db2084e..abf518c5a98 100644
--- a/jstests/auth/mongoURIAuth.js
+++ b/jstests/auth/mongoURIAuth.js
@@ -68,6 +68,6 @@ runURIAuthTest(false, true, SCRAM_SHA_256, SCRAM_SHA_256_regex);
jsTestLog("Test that a mechanism specified in CreateUser() is the chosen authentication method.");
runURIAuthTest(true, false, SCRAM_SHA_1, SCRAM_SHA_1_regex);
-jsTestLog("Test that SCRAM-SHA-1 is the default authentication method.");
+jsTestLog("Test that SCRAM-SHA-256 is the default authentication method.");
runURIAuthTest(false, false, SCRAM_SHA_256, SCRAM_SHA_256_regex);
-})(); \ No newline at end of file
+})();
diff --git a/jstests/auth/speculative-auth-replset.js b/jstests/auth/speculative-auth-replset.js
new file mode 100644
index 00000000000..65d83acba44
--- /dev/null
+++ b/jstests/auth/speculative-auth-replset.js
@@ -0,0 +1,58 @@
+// Verify that replica sets can speculatively authenticate
+// to each other during intra-cluster communication.
+// @tags: [requires_replication]
+
+(function() {
+'use strict';
+
+const rst = new ReplSetTest({nodes: 3, keyFile: 'jstests/libs/key1'});
+rst.startSet();
+rst.initiate();
+rst.awaitSecondaryNodes();
+
+const admin = rst.getPrimary().getDB('admin');
+admin.createUser({user: 'admin', pwd: 'pwd', roles: ['root']});
+admin.auth('admin', 'pwd');
+
+const baseURI = (function() {
+ let uri = 'mongodb://admin:pwd@';
+
+ for (let i = 0; i < rst.ports.length; ++i) {
+ if (i > 0) {
+ uri = uri + ',';
+ }
+ uri = uri + rst.host + ':' + rst.ports[i];
+ }
+
+ return uri + '/admin?replicaSet=' + rst.name;
+})();
+
+function test(uri) {
+ assert.eq(runMongoProgram('./mongo', uri, '--eval', ';'), 0);
+}
+
+// We've made no client connections for which speculation was possible,
+// since this connection came in during localhost auth bypass.
+// However we should have non-zero SCRAM-SHA-256 successes using internal auth.
+const mechStats =
+ assert.commandWorked(admin.runCommand({serverStatus: 1})).security.authentication.mechanisms;
+printjson(mechStats);
+assert(mechStats['SCRAM-SHA-256'] !== undefined);
+Object.keys(mechStats).forEach(function(mech) {
+ const stats = mechStats[mech].speculativeAuthenticate;
+
+ if (mech === 'SCRAM-SHA-256') {
+ assert.gte(stats.received, 2);
+ } else {
+ assert.eq(stats.received, 0);
+ }
+ assert.eq(stats.received, stats.successful);
+});
+
+test(baseURI);
+test(baseURI + '&authMechanism=SCRAM-SHA-1');
+test(baseURI + '&authMechanism=SCRAM-SHA-256');
+
+admin.logout();
+rst.stopSet();
+}());
diff --git a/jstests/auth/speculative-sasl-start.js b/jstests/auth/speculative-sasl-start.js
new file mode 100644
index 00000000000..a29d19815e7
--- /dev/null
+++ b/jstests/auth/speculative-sasl-start.js
@@ -0,0 +1,96 @@
+// Test for speculativeSaslStart during isMaster.
+
+(function() {
+'use strict';
+
+const mongod = MongoRunner.runMongod({auth: ''});
+const admin = mongod.getDB('admin');
+
+admin.createUser(
+ {user: 'admin', pwd: 'pwd', roles: ['root'], mechanisms: ['SCRAM-SHA-1', 'SCRAM-SHA-256']});
+admin.auth('admin', 'pwd');
+
+function test(uri, succeed) {
+ const shell = runMongoProgram('./mongo', uri, '--eval', ';');
+
+ if (succeed) {
+ assert.eq(0, shell);
+ } else {
+ assert.neq(0, shell);
+ }
+}
+
+function assertStats(cb) {
+ const mechStats = assert.commandWorked(admin.runCommand({serverStatus: 1}))
+ .security.authentication.mechanisms;
+ cb(mechStats);
+}
+
+// No speculative auth attempts yet.
+assertStats(function(mechStats) {
+ Object.keys(mechStats).forEach(function(mech) {
+ const stats = mechStats[mech].speculativeAuthenticate;
+ assert.eq(stats.received, 0);
+ assert.eq(stats.successful, 0);
+ });
+});
+
+function expectN(mechStats, mech, N, M) {
+ const stats = mechStats[mech].speculativeAuthenticate;
+ assert.eq(N, stats.received);
+ assert.eq(M, stats.successful);
+}
+
+const baseOKURI = 'mongodb://admin:pwd@localhost:' + mongod.port + '/admin';
+
+// Speculate SCRAM-SHA-1
+test(baseOKURI + '?authMechanism=SCRAM-SHA-1', true);
+assertStats((s) => expectN(s, 'SCRAM-SHA-1', 1, 1));
+assertStats((s) => expectN(s, 'SCRAM-SHA-256', 0, 0));
+
+// Speculate SCRAM-SHA-256
+test(baseOKURI + '?authMechanism=SCRAM-SHA-256', true);
+assertStats((s) => expectN(s, 'SCRAM-SHA-1', 1, 1));
+assertStats((s) => expectN(s, 'SCRAM-SHA-256', 1, 1));
+
+// Fallback should speculate SCRAM-SHA-256
+test(baseOKURI, true);
+assertStats((s) => expectN(s, 'SCRAM-SHA-1', 1, 1));
+assertStats((s) => expectN(s, 'SCRAM-SHA-256', 2, 2));
+
+const baseFAILURI = 'mongodb://admin:haxx@localhost:' + mongod.port + '/admin';
+
+// Invalid password should never connect regardless of speculative auth.
+test(baseFAILURI + '?authMechanism=SCRAM-SHA-1', false);
+assertStats((s) => expectN(s, 'SCRAM-SHA-1', 2, 1));
+assertStats((s) => expectN(s, 'SCRAM-SHA-256', 2, 2));
+
+test(baseFAILURI + '?authMechanism=SCRAM-SHA-256', false);
+assertStats((s) => expectN(s, 'SCRAM-SHA-1', 2, 1));
+assertStats((s) => expectN(s, 'SCRAM-SHA-256', 3, 2));
+
+test(baseFAILURI, false);
+assertStats((s) => expectN(s, 'SCRAM-SHA-1', 2, 1));
+assertStats((s) => expectN(s, 'SCRAM-SHA-256', 4, 2));
+
+// Update admin use to only allow SCRAM-SHA-1
+
+admin.updateUser('admin', {mechanisms: ['SCRAM-SHA-1']});
+
+// Fallback (SCRAM-SHA-256) should fail to speculate.
+test(baseOKURI, true);
+assertStats((s) => expectN(s, 'SCRAM-SHA-1', 2, 1));
+assertStats((s) => expectN(s, 'SCRAM-SHA-256', 5, 2));
+
+// Explicit SCRAM-SHA-1 should successfully speculate.
+test(baseOKURI + '?authMechanism=SCRAM-SHA-1', true);
+assertStats((s) => expectN(s, 'SCRAM-SHA-1', 3, 2));
+assertStats((s) => expectN(s, 'SCRAM-SHA-256', 5, 2));
+
+// Explicit SCRAM-SHA-256 should fail to speculate or connect at all.
+test(baseOKURI + '?authMechanism=SCRAM-SHA-256', false);
+assertStats((s) => expectN(s, 'SCRAM-SHA-1', 3, 2));
+assertStats((s) => expectN(s, 'SCRAM-SHA-256', 6, 2));
+
+MongoRunner.stopMongod(mongod);
+})();
diff --git a/jstests/ssl/speculative-auth-replset.js b/jstests/ssl/speculative-auth-replset.js
new file mode 100644
index 00000000000..3c10b53b678
--- /dev/null
+++ b/jstests/ssl/speculative-auth-replset.js
@@ -0,0 +1,51 @@
+// Verify that replica sets can speculatively authenticate
+// to each other during intra-cluster communication.
+// @tags: [requires_replication]
+
+(function() {
+'use strict';
+
+const x509_options = {
+ tlsMode: 'requireTLS',
+ tlsCertificateKeyFile: 'jstests/libs/server.pem',
+ tlsCAFile: 'jstests/libs/ca.pem',
+ clusterAuthMode: 'sendX509',
+};
+
+const rst = new ReplSetTest({
+ nodes: 3,
+ nodeOptions: x509_options,
+
+ // ReplSetTest needs a keyFile present in order to know we want intracluster auth.
+ keyFile: 'jstests/libs/key1',
+ // ReplicaSet needs to use localhost so that SAN/CN values match.
+ useHostName: false,
+});
+
+rst.startSet();
+rst.initiate();
+rst.awaitSecondaryNodes();
+
+const admin = rst.getPrimary().getDB('admin');
+admin.createUser({user: 'admin', pwd: 'pwd', roles: ['root']});
+admin.auth('admin', 'pwd');
+
+// We should have non-zero MONGODB-X509 successes using internal auth.
+// And we should have no other types of speculative authentications.
+const mechStats =
+ assert.commandWorked(admin.runCommand({serverStatus: 1})).security.authentication.mechanisms;
+printjson(mechStats);
+assert(mechStats['MONGODB-X509'] !== undefined);
+Object.keys(mechStats).forEach(function(mech) {
+ const stats = mechStats[mech].speculativeAuthenticate;
+ if (mech === 'MONGODB-X509') {
+ assert.gte(stats.received, 2);
+ } else {
+ assert.eq(stats.received, 0);
+ }
+ assert.eq(stats.received, stats.successful);
+});
+
+admin.logout();
+rst.stopSet();
+}());
diff --git a/jstests/ssl/speculative-authenticate.js b/jstests/ssl/speculative-authenticate.js
new file mode 100644
index 00000000000..384042e3de5
--- /dev/null
+++ b/jstests/ssl/speculative-authenticate.js
@@ -0,0 +1,68 @@
+// Test for speculativeAuthenticate during isMaster.
+
+(function() {
+'use strict';
+
+const mongod = MongoRunner.runMongod({
+ auth: '',
+ tlsMode: 'requireTLS',
+ tlsCertificateKeyFile: 'jstests/libs/server.pem',
+ tlsCAFile: 'jstests/libs/ca.pem',
+});
+const admin = mongod.getDB('admin');
+const external = mongod.getDB('$external');
+
+admin.createUser(
+ {user: 'admin', pwd: 'pwd', roles: ['root'], mechanisms: ['SCRAM-SHA-1', 'SCRAM-SHA-256']});
+admin.auth('admin', 'pwd');
+
+const X509USER = 'CN=client,OU=KernelUser,O=MongoDB,L=New York City,ST=New York,C=US';
+external.createUser({user: X509USER, roles: [{role: 'root', db: 'admin'}]});
+
+function test(uri) {
+ const x509 = runMongoProgram('./mongo',
+ '--tls',
+ '--tlsCAFile',
+ 'jstests/libs/ca.pem',
+ '--tlsCertificateKeyFile',
+ 'jstests/libs/client.pem',
+ uri,
+ '--eval',
+ ';');
+ assert.eq(0, x509);
+}
+
+function assertStats(cb) {
+ const mechStats = assert.commandWorked(admin.runCommand({serverStatus: 1}))
+ .security.authentication.mechanisms;
+ cb(mechStats);
+}
+
+// No speculative auth attempts yet.
+assertStats(function(mechStats) {
+ Object.keys(mechStats).forEach(function(mech) {
+ const stats = mechStats[mech].speculativeAuthenticate;
+ assert.eq(stats.received, 0);
+ assert.eq(stats.successful, 0);
+ });
+});
+
+// Connect with speculation and have 1/1 result.
+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);
+ 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);
+ assert.eq(stats.successful, 1);
+});
+
+MongoRunner.stopMongod(mongod);
+})();