diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2019-12-04 17:12:10 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-02-12 19:16:45 +0000 |
commit | 812c8338f496da3f43174330e37f07f0aad442d3 (patch) | |
tree | 80baa88c0eb7aec60fe1d199b27308deae87d49c /jstests | |
parent | 37d1ef0d02582ac95a2adf835a341e0ead12abb3 (diff) | |
download | mongo-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.js | 4 | ||||
-rw-r--r-- | jstests/auth/speculative-auth-replset.js | 58 | ||||
-rw-r--r-- | jstests/auth/speculative-sasl-start.js | 96 | ||||
-rw-r--r-- | jstests/ssl/speculative-auth-replset.js | 51 | ||||
-rw-r--r-- | jstests/ssl/speculative-authenticate.js | 68 |
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); +})(); |