264 lines
7.7 KiB
JavaScript
264 lines
7.7 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.
|
|
|
|
var replSetName = "replsets_server-6591";
|
|
var keyfile = "jstests/libs/key1";
|
|
var numShards = 2;
|
|
var username = "foo";
|
|
var password = "bar";
|
|
|
|
var createUser = function(mongo) {
|
|
print("============ adding a user.");
|
|
mongo.getDB("admin").createUser({user: username, pwd: password, roles: jsTest.adminUserRoles});
|
|
};
|
|
|
|
var addUsersToEachShard = function(st) {
|
|
for(i = 0; i < numShards; i++) {
|
|
print("============ adding a user to shard " + i);
|
|
var d = st["shard" + i];
|
|
d.getDB("admin").createUser({user: username, pwd: password, roles: jsTest.adminUserRoles});
|
|
}
|
|
};
|
|
|
|
var addShard = function(st, shouldPass) {
|
|
var m = MongoRunner.runMongod({ auth: "", keyFile: keyfile, useHostname: false });
|
|
var res = st.getDB("admin").runCommand({ addShard: m.host });
|
|
if (shouldPass) {
|
|
assert.commandWorked(res, "Add shard");
|
|
}
|
|
else {
|
|
assert.commandFailed(res, "Add shard");
|
|
}
|
|
return m.port;
|
|
};
|
|
|
|
|
|
var findEmptyShard = function(st, ns) {
|
|
var counts = st.chunkCounts( "foo" )
|
|
|
|
for(shard in counts){
|
|
if(counts[shard] == 0) {
|
|
return shard;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
var assertCannotRunCommands = function(mongo, st) {
|
|
print("============ ensuring that commands cannot be run.");
|
|
|
|
// CRUD
|
|
var 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();
|
|
});
|
|
|
|
var authorizeErrorCode = 13;
|
|
var res = mongo.getDB("admin").runCommand({
|
|
moveChunk: "test.foo",
|
|
find: {_id: 1},
|
|
to: "shard0000" // Arbitrary shard.
|
|
});
|
|
assert.commandFailedWithCode(res, authorizeErrorCode, "moveChunk");
|
|
assert.commandFailedWithCode(mongo.getDB("test").copyDatabase("admin", "admin2"),
|
|
authorizeErrorCode, "copyDatabase");
|
|
// Create collection
|
|
assert.commandFailedWithCode(mongo.getDB("test").createCollection(
|
|
"log", { capped: true, size: 5242880, max: 5000 } ),
|
|
authorizeErrorCode, "createCollection");
|
|
// Set/Get system parameters
|
|
var 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) {
|
|
var cmd = { setParameter: 1 };
|
|
cmd[p.param] = p.val;
|
|
assert.commandFailedWithCode(mongo.getDB("admin").runCommand(cmd),
|
|
authorizeErrorCode, "setParameter: "+p.param);
|
|
});
|
|
params.forEach(function(p) {
|
|
var cmd = { getParameter: 1 };
|
|
cmd[p.param] = 1;
|
|
assert.commandFailedWithCode(mongo.getDB("admin").runCommand(cmd),
|
|
authorizeErrorCode, "getParameter: "+p.param);
|
|
});
|
|
};
|
|
|
|
var assertCanRunCommands = function(mongo, st) {
|
|
print("============ ensuring that commands can be run.");
|
|
|
|
// CRUD
|
|
var test = mongo.getDB("test");
|
|
|
|
// this will throw if it fails
|
|
test.system.users.findOne();
|
|
|
|
assert.writeOK(test.foo.save({ _id: 0 }));
|
|
assert.writeOK(test.foo.update({ _id: 0 }, { $set: { x: 20 }}));
|
|
assert.writeOK(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();
|
|
|
|
to = findEmptyShard(st, "test.foo");
|
|
var res = mongo.getDB("admin").runCommand({
|
|
moveChunk: "test.foo",
|
|
find: {_id: 1},
|
|
to: to
|
|
});
|
|
assert.commandWorked(res);
|
|
};
|
|
|
|
var authenticate = function(mongo) {
|
|
print("============ authenticating user.");
|
|
mongo.getDB("admin").auth(username, password);
|
|
};
|
|
|
|
var setupSharding = function(shardingTest) {
|
|
var mongo = shardingTest.s;
|
|
|
|
print("============ enabling sharding on test.foo.");
|
|
mongo.getDB("admin").runCommand({enableSharding : "test"});
|
|
shardingTest.ensurePrimaryShard('test', 'shard0001');
|
|
mongo.getDB("admin").runCommand({shardCollection : "test.foo", key : {_id : 1}});
|
|
|
|
var test = mongo.getDB("test");
|
|
for(i = 1; i < 20; i++) {
|
|
test.foo.insert({_id: i});
|
|
}
|
|
};
|
|
|
|
var start = function() {
|
|
return new ShardingTest({
|
|
auth: "",
|
|
keyFile: keyfile,
|
|
shards: numShards,
|
|
chunksize: 1,
|
|
other : {
|
|
nopreallocj: 1,
|
|
useHostname: false // Must use localhost to take advantage of the localhost auth bypass
|
|
}
|
|
});
|
|
};
|
|
|
|
var shutdown = function(st) {
|
|
print("============ shutting down.");
|
|
|
|
// SERVER-8445
|
|
// Unlike MongoRunner.stopMongod and ReplSetTest.stopSet,
|
|
// ShardingTest.stop does not have a way to provide auth
|
|
// information. Therefore, we'll do this manually for now.
|
|
|
|
for(i = 0; i < st._mongos.length; i++) {
|
|
var port = st["s" + i].port;
|
|
MongoRunner.stopMongos(
|
|
port,
|
|
/*signal*/false,
|
|
{ auth : { user: username, pwd: password }}
|
|
);
|
|
}
|
|
|
|
for(i = 0; i < st._connections.length; i++) {
|
|
var port = st["shard" + i].port;
|
|
MongoRunner.stopMongod(
|
|
port,
|
|
/*signal*/false,
|
|
{ auth : { user: username, pwd: password }}
|
|
);
|
|
}
|
|
|
|
for(i = 0; i < st._configServers.length; i++) {
|
|
var c = st["config" + i].port;
|
|
MongoRunner.stopMongod(
|
|
port,
|
|
/*signal*/false,
|
|
{ auth : { user: username, pwd: password }}
|
|
);
|
|
}
|
|
|
|
st.stop();
|
|
};
|
|
|
|
var runTest = function() {
|
|
print("=====================");
|
|
print("starting shards");
|
|
print("=====================");
|
|
var st = start();
|
|
var host = st.s.host;
|
|
var extraShards = [];
|
|
|
|
var 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();
|
|
|
|
shutdown(st);
|
|
extraShards.forEach(function(sh) {
|
|
MongoRunner.stopMongod(sh);
|
|
});
|
|
}
|
|
|
|
runTest();
|