diff options
-rw-r--r-- | src/mongo/db/auth/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/auth/action_set.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/auth/action_set.h | 5 | ||||
-rw-r--r-- | src/mongo/db/auth/action_set_test.cpp | 101 | ||||
-rw-r--r-- | src/mongo/db/auth/action_type_test.cpp | 59 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_manager.cpp | 123 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_manager.h | 7 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_manager_test.cpp | 57 | ||||
-rw-r--r-- | src/mongo/db/auth/capability_set_test.cpp | 68 | ||||
-rwxr-xr-x | src/mongo/db/auth/generate_action_types.py | 91 |
10 files changed, 331 insertions, 189 deletions
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript index 510ffb2563f..ce47be521ab 100644 --- a/src/mongo/db/auth/SConscript +++ b/src/mongo/db/auth/SConscript @@ -20,7 +20,6 @@ env.StaticLibrary('authcore', ['action_set.cpp', env.StaticLibrary('auth', ['external_state.cpp'], LIBDEPS=['authcore']) env.CppUnitTest('action_set_test', 'action_set_test.cpp', LIBDEPS=['authcore']) -env.CppUnitTest('action_type_test', 'action_type_test.cpp', LIBDEPS=['authcore']) env.CppUnitTest('capability_set_test', 'capability_set_test.cpp', LIBDEPS=['authcore']) env.CppUnitTest('principal_set_test', 'principal_set_test.cpp', LIBDEPS=['authcore']) env.CppUnitTest('authorization_manager_test', 'authorization_manager_test.cpp', diff --git a/src/mongo/db/auth/action_set.cpp b/src/mongo/db/auth/action_set.cpp index 7c37cb258d5..e8580190cf6 100644 --- a/src/mongo/db/auth/action_set.cpp +++ b/src/mongo/db/auth/action_set.cpp @@ -32,6 +32,14 @@ namespace mongo { _actions.set(action.getIdentifier(), true); } + void ActionSet::addAllActionsFromSet(const ActionSet& actions) { + _actions |= actions._actions; + } + + void ActionSet::addAllActions() { + _actions = ~std::bitset<ActionType::NUM_ACTION_TYPES>(); + } + bool ActionSet::contains(const ActionType& action) const { return _actions[action.getIdentifier()]; } diff --git a/src/mongo/db/auth/action_set.h b/src/mongo/db/auth/action_set.h index f73a8161e68..ba43583d75e 100644 --- a/src/mongo/db/auth/action_set.h +++ b/src/mongo/db/auth/action_set.h @@ -33,6 +33,8 @@ namespace mongo { ActionSet() : _actions(0) {} void addAction(const ActionType& action); + void addAllActionsFromSet(const ActionSet& actionSet); + void addAllActions(); bool contains(const ActionType& action) const; @@ -49,7 +51,8 @@ namespace mongo { private: - std::bitset<128> _actions; // bitmask of actions this capability grants + // bitmask of actions this capability grants + std::bitset<ActionType::NUM_ACTION_TYPES> _actions; }; } // namespace mongo diff --git a/src/mongo/db/auth/action_set_test.cpp b/src/mongo/db/auth/action_set_test.cpp index cfb4387ae60..ba3b65af2a4 100644 --- a/src/mongo/db/auth/action_set_test.cpp +++ b/src/mongo/db/auth/action_set_test.cpp @@ -28,40 +28,32 @@ namespace { TEST(ActionSetTest, ParseActionSetFromString) { ActionSet result; - ASSERT_OK(ActionSet::parseActionSetFromString("r,w,u,d,s,c", &result)); - ASSERT_TRUE(result.contains(ActionType::READ)); - ASSERT_TRUE(result.contains(ActionType::READ_WRITE)); - ASSERT_TRUE(result.contains(ActionType::USER_ADMIN)); - ASSERT_TRUE(result.contains(ActionType::DB_ADMIN)); - ASSERT_TRUE(result.contains(ActionType::SERVER_ADMIN)); - ASSERT_TRUE(result.contains(ActionType::CLUSTER_ADMIN)); - - // Order of the letters doesn't matter - ASSERT_OK(ActionSet::parseActionSetFromString("c,u,s,w,d,r", &result)); - ASSERT_TRUE(result.contains(ActionType::READ)); - ASSERT_TRUE(result.contains(ActionType::READ_WRITE)); - ASSERT_TRUE(result.contains(ActionType::USER_ADMIN)); - ASSERT_TRUE(result.contains(ActionType::DB_ADMIN)); - ASSERT_TRUE(result.contains(ActionType::SERVER_ADMIN)); - ASSERT_TRUE(result.contains(ActionType::CLUSTER_ADMIN)); - - ASSERT_OK(ActionSet::parseActionSetFromString("r", &result)); - - ASSERT_TRUE(result.contains(ActionType::READ)); - ASSERT_FALSE(result.contains(ActionType::READ_WRITE)); - ASSERT_FALSE(result.contains(ActionType::USER_ADMIN)); - ASSERT_FALSE(result.contains(ActionType::DB_ADMIN)); - ASSERT_FALSE(result.contains(ActionType::SERVER_ADMIN)); - ASSERT_FALSE(result.contains(ActionType::CLUSTER_ADMIN)); + ASSERT_OK(ActionSet::parseActionSetFromString("find,insert,update,delete", &result)); + ASSERT_TRUE(result.contains(ActionType::FIND)); + ASSERT_TRUE(result.contains(ActionType::INSERT)); + ASSERT_TRUE(result.contains(ActionType::UPDATE)); + ASSERT_TRUE(result.contains(ActionType::DELETE)); + + // Order of the strings doesn't matter + ASSERT_OK(ActionSet::parseActionSetFromString("update,find,delete,insert", &result)); + ASSERT_TRUE(result.contains(ActionType::FIND)); + ASSERT_TRUE(result.contains(ActionType::INSERT)); + ASSERT_TRUE(result.contains(ActionType::UPDATE)); + ASSERT_TRUE(result.contains(ActionType::DELETE)); + + ASSERT_OK(ActionSet::parseActionSetFromString("find", &result)); + + ASSERT_TRUE(result.contains(ActionType::FIND)); + ASSERT_FALSE(result.contains(ActionType::INSERT)); + ASSERT_FALSE(result.contains(ActionType::UPDATE)); + ASSERT_FALSE(result.contains(ActionType::DELETE)); ASSERT_OK(ActionSet::parseActionSetFromString("", &result)); - ASSERT_FALSE(result.contains(ActionType::READ)); - ASSERT_FALSE(result.contains(ActionType::READ_WRITE)); - ASSERT_FALSE(result.contains(ActionType::USER_ADMIN)); - ASSERT_FALSE(result.contains(ActionType::DB_ADMIN)); - ASSERT_FALSE(result.contains(ActionType::SERVER_ADMIN)); - ASSERT_FALSE(result.contains(ActionType::CLUSTER_ADMIN)); + ASSERT_FALSE(result.contains(ActionType::FIND)); + ASSERT_FALSE(result.contains(ActionType::INSERT)); + ASSERT_FALSE(result.contains(ActionType::UPDATE)); + ASSERT_FALSE(result.contains(ActionType::DELETE)); ASSERT_EQUALS(ErrorCodes::FailedToParse, ActionSet::parseActionSetFromString("INVALID INPUT", &result).code()); @@ -71,40 +63,33 @@ namespace { ActionSet actionSet; ASSERT_EQUALS("", actionSet.toString()); - actionSet.addAction(ActionType::READ); - ASSERT_EQUALS("r", actionSet.toString()); - actionSet.addAction(ActionType::READ_WRITE); - ASSERT_EQUALS("r,w", actionSet.toString()); - actionSet.addAction(ActionType::USER_ADMIN); - ASSERT_EQUALS("r,w,u", actionSet.toString()); - actionSet.addAction(ActionType::DB_ADMIN); - ASSERT_EQUALS("r,w,u,d", actionSet.toString()); - actionSet.addAction(ActionType::SERVER_ADMIN); - ASSERT_EQUALS("r,w,u,d,s", actionSet.toString()); - actionSet.addAction(ActionType::CLUSTER_ADMIN); - ASSERT_EQUALS("r,w,u,d,s,c", actionSet.toString()); + actionSet.addAction(ActionType::FIND); + ASSERT_EQUALS("find", actionSet.toString()); + actionSet.addAction(ActionType::INSERT); + ASSERT_EQUALS("find,insert", actionSet.toString()); + actionSet.addAction(ActionType::UPDATE); + ASSERT_EQUALS("find,insert,update", actionSet.toString()); + actionSet.addAction(ActionType::DELETE); + ASSERT_EQUALS("delete,find,insert,update", actionSet.toString()); // Now make sure adding actions in a different order doesn't change anything. ActionSet actionSet2; - actionSet2.addAction(ActionType::DB_ADMIN); - ASSERT_EQUALS("d", actionSet2.toString()); - actionSet2.addAction(ActionType::READ); - ASSERT_EQUALS("r,d", actionSet2.toString()); - actionSet2.addAction(ActionType::CLUSTER_ADMIN); - ASSERT_EQUALS("r,d,c", actionSet2.toString()); - actionSet2.addAction(ActionType::USER_ADMIN); - ASSERT_EQUALS("r,u,d,c", actionSet2.toString()); - actionSet2.addAction(ActionType::SERVER_ADMIN); - ASSERT_EQUALS("r,u,d,s,c", actionSet2.toString()); - actionSet2.addAction(ActionType::READ_WRITE); - ASSERT_EQUALS("r,w,u,d,s,c", actionSet2.toString()); + ASSERT_EQUALS("", actionSet2.toString()); + actionSet2.addAction(ActionType::INSERT); + ASSERT_EQUALS("insert", actionSet2.toString()); + actionSet2.addAction(ActionType::DELETE); + ASSERT_EQUALS("delete,insert", actionSet2.toString()); + actionSet2.addAction(ActionType::FIND); + ASSERT_EQUALS("delete,find,insert", actionSet2.toString()); + actionSet2.addAction(ActionType::UPDATE); + ASSERT_EQUALS("delete,find,insert,update", actionSet2.toString()); } TEST(ActionSetTest, IsSupersetOf) { ActionSet set1, set2, set3; - ASSERT_OK(ActionSet::parseActionSetFromString("r,w,u", &set1)); - ASSERT_OK(ActionSet::parseActionSetFromString("r,w,d", &set2)); - ASSERT_OK(ActionSet::parseActionSetFromString("r,w", &set3)); + ASSERT_OK(ActionSet::parseActionSetFromString("find,update,insert", &set1)); + ASSERT_OK(ActionSet::parseActionSetFromString("find,update,delete", &set2)); + ASSERT_OK(ActionSet::parseActionSetFromString("find,update", &set3)); ASSERT_FALSE(set1.isSupersetOf(set2)); ASSERT_TRUE(set1.isSupersetOf(set3)); diff --git a/src/mongo/db/auth/action_type_test.cpp b/src/mongo/db/auth/action_type_test.cpp deleted file mode 100644 index 3d5c24086f3..00000000000 --- a/src/mongo/db/auth/action_type_test.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright 2012 10gen Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Unit tests of the ActionType type. - */ - -#include "mongo/db/auth/action_type.h" -#include "mongo/unittest/unittest.h" - -#define ASSERT_OK(EXPR) ASSERT_EQUALS(Status::OK(), (EXPR)) - -namespace mongo { -namespace { - - TEST(ActionTypeTest, ParseActionFromString) { - ActionType result; - ASSERT_OK(ActionType::parseActionFromString("r", &result)); - ASSERT_EQUALS(ActionType::READ.getIdentifier(), result.getIdentifier()); - ASSERT_OK(ActionType::parseActionFromString("w", &result)); - ASSERT_EQUALS(ActionType::READ_WRITE, result); - ASSERT_OK(ActionType::parseActionFromString("u", &result)); - ASSERT_EQUALS(ActionType::USER_ADMIN, result); - ASSERT_OK(ActionType::parseActionFromString("d", &result)); - ASSERT_EQUALS(ActionType::DB_ADMIN, result); - ASSERT_OK(ActionType::parseActionFromString("s", &result)); - ASSERT_EQUALS(ActionType::SERVER_ADMIN, result); - ASSERT_OK(ActionType::parseActionFromString("c", &result)); - ASSERT_EQUALS(ActionType::CLUSTER_ADMIN, result); - - ASSERT_EQUALS(ErrorCodes::FailedToParse, - ActionType::parseActionFromString("INVALID INPUT", &result).code()); - ASSERT_EQUALS(ErrorCodes::FailedToParse, - ActionType::parseActionFromString("", &result).code()); - } - - TEST(ActionTypeTest, ActionToString) { - ASSERT_EQUALS("r", ActionType::actionToString(ActionType::READ)); - ASSERT_EQUALS("w", ActionType::actionToString(ActionType::READ_WRITE)); - ASSERT_EQUALS("u", ActionType::actionToString(ActionType::USER_ADMIN)); - ASSERT_EQUALS("d", ActionType::actionToString(ActionType::DB_ADMIN)); - ASSERT_EQUALS("s", ActionType::actionToString(ActionType::SERVER_ADMIN)); - ASSERT_EQUALS("c", ActionType::actionToString(ActionType::CLUSTER_ADMIN)); - } - -} // namespace -} // namespace mongo diff --git a/src/mongo/db/auth/authorization_manager.cpp b/src/mongo/db/auth/authorization_manager.cpp index afafe95e8c4..8930cfaa032 100644 --- a/src/mongo/db/auth/authorization_manager.cpp +++ b/src/mongo/db/auth/authorization_manager.cpp @@ -18,6 +18,7 @@ #include <string> +#include "mongo/base/init.h" #include "mongo/base/status.h" #include "mongo/client/dbclientinterface.h" #include "mongo/db/auth/action_set.h" @@ -36,6 +37,106 @@ namespace mongo { Principal specialAdminPrincipal("special"); } + // ActionSets for the various system roles. These ActionSets contain all the actions that + // a user of each system role is granted. + ActionSet readRoleActions; + ActionSet readWriteRoleActions; + ActionSet userAdminRoleActions; + ActionSet dbAdminRoleActions; + ActionSet serverAdminRoleActions; + ActionSet clusterAdminRoleActions; + + // This sets up the system role ActionSets. This is what determines what actions each role + // is authorized to perform + MONGO_INITIALIZER(AuthorizationSystemRoles)(InitializerContext* context) { + // Read role + // TODO: Remove OLD_READ once commands require the proper actions + readRoleActions.addAction(ActionType::OLD_READ); + readRoleActions.addAction(ActionType::COLL_STATS); + readRoleActions.addAction(ActionType::DB_STATS); + readRoleActions.addAction(ActionType::FIND); + + // Read-write role + readWriteRoleActions.addAllActionsFromSet(readRoleActions); + // TODO: Remove OLD_WRITE once commands require the proper actions + readWriteRoleActions.addAction(ActionType::OLD_WRITE); + readWriteRoleActions.addAction(ActionType::CONVERT_TO_CAPPED); + readWriteRoleActions.addAction(ActionType::CREATE_COLLECTION); // TODO: should db admin get this also? + readWriteRoleActions.addAction(ActionType::DELETE); + readWriteRoleActions.addAction(ActionType::DROP_COLLECTION); + readWriteRoleActions.addAction(ActionType::DROP_INDEXES); + readWriteRoleActions.addAction(ActionType::EMPTYCAPPED); + readWriteRoleActions.addAction(ActionType::ENSURE_INDEX); + readWriteRoleActions.addAction(ActionType::INSERT); + readWriteRoleActions.addAction(ActionType::UPDATE); + + // User admin role + userAdminRoleActions.addAction(ActionType::USER_ADMIN); + + // DB admin role + dbAdminRoleActions.addAction(ActionType::CLEAN); + dbAdminRoleActions.addAction(ActionType::COLL_MOD); + dbAdminRoleActions.addAction(ActionType::COLL_STATS); + dbAdminRoleActions.addAction(ActionType::COMPACT); + dbAdminRoleActions.addAction(ActionType::CONVERT_TO_CAPPED); + dbAdminRoleActions.addAction(ActionType::DB_STATS); + dbAdminRoleActions.addAction(ActionType::DROP_COLLECTION); + dbAdminRoleActions.addAction(ActionType::RE_INDEX); // TODO: Should readWrite have this also? This isn't consistent with ENSURE_INDEX and DROP_INDEXES + dbAdminRoleActions.addAction(ActionType::RENAME_COLLECTION); + dbAdminRoleActions.addAction(ActionType::VALIDATE); + + // Server admin role + serverAdminRoleActions.addAction(ActionType::CLOSE_ALL_DATABASES); + serverAdminRoleActions.addAction(ActionType::CONN_POOL_STATS); + serverAdminRoleActions.addAction(ActionType::CONN_POOL_SYNC); + serverAdminRoleActions.addAction(ActionType::CPU_PROFILER); + serverAdminRoleActions.addAction(ActionType::CURSOR_INFO); + serverAdminRoleActions.addAction(ActionType::DIAG_LOGGING); + serverAdminRoleActions.addAction(ActionType::FSYNC); + serverAdminRoleActions.addAction(ActionType::GET_CMD_LINE_OPTS); + serverAdminRoleActions.addAction(ActionType::GET_LOG); + serverAdminRoleActions.addAction(ActionType::GET_PARAMETER); + serverAdminRoleActions.addAction(ActionType::GET_SHARD_MAP); + serverAdminRoleActions.addAction(ActionType::GET_SHARD_VERSION); + serverAdminRoleActions.addAction(ActionType::HOST_INFO); + serverAdminRoleActions.addAction(ActionType::LIST_DATABASES); + serverAdminRoleActions.addAction(ActionType::LOG_ROTATE); + serverAdminRoleActions.addAction(ActionType::PROFILE); + serverAdminRoleActions.addAction(ActionType::REPAIR_DATABASE); + serverAdminRoleActions.addAction(ActionType::REPL_SET_FREEZE); + serverAdminRoleActions.addAction(ActionType::REPL_SET_GET_STATUS); + serverAdminRoleActions.addAction(ActionType::REPL_SET_INITIATE); + serverAdminRoleActions.addAction(ActionType::REPL_SET_MAINTENANCE); + serverAdminRoleActions.addAction(ActionType::REPL_SET_RECONFIG); + serverAdminRoleActions.addAction(ActionType::REPL_SET_STEP_DOWN); + serverAdminRoleActions.addAction(ActionType::REPL_SET_SYNC_FROM); + serverAdminRoleActions.addAction(ActionType::RESYNC); + serverAdminRoleActions.addAction(ActionType::SET_PARAMETER); + serverAdminRoleActions.addAction(ActionType::SHUTDOWN); + serverAdminRoleActions.addAction(ActionType::TOP); + serverAdminRoleActions.addAction(ActionType::TOUCH); + + // Cluster admin role + clusterAdminRoleActions.addAction(ActionType::ADD_SHARD); + clusterAdminRoleActions.addAction(ActionType::DROP_DATABASE); // TODO: Should there be a CREATE_DATABASE also? + clusterAdminRoleActions.addAction(ActionType::ENABLE_SHARDING); + clusterAdminRoleActions.addAction(ActionType::FLUSH_ROUTER_CONFIG); + clusterAdminRoleActions.addAction(ActionType::LIST_SHARDS); + clusterAdminRoleActions.addAction(ActionType::MOVE_CHUNK); + clusterAdminRoleActions.addAction(ActionType::MOVE_PRIMARY); + clusterAdminRoleActions.addAction(ActionType::NETSTAT); + clusterAdminRoleActions.addAction(ActionType::REMOVE_SHARD); + clusterAdminRoleActions.addAction(ActionType::SET_SHARD_VERSION); // TODO: should this be internal? + clusterAdminRoleActions.addAction(ActionType::SHARD_COLLECTION); + clusterAdminRoleActions.addAction(ActionType::SHARDING_STATE); + clusterAdminRoleActions.addAction(ActionType::SPLIT); + clusterAdminRoleActions.addAction(ActionType::SPLIT_CHUNK); + clusterAdminRoleActions.addAction(ActionType::SPLIT_VECTOR); + clusterAdminRoleActions.addAction(ActionType::UNSET_SHARDING); + + return Status::OK(); + } + AuthorizationManager::AuthorizationManager(ExternalState* externalState) { _externalState.reset(externalState); } @@ -65,6 +166,16 @@ namespace mongo { return Status::OK(); } + void AuthorizationManager::grantInternalAuthorization() { + Principal* internalPrincipal = new Principal("__system"); + _authenticatedPrincipals.add(internalPrincipal); + ActionSet allActions; + allActions.addAllActions(); + Capability capability("*", internalPrincipal, allActions); + Status status = acquireCapability(capability); + verify (status == Status::OK()); + } + Status AuthorizationManager::getPrivilegeDocument(DBClientBase* conn, const std::string& dbname, const std::string& userName, @@ -129,13 +240,13 @@ namespace mongo { bool readOnly = false; ActionSet actions; if (privilegeDocument.hasField("readOnly") && privilegeDocument["readOnly"].trueValue()) { - actions.addAction(ActionType::READ); + actions.addAllActionsFromSet(readRoleActions); readOnly = true; } else { - actions.addAction(ActionType::READ_WRITE); // TODO: should this also add READ? - actions.addAction(ActionType::DB_ADMIN); - actions.addAction(ActionType::USER_ADMIN); + actions.addAllActionsFromSet(readWriteRoleActions); + actions.addAllActionsFromSet(dbAdminRoleActions); + actions.addAllActionsFromSet(userAdminRoleActions); } if (dbname == "admin" || dbname == "local") { @@ -143,8 +254,8 @@ namespace mongo { result->grantCapability(Capability("*", principal, actions)); // Make server and cluster admin actions available on admin database. if (!readOnly) { - actions.addAction(ActionType::SERVER_ADMIN); - actions.addAction(ActionType::CLUSTER_ADMIN); + actions.addAllActionsFromSet(serverAdminRoleActions); + actions.addAllActionsFromSet(clusterAdminRoleActions); } } diff --git a/src/mongo/db/auth/authorization_manager.h b/src/mongo/db/auth/authorization_manager.h index 9ee38ace641..2f3a7528f78 100644 --- a/src/mongo/db/auth/authorization_manager.h +++ b/src/mongo/db/auth/authorization_manager.h @@ -55,6 +55,11 @@ namespace mongo { // Grant this connection the given capability. Status acquireCapability(const Capability& capability); + // This should be called when the connection gets authenticated as the internal user. + // This grants a capability on all the actions for the internal role, with the + // internalPrincipal as the principal. + void grantInternalAuthorization(); + // Checks if this connection has the capabilities required to perform the given action // on the given resource. Contains all the authorization logic including handling things // like the localhost exception. If it is authorized, returns the principal that granted @@ -95,8 +100,6 @@ namespace mongo { CapabilitySet _aquiredCapabilities; // All principals who have been authenticated on this connection PrincipalSet _authenticatedPrincipals; - - // TODO: handle temporary authorization from $auth table for commands }; } // namespace mongo diff --git a/src/mongo/db/auth/authorization_manager_test.cpp b/src/mongo/db/auth/authorization_manager_test.cpp index 38c1b321056..886b72917b7 100644 --- a/src/mongo/db/auth/authorization_manager_test.cpp +++ b/src/mongo/db/auth/authorization_manager_test.cpp @@ -34,28 +34,41 @@ namespace { TEST(AuthorizationManagerTest, AcquireCapabilityAndCheckAuthorization) { Principal* principal = new Principal("Spencer"); ActionSet actions; - actions.addAction(ActionType::READ_WRITE); + actions.addAction(ActionType::INSERT); Capability writeCapability("test", principal, actions); Capability allDBsWriteCapability("*", principal, actions); ExternalStateMock* externalState = new ExternalStateMock(); AuthorizationManager authManager(externalState); - ASSERT_NULL(authManager.checkAuthorization("test", ActionType::READ_WRITE)); + ASSERT_NULL(authManager.checkAuthorization("test", ActionType::INSERT)); externalState->setReturnValueForShouldIgnoreAuthChecks(true); ASSERT_EQUALS("special", - authManager.checkAuthorization("test", ActionType::READ_WRITE)->getName()); + authManager.checkAuthorization("test", ActionType::INSERT)->getName()); externalState->setReturnValueForShouldIgnoreAuthChecks(false); - ASSERT_NULL(authManager.checkAuthorization("test", ActionType::READ_WRITE)); + ASSERT_NULL(authManager.checkAuthorization("test", ActionType::INSERT)); ASSERT_EQUALS(ErrorCodes::UserNotFound, authManager.acquireCapability(writeCapability).code()); authManager.addAuthorizedPrincipal(principal); ASSERT_OK(authManager.acquireCapability(writeCapability)); - ASSERT_EQUALS(principal, authManager.checkAuthorization("test", ActionType::READ_WRITE)); + ASSERT_EQUALS(principal, authManager.checkAuthorization("test", ActionType::INSERT)); - ASSERT_NULL(authManager.checkAuthorization("otherDb", ActionType::READ_WRITE)); + ASSERT_NULL(authManager.checkAuthorization("otherDb", ActionType::INSERT)); ASSERT_OK(authManager.acquireCapability(allDBsWriteCapability)); - ASSERT_EQUALS(principal, authManager.checkAuthorization("otherDb", ActionType::READ_WRITE)); + ASSERT_EQUALS(principal, authManager.checkAuthorization("otherDb", ActionType::INSERT)); + } + + TEST(AuthorizationManagerTest, GrantInternalAuthorization) { + ExternalStateMock* externalState = new ExternalStateMock(); + AuthorizationManager authManager(externalState); + + ASSERT_NULL(authManager.checkAuthorization("test", ActionType::INSERT)); + ASSERT_NULL(authManager.checkAuthorization("test", ActionType::REPL_SET_HEARTBEAT)); + + authManager.grantInternalAuthorization(); + + ASSERT_NON_NULL(authManager.checkAuthorization("test", ActionType::INSERT)); + ASSERT_NON_NULL(authManager.checkAuthorization("test", ActionType::REPL_SET_HEARTBEAT)); } TEST(AuthorizationManagerTest, GetCapabilitiesFromPrivilegeDocument) { @@ -76,37 +89,37 @@ namespace { principal, readOnly, &capabilitySet)); - ASSERT_NULL(capabilitySet.getCapabilityForAction("test", ActionType::READ_WRITE)); - ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("test", ActionType::READ)); + ASSERT_NULL(capabilitySet.getCapabilityForAction("test", ActionType::INSERT)); + ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("test", ActionType::FIND)); ASSERT_OK(AuthorizationManager::buildCapabilitySet("test", principal, readWrite, &capabilitySet)); - ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("test", ActionType::READ)); - ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("test", ActionType::READ_WRITE)); + ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("test", ActionType::FIND)); + ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("test", ActionType::INSERT)); ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("test", ActionType::USER_ADMIN)); - ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("test", ActionType::DB_ADMIN)); - ASSERT_NULL(capabilitySet.getCapabilityForAction("test", ActionType::SERVER_ADMIN)); - ASSERT_NULL(capabilitySet.getCapabilityForAction("test", ActionType::CLUSTER_ADMIN)); + ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("test", ActionType::COMPACT)); + ASSERT_NULL(capabilitySet.getCapabilityForAction("test", ActionType::SHUTDOWN)); + ASSERT_NULL(capabilitySet.getCapabilityForAction("test", ActionType::ADD_SHARD)); - ASSERT_NULL(capabilitySet.getCapabilityForAction("admin", ActionType::READ)); - ASSERT_NULL(capabilitySet.getCapabilityForAction("*", ActionType::READ)); + ASSERT_NULL(capabilitySet.getCapabilityForAction("admin", ActionType::FIND)); + ASSERT_NULL(capabilitySet.getCapabilityForAction("*", ActionType::FIND)); ASSERT_OK(AuthorizationManager::buildCapabilitySet("admin", principal, readOnly, &capabilitySet)); - ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("admin", ActionType::READ)); - ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("*", ActionType::READ)); + ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("admin", ActionType::FIND)); + ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("*", ActionType::FIND)); - ASSERT_NULL(capabilitySet.getCapabilityForAction("admin", ActionType::READ_WRITE)); - ASSERT_NULL(capabilitySet.getCapabilityForAction("*", ActionType::READ_WRITE)); + ASSERT_NULL(capabilitySet.getCapabilityForAction("admin", ActionType::INSERT)); + ASSERT_NULL(capabilitySet.getCapabilityForAction("*", ActionType::INSERT)); ASSERT_OK(AuthorizationManager::buildCapabilitySet("admin", principal, readWrite, &capabilitySet)); - ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("admin", ActionType::READ_WRITE)); - ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("*", ActionType::READ_WRITE)); + ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("admin", ActionType::INSERT)); + ASSERT_NON_NULL(capabilitySet.getCapabilityForAction("*", ActionType::INSERT)); } } // namespace diff --git a/src/mongo/db/auth/capability_set_test.cpp b/src/mongo/db/auth/capability_set_test.cpp index 84eeb572d2a..5293ed5579a 100644 --- a/src/mongo/db/auth/capability_set_test.cpp +++ b/src/mongo/db/auth/capability_set_test.cpp @@ -33,68 +33,68 @@ namespace { Principal user1("user1"); Principal user2("user2"); - ASSERT_OK(ActionSet::parseActionSetFromString("r,w,u,d", &actions)); - Capability fooAdmin("foo", &user1, actions); + ASSERT_OK(ActionSet::parseActionSetFromString("find,update", &actions)); + Capability fooUser("foo", &user2, actions); - ASSERT_OK(ActionSet::parseActionSetFromString("r,w", &actions)); - Capability barUser("bar", &user1, actions); + ASSERT_OK(ActionSet::parseActionSetFromString("find,update,userAdmin,delete", &actions)); + Capability fooUser2("foo", &user1, actions); - ASSERT_OK(ActionSet::parseActionSetFromString("r,w", &actions)); - Capability fooUser("foo", &user2, actions); + ASSERT_OK(ActionSet::parseActionSetFromString("find,update", &actions)); + Capability barUser("bar", &user1, actions); - ASSERT_OK(ActionSet::parseActionSetFromString("r", &actions)); + ASSERT_OK(ActionSet::parseActionSetFromString("find", &actions)); Capability barReadOnly("bar", &user2, actions); const Capability* capPtr; // No capabilities - ASSERT(!capSet.getCapabilityForAction("foo", ActionType::READ)); + ASSERT(!capSet.getCapabilityForAction("foo", ActionType::FIND)); capSet.grantCapability(fooUser); - capPtr = capSet.getCapabilityForAction("foo", ActionType::READ); - ASSERT_TRUE(capPtr->includesAction(ActionType::READ)); - ASSERT_FALSE(capPtr->includesAction(ActionType::DB_ADMIN)); + capPtr = capSet.getCapabilityForAction("foo", ActionType::FIND); + ASSERT_TRUE(capPtr->includesAction(ActionType::FIND)); + ASSERT_FALSE(capPtr->includesAction(ActionType::DELETE)); - ASSERT(!capSet.getCapabilityForAction("foo", ActionType::DB_ADMIN)); + ASSERT(!capSet.getCapabilityForAction("foo", ActionType::DELETE)); - capSet.grantCapability(fooAdmin); + capSet.grantCapability(fooUser2); capPtr = capSet.getCapabilityForAction("foo", ActionType::USER_ADMIN); - ASSERT_TRUE(capPtr->includesAction(ActionType::READ)); - ASSERT_TRUE(capPtr->includesAction(ActionType::DB_ADMIN)); + ASSERT_TRUE(capPtr->includesAction(ActionType::FIND)); + ASSERT_TRUE(capPtr->includesAction(ActionType::DELETE)); // No capabilities - ASSERT(!capSet.getCapabilityForAction("bar", ActionType::READ)); + ASSERT(!capSet.getCapabilityForAction("bar", ActionType::FIND)); capSet.grantCapability(barReadOnly); - capPtr = capSet.getCapabilityForAction("bar", ActionType::READ); - ASSERT_TRUE(capPtr->includesAction(ActionType::READ)); - ASSERT_FALSE(capPtr->includesAction(ActionType::READ_WRITE)); - ASSERT_FALSE(capPtr->includesAction(ActionType::DB_ADMIN)); + capPtr = capSet.getCapabilityForAction("bar", ActionType::FIND); + ASSERT_TRUE(capPtr->includesAction(ActionType::FIND)); + ASSERT_FALSE(capPtr->includesAction(ActionType::UPDATE)); + ASSERT_FALSE(capPtr->includesAction(ActionType::DELETE)); - ASSERT(!capSet.getCapabilityForAction("bar", ActionType::READ_WRITE)); + ASSERT(!capSet.getCapabilityForAction("bar", ActionType::UPDATE)); capSet.grantCapability(barUser); - capPtr = capSet.getCapabilityForAction("bar", ActionType::READ_WRITE); - ASSERT_TRUE(capPtr->includesAction(ActionType::READ)); - ASSERT_TRUE(capPtr->includesAction(ActionType::READ_WRITE)); - ASSERT_FALSE(capPtr->includesAction(ActionType::DB_ADMIN)); + capPtr = capSet.getCapabilityForAction("bar", ActionType::UPDATE); + ASSERT_TRUE(capPtr->includesAction(ActionType::FIND)); + ASSERT_TRUE(capPtr->includesAction(ActionType::UPDATE)); + ASSERT_FALSE(capPtr->includesAction(ActionType::DELETE)); // Now let's start revoking capabilities capSet.revokeCapabilitiesFromPrincipal(&user1); - capPtr = capSet.getCapabilityForAction("foo", ActionType::READ); - ASSERT_TRUE(capPtr->includesAction(ActionType::READ)); - ASSERT_FALSE(capPtr->includesAction(ActionType::DB_ADMIN)); + capPtr = capSet.getCapabilityForAction("foo", ActionType::FIND); + ASSERT_TRUE(capPtr->includesAction(ActionType::FIND)); + ASSERT_FALSE(capPtr->includesAction(ActionType::DELETE)); - capPtr = capSet.getCapabilityForAction("bar", ActionType::READ); - ASSERT_TRUE(capPtr->includesAction(ActionType::READ)); - ASSERT_FALSE(capPtr->includesAction(ActionType::READ_WRITE)); - ASSERT_FALSE(capPtr->includesAction(ActionType::DB_ADMIN)); + capPtr = capSet.getCapabilityForAction("bar", ActionType::FIND); + ASSERT_TRUE(capPtr->includesAction(ActionType::FIND)); + ASSERT_FALSE(capPtr->includesAction(ActionType::UPDATE)); + ASSERT_FALSE(capPtr->includesAction(ActionType::DELETE)); capSet.revokeCapabilitiesFromPrincipal(&user2); - ASSERT(!capSet.getCapabilityForAction("foo", ActionType::READ)); - ASSERT(!capSet.getCapabilityForAction("bar", ActionType::READ)); + ASSERT(!capSet.getCapabilityForAction("foo", ActionType::FIND)); + ASSERT(!capSet.getCapabilityForAction("bar", ActionType::FIND)); } } // namespace diff --git a/src/mongo/db/auth/generate_action_types.py b/src/mongo/db/auth/generate_action_types.py index a9eddb6c331..3487f14a34b 100755 --- a/src/mongo/db/auth/generate_action_types.py +++ b/src/mongo/db/auth/generate_action_types.py @@ -26,12 +26,89 @@ import sys # List of tuples describing the ActionTypes that should be created. # The first value in the tuple is the name of the enum, the second is the string # representation. -actionTypes = [("READ", "r"), - ("READ_WRITE", "w"), - ("USER_ADMIN", "u"), - ("DB_ADMIN", "d"), - ("SERVER_ADMIN", "s"), - ("CLUSTER_ADMIN", "c")] +actionTypes = [("ADD_SHARD", "addShard"), + ("APPLY_OPS", "applyOps"), + ("CAPTRUNC", "captrunc"), + ("CLEAN", "clean"), + ("CLOSE_ALL_DATABASES", "closeAllDatabases"), + ("COLL_MOD", "collMod"), + ("COLL_STATS", "collStats"), + ("COMPACT", "compact"), + ("CONN_POOL_STATS", "connPoolStats"), + ("CONN_POOL_SYNC", "connPoolSync"), + ("CONVERT_TO_CAPPED", "convertToCapped"), + ("CPU_PROFILER", "cpuProfiler"), + ("CREATE_COLLECTION", "createCollection"), + ("CURSOR_INFO", "cursorInfo"), + ("DB_HASH", "dbHash"), + ("DB_STATS", "dbStats"), + ("DELETE", "delete"), + ("DIAG_LOGGING", "diagLogging"), + ("DROP_COLLECTION", "dropCollection"), + ("DROP_DATABASE", "dropDatabase"), + ("DROP_INDEXES", "dropIndexes"), + ("EMPTYCAPPED", "emptycapped"), + ("ENABLE_SHARDING", "enableSharding"), + ("ENSURE_INDEX", "ensureIndex"), + ("FIND", "find"), + ("FLUSH_ROUTER_CONFIG", "flushRouterConfig"), + ("FSYNC", "fsync"), + ("GET_CMD_LINE_OPTS", "getCmdLineOpts"), + ("GET_LOG", "getLog"), + ("GET_PARAMETER", "getParameter"), + ("GET_SHARD_MAP", "getShardMap"), + ("GET_SHARD_VERSION", "getShardVersion"), + ("HANDSHAKE", "handshake"), + ("HOST_INFO", "hostInfo"), + ("INSERT", "insert"), + ("LIST_DATABASES", "listDatabases"), + ("LIST_SHARDS", "listShards"), + ("LOG_ROTATE", "logRotate"), + ("MOVE_CHUNK", "moveChunk"), + ("MOVE_PRIMARY", "movePrimary"), + ("NETSTAT", "netstat"), + ("PROFILE", "profile"), + ("RE_INDEX", "reIndex"), + ("REMOVE_SHARD", "removeShard"), + ("RENAME_COLLECTION", "renameCollection"), + ("REPAIR_DATABASE", "repairDatabase"), + ("REPL_SET_ELECT", "replSetElect"), + ("REPL_SET_FREEZE", "replSetFreeze"), + ("REPL_SET_FRESH", "replSetFresh"), + ("REPL_SET_GET_RBID", "replSetGetRBID"), + ("REPL_SET_GET_STATUS", "replSetGetStatus"), + ("REPL_SET_HEARTBEAT", "replSetHeartbeat"), + ("REPL_SET_INITIATE", "replSetInitiate"), + ("REPL_SET_MAINTENANCE", "replSetMaintenance"), + ("REPL_SET_RECONFIG", "replSetReconfig"), + ("REPL_SET_STEP_DOWN", "replSetStepDown"), + ("REPL_SET_SYNC_FROM", "replSetSyncFrom"), + ("RESYNC", "resync"), + ("SET_PARAMETER", "setParameter"), + ("SET_SHARD_VERSION", "setShardVersion"), + ("SHARD_COLLECTION", "shardCollection"), + ("SHARDING_STATE", "shardingState"), + ("SHUTDOWN", "shutdown"), + ("SPLIT", "split"), + ("SPLIT_CHUNK", "splitChunk"), + ("SPLIT_VECTOR", "splitVector"), + ("TOP", "top"), + ("TOUCH", "touch"), + ("UNSET_SHARDING", "unsetSharding"), + ("UPDATE", "update"), + ("USER_ADMIN", "userAdmin"), + ("VALIDATE", "validate"), + ("WRITEBACKLISTEN", "writebacklisten"), + ("WRITE_BACKS_QUEUED", "writeBacksQueued"), + ("_MIGRATE_CLONE", "_migrateClone"), + ("_RECV_CHUNK_ABORT", "_recvChunkAbort"), + ("_RECV_CHUNK_COMMIT", "_recvChunkCommit"), + ("_RECV_CHUNK_START", "_recvChunkStart"), + ("_RECV_CHUNK_STATUS", "_recvChunkStatus"), + ("_TRANSFER_MODS", "_transferMods"), + ("OLD_READ", "oldRead"), # Temporary. For easing AuthorizationManager integration + ("OLD_WRITE", "oldWrite")] # Temporary. For easing AuthorizationManager integration + headerFileTemplate = """// AUTO-GENERATED FILE DO NOT EDIT // See src/mongo/db/auth/generate_action_types.py @@ -87,6 +164,8 @@ namespace mongo { ACTION_TYPE_END_VALUE, // Should always be last in this enum }; + static const int NUM_ACTION_TYPES = ACTION_TYPE_END_VALUE; + private: uint32_t _identifier; // unique identifier for this action. |