diff options
author | Amalia Hawkins <amalia.hawkins@10gen.com> | 2015-04-24 11:54:40 -0400 |
---|---|---|
committer | Amalia Hawkins <amalia.hawkins@10gen.com> | 2015-04-28 10:49:21 -0400 |
commit | 913050a185855aaccd725d95f04eaf6dd414525f (patch) | |
tree | 78344a44120f0126d35c53a90582321715a3e764 | |
parent | b2cbcdce48096da0ba4e7edf58fe8023871b3fcb (diff) | |
download | mongo-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.js | 31 | ||||
-rw-r--r-- | src/mongo/db/auth/SConscript | 6 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_session.cpp | 12 | ||||
-rw-r--r-- | src/mongo/db/auth/authz_session_external_state.h | 5 | ||||
-rw-r--r-- | src/mongo/db/auth/authz_session_external_state_d.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/auth/authz_session_external_state_d.h | 2 | ||||
-rw-r--r-- | src/mongo/db/auth/authz_session_external_state_mock.h | 7 | ||||
-rw-r--r-- | src/mongo/db/auth/authz_session_external_state_server_common.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/auth/authz_session_external_state_server_common.h | 1 |
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); |