mirror of https://github.com/mongodb/mongo
254 lines
7.3 KiB
JavaScript
254 lines
7.3 KiB
JavaScript
// SERVER-6591: Localhost authentication exception doesn't work right on sharded cluster
|
|
//
|
|
// This test is to ensure that localhost authentication works correctly against a sharded
|
|
// cluster whether they are hosted with "localhost" or a hostname.
|
|
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
|
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
|
|
|
// The following checks, which occurs on ShardingTest.stop, involve using a mongos to read data on
|
|
// the config server, but this test uses a special shutdown function which stops the mongoses before
|
|
// calling ShardingTest.stop.
|
|
// @tags : [requires_scripting]
|
|
TestData.skipCheckingUUIDsConsistentAcrossCluster = true;
|
|
TestData.skipCheckingIndexesConsistentAcrossCluster = true;
|
|
TestData.skipCheckOrphans = true;
|
|
TestData.skipCheckShardFilteringMetadata = true;
|
|
TestData.skipCheckMetadataConsistency = true;
|
|
|
|
let replSetName = "replsets_server-6591";
|
|
let keyfile = "jstests/libs/key1";
|
|
let numShards = 2;
|
|
let username = "foo";
|
|
let password = "bar";
|
|
let adhocShard = 0;
|
|
|
|
let createUser = function (mongo) {
|
|
print("============ adding a user.");
|
|
mongo.getDB("admin").createUser({user: username, pwd: password, roles: jsTest.adminUserRoles});
|
|
};
|
|
|
|
let addUsersToEachShard = function (st) {
|
|
// In config shard mode skip the first shard because it is also the config server and will
|
|
// already have a user made on it through mongos.
|
|
for (let i = TestData.configShard ? 1 : 0; i < numShards; i++) {
|
|
print("============ adding a user to shard " + i);
|
|
let d = st["shard" + i];
|
|
d.getDB("admin").createUser({user: username, pwd: password, roles: jsTest.adminUserRoles});
|
|
}
|
|
};
|
|
|
|
let addShard = function (st, shouldPass) {
|
|
adhocShard++;
|
|
const rs = new ReplSetTest({nodes: 1, host: "localhost", name: "localhostAuthShard-" + adhocShard});
|
|
rs.startSet({shardsvr: "", keyFile: keyfile, auth: ""});
|
|
rs.initiate();
|
|
|
|
let res = st.getDB("admin").runCommand({addShard: rs.getURL()});
|
|
if (shouldPass) {
|
|
assert.commandWorked(res, "Add shard");
|
|
} else {
|
|
assert.commandFailed(res, "Add shard");
|
|
}
|
|
return rs;
|
|
};
|
|
|
|
let findEmptyShard = function (st, ns) {
|
|
let counts = st.chunkCounts("foo");
|
|
|
|
for (let shard in counts) {
|
|
if (counts[shard] == 0) {
|
|
return shard;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
let assertCannotRunCommands = function (mongo, st) {
|
|
print("============ ensuring that commands cannot be run.");
|
|
|
|
// CRUD
|
|
let test = mongo.getDB("test");
|
|
assert.throws(function () {
|
|
test.system.users.findOne();
|
|
});
|
|
assert.writeError(test.foo.save({_id: 0}));
|
|
assert.throws(function () {
|
|
test.foo.findOne({_id: 0});
|
|
});
|
|
assert.writeError(test.foo.update({_id: 0}, {$set: {x: 20}}));
|
|
assert.writeError(test.foo.remove({_id: 0}));
|
|
|
|
// Multi-shard
|
|
assert.throws(function () {
|
|
test.foo.mapReduce(
|
|
function () {
|
|
emit(1, 1);
|
|
},
|
|
function (id, count) {
|
|
return Array.sum(count);
|
|
},
|
|
{out: "other"},
|
|
);
|
|
});
|
|
|
|
// Config
|
|
assert.throws(function () {
|
|
mongo.getDB("config").shards.findOne();
|
|
});
|
|
|
|
let authorizeErrorCode = 13;
|
|
let res = mongo.getDB("admin").runCommand({
|
|
moveChunk: "test.foo",
|
|
find: {_id: 1},
|
|
to: st.shard0.shardName, // Arbitrary shard.
|
|
});
|
|
assert.commandFailedWithCode(res, authorizeErrorCode, "moveChunk");
|
|
// Create collection
|
|
assert.commandFailedWithCode(
|
|
mongo.getDB("test").createCollection("log", {capped: true, size: 5242880, max: 5000}),
|
|
authorizeErrorCode,
|
|
"createCollection",
|
|
);
|
|
// Set/Get system parameters
|
|
let params = [
|
|
{param: "journalCommitInterval", val: 200},
|
|
{param: "logLevel", val: 2},
|
|
{param: "logUserIds", val: 1},
|
|
{param: "notablescan", val: 1},
|
|
{param: "quiet", val: 1},
|
|
{param: "replApplyBatchSize", val: 10},
|
|
{param: "replIndexPrefetch", val: "none"},
|
|
{param: "syncdelay", val: 30},
|
|
{param: "traceExceptions", val: true},
|
|
{param: "sslMode", val: "preferSSL"},
|
|
{param: "clusterAuthMode", val: "sendX509"},
|
|
{param: "userCacheInvalidationIntervalSecs", val: 300},
|
|
];
|
|
params.forEach(function (p) {
|
|
let cmd = {setParameter: 1};
|
|
cmd[p.param] = p.val;
|
|
assert.commandFailedWithCode(
|
|
mongo.getDB("admin").runCommand(cmd),
|
|
authorizeErrorCode,
|
|
"setParameter: " + p.param,
|
|
);
|
|
});
|
|
params.forEach(function (p) {
|
|
let cmd = {getParameter: 1};
|
|
cmd[p.param] = 1;
|
|
assert.commandFailedWithCode(
|
|
mongo.getDB("admin").runCommand(cmd),
|
|
authorizeErrorCode,
|
|
"getParameter: " + p.param,
|
|
);
|
|
});
|
|
};
|
|
|
|
let assertCanRunCommands = function (mongo, st) {
|
|
print("============ ensuring that commands can be run.");
|
|
|
|
// CRUD
|
|
let test = mongo.getDB("test");
|
|
|
|
// this will throw if it fails
|
|
test.system.users.findOne();
|
|
|
|
assert.commandWorked(test.foo.save({_id: 0}));
|
|
assert.commandWorked(test.foo.update({_id: 0}, {$set: {x: 20}}));
|
|
assert.commandWorked(test.foo.remove({_id: 0}));
|
|
|
|
// Multi-shard
|
|
test.foo.mapReduce(
|
|
function () {
|
|
emit(1, 1);
|
|
},
|
|
function (id, count) {
|
|
return Array.sum(count);
|
|
},
|
|
{out: "other"},
|
|
);
|
|
|
|
// Config
|
|
// this will throw if it fails
|
|
mongo.getDB("config").shards.findOne();
|
|
|
|
let to = findEmptyShard(st, "test.foo");
|
|
let res = mongo.getDB("admin").runCommand({moveChunk: "test.foo", find: {_id: 1}, to: to});
|
|
assert.commandWorked(res);
|
|
};
|
|
|
|
let authenticate = function (mongo) {
|
|
print("============ authenticating user.");
|
|
mongo.getDB("admin").auth(username, password);
|
|
};
|
|
|
|
let setupSharding = function (shardingTest) {
|
|
let mongo = shardingTest.s;
|
|
|
|
print("============ enabling sharding on test.foo.");
|
|
mongo.getDB("admin").runCommand({enableSharding: "test", primaryShard: st.shard1.shardName});
|
|
mongo.getDB("admin").runCommand({shardCollection: "test.foo", key: {_id: 1}});
|
|
|
|
let test = mongo.getDB("test");
|
|
for (let i = 1; i < 20; i++) {
|
|
test.foo.insert({_id: i});
|
|
}
|
|
};
|
|
|
|
let start = function () {
|
|
return new ShardingTest({
|
|
auth: "",
|
|
shards: numShards,
|
|
other: {
|
|
keyFile: keyfile,
|
|
chunkSize: 1,
|
|
useHostname: false, // Must use localhost to take advantage of the localhost auth bypass
|
|
},
|
|
});
|
|
};
|
|
|
|
print("=====================");
|
|
print("starting shards");
|
|
print("=====================");
|
|
var st = start();
|
|
let host = st.s.host;
|
|
let extraShards = [];
|
|
|
|
let mongo = new Mongo(host);
|
|
|
|
assertCannotRunCommands(mongo, st);
|
|
|
|
extraShards.push(addShard(st, 1));
|
|
createUser(mongo);
|
|
|
|
authenticate(mongo);
|
|
authenticate(st.s);
|
|
setupSharding(st);
|
|
|
|
addUsersToEachShard(st);
|
|
st.printShardingStatus();
|
|
|
|
assertCanRunCommands(mongo, st);
|
|
|
|
print("===============================");
|
|
print("reconnecting with a new client.");
|
|
print("===============================");
|
|
|
|
mongo = new Mongo(host);
|
|
|
|
assertCannotRunCommands(mongo, st);
|
|
extraShards.push(addShard(mongo, 0));
|
|
|
|
authenticate(mongo);
|
|
|
|
assertCanRunCommands(mongo, st);
|
|
extraShards.push(addShard(mongo, 1));
|
|
st.printShardingStatus();
|
|
|
|
extraShards.forEach(function (rs) {
|
|
rs.stopSet();
|
|
});
|
|
st.stop();
|