summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@10gen.com>2013-11-07 11:56:08 -0500
committerAndy Schwerin <schwerin@10gen.com>2013-11-08 14:22:14 -0500
commit33f16ec7ed5faf0f5bcf8e6677447a8024f0e7f7 (patch)
treedc8c1636bfa0650a2f0a1f6cb2a333cd858cad90 /src/mongo/db
parentd0fa8b74df7c4a5d1ac897110610d6582f17556b (diff)
downloadmongo-33f16ec7ed5faf0f5bcf8e6677447a8024f0e7f7.tar.gz
SERVER-9516 Factor out common code from mock & mongod implementations of AuthzManagerExternalState.
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/auth/SConscript1
-rw-r--r--src/mongo/db/auth/authorization_session_test.cpp20
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_d.cpp407
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_d.h45
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_local.cpp338
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_local.h107
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_mock.cpp108
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_mock.h16
8 files changed, 590 insertions, 452 deletions
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript
index a86d079b26a..46055ad149f 100644
--- a/src/mongo/db/auth/SConscript
+++ b/src/mongo/db/auth/SConscript
@@ -14,6 +14,7 @@ env.StaticLibrary('authcore', ['action_set.cpp',
'authorization_session.cpp',
'authz_documents_update_guard.cpp',
'authz_manager_external_state.cpp',
+ 'authz_manager_external_state_local.cpp',
'authz_session_external_state.cpp',
'privilege.cpp',
'privilege_parser.cpp',
diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp
index 5a38ce053a5..3489196da6a 100644
--- a/src/mongo/db/auth/authorization_session_test.cpp
+++ b/src/mongo/db/auth/authorization_session_test.cpp
@@ -334,7 +334,12 @@ namespace {
ASSERT(user->isValid());
// Change the user to be read-only
- managerState->clearPrivilegeDocuments();
+ int ignored;
+ managerState->remove(
+ AuthorizationManager::usersCollectionNamespace,
+ BSONObj(),
+ BSONObj(),
+ &ignored);
ASSERT_OK(managerState->insertPrivilegeDocument("admin",
BSON("user" << "spencer" <<
"db" << "test" <<
@@ -357,7 +362,11 @@ namespace {
ASSERT(user->isValid());
// Delete the user.
- managerState->clearPrivilegeDocuments();
+ managerState->remove(
+ AuthorizationManager::usersCollectionNamespace,
+ BSONObj(),
+ BSONObj(),
+ &ignored);
// Make sure that invalidating the user causes the session to reload its privileges.
authzManager->invalidateUserByName(user->getName());
authzSession->startRequest(); // Refreshes cached data for invalid users
@@ -390,8 +399,13 @@ namespace {
ASSERT(user->isValid());
// Change the user to be read-only
+ int ignored;
managerState->setFindsShouldFail(true);
- managerState->clearPrivilegeDocuments();
+ managerState->remove(
+ AuthorizationManager::usersCollectionNamespace,
+ BSONObj(),
+ BSONObj(),
+ &ignored);
ASSERT_OK(managerState->insertPrivilegeDocument("admin",
BSON("user" << "spencer" <<
"db" << "test" <<
diff --git a/src/mongo/db/auth/authz_manager_external_state_d.cpp b/src/mongo/db/auth/authz_manager_external_state_d.cpp
index 92f92f46e24..60958cdeff1 100644
--- a/src/mongo/db/auth/authz_manager_external_state_d.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_d.cpp
@@ -33,14 +33,9 @@
#include <string>
#include "mongo/base/status.h"
-#include "mongo/bson/mutable/document.h"
-#include "mongo/bson/mutable/element.h"
-#include "mongo/bson/util/bson_extract.h"
#include "mongo/db/auth/authorization_manager.h"
-#include "mongo/db/auth/user_document_parser.h"
#include "mongo/db/auth/user_name.h"
#include "mongo/db/client.h"
-#include "mongo/db/d_concurrency.h"
#include "mongo/db/dbhelpers.h"
#include "mongo/db/instance.h"
#include "mongo/db/jsobj.h"
@@ -49,245 +44,40 @@
namespace mongo {
- AuthzManagerExternalStateMongod::AuthzManagerExternalStateMongod() :
- _roleGraphState(roleGraphStateInitial) {}
-
+ AuthzManagerExternalStateMongod::AuthzManagerExternalStateMongod() {}
AuthzManagerExternalStateMongod::~AuthzManagerExternalStateMongod() {}
- Status AuthzManagerExternalStateMongod::initialize() {
- Status status = _initializeRoleGraph();
- if (!status.isOK()) {
- if (status == ErrorCodes::GraphContainsCycle) {
- error() << "Cycle detected in admin.system.roles; role inheritance disabled. "
- "Remove the listed cycle and any others to re-enable role inheritance. " <<
- status.reason();
- }
- else {
- error() << "Could not generate role graph from admin.system.roles; "
- "only system roles available. TODO EXPLAIN REMEDY. " << status;
- }
- }
-
- return Status::OK();
- }
-
-namespace {
- const Status userNotFoundStatus(ErrorCodes::UserNotFound, "User not found");
-
- void addRoleNameToObjectElement(mutablebson::Element object, const RoleName& role) {
- fassert(17153, object.appendString(AuthorizationManager::ROLE_NAME_FIELD_NAME, role.getRole()));
- fassert(17154, object.appendString(AuthorizationManager::ROLE_SOURCE_FIELD_NAME, role.getDB()));
- }
-
- void addRoleNameObjectsToArrayElement(mutablebson::Element array, RoleNameIterator roles) {
- for (; roles.more(); roles.next()) {
- mutablebson::Element roleElement = array.getDocument().makeElementObject("");
- addRoleNameToObjectElement(roleElement, roles.get());
- fassert(17155, array.pushBack(roleElement));
- }
- }
-
- void addPrivilegeObjectsOrWarningsToArrayElement(mutablebson::Element privilegesElement,
- mutablebson::Element warningsElement,
- const PrivilegeVector& privileges) {
- std::string errmsg;
- for (size_t i = 0; i < privileges.size(); ++i) {
- ParsedPrivilege pp;
- if (ParsedPrivilege::privilegeToParsedPrivilege(privileges[i], &pp, &errmsg)) {
- fassert(17156, privilegesElement.appendObject("", pp.toBSON()));
- } else {
- fassert(17157,
- warningsElement.appendString(
- "",
- std::string(mongoutils::str::stream() <<
- "Skipped privileges on resource " <<
- privileges[i].getResourcePattern().toString() <<
- ". Reason: " << errmsg)));
- }
- }
- }
-} // namespace
-
- Status AuthzManagerExternalStateMongod::getStoredAuthorizationVersion(int* outVersion) {
- {
- Client::ReadContext ctx(AuthorizationManager::versionCollectionNamespace.ns());
- BSONObj versionDoc;
- if (Helpers::findOne(AuthorizationManager::versionCollectionNamespace.ns(),
- AuthorizationManager::versionDocumentQuery,
- versionDoc)) {
- BSONElement versionElement = versionDoc[
- AuthorizationManager::schemaVersionFieldName];
- if (versionElement.isNumber()) {
- *outVersion = versionElement.numberInt();
- return Status::OK();
- }
- else if (versionElement.eoo()) {
- return Status(ErrorCodes::NoSuchKey, "No currentVersion field in version document.");
- }
- else {
- return Status(ErrorCodes::TypeMismatch, mongoutils::str::stream() <<
- "Bad (non-numeric) type " << versionElement.type() <<
- "for currentVersion field in version document");
- }
- }
- }
- if (hasAnyPrivilegeDocuments()) {
- *outVersion = AuthorizationManager::schemaVersion24;
- }
- else {
- *outVersion = AuthorizationManager::schemaVersion26Final;
- }
- return Status::OK();
- }
-
- Status AuthzManagerExternalStateMongod::getUserDescription(const UserName& userName,
- BSONObj* result) {
+ Status AuthzManagerExternalStateMongod::_getUserDocument(const UserName& userName,
+ BSONObj* userDoc) {
- BSONObj userDoc;
- {
- Client::ReadContext ctx("admin");
- int authzVersion;
- Status status = getStoredAuthorizationVersion(&authzVersion);
- if (!status.isOK())
- return status;
-
- switch (authzVersion) {
- case AuthorizationManager::schemaVersion26Upgrade:
- case AuthorizationManager::schemaVersion26Final:
- break;
- default:
- return Status(ErrorCodes::AuthSchemaIncompatible, mongoutils::str::stream() <<
- "Unsupported schema version for getUserDescription(): " <<
- authzVersion);
- }
-
- status = findOne(
- (authzVersion == AuthorizationManager::schemaVersion26Final ?
- AuthorizationManager::usersCollectionNamespace :
- AuthorizationManager::usersAltCollectionNamespace),
- BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() <<
- AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB()),
- &userDoc);
- if (status == ErrorCodes::NoMatchingDocument) {
- status = Status(ErrorCodes::UserNotFound, mongoutils::str::stream() <<
- "Could not find description of user " << userName.getFullName());
- }
- if (!status.isOK())
- return status;
- }
-
- BSONElement directRolesElement;
- Status status = bsonExtractTypedField(userDoc, "roles", Array, &directRolesElement);
- if (!status.isOK())
- return status;
- std::vector<RoleName> directRoles;
- status = V2UserDocumentParser::parseRoleVector(BSONArray(directRolesElement.Obj()),
- &directRoles);
+ Client::ReadContext ctx("admin");
+ int authzVersion;
+ Status status = getStoredAuthorizationVersion(&authzVersion);
if (!status.isOK())
return status;
- unordered_set<RoleName> indirectRoles;
- PrivilegeVector allPrivileges;
- bool isRoleGraphInconsistent;
- {
- boost::lock_guard<boost::mutex> lk(_roleGraphMutex);
- isRoleGraphInconsistent = _roleGraphState == roleGraphStateConsistent;
- for (size_t i = 0; i < directRoles.size(); ++i) {
- const RoleName& role(directRoles[i]);
- indirectRoles.insert(role);
- if (isRoleGraphInconsistent) {
- for (RoleNameIterator subordinates = _roleGraph.getIndirectSubordinates(role);
- subordinates.more();
- subordinates.next()) {
-
- indirectRoles.insert(subordinates.get());
- }
- }
- const PrivilegeVector& rolePrivileges(
- isRoleGraphInconsistent ?
- _roleGraph.getAllPrivileges(role) :
- _roleGraph.getDirectPrivileges(role));
- for (PrivilegeVector::const_iterator priv = rolePrivileges.begin(),
- end = rolePrivileges.end();
- priv != end;
- ++priv) {
-
- Privilege::addPrivilegeToPrivilegeVector(&allPrivileges, *priv);
- }
- }
- }
-
- mutablebson::Document resultDoc(userDoc, mutablebson::Document::kInPlaceDisabled);
- mutablebson::Element indirectRolesElement = resultDoc.makeElementArray("indirectRoles");
- mutablebson::Element privilegesElement = resultDoc.makeElementArray("privileges");
- mutablebson::Element warningsElement = resultDoc.makeElementArray("warnings");
- fassert(17158, resultDoc.root().pushBack(privilegesElement));
- fassert(17159, resultDoc.root().pushBack(indirectRolesElement));
- if (!isRoleGraphInconsistent) {
- fassert(17160, warningsElement.appendString(
- "", "Role graph inconsistent, only direct privileges available."));
- }
- addRoleNameObjectsToArrayElement(indirectRolesElement,
- makeRoleNameIteratorForContainer(indirectRoles));
- addPrivilegeObjectsOrWarningsToArrayElement(
- privilegesElement, warningsElement, allPrivileges);
- if (warningsElement.hasChildren()) {
- fassert(17161, resultDoc.root().pushBack(warningsElement));
- }
- *result = resultDoc.getObject();
- return Status::OK();
- }
-
- Status AuthzManagerExternalStateMongod::getRoleDescription(const RoleName& roleName,
- BSONObj* result) {
- boost::lock_guard<boost::mutex> lk(_roleGraphMutex);
- if (!_roleGraph.roleExists(roleName))
- return Status(ErrorCodes::RoleNotFound, "No role named " + roleName.toString());
-
- mutablebson::Document resultDoc;
- fassert(17162, resultDoc.root().appendString(
- AuthorizationManager::ROLE_NAME_FIELD_NAME, roleName.getRole()));
- fassert(17163, resultDoc.root().appendString(
- AuthorizationManager::ROLE_SOURCE_FIELD_NAME, roleName.getDB()));
- mutablebson::Element rolesElement = resultDoc.makeElementArray("roles");
- fassert(17164, resultDoc.root().pushBack(rolesElement));
- mutablebson::Element indirectRolesElement = resultDoc.makeElementArray("indirectRoles");
- fassert(17165, resultDoc.root().pushBack(indirectRolesElement));
- mutablebson::Element privilegesElement = resultDoc.makeElementArray("privileges");
- fassert(17166, resultDoc.root().pushBack(privilegesElement));
- mutablebson::Element warningsElement = resultDoc.makeElementArray("warnings");
-
- addRoleNameObjectsToArrayElement(rolesElement, _roleGraph.getDirectSubordinates(roleName));
- if (_roleGraphState == roleGraphStateConsistent) {
- addRoleNameObjectsToArrayElement(
- indirectRolesElement, _roleGraph.getIndirectSubordinates(roleName));
- addPrivilegeObjectsOrWarningsToArrayElement(
- privilegesElement, warningsElement, _roleGraph.getAllPrivileges(roleName));
- }
- else {
- warningsElement.appendString(
- "", "Role graph state inconsistent; only direct privileges available.");
- addPrivilegeObjectsOrWarningsToArrayElement(
- privilegesElement, warningsElement, _roleGraph.getDirectPrivileges(roleName));
+ switch (authzVersion) {
+ case AuthorizationManager::schemaVersion26Upgrade:
+ case AuthorizationManager::schemaVersion26Final:
+ break;
+ default:
+ return Status(ErrorCodes::AuthSchemaIncompatible, mongoutils::str::stream() <<
+ "Unsupported schema version for getUserDescription(): " <<
+ authzVersion);
}
- if (warningsElement.hasChildren()) {
- fassert(17167, resultDoc.root().pushBack(warningsElement));
- }
- *result = resultDoc.getObject();
- return Status::OK();
- }
-
- Status AuthzManagerExternalStateMongod::findOne(const NamespaceString& collectionName,
- const BSONObj& query,
- BSONObj* result) {
- Client::ReadContext ctx(collectionName);
- if (!Helpers::findOne(collectionName.ns(), query, *result)) {
- return Status(ErrorCodes::NoMatchingDocument, mongoutils::str::stream() <<
- "No document in " << collectionName.ns() << " matches " << query);
+ status = findOne(
+ (authzVersion == AuthorizationManager::schemaVersion26Final ?
+ AuthorizationManager::usersCollectionNamespace :
+ AuthorizationManager::usersAltCollectionNamespace),
+ BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() <<
+ AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB()),
+ userDoc);
+ if (status == ErrorCodes::NoMatchingDocument) {
+ status = Status(ErrorCodes::UserNotFound, mongoutils::str::stream() <<
+ "Could not find user " << userName.getFullName());
}
- *result = result->getOwned();
- return Status::OK();
+ return status;
}
Status AuthzManagerExternalStateMongod::query(
@@ -311,6 +101,23 @@ namespace {
return Status::OK();
}
+ Status AuthzManagerExternalStateMongod::findOne(
+ const NamespaceString& collectionName,
+ const BSONObj& query,
+ BSONObj* result) {
+
+ Client::ReadContext ctx(collectionName.ns());
+ BSONObj found;
+ if (Helpers::findOne(collectionName.ns(),
+ query,
+ found)) {
+ *result = found.getOwned();
+ return Status::OK();
+ }
+ return Status(ErrorCodes::NoMatchingDocument, mongoutils::str::stream() <<
+ "No document in " << collectionName.ns() << " matches " << query);
+ }
+
Status AuthzManagerExternalStateMongod::insert(
const NamespaceString& collectionName,
const BSONObj& document,
@@ -399,13 +206,48 @@ namespace {
const BSONObj& pattern,
bool unique,
const BSONObj& writeConcern) {
- fassertFailed(17095);
+ DBDirectClient client;
+ try {
+ if (client.ensureIndex(collectionName.ns(),
+ pattern,
+ unique)) {
+ BSONObjBuilder gleBuilder;
+ gleBuilder.append("getLastError", 1);
+ gleBuilder.appendElements(writeConcern);
+ BSONObj res;
+ client.runCommand("admin", gleBuilder.done(), res);
+ string errstr = client.getLastErrorString(res);
+ if (!errstr.empty()) {
+ return Status(ErrorCodes::UnknownError, errstr);
+ }
+ }
+ return Status::OK();
+ }
+ catch (const DBException& ex) {
+ return ex.toStatus();
+ }
}
Status AuthzManagerExternalStateMongod::dropIndexes(
const NamespaceString& collectionName,
const BSONObj& writeConcern) {
- fassertFailed(0);
+ DBDirectClient client;
+ try {
+ client.dropIndexes(collectionName.ns());
+ BSONObjBuilder gleBuilder;
+ gleBuilder.append("getLastError", 1);
+ gleBuilder.appendElements(writeConcern);
+ BSONObj res;
+ client.runCommand("admin", gleBuilder.done(), res);
+ string errstr = client.getLastErrorString(res);
+ if (!errstr.empty()) {
+ return Status(ErrorCodes::UnknownError, errstr);
+ }
+ return Status::OK();
+ }
+ catch (const DBException& ex) {
+ return ex.toStatus();
+ }
}
bool AuthzManagerExternalStateMongod::tryAcquireAuthzUpdateLock(const StringData& why) {
@@ -418,95 +260,4 @@ namespace {
return _authzDataUpdateLock.unlock();
}
-namespace {
-
- /**
- * Adds the role described in "doc" to "roleGraph". If the role cannot be added, due to
- * some error in "doc", logs a warning.
- */
- void addRoleFromDocumentOrWarn(RoleGraph* roleGraph, const BSONObj& doc) {
- Status status = roleGraph->addRoleFromDocument(doc);
- if (!status.isOK()) {
- warning() << "Skipping invalid role document. " << status << "; document " << doc;
- }
- }
-
-
-} // namespace
-
- Status AuthzManagerExternalStateMongod::_initializeRoleGraph() {
- boost::lock_guard<boost::mutex> lkInitialzeRoleGraph(_roleGraphMutex);
-
- _roleGraphState = roleGraphStateInitial;
- _roleGraph = RoleGraph();
-
- RoleGraph newRoleGraph;
- Status status = query(
- AuthorizationManager::rolesCollectionNamespace,
- BSONObj(),
- BSONObj(),
- boost::bind(addRoleFromDocumentOrWarn, &newRoleGraph, _1));
- if (!status.isOK())
- return status;
-
- status = newRoleGraph.recomputePrivilegeData();
-
- RoleGraphState newState;
- if (status == ErrorCodes::GraphContainsCycle) {
- error() << "Inconsistent role graph during authorization manager intialization. Only "
- "direct privileges available. " << status.reason();
- newState = roleGraphStateHasCycle;
- status = Status::OK();
- }
- else if (status.isOK()) {
- newState = roleGraphStateConsistent;
- }
- else {
- newState = roleGraphStateInitial;
- }
-
- if (status.isOK()) {
- _roleGraph.swap(newRoleGraph);
- _roleGraphState = newState;
- }
- return status;
- }
-
- void AuthzManagerExternalStateMongod::logOp(
- const char* op,
- const char* ns,
- const BSONObj& o,
- BSONObj* o2,
- bool* b) {
-
- if (ns == AuthorizationManager::rolesCollectionNamespace.ns() ||
- ns == AuthorizationManager::adminCommandNamespace.ns()) {
-
- boost::lock_guard<boost::mutex> lk(_roleGraphMutex);
- Status status = _roleGraph.handleLogOp(op, NamespaceString(ns), o, o2);
-
- if (status == ErrorCodes::OplogOperationUnsupported) {
- _roleGraph = RoleGraph();
- _roleGraphState = roleGraphStateInitial;
- error() << "Unsupported modification to roles collection in oplog; "
- "TODO how to remedy. " << status << " Oplog entry: " << op;
- }
- else if (!status.isOK()) {
- warning() << "Skipping bad update to roles collection in oplog. " << status <<
- " Oplog entry: " << op;
- }
- status = _roleGraph.recomputePrivilegeData();
- if (status == ErrorCodes::GraphContainsCycle) {
- _roleGraphState = roleGraphStateHasCycle;
- error() << "Inconsistent role graph during authorization manager intialization. "
- "Only direct privileges available. " << status.reason() <<
- " after applying oplog entry " << op;
- }
- else {
- fassert(17183, status);
- _roleGraphState = roleGraphStateConsistent;
- }
- }
- }
-
} // namespace mongo
diff --git a/src/mongo/db/auth/authz_manager_external_state_d.h b/src/mongo/db/auth/authz_manager_external_state_d.h
index 22e99d5573a..193126d2247 100644
--- a/src/mongo/db/auth/authz_manager_external_state_d.h
+++ b/src/mongo/db/auth/authz_manager_external_state_d.h
@@ -34,7 +34,7 @@
#include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h"
-#include "mongo/db/auth/authz_manager_external_state.h"
+#include "mongo/db/auth/authz_manager_external_state_local.h"
#include "mongo/db/auth/role_graph.h"
#include "mongo/db/auth/user_name.h"
@@ -43,19 +43,13 @@ namespace mongo {
/**
* The implementation of AuthzManagerExternalState functionality for mongod.
*/
- class AuthzManagerExternalStateMongod : public AuthzManagerExternalState {
+ class AuthzManagerExternalStateMongod : public AuthzManagerExternalStateLocal {
MONGO_DISALLOW_COPYING(AuthzManagerExternalStateMongod);
public:
AuthzManagerExternalStateMongod();
virtual ~AuthzManagerExternalStateMongod();
- virtual Status initialize();
-
- virtual Status getStoredAuthorizationVersion(int* outVersion);
- virtual Status getUserDescription(const UserName& userName, BSONObj* result);
- virtual Status getRoleDescription(const RoleName& roleName, BSONObj* result);
-
virtual Status getAllDatabaseNames(std::vector<std::string>* dbnames);
virtual Status findOne(const NamespaceString& collectionName,
@@ -88,41 +82,8 @@ namespace mongo {
virtual bool tryAcquireAuthzUpdateLock(const StringData& why);
virtual void releaseAuthzUpdateLock();
- virtual void logOp(
- const char* op,
- const char* ns,
- const BSONObj& o,
- BSONObj* o2,
- bool* b);
-
private:
- enum RoleGraphState {
- roleGraphStateInitial = 0,
- roleGraphStateConsistent,
- roleGraphStateHasCycle
- };
-
- /**
- * Initializes the role graph from the contents of the admin.system.roles collection.
- */
- Status _initializeRoleGraph();
-
- /**
- * Eventually consistent, in-memory representation of all roles in the system (both
- * user-defined and built-in). Synchronized via _roleGraphMutex.
- */
- RoleGraph _roleGraph;
-
- /**
- * State of _roleGraph, one of "initial", "consistent" and "has cycle". Synchronized via
- * _roleGraphMutex.
- */
- RoleGraphState _roleGraphState;
-
- /**
- * Guards _roleGraphState and _roleGraph.
- */
- boost::mutex _roleGraphMutex;
+ virtual Status _getUserDocument(const UserName& userName, BSONObj* userDoc);
boost::timed_mutex _authzDataUpdateLock;
};
diff --git a/src/mongo/db/auth/authz_manager_external_state_local.cpp b/src/mongo/db/auth/authz_manager_external_state_local.cpp
new file mode 100644
index 00000000000..13cf991bda7
--- /dev/null
+++ b/src/mongo/db/auth/authz_manager_external_state_local.cpp
@@ -0,0 +1,338 @@
+/**
+* Copyright (C) 2012 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* As a special exception, the copyright holders give permission to link the
+* code of portions of this program with the OpenSSL library under certain
+* conditions as described in each individual source file and distribute
+* linked combinations including the program with the OpenSSL library. You
+* must comply with the GNU Affero General Public License in all respects for
+* all of the code used other than as permitted herein. If you modify file(s)
+* with this exception, you may extend this exception to your version of the
+* file(s), but you are not obligated to do so. If you do not wish to do so,
+* delete this exception statement from your version. If you delete this
+* exception statement from all source files in the program, then also delete
+* it in the license file.
+*/
+
+#include "mongo/db/auth/authz_manager_external_state_local.h"
+
+#include "mongo/base/status.h"
+#include "mongo/bson/mutable/document.h"
+#include "mongo/bson/mutable/element.h"
+#include "mongo/bson/util/bson_extract.h"
+#include "mongo/db/auth/authorization_manager.h"
+#include "mongo/db/auth/user_document_parser.h"
+#include "mongo/util/mongoutils/str.h"
+
+namespace mongo {
+
+ AuthzManagerExternalStateLocal::AuthzManagerExternalStateLocal() :
+ _roleGraphState(roleGraphStateInitial) {}
+ AuthzManagerExternalStateLocal::~AuthzManagerExternalStateLocal() {}
+
+ Status AuthzManagerExternalStateLocal::initialize() {
+ Status status = _initializeRoleGraph();
+ if (!status.isOK()) {
+ if (status == ErrorCodes::GraphContainsCycle) {
+ error() << "Cycle detected in admin.system.roles; role inheritance disabled. "
+ "Remove the listed cycle and any others to re-enable role inheritance. " <<
+ status.reason();
+ }
+ else {
+ error() << "Could not generate role graph from admin.system.roles; "
+ "only system roles available. TODO EXPLAIN REMEDY. " << status;
+ }
+ }
+
+ return Status::OK();
+ }
+
+ Status AuthzManagerExternalStateLocal::getStoredAuthorizationVersion(int* outVersion) {
+ BSONObj versionDoc;
+ Status status = findOne(AuthorizationManager::versionCollectionNamespace,
+ AuthorizationManager::versionDocumentQuery,
+ &versionDoc);
+ if (status.isOK()) {
+ BSONElement versionElement = versionDoc[AuthorizationManager::schemaVersionFieldName];
+ if (versionElement.isNumber()) {
+ *outVersion = versionElement.numberInt();
+ return Status::OK();
+ }
+ else if (versionElement.eoo()) {
+ return Status(ErrorCodes::NoSuchKey, mongoutils::str::stream() <<
+ "No " << AuthorizationManager::schemaVersionFieldName <<
+ " field in version document.");
+ }
+ else {
+ return Status(ErrorCodes::TypeMismatch, mongoutils::str::stream() <<
+ "Bad (non-numeric) type " << versionElement.type() <<
+ "for " << AuthorizationManager::schemaVersionFieldName <<
+ " field in version document");
+ }
+ }
+ else if (status == ErrorCodes::NoMatchingDocument) {
+ if (hasAnyPrivilegeDocuments()) {
+ *outVersion = AuthorizationManager::schemaVersion24;
+ }
+ else {
+ *outVersion = AuthorizationManager::schemaVersion26Final;
+ }
+ return Status::OK();
+ }
+ else {
+ return status;
+ }
+ }
+
+namespace {
+ void addRoleNameToObjectElement(mutablebson::Element object, const RoleName& role) {
+ fassert(17153, object.appendString(AuthorizationManager::ROLE_NAME_FIELD_NAME,
+ role.getRole()));
+ fassert(17154, object.appendString(AuthorizationManager::ROLE_SOURCE_FIELD_NAME,
+ role.getDB()));
+ }
+
+ void addRoleNameObjectsToArrayElement(mutablebson::Element array, RoleNameIterator roles) {
+ for (; roles.more(); roles.next()) {
+ mutablebson::Element roleElement = array.getDocument().makeElementObject("");
+ addRoleNameToObjectElement(roleElement, roles.get());
+ fassert(17155, array.pushBack(roleElement));
+ }
+ }
+
+ void addPrivilegeObjectsOrWarningsToArrayElement(mutablebson::Element privilegesElement,
+ mutablebson::Element warningsElement,
+ const PrivilegeVector& privileges) {
+ std::string errmsg;
+ for (size_t i = 0; i < privileges.size(); ++i) {
+ ParsedPrivilege pp;
+ if (ParsedPrivilege::privilegeToParsedPrivilege(privileges[i], &pp, &errmsg)) {
+ fassert(17156, privilegesElement.appendObject("", pp.toBSON()));
+ } else {
+ fassert(17157,
+ warningsElement.appendString(
+ "",
+ std::string(mongoutils::str::stream() <<
+ "Skipped privileges on resource " <<
+ privileges[i].getResourcePattern().toString() <<
+ ". Reason: " << errmsg)));
+ }
+ }
+ }
+} // namespace
+
+ Status AuthzManagerExternalStateLocal::getUserDescription(
+ const UserName& userName,
+ BSONObj* result) {
+
+ BSONObj userDoc;
+ Status status = _getUserDocument(userName, &userDoc);
+ if (!status.isOK())
+ return status;
+
+ BSONElement directRolesElement;
+ status = bsonExtractTypedField(userDoc, "roles", Array, &directRolesElement);
+ if (!status.isOK())
+ return status;
+ std::vector<RoleName> directRoles;
+ status = V2UserDocumentParser::parseRoleVector(BSONArray(directRolesElement.Obj()),
+ &directRoles);
+ if (!status.isOK())
+ return status;
+
+ unordered_set<RoleName> indirectRoles;
+ PrivilegeVector allPrivileges;
+ bool isRoleGraphInconsistent;
+ {
+ boost::lock_guard<boost::mutex> lk(_roleGraphMutex);
+ isRoleGraphInconsistent = _roleGraphState == roleGraphStateConsistent;
+ for (size_t i = 0; i < directRoles.size(); ++i) {
+ const RoleName& role(directRoles[i]);
+ indirectRoles.insert(role);
+ if (isRoleGraphInconsistent) {
+ for (RoleNameIterator subordinates = _roleGraph.getIndirectSubordinates(role);
+ subordinates.more();
+ subordinates.next()) {
+
+ indirectRoles.insert(subordinates.get());
+ }
+ }
+ const PrivilegeVector& rolePrivileges(
+ isRoleGraphInconsistent ?
+ _roleGraph.getAllPrivileges(role) :
+ _roleGraph.getDirectPrivileges(role));
+ for (PrivilegeVector::const_iterator priv = rolePrivileges.begin(),
+ end = rolePrivileges.end();
+ priv != end;
+ ++priv) {
+
+ Privilege::addPrivilegeToPrivilegeVector(&allPrivileges, *priv);
+ }
+ }
+ }
+
+ mutablebson::Document resultDoc(userDoc, mutablebson::Document::kInPlaceDisabled);
+ mutablebson::Element indirectRolesElement = resultDoc.makeElementArray("indirectRoles");
+ mutablebson::Element privilegesElement = resultDoc.makeElementArray("privileges");
+ mutablebson::Element warningsElement = resultDoc.makeElementArray("warnings");
+ fassert(17158, resultDoc.root().pushBack(privilegesElement));
+ fassert(17159, resultDoc.root().pushBack(indirectRolesElement));
+ if (!isRoleGraphInconsistent) {
+ fassert(17160, warningsElement.appendString(
+ "", "Role graph inconsistent, only direct privileges available."));
+ }
+ addRoleNameObjectsToArrayElement(indirectRolesElement,
+ makeRoleNameIteratorForContainer(indirectRoles));
+ addPrivilegeObjectsOrWarningsToArrayElement(
+ privilegesElement, warningsElement, allPrivileges);
+ if (warningsElement.hasChildren()) {
+ fassert(17161, resultDoc.root().pushBack(warningsElement));
+ }
+ *result = resultDoc.getObject();
+ return Status::OK();
+ }
+
+ Status AuthzManagerExternalStateLocal::getRoleDescription(
+ const RoleName& roleName,
+ BSONObj* result) {
+ boost::lock_guard<boost::mutex> lk(_roleGraphMutex);
+ if (!_roleGraph.roleExists(roleName))
+ return Status(ErrorCodes::RoleNotFound, "No role named " + roleName.toString());
+
+ mutablebson::Document resultDoc;
+ fassert(17162, resultDoc.root().appendString(
+ AuthorizationManager::ROLE_NAME_FIELD_NAME, roleName.getRole()));
+ fassert(17163, resultDoc.root().appendString(
+ AuthorizationManager::ROLE_SOURCE_FIELD_NAME, roleName.getDB()));
+ mutablebson::Element rolesElement = resultDoc.makeElementArray("roles");
+ fassert(17164, resultDoc.root().pushBack(rolesElement));
+ mutablebson::Element indirectRolesElement = resultDoc.makeElementArray("indirectRoles");
+ fassert(17165, resultDoc.root().pushBack(indirectRolesElement));
+ mutablebson::Element privilegesElement = resultDoc.makeElementArray("privileges");
+ fassert(17166, resultDoc.root().pushBack(privilegesElement));
+ mutablebson::Element warningsElement = resultDoc.makeElementArray("warnings");
+
+ addRoleNameObjectsToArrayElement(rolesElement, _roleGraph.getDirectSubordinates(roleName));
+ if (_roleGraphState == roleGraphStateConsistent) {
+ addRoleNameObjectsToArrayElement(
+ indirectRolesElement, _roleGraph.getIndirectSubordinates(roleName));
+ addPrivilegeObjectsOrWarningsToArrayElement(
+ privilegesElement, warningsElement, _roleGraph.getAllPrivileges(roleName));
+ }
+ else {
+ warningsElement.appendString(
+ "", "Role graph state inconsistent; only direct privileges available.");
+ addPrivilegeObjectsOrWarningsToArrayElement(
+ privilegesElement, warningsElement, _roleGraph.getDirectPrivileges(roleName));
+ }
+ if (warningsElement.hasChildren()) {
+ fassert(17167, resultDoc.root().pushBack(warningsElement));
+ }
+ *result = resultDoc.getObject();
+ return Status::OK();
+ }
+
+namespace {
+
+ /**
+ * Adds the role described in "doc" to "roleGraph". If the role cannot be added, due to
+ * some error in "doc", logs a warning.
+ */
+ void addRoleFromDocumentOrWarn(RoleGraph* roleGraph, const BSONObj& doc) {
+ Status status = roleGraph->addRoleFromDocument(doc);
+ if (!status.isOK()) {
+ warning() << "Skipping invalid role document. " << status << "; document " << doc;
+ }
+ }
+
+
+} // namespace
+
+ Status AuthzManagerExternalStateLocal::_initializeRoleGraph() {
+ boost::lock_guard<boost::mutex> lkInitialzeRoleGraph(_roleGraphMutex);
+
+ _roleGraphState = roleGraphStateInitial;
+ _roleGraph = RoleGraph();
+
+ RoleGraph newRoleGraph;
+ Status status = query(
+ AuthorizationManager::rolesCollectionNamespace,
+ BSONObj(),
+ BSONObj(),
+ boost::bind(addRoleFromDocumentOrWarn, &newRoleGraph, _1));
+ if (!status.isOK())
+ return status;
+
+ status = newRoleGraph.recomputePrivilegeData();
+
+ RoleGraphState newState;
+ if (status == ErrorCodes::GraphContainsCycle) {
+ error() << "Inconsistent role graph during authorization manager intialization. Only "
+ "direct privileges available. " << status.reason();
+ newState = roleGraphStateHasCycle;
+ status = Status::OK();
+ }
+ else if (status.isOK()) {
+ newState = roleGraphStateConsistent;
+ }
+ else {
+ newState = roleGraphStateInitial;
+ }
+
+ if (status.isOK()) {
+ _roleGraph.swap(newRoleGraph);
+ _roleGraphState = newState;
+ }
+ return status;
+ }
+
+ void AuthzManagerExternalStateLocal::logOp(
+ const char* op,
+ const char* ns,
+ const BSONObj& o,
+ BSONObj* o2,
+ bool* b) {
+
+ if (ns == AuthorizationManager::rolesCollectionNamespace.ns() ||
+ ns == AuthorizationManager::adminCommandNamespace.ns()) {
+
+ boost::lock_guard<boost::mutex> lk(_roleGraphMutex);
+ Status status = _roleGraph.handleLogOp(op, NamespaceString(ns), o, o2);
+
+ if (status == ErrorCodes::OplogOperationUnsupported) {
+ _roleGraph = RoleGraph();
+ _roleGraphState = roleGraphStateInitial;
+ error() << "Unsupported modification to roles collection in oplog; "
+ "TODO how to remedy. " << status << " Oplog entry: " << op;
+ }
+ else if (!status.isOK()) {
+ warning() << "Skipping bad update to roles collection in oplog. " << status <<
+ " Oplog entry: " << op;
+ }
+ status = _roleGraph.recomputePrivilegeData();
+ if (status == ErrorCodes::GraphContainsCycle) {
+ _roleGraphState = roleGraphStateHasCycle;
+ error() << "Inconsistent role graph during authorization manager intialization. "
+ "Only direct privileges available. " << status.reason() <<
+ " after applying oplog entry " << op;
+ }
+ else {
+ fassert(17183, status);
+ _roleGraphState = roleGraphStateConsistent;
+ }
+ }
+ }
+
+} // namespace mongo
diff --git a/src/mongo/db/auth/authz_manager_external_state_local.h b/src/mongo/db/auth/authz_manager_external_state_local.h
new file mode 100644
index 00000000000..14016dacbc5
--- /dev/null
+++ b/src/mongo/db/auth/authz_manager_external_state_local.h
@@ -0,0 +1,107 @@
+/**
+* Copyright (C) 2012 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* As a special exception, the copyright holders give permission to link the
+* code of portions of this program with the OpenSSL library under certain
+* conditions as described in each individual source file and distribute
+* linked combinations including the program with the OpenSSL library. You
+* must comply with the GNU Affero General Public License in all respects for
+* all of the code used other than as permitted herein. If you modify file(s)
+* with this exception, you may extend this exception to your version of the
+* file(s), but you are not obligated to do so. If you do not wish to do so,
+* delete this exception statement from your version. If you delete this
+* exception statement from all source files in the program, then also delete
+* it in the license file.
+*/
+
+#pragma once
+
+#include <boost/function.hpp>
+#include <boost/thread/mutex.hpp>
+#include <string>
+
+#include "mongo/base/disallow_copying.h"
+#include "mongo/base/status.h"
+#include "mongo/db/auth/authz_manager_external_state.h"
+#include "mongo/db/auth/role_graph.h"
+#include "mongo/db/auth/role_name.h"
+#include "mongo/db/auth/user_name.h"
+
+namespace mongo {
+
+ /**
+ * Common implementation of AuthzManagerExternalState for systems where role
+ * and user information are stored locally.
+ */
+ class AuthzManagerExternalStateLocal : public AuthzManagerExternalState {
+ MONGO_DISALLOW_COPYING(AuthzManagerExternalStateLocal);
+
+ public:
+ virtual ~AuthzManagerExternalStateLocal();
+
+ virtual Status initialize();
+
+ virtual Status getStoredAuthorizationVersion(int* outVersion);
+ virtual Status getUserDescription(const UserName& userName, BSONObj* result);
+ virtual Status getRoleDescription(const RoleName& roleName, BSONObj* result);
+
+ virtual void logOp(
+ const char* op,
+ const char* ns,
+ const BSONObj& o,
+ BSONObj* o2,
+ bool* b);
+
+ protected:
+ AuthzManagerExternalStateLocal();
+
+ private:
+ enum RoleGraphState {
+ roleGraphStateInitial = 0,
+ roleGraphStateConsistent,
+ roleGraphStateHasCycle
+ };
+
+ /**
+ * Initializes the role graph from the contents of the admin.system.roles collection.
+ */
+ Status _initializeRoleGraph();
+
+ /**
+ * Fetches the user document for "userName" from local storage, and stores it into "result".
+ */
+ virtual Status _getUserDocument(const UserName& userName, BSONObj* result) = 0;
+
+ /**
+ * Eventually consistent, in-memory representation of all roles in the system (both
+ * user-defined and built-in). Synchronized via _roleGraphMutex.
+ */
+ RoleGraph _roleGraph;
+
+ /**
+ * State of _roleGraph, one of "initial", "consistent" and "has cycle". Synchronized via
+ * _roleGraphMutex.
+ */
+ RoleGraphState _roleGraphState;
+
+ /**
+ * Guards _roleGraphState and _roleGraph.
+ */
+ boost::mutex _roleGraphMutex;
+
+ boost::timed_mutex _authzDataUpdateLock;
+ };
+
+} // namespace mongo
diff --git a/src/mongo/db/auth/authz_manager_external_state_mock.cpp b/src/mongo/db/auth/authz_manager_external_state_mock.cpp
index 21e2dac4662..26b3f38eca2 100644
--- a/src/mongo/db/auth/authz_manager_external_state_mock.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_mock.cpp
@@ -82,79 +82,56 @@ namespace {
AuthzManagerExternalStateMock::AuthzManagerExternalStateMock() {}
AuthzManagerExternalStateMock::~AuthzManagerExternalStateMock() {}
- Status AuthzManagerExternalStateMock::initialize() {
- return Status::OK();
+ void AuthzManagerExternalStateMock::setAuthzVersion(int version) {
+ uassertStatusOK(
+ updateOne(AuthorizationManager::versionCollectionNamespace,
+ AuthorizationManager::versionDocumentQuery,
+ BSON("$set" << BSON(AuthorizationManager::schemaVersionFieldName <<
+ version)),
+ true,
+ BSONObj()));
}
Status AuthzManagerExternalStateMock::getStoredAuthorizationVersion(int* outVersion) {
- if (_authzVersion < 0) {
- return Status(ErrorCodes::UnknownError,
- "Mock configured to fail getStoredAuthorizationVersion()");
+ Status status = AuthzManagerExternalStateLocal::getStoredAuthorizationVersion(outVersion);
+ if (status.isOK() && outVersion < 0) {
+ status = Status(ErrorCodes::UnknownError,
+ "Mock configured to fail getStoredAuthorizationVersion()");
}
- *outVersion = _authzVersion;
- return Status::OK();
+ return status;
}
- Status AuthzManagerExternalStateMock::getUserDescription(
- const UserName& userName, BSONObj* result) {
- BSONObj privDoc;
- Status status = _findUser(
- "admin.system.users",
- BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() <<
- AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB()),
- &privDoc);
+ Status AuthzManagerExternalStateMock::_getUserDocument(const UserName& userName,
+ BSONObj* userDoc) {
+ int authzVersion;
+ Status status = getStoredAuthorizationVersion(&authzVersion);
if (!status.isOK())
return status;
- unordered_set<RoleName> indirectRoles;
- PrivilegeVector allPrivileges;
- for (BSONObjIterator iter(privDoc["roles"].Obj()); iter.more(); iter.next()) {
- if (!(*iter)["hasRole"].trueValue())
- continue;
- RoleName roleName((*iter)[AuthorizationManager::ROLE_NAME_FIELD_NAME].str(),
- (*iter)[AuthorizationManager::ROLE_SOURCE_FIELD_NAME].str());
- indirectRoles.insert(roleName);
- for (RoleNameIterator subordinates = _roleGraph.getIndirectSubordinates(
- roleName);
- subordinates.more();
- subordinates.next()) {
-
- indirectRoles.insert(subordinates.get());
- }
- const PrivilegeVector& rolePrivileges(_roleGraph.getAllPrivileges(roleName));
- for (PrivilegeVector::const_iterator priv = rolePrivileges.begin(),
- end = rolePrivileges.end();
- priv != end;
- ++priv) {
-
- Privilege::addPrivilegeToPrivilegeVector(&allPrivileges, *priv);
- }
+ switch (authzVersion) {
+ case AuthorizationManager::schemaVersion26Upgrade:
+ case AuthorizationManager::schemaVersion26Final:
+ break;
+ default:
+ return Status(ErrorCodes::AuthSchemaIncompatible, mongoutils::str::stream() <<
+ "Unsupported schema version for getUserDescription(): " <<
+ authzVersion);
}
- mutablebson::Document userDoc(privDoc, mutablebson::Document::kInPlaceDisabled);
- mutablebson::Element indirectRolesElement = userDoc.makeElementArray("indirectRoles");
- mutablebson::Element privilegesElement = userDoc.makeElementArray("privileges");
- mutablebson::Element warningsElement = userDoc.makeElementArray("warnings");
- fassert(17180, userDoc.root().pushBack(privilegesElement));
- fassert(17181, userDoc.root().pushBack(indirectRolesElement));
-
- addRoleNameObjectsToArrayElement(indirectRolesElement,
- makeRoleNameIteratorForContainer(indirectRoles));
- addPrivilegeObjectsOrWarningsToArrayElement(
- privilegesElement, warningsElement, allPrivileges);
- if (warningsElement.hasChildren()) {
- fassert(17182, userDoc.root().pushBack(warningsElement));
+ status = findOne(
+ (authzVersion == AuthorizationManager::schemaVersion26Final ?
+ AuthorizationManager::usersCollectionNamespace :
+ AuthorizationManager::usersAltCollectionNamespace),
+ BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() <<
+ AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB()),
+ userDoc);
+ if (status == ErrorCodes::NoMatchingDocument) {
+ status = Status(ErrorCodes::UserNotFound, mongoutils::str::stream() <<
+ "Could not find user " << userName.getFullName());
}
- *result = userDoc.getObject();
- return Status::OK();
- }
-
- Status AuthzManagerExternalStateMock::getRoleDescription(
- const RoleName& roleName, BSONObj* result) {
- return Status(ErrorCodes::RoleNotFound, "Not implemented");
+ return status;
}
-
Status AuthzManagerExternalStateMock::updatePrivilegeDocument(const UserName& user,
const BSONObj& updateObj,
const BSONObj&) {
@@ -174,10 +151,6 @@ namespace {
return insert(usersCollection, userObj, writeConcern);
}
- void AuthzManagerExternalStateMock::clearPrivilegeDocuments() {
- _documents.clear();
- }
-
Status AuthzManagerExternalStateMock::getAllDatabaseNames(
std::vector<std::string>* dbnames) {
unordered_set<std::string> dbnameSet;
@@ -193,12 +166,11 @@ namespace {
const std::string& usersNamespace,
const BSONObj& query,
BSONObj* result) {
- Status status = findOne(NamespaceString(usersNamespace), query, result);
- if (status == ErrorCodes::NoMatchingDocument) {
- status = Status(ErrorCodes::UserNotFound,
- "No matching user for query " + query.toString());
+ if (!findOne(NamespaceString(usersNamespace), query, result).isOK()) {
+ return Status(ErrorCodes::UserNotFound,
+ "No matching user for query " + query.toString());
}
- return status;
+ return Status::OK();
}
Status AuthzManagerExternalStateMock::findOne(
diff --git a/src/mongo/db/auth/authz_manager_external_state_mock.h b/src/mongo/db/auth/authz_manager_external_state_mock.h
index 8ca0dfc7f28..770841546bf 100644
--- a/src/mongo/db/auth/authz_manager_external_state_mock.h
+++ b/src/mongo/db/auth/authz_manager_external_state_mock.h
@@ -35,7 +35,7 @@
#include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h"
-#include "mongo/db/auth/authz_manager_external_state.h"
+#include "mongo/db/auth/authz_manager_external_state_local.h"
#include "mongo/db/auth/role_graph.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_string.h"
@@ -45,7 +45,7 @@ namespace mongo {
/**
* Mock of the AuthzManagerExternalState class used only for testing.
*/
- class AuthzManagerExternalStateMock : public AuthzManagerExternalState {
+ class AuthzManagerExternalStateMock : public AuthzManagerExternalStateLocal {
MONGO_DISALLOW_COPYING(AuthzManagerExternalStateMock);
public:
@@ -53,13 +53,9 @@ namespace mongo {
AuthzManagerExternalStateMock();
virtual ~AuthzManagerExternalStateMock();
- void setAuthzVersion(int v) { _authzVersion = v; }
+ void setAuthzVersion(int version);
- virtual Status initialize();
virtual Status getStoredAuthorizationVersion(int* outVersion);
- virtual Status getUserDescription(const UserName& userName, BSONObj* result);
- virtual Status getRoleDescription(const RoleName& roleName, BSONObj* result);
-
virtual Status insertPrivilegeDocument(const std::string& dbname,
const BSONObj& userObj,
@@ -74,8 +70,6 @@ namespace mongo {
const BSONObj& writeConcern,
int* numRemoved);
- void clearPrivilegeDocuments();
-
virtual Status getAllDatabaseNames(std::vector<std::string>* dbnames);
virtual Status findOne(const NamespaceString& collectionName,
@@ -128,6 +122,8 @@ namespace mongo {
typedef std::vector<BSONObj> BSONObjCollection;
typedef std::map<NamespaceString, BSONObjCollection> NamespaceDocumentMap;
+ virtual Status _getUserDocument(const UserName& userName, BSONObj* userDoc);
+
Status _findOneIter(const NamespaceString& collectionName,
const BSONObj& query,
BSONObjCollection::iterator* result);
@@ -138,8 +134,6 @@ namespace mongo {
NamespaceDocumentMap _documents; // Mock database.
- RoleGraph _roleGraph;
- int _authzVersion;
};
} // namespace mongo