Files
mongo/jstests/auth/copyauth.js
Max Hirschhorn 0ed1b71a50 SERVER-31456 Set initial{Cluster,Operation}Time in concurrency suite.
Ensures that the FSM worker threads are guaranteed to observe the
effects of the $config.setup() function being called since they'll
specify an afterClusterTime beyond that point.
2017-10-14 21:54:02 -04:00

271 lines
11 KiB
JavaScript

// Test copyDatabase command with various combinations of authed/unauthed and single node/replica
// set source and dest.
TestData.authMechanism = "SCRAM-SHA-1"; // SERVER-11428
DB.prototype._defaultAuthenticationMechanism = "SCRAM-SHA-1"; // SERVER-11428
// We turn off gossiping the mongo shell's clusterTime because this test connects to replica sets
// and sharded clusters as a user other than __system. Attempting to advance the clusterTime while
// it has been signed with a dummy key results in an authorization error.
TestData.skipGossipingClusterTime = true;
var baseName = "jstests_clone_copyauth";
/*
* Helper to spawn a replica set, sharded cluster, or a single mongod and hide it all behind the
* same interface.
*
* Arguments:
*
* clusterType - type of cluster to start. Options are "sharded", "repl", or "single".
* startWithAuth - whether to start the cluster with authentication.
* startWithTransitionToAuth - whether to start the cluster with --transitionToAuth (startWithAuth
* must also be true).
*
* Member variables:
*
* conn - a connection to the node used to access this cluster, whether it's the mongod, a primary
* mongod in a replica set, or a mongos.
* connString - the full connection string used to connect to this cluster. For a replica set this
* is the full connection string including the replica set name.
*
* Member functions:
*
* stop() - stop and cleanup whatever nodes the helper spawned when it was created.
*/
function ClusterSpawnHelper(clusterType, startWithAuth, startWithTransitionToAuth) {
var singleNodeConfig = {};
if (startWithAuth) {
singleNodeConfig.keyFile = "jstests/libs/key1";
if (startWithTransitionToAuth) {
singleNodeConfig.transitionToAuth = "";
}
}
if (clusterType === "sharded") {
var shardingTestConfig = {
name: baseName + "_source",
keyFile: singleNodeConfig.keyFile,
mongos: [singleNodeConfig],
shards: [singleNodeConfig],
config: [singleNodeConfig]
};
var shardingTest = new ShardingTest(shardingTestConfig);
this.conn = shardingTest.s;
this.connString = this.conn.host;
} else if (clusterType === "repl") {
var replSetTestConfig = {
name: baseName + "_source",
nodes: 3,
nodeOptions: singleNodeConfig,
keyFile: singleNodeConfig.keyFile
};
var replSetTest = new ReplSetTest(replSetTestConfig);
replSetTest.startSet();
replSetTest.initiate();
if (startWithAuth) {
authutil.asCluster(
replSetTest.nodes, replSetTestConfig.nodeOptions.keyFile, function() {
replSetTest.awaitReplication();
});
} else {
replSetTest.awaitReplication();
}
this.conn = replSetTest.getPrimary();
this.connString = replSetTest.getURL();
} else {
this.conn = MongoRunner.runMongod(singleNodeConfig);
this.connString = this.conn.host;
}
this.stop = function() {
if (clusterType === "sharded") {
shardingTest.stop();
} else if (clusterType === "repl") {
replSetTest.stopSet();
} else {
MongoRunner.stopMongod(this.conn);
}
};
}
/*
* Helper to test the running the "copydb" command between various kinds of clusters and various
* combinations of authentication on the source and target.
*
* @param {Object} configObj
*
* {
* sourceClusterType {string}: Type of cluster to use as the source of the copy. Options are
* "single", "repl", "sharded".
* isSourceUsingAuth {bool}: Whether to use auth in the source cluster for the copy.
* targetClusterType {string}: Type of cluster to use as the target of the copy. Options are
* "single", "repl", "sharded".
* isTargetUsingAuth {bool}: Whether to use auth in the target cluster for the copy.
* }
*/
function copydbBetweenClustersTest(configObj) {
// First sanity check the arguments in our configObj
var requiredKeys = [
'sourceClusterType',
'isSourceUsingAuth',
'targetClusterType',
'isTargetUsingAuth',
'isSourceUsingTransitionToAuth',
'isTargetUsingTransitionToAuth'
];
var i;
for (i = 0; i < requiredKeys.length; i++) {
assert(configObj.hasOwnProperty(requiredKeys[i]),
"Missing required key: " + requiredKeys[i] + " in config object");
}
// 1. Get a connection to the source database, insert data and setup auth if applicable
source = new ClusterSpawnHelper(configObj.sourceClusterType,
configObj.isSourceUsingAuth,
configObj.isSourceUsingTransitionToAuth);
if (configObj.isSourceUsingAuth) {
// Create a super user so we can create a regular user and not be locked out afterwards
source.conn.getDB("admin").createUser(
{user: "sourceSuperUser", pwd: "sourceSuperUser", roles: ["root"]});
source.conn.getDB("admin").auth("sourceSuperUser", "sourceSuperUser");
source.conn.getDB(baseName)[baseName].save({i: 1});
assert.eq(1, source.conn.getDB(baseName)[baseName].count());
assert.eq(1, source.conn.getDB(baseName)[baseName].findOne().i);
// Insert a document and create a regular user that we will use for the target
// authenticating with the source
source.conn.getDB(baseName).createUser({user: "foo", pwd: "bar", roles: ["dbOwner"]});
source.conn.getDB("admin").logout();
var readWhenLoggedOut = function() {
source.conn.getDB(baseName)[baseName].findOne();
};
if (configObj.isSourceUsingTransitionToAuth) {
// transitionToAuth does not turn on access control
assert.doesNotThrow(readWhenLoggedOut);
} else {
assert.throws(readWhenLoggedOut);
}
} else {
source.conn.getDB(baseName)[baseName].save({i: 1});
assert.eq(1, source.conn.getDB(baseName)[baseName].count());
assert.eq(1, source.conn.getDB(baseName)[baseName].findOne().i);
}
// 2. Get a connection to the target database, and set up auth if necessary
target = new ClusterSpawnHelper(configObj.targetClusterType,
configObj.isTargetUsingAuth,
configObj.isTargetUsingTransitionToAuth);
if (configObj.isTargetUsingAuth) {
target.conn.getDB("admin").createUser(
{user: "targetSuperUser", pwd: "targetSuperUser", roles: ["root"]});
var readWhenLoggedOut = function() {
target.conn.getDB(baseName)[baseName].findOne();
};
if (configObj.isTargetUsingTransitionToAuth) {
// transitionToAuth does not turn on access control
assert.doesNotThrow(readWhenLoggedOut);
} else {
assert.throws(readWhenLoggedOut);
}
target.conn.getDB("admin").auth("targetSuperUser", "targetSuperUser");
}
// 3. Run the copydb command
target.conn.getDB(baseName).dropDatabase();
assert.eq(0, target.conn.getDB(baseName)[baseName].count());
if (configObj.isSourceUsingAuth) {
// We only need to pass username and password if the target has to send authentication
// information to the source cluster
assert.commandWorked(target.conn.getDB(baseName).copyDatabase(
baseName, baseName, source.connString, "foo", "bar"));
} else {
// We are copying from a cluster with no auth
assert.commandWorked(
target.conn.getDB(baseName).copyDatabase(baseName, baseName, source.connString));
}
assert.eq(1, target.conn.getDB(baseName)[baseName].count());
assert.eq(1, target.conn.getDB(baseName)[baseName].findOne().i);
// 4. Do any necessary cleanup
source.stop();
target.stop();
}
(function() {
"use strict";
var sourceClusterTypeValues = ["single", "repl", "sharded"];
var isSourceUsingAuthValues = [true, false];
var isSourceUsingTransitionToAuthValues = [true, false];
var targetClusterTypeValues = ["single", "repl", "sharded"];
var isTargetUsingAuthValues = [true, false];
var isTargetUsingTransitionToAuthValues = [true, false];
for (var i = 0; i < sourceClusterTypeValues.length; i++) {
for (var j = 0; j < isSourceUsingAuthValues.length; j++) {
for (var k = 0; k < targetClusterTypeValues.length; k++) {
for (var l = 0; l < isTargetUsingAuthValues.length; l++) {
if (sourceClusterTypeValues[i] === "sharded" &&
targetClusterTypeValues[k] === "sharded") {
// SERVER-13112
continue;
}
if (sourceClusterTypeValues[i] === "repl" &&
targetClusterTypeValues[k] === "repl") {
// SERVER-13077
continue;
}
if (isSourceUsingAuthValues[j] === true &&
targetClusterTypeValues[k] === "sharded") {
// SERVER-6427
continue;
}
if (sourceClusterTypeValues[i] === "repl" &&
isSourceUsingAuthValues[j] === false &&
targetClusterTypeValues[k] === "sharded" &&
isTargetUsingAuthValues[l] === true) {
// SERVER-18103
continue;
}
for (var m = 0; m < isSourceUsingTransitionToAuthValues.length; m++) {
if (isSourceUsingTransitionToAuthValues[m] === true &&
isSourceUsingAuthValues[j] === false) {
// transitionToAuth requires auth parameters
continue;
}
for (var n = 0; n < isTargetUsingTransitionToAuthValues.length; n++) {
if (isTargetUsingTransitionToAuthValues[n] === true &&
isTargetUsingAuthValues[l] === false) {
// transitionToAuth requires auth parameters
continue;
}
var testCase = {
'sourceClusterType': sourceClusterTypeValues[i],
'isSourceUsingAuth': isSourceUsingAuthValues[j],
'targetClusterType': targetClusterTypeValues[k],
'isTargetUsingAuth': isTargetUsingAuthValues[l],
'isSourceUsingTransitionToAuth':
isSourceUsingTransitionToAuthValues[m],
'isTargetUsingTransitionToAuth':
isTargetUsingTransitionToAuthValues[n]
};
print("Running copydb with auth test:");
printjson(testCase);
copydbBetweenClustersTest(testCase);
}
}
}
}
}
}
}());
print(baseName + " success!");