summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer T Brody <spencer@10gen.com>2013-04-01 16:48:11 -0400
committerEric Milkie <milkie@10gen.com>2013-04-18 11:46:48 -0400
commite01102d1dfdfe64293bd7db38d798da87c48c01a (patch)
tree317d0202b01145b5650ea6cb64142e2d3ca01da4
parent036337a5c0757e7a06ea3fc3f98efd467b27b43e (diff)
downloadmongo-e01102d1dfdfe64293bd7db38d798da87c48c01a.tar.gz
SERVER-9093 Make copydb command work on mongos with auth
Conflicts: src/mongo/s/commands_public.cpp
-rw-r--r--jstests/sharding/auth_copydb.js40
-rw-r--r--src/mongo/db/cloner.cpp2
-rw-r--r--src/mongo/db/commands.h26
-rw-r--r--src/mongo/s/commands_public.cpp21
4 files changed, 53 insertions, 36 deletions
diff --git a/jstests/sharding/auth_copydb.js b/jstests/sharding/auth_copydb.js
new file mode 100644
index 00000000000..23be714127b
--- /dev/null
+++ b/jstests/sharding/auth_copydb.js
@@ -0,0 +1,40 @@
+// Tests the copydb command on mongos with auth
+
+
+var st = new ShardingTest({ shards : 1,
+ mongos : 1,
+ keyFile : "jstests/libs/key1"});
+var mongos = st.s0;
+var destAdminDB = mongos.getDB('admin');
+var destTestDB = mongos.getDB('test');
+
+var sourceMongodConn = MongoRunner.runMongod({});
+var sourceTestDB = sourceMongodConn.getDB('test');
+
+sourceTestDB.foo.insert({a:1});
+
+destAdminDB.addUser('admin', 'password'); // Turns on access control enforcement
+
+jsTestLog("Running copydb that should fail");
+var res = destAdminDB.runCommand({copydb:1,
+ fromhost: sourceMongodConn.host,
+ fromdb:'test',
+ todb:'test'});
+printjson(res);
+assert.commandFailed(res);
+
+destAdminDB.auth('admin', 'password');
+assert.eq(0, destTestDB.foo.count()); // Be extra sure the copydb didn't secretly succeed.
+
+jsTestLog("Running copydb that should succeed");
+res = destAdminDB.runCommand({copydb:1,
+ fromhost: sourceMongodConn.host,
+ fromdb:'test',
+ todb:'test'});
+printjson(res);
+assert.commandWorked(res);
+
+assert.eq(1, destTestDB.foo.count());
+assert.eq(1, destTestDB.foo.findOne().a);
+
+st.stop();
diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp
index 233410b4590..d9600912715 100644
--- a/src/mongo/db/cloner.cpp
+++ b/src/mongo/db/cloner.cpp
@@ -762,7 +762,7 @@ namespace mongo {
// source DB.
ActionSet actions;
actions.addAction(ActionType::copyDBTarget);
- out->push_back(Privilege(dbname, actions));
+ out->push_back(Privilege(dbname, actions)); // NOTE: dbname is always admin
}
virtual void help( stringstream &help ) const {
help << "copy a database from another host to this host\n";
diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h
index 3ae7c1d6200..b041a726412 100644
--- a/src/mongo/db/commands.h
+++ b/src/mongo/db/commands.h
@@ -187,32 +187,6 @@ namespace mongo {
static int testCommandsEnabled;
};
- // This will be registered instead of the real implementations of any commands that don't work
- // when auth is enabled.
- class NotWithAuthCmd : public Command {
- public:
- NotWithAuthCmd(const char* cmdName) : Command(cmdName) { }
- virtual bool slaveOk() const { return true; }
- virtual LockType locktype() const { return NONE; }
- virtual bool requiresAuth() { return false; }
- virtual void addRequiredPrivileges(const std::string& dbname,
- const BSONObj& cmdObj,
- std::vector<Privilege>* out) {}
- virtual void help( stringstream &help ) const {
- help << name << " is not supported when running with authentication enabled";
- }
- virtual bool run(const string&,
- BSONObj& cmdObj,
- int,
- string& errmsg,
- BSONObjBuilder& result,
- bool fromRepl) {
- errmsg = name + " is not supported when running with authentication enabled";
- log() << errmsg << std::endl;
- return false;
- }
- };
-
class CmdShutdown : public Command {
public:
virtual bool requiresAuth() { return true; }
diff --git a/src/mongo/s/commands_public.cpp b/src/mongo/s/commands_public.cpp
index e408cca73db..1c2ff52364a 100644
--- a/src/mongo/s/commands_public.cpp
+++ b/src/mongo/s/commands_public.cpp
@@ -522,12 +522,18 @@ namespace mongo {
class CopyDBCmd : public PublicGridCommand {
public:
CopyDBCmd() : PublicGridCommand( "copydb" ) {}
+ virtual bool adminOnly() const {
+ return true;
+ }
virtual void addRequiredPrivileges(const std::string& dbname,
const BSONObj& cmdObj,
std::vector<Privilege>* out) {
- // Should never get here because this command shouldn't get registered when auth is
- // enabled
- verify(0);
+ // Note: privileges required are currently only granted to old-style users for
+ // backwards compatibility, since we can't properly handle auth checking for the
+ // read from the source DB.
+ ActionSet actions;
+ actions.addAction(ActionType::copyDBTarget);
+ out->push_back(Privilege(dbname, actions)); // NOTE: dbname is always admin
}
bool run(const string& dbName, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
string todb = cmdObj.getStringField("todb");
@@ -562,12 +568,9 @@ namespace mongo {
}
};
MONGO_INITIALIZER(RegisterCopyDBCommand)(InitializerContext* context) {
- if (noauth) {
- // Leaked intentionally: a Command registers itself when constructed.
- new CopyDBCmd();
- } else {
- new NotWithAuthCmd("copydb");
- }
+ // Leaked intentionally: a Command registers itself when constructed.
+ // NOTE: this initializer block cannot be removed due to SERVER-9167
+ new CopyDBCmd();
return Status::OK();
}