summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmalia Hawkins <amalia.hawkins@10gen.com>2015-04-24 11:54:40 -0400
committerAmalia Hawkins <amalia.hawkins@10gen.com>2015-04-28 10:49:21 -0400
commit913050a185855aaccd725d95f04eaf6dd414525f (patch)
tree78344a44120f0126d35c53a90582321715a3e764
parentb2cbcdce48096da0ba4e7edf58fe8023871b3fcb (diff)
downloadmongo-913050a185855aaccd725d95f04eaf6dd414525f.tar.gz
SERVER-18140: Allow getParameter to be executed locally against an arbiter in an authenticated replica set
(cherry-picked from commit e6cddcf94d2e2bdc30c7f36e77eb377085146adb)
-rw-r--r--jstests/auth/arbiter.js31
-rw-r--r--src/mongo/db/auth/SConscript6
-rw-r--r--src/mongo/db/auth/authorization_session.cpp12
-rw-r--r--src/mongo/db/auth/authz_session_external_state.h5
-rw-r--r--src/mongo/db/auth/authz_session_external_state_d.cpp8
-rw-r--r--src/mongo/db/auth/authz_session_external_state_d.h2
-rw-r--r--src/mongo/db/auth/authz_session_external_state_mock.h7
-rw-r--r--src/mongo/db/auth/authz_session_external_state_server_common.cpp4
-rw-r--r--src/mongo/db/auth/authz_session_external_state_server_common.h1
9 files changed, 72 insertions, 4 deletions
diff --git a/jstests/auth/arbiter.js b/jstests/auth/arbiter.js
new file mode 100644
index 00000000000..9e7f048e1df
--- /dev/null
+++ b/jstests/auth/arbiter.js
@@ -0,0 +1,31 @@
+// Certain commands should be run-able from arbiters under localhost, but not from
+// any other nodes in the replset.
+
+var name = "arbiter_localhost_test";
+var key = "jstests/libs/key1";
+var replTest = new ReplSetTest({ name: name, nodes: 3, keyFile: key });
+var nodes = replTest.nodeList();
+
+replTest.startSet();
+replTest.initiate({_id: name,
+ members: [
+ { "_id": 0, "host": nodes[0], priority: 3 },
+ { "_id": 1, "host": nodes[1] },
+ { "_id": 2, "host": nodes[2], arbiterOnly: true }
+ ],
+ });
+
+var primaryAdmin = replTest.nodes[0].getDB("admin");
+var arbiterAdmin = replTest.nodes[2].getDB("admin");
+
+var cmd0 = { getCmdLineOpts: 1 };
+var cmd1 = { getParameter: 1, logLevel: 1 };
+var cmd2 = { serverStatus: 1 };
+
+assert.commandFailedWithCode(primaryAdmin.runCommand(cmd0), 13);
+assert.commandFailedWithCode(primaryAdmin.runCommand(cmd1), 13);
+assert.commandFailedWithCode(primaryAdmin.runCommand(cmd2), 13);
+
+assert.commandWorked(arbiterAdmin.runCommand(cmd0));
+assert.commandWorked(arbiterAdmin.runCommand(cmd1));
+assert.commandWorked(arbiterAdmin.runCommand(cmd2));
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript
index 2f15a110423..faa5a5b6d88 100644
--- a/src/mongo/db/auth/SConscript
+++ b/src/mongo/db/auth/SConscript
@@ -62,7 +62,11 @@ env.Library('authmongod',
['authz_manager_external_state_d.cpp',
'authz_session_external_state_d.cpp',
'auth_index_d.cpp'],
- LIBDEPS=['authservercommon', '$BUILD_DIR/mongo/server_parameters'])
+ LIBDEPS=[
+ 'authservercommon',
+ '$BUILD_DIR/mongo/db/repl/repl_coordinator_global',
+ '$BUILD_DIR/mongo/server_parameters',
+ ])
env.Library('authmongos',
['authz_manager_external_state_s.cpp',
diff --git a/src/mongo/db/auth/authorization_session.cpp b/src/mongo/db/auth/authorization_session.cpp
index 9c18ebe2079..ae357bbe373 100644
--- a/src/mongo/db/auth/authorization_session.cpp
+++ b/src/mongo/db/auth/authorization_session.cpp
@@ -158,11 +158,19 @@ namespace {
Privilege(externalDBResource, ActionType::createUser);
ActionSet setupServerConfigActionSet;
+
+ // If this server is an arbiter, add specific privileges meant to circumvent
+ // the behavior of an arbiter in an authenticated replset. See SERVER-5479.
+ if (_externalState->serverIsArbiter()) {
+ setupServerConfigActionSet.addAction(ActionType::getCmdLineOpts);
+ setupServerConfigActionSet.addAction(ActionType::getParameter);
+ setupServerConfigActionSet.addAction(ActionType::serverStatus);
+ setupServerConfigActionSet.addAction(ActionType::shutdown);
+ }
+
setupServerConfigActionSet.addAction(ActionType::addShard);
- setupServerConfigActionSet.addAction(ActionType::getCmdLineOpts);
setupServerConfigActionSet.addAction(ActionType::replSetConfigure);
setupServerConfigActionSet.addAction(ActionType::replSetGetStatus);
- setupServerConfigActionSet.addAction(ActionType::serverStatus);
Privilege setupServerConfigPrivilege =
Privilege(ResourcePattern::forClusterResource(), setupServerConfigActionSet);
diff --git a/src/mongo/db/auth/authz_session_external_state.h b/src/mongo/db/auth/authz_session_external_state.h
index 2e1b41a0565..a0b90b15fef 100644
--- a/src/mongo/db/auth/authz_session_external_state.h
+++ b/src/mongo/db/auth/authz_session_external_state.h
@@ -67,6 +67,11 @@ namespace mongo {
// shouldAllowLocalhost or we could ignore auth checks incorrectly.
virtual bool shouldAllowLocalhost() const = 0;
+ // Returns true if this connection should allow extra server configuration actions under
+ // the localhost exception. This condition is used to allow special privileges on arbiters.
+ // See SERVER-5479 for details on when this may be removed.
+ virtual bool serverIsArbiter() const = 0;
+
// Should be called at the beginning of every new request. This performs the checks
// necessary to determine if localhost connections should be given full access.
virtual void startRequest(OperationContext* txn) = 0;
diff --git a/src/mongo/db/auth/authz_session_external_state_d.cpp b/src/mongo/db/auth/authz_session_external_state_d.cpp
index dc78555b707..65f30b5ce75 100644
--- a/src/mongo/db/auth/authz_session_external_state_d.cpp
+++ b/src/mongo/db/auth/authz_session_external_state_d.cpp
@@ -36,6 +36,7 @@
#include "mongo/db/instance.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/operation_context.h"
+#include "mongo/db/repl/replication_coordinator_global.h"
#include "mongo/scripting/engine.h"
#include "mongo/util/assert_util.h"
@@ -60,4 +61,11 @@ namespace mongo {
AuthzSessionExternalStateServerCommon::shouldIgnoreAuthChecks();
}
+ bool AuthzSessionExternalStateMongod::serverIsArbiter() const {
+ // Arbiters have access to extra privileges under localhost. See SERVER-5479.
+ return (repl::getGlobalReplicationCoordinator()->getReplicationMode() ==
+ repl::ReplicationCoordinator::modeReplSet &&
+ repl::getGlobalReplicationCoordinator()->getMemberState().arbiter());
+ }
+
} // namespace mongo
diff --git a/src/mongo/db/auth/authz_session_external_state_d.h b/src/mongo/db/auth/authz_session_external_state_d.h
index 0df26d507c7..8af5cc41e61 100644
--- a/src/mongo/db/auth/authz_session_external_state_d.h
+++ b/src/mongo/db/auth/authz_session_external_state_d.h
@@ -47,6 +47,8 @@ namespace mongo {
virtual bool shouldIgnoreAuthChecks() const;
+ virtual bool serverIsArbiter() const;
+
virtual void startRequest(OperationContext* txn);
};
diff --git a/src/mongo/db/auth/authz_session_external_state_mock.h b/src/mongo/db/auth/authz_session_external_state_mock.h
index 0acc98366ea..6e26c1bbceb 100644
--- a/src/mongo/db/auth/authz_session_external_state_mock.h
+++ b/src/mongo/db/auth/authz_session_external_state_mock.h
@@ -44,7 +44,7 @@ namespace mongo {
public:
AuthzSessionExternalStateMock(AuthorizationManager* authzManager) :
AuthzSessionExternalState(authzManager), _ignoreAuthChecksReturnValue(false),
- _allowLocalhostReturnValue(false) {}
+ _allowLocalhostReturnValue(false), _serverIsArbiterReturnValue(false) {}
virtual bool shouldIgnoreAuthChecks() const {
return _ignoreAuthChecksReturnValue;
@@ -54,6 +54,10 @@ namespace mongo {
return _allowLocalhostReturnValue;
}
+ virtual bool serverIsArbiter() const {
+ return _serverIsArbiterReturnValue;
+ }
+
void setReturnValueForShouldIgnoreAuthChecks(bool returnValue) {
_ignoreAuthChecksReturnValue = returnValue;
}
@@ -67,6 +71,7 @@ namespace mongo {
private:
bool _ignoreAuthChecksReturnValue;
bool _allowLocalhostReturnValue;
+ bool _serverIsArbiterReturnValue;
};
} // namespace mongo
diff --git a/src/mongo/db/auth/authz_session_external_state_server_common.cpp b/src/mongo/db/auth/authz_session_external_state_server_common.cpp
index 4ffc69d59e7..453980e19f7 100644
--- a/src/mongo/db/auth/authz_session_external_state_server_common.cpp
+++ b/src/mongo/db/auth/authz_session_external_state_server_common.cpp
@@ -75,6 +75,10 @@ namespace {
}
}
+ bool AuthzSessionExternalStateServerCommon::serverIsArbiter() const {
+ return false;
+ }
+
bool AuthzSessionExternalStateServerCommon::shouldAllowLocalhost() const {
ClientBasic* client = ClientBasic::getCurrent();
return _allowLocalhost && client->getIsLocalHostConnection();
diff --git a/src/mongo/db/auth/authz_session_external_state_server_common.h b/src/mongo/db/auth/authz_session_external_state_server_common.h
index 59599a6befd..f96035dcade 100644
--- a/src/mongo/db/auth/authz_session_external_state_server_common.h
+++ b/src/mongo/db/auth/authz_session_external_state_server_common.h
@@ -46,6 +46,7 @@ namespace mongo {
virtual bool shouldAllowLocalhost() const;
virtual bool shouldIgnoreAuthChecks() const;
+ virtual bool serverIsArbiter() const;
protected:
AuthzSessionExternalStateServerCommon(AuthorizationManager* authzManager);