summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Alabi <alabidan@gmail.com>2015-05-21 08:49:11 -0400
committerDaniel Alabi <alabidan@gmail.com>2015-05-21 13:43:43 -0400
commitc19715f0411f834e761128e64ec24488997383e6 (patch)
treef7b888a157f49b63fd13a0e1d4b11fe9a6d86132 /src
parent70c7cba06315b14a92a4d46bf2244b990cda902b (diff)
downloadmongo-c19715f0411f834e761128e64ec24488997383e6.tar.gz
SERVER-18478 Clean up AuthzManagerExternalState
Removed insert/remove/update from the AuthzManagerExternalState* interfaces
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/auth/authorization_manager.cpp119
-rw-r--r--src/mongo/db/auth/authorization_manager.h82
-rw-r--r--src/mongo/db/auth/authorization_manager_test.cpp2
-rw-r--r--src/mongo/db/auth/authorization_session_test.cpp11
-rw-r--r--src/mongo/db/auth/authz_manager_external_state.cpp89
-rw-r--r--src/mongo/db/auth/authz_manager_external_state.h73
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_d.cpp86
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_d.h17
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_mock.cpp7
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_mock.h7
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_s.cpp50
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_s.h18
-rw-r--r--src/mongo/db/commands/user_management_commands.cpp684
-rw-r--r--src/mongo/db/commands/user_management_commands.h50
-rw-r--r--src/mongo/db/commands/user_management_commands_common.cpp173
15 files changed, 614 insertions, 854 deletions
diff --git a/src/mongo/db/auth/authorization_manager.cpp b/src/mongo/db/auth/authorization_manager.cpp
index 4a1def087c4..1cd1a137450 100644
--- a/src/mongo/db/auth/authorization_manager.cpp
+++ b/src/mongo/db/auth/authorization_manager.cpp
@@ -329,107 +329,6 @@ namespace mongo {
return _privilegeDocsExist;
}
- Status AuthorizationManager::writeAuthSchemaVersionIfNeeded(OperationContext* txn,
- int foundSchemaVersion) {
- Status status = _externalState->updateOne(
- txn,
- AuthorizationManager::versionCollectionNamespace,
- AuthorizationManager::versionDocumentQuery,
- BSON("$set" << BSON(AuthorizationManager::schemaVersionFieldName <<
- foundSchemaVersion)),
- true, // upsert
- BSONObj()); // write concern
- if (status == ErrorCodes::NoMatchingDocument) { // SERVER-11492
- status = Status::OK();
- }
- return status;
- }
-
- Status AuthorizationManager::insertPrivilegeDocument(OperationContext* txn,
- const std::string& dbname,
- const BSONObj& userObj,
- const BSONObj& writeConcern) const {
- return _externalState->insertPrivilegeDocument(txn, dbname, userObj, writeConcern);
- }
-
- Status AuthorizationManager::updatePrivilegeDocument(OperationContext* txn,
- const UserName& user,
- const BSONObj& updateObj,
- const BSONObj& writeConcern) const {
- return _externalState->updatePrivilegeDocument(txn, user, updateObj, writeConcern);
- }
-
- Status AuthorizationManager::removePrivilegeDocuments(OperationContext* txn,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved) const {
- return _externalState->removePrivilegeDocuments(txn, query, writeConcern, numRemoved);
- }
-
- Status AuthorizationManager::removeRoleDocuments(OperationContext* txn,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved) const {
- Status status = _externalState->remove(txn,
- rolesCollectionNamespace,
- query,
- writeConcern,
- numRemoved);
- if (status.code() == ErrorCodes::UnknownError) {
- return Status(ErrorCodes::RoleModificationFailed, status.reason());
- }
- return status;
- }
-
- Status AuthorizationManager::insertRoleDocument(OperationContext* txn,
- const BSONObj& roleObj,
- const BSONObj& writeConcern) const {
- Status status = _externalState->insert(txn,
- rolesCollectionNamespace,
- roleObj,
- writeConcern);
- if (status.isOK()) {
- return status;
- }
- if (status.code() == ErrorCodes::DuplicateKey) {
- std::string name = roleObj[AuthorizationManager::ROLE_NAME_FIELD_NAME].String();
- std::string source = roleObj[AuthorizationManager::ROLE_DB_FIELD_NAME].String();
- return Status(ErrorCodes::DuplicateKey,
- mongoutils::str::stream() << "Role \"" << name << "@" << source <<
- "\" already exists");
- }
- if (status.code() == ErrorCodes::UnknownError) {
- return Status(ErrorCodes::RoleModificationFailed, status.reason());
- }
- return status;
- }
-
- Status AuthorizationManager::updateRoleDocument(OperationContext* txn,
- const RoleName& role,
- const BSONObj& updateObj,
- const BSONObj& writeConcern) const {
- Status status = _externalState->updateOne(
- txn,
- rolesCollectionNamespace,
- BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME << role.getRole() <<
- AuthorizationManager::ROLE_DB_FIELD_NAME << role.getDB()),
- updateObj,
- false,
- writeConcern);
- if (status.isOK()) {
- return status;
- }
- if (status.code() == ErrorCodes::NoMatchingDocument) {
- return Status(ErrorCodes::RoleNotFound,
- mongoutils::str::stream() << "Role " << role.getFullName() <<
- " not found");
- }
- if (status.code() == ErrorCodes::UnknownError) {
- return Status(ErrorCodes::RoleModificationFailed, status.reason());
- }
- return status;
- }
-
Status AuthorizationManager::queryAuthzDocument(
OperationContext* txn,
const NamespaceString& collectionName,
@@ -439,24 +338,6 @@ namespace mongo {
return _externalState->query(txn, collectionName, query, projection, resultProcessor);
}
- Status AuthorizationManager::updateAuthzDocuments(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& updatePattern,
- bool upsert,
- bool multi,
- const BSONObj& writeConcern,
- int* nMatched) const {
- return _externalState->update(txn,
- collectionName,
- query,
- updatePattern,
- upsert,
- multi,
- writeConcern,
- nMatched);
- }
-
Status AuthorizationManager::getBSONForPrivileges(const PrivilegeVector& privileges,
mutablebson::Element resultArray) {
for (PrivilegeVector::const_iterator it = privileges.begin();
diff --git a/src/mongo/db/auth/authorization_manager.h b/src/mongo/db/auth/authorization_manager.h
index 7a42df327db..1f8db64b6d9 100644
--- a/src/mongo/db/auth/authorization_manager.h
+++ b/src/mongo/db/auth/authorization_manager.h
@@ -199,88 +199,6 @@ namespace mongo {
bool hasAnyPrivilegeDocuments(OperationContext* txn);
/**
- * Updates the auth schema version document to reflect the current state of the system.
- * 'foundSchemaVersion' is the authSchemaVersion to update with.
- */
- Status writeAuthSchemaVersionIfNeeded(OperationContext* txn,
- int foundSchemaVersion);
-
- /**
- * Creates the given user object in the given database.
- * 'writeConcern' contains the arguments to be passed to getLastError to block for
- * successful completion of the write.
- */
- Status insertPrivilegeDocument(OperationContext* txn,
- const std::string& dbname,
- const BSONObj& userObj,
- const BSONObj& writeConcern) const;
-
- /**
- * Updates the given user object with the given update modifier.
- * 'writeConcern' contains the arguments to be passed to getLastError to block for
- * successful completion of the write.
- */
- Status updatePrivilegeDocument(OperationContext* txn,
- const UserName& user,
- const BSONObj& updateObj,
- const BSONObj& writeConcern) const;
-
- /*
- * Removes users for the given database matching the given query.
- * Writes into *numRemoved the number of user documents that were modified.
- * 'writeConcern' contains the arguments to be passed to getLastError to block for
- * successful completion of the write.
- */
- Status removePrivilegeDocuments(OperationContext* txn,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved) const;
-
- /**
- * Creates the given role object in the given database.
- * 'writeConcern' contains the arguments to be passed to getLastError to block for
- * successful completion of the write.
- */
- Status insertRoleDocument(OperationContext* txn,
- const BSONObj& roleObj,
- const BSONObj& writeConcern) const;
-
- /**
- * Updates the given role object with the given update modifier.
- * 'writeConcern' contains the arguments to be passed to getLastError to block for
- * successful completion of the write.
- */
- Status updateRoleDocument(OperationContext* txn,
- const RoleName& role,
- const BSONObj& updateObj,
- const BSONObj& writeConcern) const;
-
- /**
- * Updates documents matching "query" according to "updatePattern" in "collectionName".
- * Should only be called on collections with authorization documents in them
- * (ie admin.system.users and admin.system.roles).
- */
- Status updateAuthzDocuments(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& updatePattern,
- bool upsert,
- bool multi,
- const BSONObj& writeConcern,
- int* nMatched) const;
-
- /*
- * Removes roles matching the given query.
- * Writes into *numRemoved the number of role documents that were modified.
- * 'writeConcern' contains the arguments to be passed to getLastError to block for
- * successful completion of the write.
- */
- Status removeRoleDocuments(OperationContext* txn,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved) const;
-
- /**
* Finds all documents matching "query" in "collectionName". For each document returned,
* calls the function resultProcessor on it.
* Should only be called on collections with authorization documents in them
diff --git a/src/mongo/db/auth/authorization_manager_test.cpp b/src/mongo/db/auth/authorization_manager_test.cpp
index d91d09f499a..65a2f84243c 100644
--- a/src/mongo/db/auth/authorization_manager_test.cpp
+++ b/src/mongo/db/auth/authorization_manager_test.cpp
@@ -178,7 +178,6 @@ namespace {
ASSERT_OK(externalState->insertPrivilegeDocument(
&txn,
- "admin",
BSON("_id" << "admin.v2read" <<
"user" << "v2read" <<
"db" << "test" <<
@@ -187,7 +186,6 @@ namespace {
BSONObj()));
ASSERT_OK(externalState->insertPrivilegeDocument(
&txn,
- "admin",
BSON("_id" << "admin.v2cluster" <<
"user" << "v2cluster" <<
"db" << "admin" <<
diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp
index 5e55ed3b93a..5ce06edb4a7 100644
--- a/src/mongo/db/auth/authorization_session_test.cpp
+++ b/src/mongo/db/auth/authorization_session_test.cpp
@@ -138,7 +138,6 @@ namespace {
// Add a user with readWrite and dbAdmin on the test DB
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "spencer" <<
"db" << "test" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
@@ -158,7 +157,6 @@ namespace {
// Add an admin user with readWriteAnyDatabase
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "admin" <<
"db" << "admin" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
@@ -200,7 +198,6 @@ namespace {
TEST_F(AuthorizationSessionTest, DuplicateRolesOK) {
// Add a user with doubled-up readWrite and single dbAdmin on the test DB
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "spencer" <<
"db" << "test" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
@@ -223,7 +220,6 @@ namespace {
TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "rw" <<
"db" << "test" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
@@ -233,7 +229,6 @@ namespace {
"db" << "test"))),
BSONObj()));
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "useradmin" <<
"db" << "test" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
@@ -241,7 +236,6 @@ namespace {
"db" << "test"))),
BSONObj()));
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "rwany" <<
"db" << "test" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
@@ -251,7 +245,6 @@ namespace {
"db" << "admin"))),
BSONObj()));
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "useradminany" <<
"db" << "test" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
@@ -341,7 +334,6 @@ namespace {
TEST_F(AuthorizationSessionTest, InvalidateUser) {
// Add a readWrite user
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "spencer" <<
"db" << "test" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
@@ -367,7 +359,6 @@ namespace {
BSONObj(),
&ignored);
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "spencer" <<
"db" << "test" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
@@ -406,7 +397,6 @@ namespace {
TEST_F(AuthorizationSessionTest, UseOldUserInfoInFaceOfConnectivityProblems) {
// Add a readWrite user
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "spencer" <<
"db" << "test" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
@@ -433,7 +423,6 @@ namespace {
BSONObj(),
&ignored);
ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- "admin",
BSON("user" << "spencer" <<
"db" << "test" <<
"credentials" << BSON("MONGODB-CR" << "a") <<
diff --git a/src/mongo/db/auth/authz_manager_external_state.cpp b/src/mongo/db/auth/authz_manager_external_state.cpp
index 9d9d1763439..ded9792e7c2 100644
--- a/src/mongo/db/auth/authz_manager_external_state.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state.cpp
@@ -59,93 +59,4 @@ namespace mongo {
return status != ErrorCodes::NoMatchingDocument;
}
-
- Status AuthzManagerExternalState::insertPrivilegeDocument(OperationContext* txn,
- const string& dbname,
- const BSONObj& userObj,
- const BSONObj& writeConcern) {
- Status status = insert(txn, NamespaceString("admin.system.users"), userObj, writeConcern);
- if (status.isOK()) {
- return status;
- }
- if (status.code() == ErrorCodes::DuplicateKey) {
- std::string name = userObj[AuthorizationManager::USER_NAME_FIELD_NAME].String();
- std::string source = userObj[AuthorizationManager::USER_DB_FIELD_NAME].String();
- return Status(ErrorCodes::DuplicateKey,
- mongoutils::str::stream() << "User \"" << name << "@" << source <<
- "\" already exists");
- }
- if (status.code() == ErrorCodes::UnknownError) {
- return Status(ErrorCodes::UserModificationFailed, status.reason());
- }
- return status;
- }
-
- Status AuthzManagerExternalState::updatePrivilegeDocument(OperationContext* txn,
- const UserName& user,
- const BSONObj& updateObj,
- const BSONObj& writeConcern) {
- Status status = updateOne(
- txn,
- NamespaceString("admin.system.users"),
- BSON(AuthorizationManager::USER_NAME_FIELD_NAME << user.getUser() <<
- AuthorizationManager::USER_DB_FIELD_NAME << user.getDB()),
- updateObj,
- false,
- writeConcern);
- if (status.isOK()) {
- return status;
- }
- if (status.code() == ErrorCodes::NoMatchingDocument) {
- return Status(ErrorCodes::UserNotFound,
- mongoutils::str::stream() << "User " << user.getFullName() <<
- " not found");
- }
- if (status.code() == ErrorCodes::UnknownError) {
- return Status(ErrorCodes::UserModificationFailed, status.reason());
- }
- return status;
- }
-
- Status AuthzManagerExternalState::removePrivilegeDocuments(OperationContext* txn,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved) {
- Status status = remove(txn,
- NamespaceString("admin.system.users"),
- query,
- writeConcern,
- numRemoved);
- if (status.code() == ErrorCodes::UnknownError) {
- return Status(ErrorCodes::UserModificationFailed, status.reason());
- }
- return status;
- }
-
- Status AuthzManagerExternalState::updateOne(
- OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& updatePattern,
- bool upsert,
- const BSONObj& writeConcern) {
- int nMatched;
- Status status = update(txn,
- collectionName,
- query,
- updatePattern,
- upsert,
- false,
- writeConcern,
- &nMatched);
- if (!status.isOK()) {
- return status;
- }
- dassert(nMatched == 1 || nMatched == 0);
- if (nMatched == 0) {
- return Status(ErrorCodes::NoMatchingDocument, "No document found");
- }
- return Status::OK();
- }
-
} // namespace mongo
diff --git a/src/mongo/db/auth/authz_manager_external_state.h b/src/mongo/db/auth/authz_manager_external_state.h
index 05b1ba18aeb..4c08e181a0a 100644
--- a/src/mongo/db/auth/authz_manager_external_state.h
+++ b/src/mongo/db/auth/authz_manager_external_state.h
@@ -132,33 +132,6 @@ namespace mongo {
bool hasAnyPrivilegeDocuments(OperationContext* txn);
/**
- * Creates the given user object in the given database.
- *
- * TODO(spencer): remove dbname argument once users are only written into the admin db
- */
- Status insertPrivilegeDocument(OperationContext* txn,
- const std::string& dbname,
- const BSONObj& userObj,
- const BSONObj& writeConcern);
-
- /**
- * Updates the given user object with the given update modifier.
- */
- Status updatePrivilegeDocument(OperationContext* txn,
- const UserName& user,
- const BSONObj& updateObj,
- const BSONObj& writeConcern);
-
- /**
- * Removes users for the given database matching the given query.
- * Writes into *numRemoved the number of user documents that were modified.
- */
- Status removePrivilegeDocuments(OperationContext* txn,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved);
-
- /**
* Finds a document matching "query" in "collectionName", and store a shared-ownership
* copy into "result".
*
@@ -180,52 +153,6 @@ namespace mongo {
const BSONObj& projection,
const stdx::function<void(const BSONObj&)>& resultProcessor) = 0;
- /**
- * Inserts "document" into "collectionName".
- * If there is a duplicate key error, returns a Status with code DuplicateKey.
- */
- virtual Status insert(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& document,
- const BSONObj& writeConcern) = 0;
-
- /**
- * Update one document matching "query" according to "updatePattern" in "collectionName".
- *
- * If "upsert" is true and no document matches "query", inserts one using "query" as a
- * template.
- * If "upsert" is false and no document matches "query", return a Status with the code
- * NoMatchingDocument. The Status message in that case is not very descriptive and should
- * not be displayed to the end user.
- */
- virtual Status updateOne(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& updatePattern,
- bool upsert,
- const BSONObj& writeConcern);
-
- /**
- * Updates documents matching "query" according to "updatePattern" in "collectionName".
- */
- virtual Status update(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& updatePattern,
- bool upsert,
- bool multi,
- const BSONObj& writeConcern,
- int* nMatched) = 0;
-
- /**
- * Removes all documents matching "query" from "collectionName".
- */
- virtual Status remove(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved) = 0;
-
virtual void logOp(
OperationContext* txn,
const char* op,
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 79e81727242..d62771144ca 100644
--- a/src/mongo/db/auth/authz_manager_external_state_d.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_d.cpp
@@ -101,90 +101,4 @@ namespace mongo {
"No document in " << collectionName.ns() << " matches " << query);
}
- Status AuthzManagerExternalStateMongod::insert(
- OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& document,
- const BSONObj& writeConcern) {
- try {
- DBDirectClient client(txn);
- client.insert(collectionName, document);
-
- // Handle write concern
- 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::OK();
- }
- if (res.hasField("code") && res["code"].Int() == ASSERT_ID_DUPKEY) {
- return Status(ErrorCodes::DuplicateKey, errstr);
- }
- return Status(ErrorCodes::UnknownError, errstr);
- } catch (const DBException& e) {
- return e.toStatus();
- }
- }
-
- Status AuthzManagerExternalStateMongod::update(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& updatePattern,
- bool upsert,
- bool multi,
- const BSONObj& writeConcern,
- int* nMatched) {
- try {
- DBDirectClient client(txn);
- client.update(collectionName, query, updatePattern, upsert, multi);
-
- // Handle write concern
- BSONObjBuilder gleBuilder;
- gleBuilder.append("getLastError", 1);
- gleBuilder.appendElements(writeConcern);
- BSONObj res;
- client.runCommand("admin", gleBuilder.done(), res);
- string err = client.getLastErrorString(res);
- if (!err.empty()) {
- return Status(ErrorCodes::UnknownError, err);
- }
-
- *nMatched = res["n"].numberInt();
- return Status::OK();
- } catch (const DBException& e) {
- return e.toStatus();
- }
- }
-
- Status AuthzManagerExternalStateMongod::remove(
- OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved) {
- try {
- DBDirectClient client(txn);
- client.remove(collectionName, query);
-
- // Handle write concern
- 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);
- }
-
- *numRemoved = res["n"].numberInt();
- return Status::OK();
- } catch (const DBException& e) {
- return e.toStatus();
- }
- }
-
} // 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 3c8fa8aa1c6..b288bc6321c 100644
--- a/src/mongo/db/auth/authz_manager_external_state_d.h
+++ b/src/mongo/db/auth/authz_manager_external_state_d.h
@@ -62,23 +62,6 @@ namespace mongo {
const BSONObj& query,
const BSONObj& projection,
const stdx::function<void(const BSONObj&)>& resultProcessor);
- virtual Status insert(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& document,
- const BSONObj& writeConcern);
- virtual Status update(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& updatePattern,
- bool upsert,
- bool multi,
- const BSONObj& writeConcern,
- int* nMatched);
- virtual Status remove(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved);
};
} // 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 047ca78d52c..92274c74627 100644
--- a/src/mongo/db/auth/authz_manager_external_state_mock.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_mock.cpp
@@ -174,6 +174,13 @@ namespace {
return Status::OK();
}
+ Status AuthzManagerExternalStateMock::insertPrivilegeDocument(
+ OperationContext* txn,
+ const BSONObj& userObj,
+ const BSONObj& writeConcern) {
+ return insert(txn, AuthorizationManager::usersCollectionNamespace, userObj, writeConcern);
+ }
+
Status AuthzManagerExternalStateMock::updateOne(
OperationContext* txn,
const NamespaceString& collectionName,
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 585d954e7ba..43f3abb2546 100644
--- a/src/mongo/db/auth/authz_manager_external_state_mock.h
+++ b/src/mongo/db/auth/authz_manager_external_state_mock.h
@@ -72,6 +72,13 @@ namespace mongo {
const BSONObj& projection, // Currently unused in mock
const stdx::function<void(const BSONObj&)>& resultProcessor);
+ /**
+ * Inserts the given user object into the "admin" database.
+ */
+ Status insertPrivilegeDocument(OperationContext* txn,
+ const BSONObj& userObj,
+ const BSONObj& writeConcern);
+
// This implementation does not understand uniqueness constraints.
virtual Status insert(OperationContext* txn,
const NamespaceString& collectionName,
diff --git a/src/mongo/db/auth/authz_manager_external_state_s.cpp b/src/mongo/db/auth/authz_manager_external_state_s.cpp
index 19e32f62003..d05fac906f2 100644
--- a/src/mongo/db/auth/authz_manager_external_state_s.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_s.cpp
@@ -44,7 +44,6 @@
#include "mongo/db/auth/authz_session_external_state_s.h"
#include "mongo/db/auth/user_name.h"
#include "mongo/db/jsobj.h"
-#include "mongo/s/catalog/catalog_manager.h"
#include "mongo/s/client/shard_registry.h"
#include "mongo/s/config.h"
#include "mongo/s/grid.h"
@@ -283,53 +282,4 @@ namespace {
}
}
- Status AuthzManagerExternalStateMongos::insert(
- OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& document,
- const BSONObj& writeConcern) {
-
- return grid.catalogManager()->insert(collectionName, document, NULL);
- }
-
- Status AuthzManagerExternalStateMongos::update(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& updatePattern,
- bool upsert,
- bool multi,
- const BSONObj& writeConcern,
- int* nMatched) {
-
- BatchedCommandResponse response;
- Status res = grid.catalogManager()->update(collectionName,
- query,
- updatePattern,
- upsert,
- multi,
- &response);
- if (res.isOK()) {
- *nMatched = response.getN();
- }
-
- return res;
- }
-
- Status AuthzManagerExternalStateMongos::remove(
- OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved) {
-
- BatchedCommandResponse response;
-
- Status res = grid.catalogManager()->remove(collectionName, query, 0, &response);
- if (res.isOK()) {
- *numRemoved = response.getN();
- }
-
- return res;
- }
-
} // namespace mongo
diff --git a/src/mongo/db/auth/authz_manager_external_state_s.h b/src/mongo/db/auth/authz_manager_external_state_s.h
index 31295aa3ec3..606f423f61c 100644
--- a/src/mongo/db/auth/authz_manager_external_state_s.h
+++ b/src/mongo/db/auth/authz_manager_external_state_s.h
@@ -87,24 +87,6 @@ namespace mongo {
const BSONObj& query,
const BSONObj& projection,
const stdx::function<void(const BSONObj&)>& resultProcessor);
-
- virtual Status insert(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& document,
- const BSONObj& writeConcern);
- virtual Status update(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& updatePattern,
- bool upsert,
- bool multi,
- const BSONObj& writeConcern,
- int* nMatched);
- virtual Status remove(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- const BSONObj& writeConcern,
- int* numRemoved);
};
} // namespace mongo
diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp
index 7e2e1c100b3..58d17a75fa5 100644
--- a/src/mongo/db/commands/user_management_commands.cpp
+++ b/src/mongo/db/commands/user_management_commands.cpp
@@ -58,6 +58,7 @@
#include "mongo/db/auth/user_management_commands_parser.h"
#include "mongo/db/client.h"
#include "mongo/db/commands.h"
+#include "mongo/db/dbdirectclient.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/service_context.h"
@@ -85,8 +86,527 @@ namespace {
const Seconds authzDataMutexAcquisitionTimeout{5};
+ BSONArray roleSetToBSONArray(const unordered_set<RoleName>& roles) {
+ BSONArrayBuilder rolesArrayBuilder;
+ for (unordered_set<RoleName>::const_iterator it = roles.begin(); it != roles.end(); ++it) {
+ const RoleName& role = *it;
+ rolesArrayBuilder.append(
+ BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME << role.getRole() <<
+ AuthorizationManager::ROLE_DB_FIELD_NAME << role.getDB()));
+ }
+ return rolesArrayBuilder.arr();
+ }
+
+ BSONArray rolesVectorToBSONArray(const std::vector<RoleName>& roles) {
+ BSONArrayBuilder rolesArrayBuilder;
+ for (std::vector<RoleName>::const_iterator it = roles.begin(); it != roles.end(); ++it) {
+ const RoleName& role = *it;
+ rolesArrayBuilder.append(
+ BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME << role.getRole() <<
+ AuthorizationManager::ROLE_DB_FIELD_NAME << role.getDB()));
+ }
+ return rolesArrayBuilder.arr();
+ }
+
+ Status privilegeVectorToBSONArray(const PrivilegeVector& privileges, BSONArray* result) {
+ BSONArrayBuilder arrBuilder;
+ for (PrivilegeVector::const_iterator it = privileges.begin();
+ it != privileges.end(); ++it) {
+ const Privilege& privilege = *it;
+
+ ParsedPrivilege parsedPrivilege;
+ std::string errmsg;
+ if (!ParsedPrivilege::privilegeToParsedPrivilege(privilege,
+ &parsedPrivilege,
+ &errmsg)) {
+ return Status(ErrorCodes::FailedToParse, errmsg);
+ }
+ if (!parsedPrivilege.isValid(&errmsg)) {
+ return Status(ErrorCodes::FailedToParse, errmsg);
+ }
+ arrBuilder.append(parsedPrivilege.toBSON());
+ }
+ *result = arrBuilder.arr();
+ return Status::OK();
+ }
+
+ /**
+ * Used to get all current roles of the user identified by 'userName'.
+ */
+ Status getCurrentUserRoles(OperationContext* txn,
+ AuthorizationManager* authzManager,
+ const UserName& userName,
+ unordered_set<RoleName>* roles) {
+ User* user;
+ authzManager->invalidateUserByName(userName); // Need to make sure cache entry is up to date
+ Status status = authzManager->acquireUser(txn, userName, &user);
+ if (!status.isOK()) {
+ return status;
+ }
+ RoleNameIterator rolesIt = user->getRoles();
+ while (rolesIt.more()) {
+ roles->insert(rolesIt.next());
+ }
+ authzManager->releaseUser(user);
+ return Status::OK();
+ }
+
+ /**
+ * Checks that every role in "rolesToAdd" exists, that adding each of those roles to "role"
+ * will not result in a cycle to the role graph, and that every role being added comes from the
+ * same database as the role it is being added to (or that the role being added to is from the
+ * "admin" database.
+ */
+ Status checkOkayToGrantRolesToRole(const RoleName& role,
+ const std::vector<RoleName> rolesToAdd,
+ AuthorizationManager* authzManager) {
+ for (std::vector<RoleName>::const_iterator it = rolesToAdd.begin();
+ it != rolesToAdd.end(); ++it) {
+ const RoleName& roleToAdd = *it;
+ if (roleToAdd == role) {
+ return Status(ErrorCodes::InvalidRoleModification,
+ mongoutils::str::stream() << "Cannot grant role " <<
+ role.getFullName() << " to itself.");
+ }
+
+ if (role.getDB() != "admin" && roleToAdd.getDB() != role.getDB()) {
+ return Status(ErrorCodes::InvalidRoleModification,
+ str::stream() << "Roles on the \'" << role.getDB() <<
+ "\' database cannot be granted roles from other databases");
+ }
+
+ BSONObj roleToAddDoc;
+ Status status = authzManager->getRoleDescription(roleToAdd, false, &roleToAddDoc);
+ if (status == ErrorCodes::RoleNotFound) {
+ return Status(ErrorCodes::RoleNotFound,
+ "Cannot grant nonexistent role " + roleToAdd.toString());
+ }
+ if (!status.isOK()) {
+ return status;
+ }
+ std::vector<RoleName> indirectRoles;
+ status = auth::parseRoleNamesFromBSONArray(
+ BSONArray(roleToAddDoc["inheritedRoles"].Obj()),
+ role.getDB(),
+ &indirectRoles);
+ if (!status.isOK()) {
+ return status;
+ }
+
+ if (sequenceContains(indirectRoles, role)) {
+ return Status(ErrorCodes::InvalidRoleModification,
+ mongoutils::str::stream() << "Granting " <<
+ roleToAdd.getFullName() << " to " << role.getFullName()
+ << " would introduce a cycle in the role graph.");
+ }
+ }
+ return Status::OK();
+ }
+
+ /**
+ * Checks that every privilege being granted targets just the database the role is from, or that
+ * the role is from the "admin" db.
+ */
+ Status checkOkayToGrantPrivilegesToRole(const RoleName& role,
+ const PrivilegeVector& privileges) {
+ if (role.getDB() == "admin") {
+ return Status::OK();
+ }
+
+ for (PrivilegeVector::const_iterator it = privileges.begin();
+ it != privileges.end(); ++it) {
+ const ResourcePattern& resource = (*it).getResourcePattern();
+ if ((resource.isDatabasePattern() || resource.isExactNamespacePattern()) &&
+ (resource.databaseToMatch() == role.getDB())) {
+ continue;
+ }
+
+ return Status(ErrorCodes::InvalidRoleModification,
+ str::stream() << "Roles on the \'" << role.getDB() <<
+ "\' database cannot be granted privileges that target other "
+ "databases or the cluster");
+ }
+
+ return Status::OK();
+ }
+
+ void appendBSONObjToBSONArrayBuilder(BSONArrayBuilder* array, const BSONObj& obj) {
+ array->append(obj);
+ }
+
+ /**
+ * Inserts "document" into "collectionName".
+ * If there is a duplicate key error, returns a Status with code DuplicateKey.
+ *
+ * Should only be called on collections with authorization documents in them
+ * (ie admin.system.users and admin.system.roles).
+ */
+ Status insertAuthzDocument(OperationContext* txn,
+ const NamespaceString& collectionName,
+ const BSONObj& document,
+ const BSONObj& writeConcern) {
+ try {
+ DBDirectClient client(txn);
+ client.insert(collectionName, document);
+
+ // Handle write concern
+ 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::OK();
+ }
+ if (res.hasField("code") && res["code"].Int() == ASSERT_ID_DUPKEY) {
+ return Status(ErrorCodes::DuplicateKey, errstr);
+ }
+ return Status(ErrorCodes::UnknownError, errstr);
+ } catch (const DBException& e) {
+ return e.toStatus();
+ }
+ }
+
+ /**
+ * Updates documents matching "query" according to "updatePattern" in "collectionName".
+ *
+ * Should only be called on collections with authorization documents in them
+ * (ie admin.system.users and admin.system.roles).
+ */
+ Status updateAuthzDocuments(OperationContext* txn,
+ const NamespaceString& collectionName,
+ const BSONObj& query,
+ const BSONObj& updatePattern,
+ bool upsert,
+ bool multi,
+ const BSONObj& writeConcern,
+ int* nMatched) {
+ try {
+ DBDirectClient client(txn);
+ client.update(collectionName, query, updatePattern, upsert, multi);
+
+ // Handle write concern
+ 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()) {
+ *nMatched = res["n"].numberInt();
+ return Status::OK();
+ }
+ return Status(ErrorCodes::UnknownError, errstr);
+ } catch (const DBException& e) {
+ return e.toStatus();
+ }
+ }
+
+ /**
+ * Update one document matching "query" according to "updatePattern" in "collectionName".
+ *
+ * If "upsert" is true and no document matches "query", inserts one using "query" as a
+ * template.
+ * If "upsert" is false and no document matches "query", return a Status with the code
+ * NoMatchingDocument. The Status message in that case is not very descriptive and should
+ * not be displayed to the end user.
+ *
+ * Should only be called on collections with authorization documents in them
+ * (ie admin.system.users and admin.system.roles).
+ */
+ Status updateOneAuthzDocument(
+ OperationContext* txn,
+ const NamespaceString& collectionName,
+ const BSONObj& query,
+ const BSONObj& updatePattern,
+ bool upsert,
+ const BSONObj& writeConcern) {
+ int nMatched;
+ Status status = updateAuthzDocuments(txn,
+ collectionName,
+ query,
+ updatePattern,
+ upsert,
+ false,
+ writeConcern,
+ &nMatched);
+ if (!status.isOK()) {
+ return status;
+ }
+ dassert(nMatched == 1 || nMatched == 0);
+ if (nMatched == 0) {
+ return Status(ErrorCodes::NoMatchingDocument, "No document found");
+ }
+ return Status::OK();
+ }
+
+ /**
+ * Removes all documents matching "query" from "collectionName".
+ *
+ * Should only be called on collections with authorization documents in them
+ * (ie admin.system.users and admin.system.roles).
+ */
+ Status removeAuthzDocuments(
+ OperationContext* txn,
+ const NamespaceString& collectionName,
+ const BSONObj& query,
+ const BSONObj& writeConcern,
+ int* numRemoved) {
+ try {
+ DBDirectClient client(txn);
+ client.remove(collectionName, query);
+
+ // Handle write concern
+ 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()) {
+ *numRemoved = res["n"].numberInt();
+ return Status::OK();
+ }
+ return Status(ErrorCodes::UnknownError, errstr);
+ } catch (const DBException& e) {
+ return e.toStatus();
+ }
+ }
+
+ /**
+ * Creates the given role object in the given database.
+ * 'writeConcern' contains the arguments to be passed to getLastError to block for
+ * successful completion of the write.
+ */
+ Status insertRoleDocument(OperationContext* txn,
+ const BSONObj& roleObj,
+ const BSONObj& writeConcern) {
+ Status status = insertAuthzDocument(txn,
+ AuthorizationManager::rolesCollectionNamespace,
+ roleObj,
+ writeConcern);
+ if (status.isOK()) {
+ return status;
+ }
+ if (status.code() == ErrorCodes::DuplicateKey) {
+ std::string name = roleObj[AuthorizationManager::ROLE_NAME_FIELD_NAME].String();
+ std::string source = roleObj[AuthorizationManager::ROLE_DB_FIELD_NAME].String();
+ return Status(ErrorCodes::DuplicateKey,
+ str::stream() << "Role \"" << name << "@" << source
+ << "\" already exists");
+ }
+ if (status.code() == ErrorCodes::UnknownError) {
+ return Status(ErrorCodes::RoleModificationFailed, status.reason());
+ }
+ return status;
+ }
+
+ /**
+ * Updates the given role object with the given update modifier.
+ * 'writeConcern' contains the arguments to be passed to getLastError to block for
+ * successful completion of the write.
+ */
+ Status updateRoleDocument(OperationContext* txn,
+ const RoleName& role,
+ const BSONObj& updateObj,
+ const BSONObj& writeConcern) {
+ Status status = updateOneAuthzDocument(
+ txn,
+ AuthorizationManager::rolesCollectionNamespace,
+ BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME << role.getRole() <<
+ AuthorizationManager::ROLE_DB_FIELD_NAME << role.getDB()),
+ updateObj,
+ false,
+ writeConcern);
+ if (status.isOK()) {
+ return status;
+ }
+ if (status.code() == ErrorCodes::NoMatchingDocument) {
+ return Status(ErrorCodes::RoleNotFound,
+ str::stream() << "Role " << role.getFullName()
+ << " not found");
+ }
+ if (status.code() == ErrorCodes::UnknownError) {
+ return Status(ErrorCodes::RoleModificationFailed, status.reason());
+ }
+ return status;
+ }
+
+ /**
+ * Removes roles matching the given query.
+ * Writes into *numRemoved the number of role documents that were modified.
+ * 'writeConcern' contains the arguments to be passed to getLastError to block for
+ * successful completion of the write.
+ */
+ Status removeRoleDocuments(OperationContext* txn,
+ const BSONObj& query,
+ const BSONObj& writeConcern,
+ int* numRemoved) {
+ Status status = removeAuthzDocuments(txn,
+ AuthorizationManager::rolesCollectionNamespace,
+ query,
+ writeConcern,
+ numRemoved);
+ if (status.code() == ErrorCodes::UnknownError) {
+ return Status(ErrorCodes::RoleModificationFailed, status.reason());
+ }
+ return status;
+ }
+
+ /**
+ * Creates the given user object in the given database.
+ * 'writeConcern' contains the arguments to be passed to getLastError to block for
+ * successful completion of the write.
+ */
+ Status insertPrivilegeDocument(OperationContext* txn,
+ const BSONObj& userObj,
+ const BSONObj& writeConcern) {
+ Status status = insertAuthzDocument(txn,
+ AuthorizationManager::usersCollectionNamespace,
+ userObj,
+ writeConcern);
+ if (status.isOK()) {
+ return status;
+ }
+ if (status.code() == ErrorCodes::DuplicateKey) {
+ std::string name = userObj[AuthorizationManager::USER_NAME_FIELD_NAME].String();
+ std::string source = userObj[AuthorizationManager::USER_DB_FIELD_NAME].String();
+ return Status(ErrorCodes::DuplicateKey,
+ str::stream() << "User \"" << name << "@" << source
+ << "\" already exists");
+ }
+ if (status.code() == ErrorCodes::UnknownError) {
+ return Status(ErrorCodes::UserModificationFailed, status.reason());
+ }
+ return status;
+ }
+
+ /**
+ * Updates the given user object with the given update modifier.
+ * 'writeConcern' contains the arguments to be passed to getLastError to block for
+ * successful completion of the write.
+ */
+ Status updatePrivilegeDocument(OperationContext* txn,
+ const UserName& user,
+ const BSONObj& updateObj,
+ const BSONObj& writeConcern) {
+ Status status = updateOneAuthzDocument(
+ txn,
+ AuthorizationManager::usersCollectionNamespace,
+ BSON(AuthorizationManager::USER_NAME_FIELD_NAME << user.getUser() <<
+ AuthorizationManager::USER_DB_FIELD_NAME << user.getDB()),
+ updateObj,
+ false,
+ writeConcern);
+ if (status.isOK()) {
+ return status;
+ }
+ if (status.code() == ErrorCodes::NoMatchingDocument) {
+ return Status(ErrorCodes::UserNotFound,
+ str::stream() << "User " << user.getFullName()
+ << " not found");
+ }
+ if (status.code() == ErrorCodes::UnknownError) {
+ return Status(ErrorCodes::UserModificationFailed, status.reason());
+ }
+ return status;
+ }
+
+ /**
+ * Removes users for the given database matching the given query.
+ * Writes into *numRemoved the number of user documents that were modified.
+ * 'writeConcern' contains the arguments to be passed to getLastError to block for
+ * successful completion of the write.
+ */
+ Status removePrivilegeDocuments(OperationContext* txn,
+ const BSONObj& query,
+ const BSONObj& writeConcern,
+ int* numRemoved) {
+ Status status = removeAuthzDocuments(txn,
+ AuthorizationManager::usersCollectionNamespace,
+ query,
+ writeConcern,
+ numRemoved);
+ if (status.code() == ErrorCodes::UnknownError) {
+ return Status(ErrorCodes::UserModificationFailed, status.reason());
+ }
+ return status;
+ }
+
+ /**
+ * Updates the auth schema version document to reflect the current state of the system.
+ * 'foundSchemaVersion' is the authSchemaVersion to update with.
+ */
+ Status writeAuthSchemaVersionIfNeeded(OperationContext* txn,
+ AuthorizationManager* authzManager,
+ int foundSchemaVersion) {
+ Status status = updateOneAuthzDocument(txn,
+ AuthorizationManager::versionCollectionNamespace,
+ AuthorizationManager::versionDocumentQuery,
+ BSON("$set" << BSON(AuthorizationManager::schemaVersionFieldName
+ << foundSchemaVersion)),
+ true, // upsert
+ BSONObj()); // write concern
+ if (status == ErrorCodes::NoMatchingDocument) { // SERVER-11492
+ status = Status::OK();
+ }
+
+ return status;
+ }
+
+ /**
+ * Returns Status::OK() if the current Auth schema version is at least the auth schema version
+ * for the MongoDB 2.6 and 3.0 MongoDB-CR/SCRAM mixed auth mode.
+ * Returns an error otherwise.
+ */
+ Status requireAuthSchemaVersion26Final(OperationContext* txn,
+ AuthorizationManager* authzManager) {
+ int foundSchemaVersion;
+ Status status = authzManager->getAuthorizationVersion(txn, &foundSchemaVersion);
+ if (!status.isOK()) {
+ return status;
+ }
+
+ if (foundSchemaVersion < AuthorizationManager::schemaVersion26Final) {
+ return Status(
+ ErrorCodes::AuthSchemaIncompatible,
+ str::stream() << "User and role management commands require auth data to have "
+ << "at least schema version "
+ << AuthorizationManager::schemaVersion26Final
+ << " but found " << foundSchemaVersion);
+ }
+ return writeAuthSchemaVersionIfNeeded(txn, authzManager, foundSchemaVersion);
+ }
+
+ /**
+ * Returns Status::OK() if the current Auth schema version is at least the auth schema version
+ * for MongoDB 2.6 during the upgrade process.
+ * Returns an error otherwise.
+ */
+ Status requireAuthSchemaVersion26UpgradeOrFinal(OperationContext* txn,
+ AuthorizationManager* authzManager) {
+ int foundSchemaVersion;
+ Status status = authzManager->getAuthorizationVersion(txn, &foundSchemaVersion);
+ if (!status.isOK()) {
+ return status;
+ }
+
+ if (foundSchemaVersion < AuthorizationManager::schemaVersion26Upgrade) {
+ return Status(
+ ErrorCodes::AuthSchemaIncompatible,
+ str::stream() << "The usersInfo and rolesInfo commands require auth data to "
+ << "have at least schema version "
+ << AuthorizationManager::schemaVersion26Upgrade
+ << " but found " << foundSchemaVersion);
+ }
+ return Status::OK();
+ }
+
} // namespace
+
+
class CmdCreateUser : public Command {
public:
@@ -205,7 +725,7 @@ namespace {
if (args.hasCustomData) {
userObjBuilder.append("customData", args.customData);
}
- userObjBuilder.append("roles", auth::rolesVectorToBSONArray(args.roles));
+ userObjBuilder.append("roles", rolesVectorToBSONArray(args.roles));
BSONObj userObj = userObjBuilder.obj();
V2UserDocumentParser parser;
@@ -222,7 +742,7 @@ namespace {
Status(ErrorCodes::LockBusy, "Could not lock auth data update lock."));
}
- status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -241,10 +761,9 @@ namespace {
args.hasHashedPassword,
args.hasCustomData? &args.customData : NULL,
args.roles);
- status = authzManager->insertPrivilegeDocument(txn,
- dbname,
- userObj,
- args.writeConcern);
+ status = insertPrivilegeDocument(txn,
+ userObj,
+ args.writeConcern);
return appendCommandStatus(result, status);
}
@@ -331,7 +850,7 @@ namespace {
updateSetBuilder.append("customData", args.customData);
}
if (args.hasRoles) {
- updateSetBuilder.append("roles", auth::rolesVectorToBSONArray(args.roles));
+ updateSetBuilder.append("roles", rolesVectorToBSONArray(args.roles));
}
ServiceContext* serviceContext = txn->getClient()->getServiceContext();
@@ -344,7 +863,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -367,10 +886,10 @@ namespace {
args.hasCustomData? &args.customData : NULL,
args.hasRoles? &args.roles : NULL);
- status = authzManager->updatePrivilegeDocument(txn,
- args.userName,
- BSON("$set" << updateSetBuilder.done()),
- args.writeConcern);
+ status = updatePrivilegeDocument(txn,
+ args.userName,
+ BSON("$set" << updateSetBuilder.done()),
+ args.writeConcern);
// Must invalidate even on bad status - what if the write succeeded but the GLE failed?
authzManager->invalidateUserByName(args.userName);
return appendCommandStatus(result, status);
@@ -418,7 +937,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- Status status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -438,7 +957,7 @@ namespace {
audit::logDropUser(ClientBasic::getCurrent(), userName);
- status = authzManager->removePrivilegeDocuments(
+ status = removePrivilegeDocuments(
txn,
BSON(AuthorizationManager::USER_NAME_FIELD_NAME << userName.getUser() <<
AuthorizationManager::USER_DB_FIELD_NAME << userName.getDB()),
@@ -499,7 +1018,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- Status status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -516,7 +1035,7 @@ namespace {
audit::logDropAllUsersFromDatabase(ClientBasic::getCurrent(), dbname);
- status = authzManager->removePrivilegeDocuments(
+ status = removePrivilegeDocuments(
txn,
BSON(AuthorizationManager::USER_DB_FIELD_NAME << dbname),
writeConcern,
@@ -569,7 +1088,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- Status status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -589,7 +1108,7 @@ namespace {
UserName userName(userNameString, dbname);
unordered_set<RoleName> userRoles;
- status = auth::getCurrentUserRoles(txn, authzManager, userName, &userRoles);
+ status = getCurrentUserRoles(txn, authzManager, userName, &userRoles);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -608,8 +1127,8 @@ namespace {
audit::logGrantRolesToUser(ClientBasic::getCurrent(),
userName,
roles);
- BSONArray newRolesBSONArray = auth::roleSetToBSONArray(userRoles);
- status = authzManager->updatePrivilegeDocument(
+ BSONArray newRolesBSONArray = roleSetToBSONArray(userRoles);
+ status = updatePrivilegeDocument(
txn, userName, BSON("$set" << BSON("roles" << newRolesBSONArray)), writeConcern);
// Must invalidate even on bad status - what if the write succeeded but the GLE failed?
authzManager->invalidateUserByName(userName);
@@ -654,7 +1173,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- Status status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -674,7 +1193,7 @@ namespace {
UserName userName(userNameString, dbname);
unordered_set<RoleName> userRoles;
- status = auth::getCurrentUserRoles(txn, authzManager, userName, &userRoles);
+ status = getCurrentUserRoles(txn, authzManager, userName, &userRoles);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -693,8 +1212,8 @@ namespace {
audit::logRevokeRolesFromUser(ClientBasic::getCurrent(),
userName,
roles);
- BSONArray newRolesBSONArray = auth::roleSetToBSONArray(userRoles);
- status = authzManager->updatePrivilegeDocument(
+ BSONArray newRolesBSONArray = roleSetToBSONArray(userRoles);
+ status = updatePrivilegeDocument(
txn, userName, BSON("$set" << BSON("roles" << newRolesBSONArray)), writeConcern);
// Must invalidate even on bad status - what if the write succeeded but the GLE failed?
authzManager->invalidateUserByName(userName);
@@ -740,9 +1259,8 @@ namespace {
return appendCommandStatus(result, status);
}
- status =
- auth::requireAuthSchemaVersion26UpgradeOrFinal(txn,
- getGlobalAuthorizationManager());
+ status = requireAuthSchemaVersion26UpgradeOrFinal(txn,
+ getGlobalAuthorizationManager());
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -804,7 +1322,7 @@ namespace {
projection.append("credentials", 0);
}
const stdx::function<void(const BSONObj&)> function = stdx::bind(
- auth::appendBSONObjToBSONArrayBuilder,
+ appendBSONObjToBSONArrayBuilder,
&usersArrayBuilder,
stdx::placeholders::_1);
authzManager->queryAuthzDocument(txn,
@@ -897,13 +1415,13 @@ namespace {
args.roleName.getDB());
BSONArray privileges;
- status = auth::privilegeVectorToBSONArray(args.privileges, &privileges);
+ status = privilegeVectorToBSONArray(args.privileges, &privileges);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
roleObjBuilder.append("privileges", privileges);
- roleObjBuilder.append("roles", auth::rolesVectorToBSONArray(args.roles));
+ roleObjBuilder.append("roles", rolesVectorToBSONArray(args.roles));
ServiceContext* serviceContext = txn->getClient()->getServiceContext();
boost::unique_lock<boost::timed_mutex> lk(getAuthzDataMutex(serviceContext),
@@ -915,18 +1433,18 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
// Role existence has to be checked after acquiring the update lock
- status = auth::checkOkayToGrantRolesToRole(args.roleName, args.roles, authzManager);
+ status = checkOkayToGrantRolesToRole(args.roleName, args.roles, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
- status = auth::checkOkayToGrantPrivilegesToRole(args.roleName, args.privileges);
+ status = checkOkayToGrantPrivilegesToRole(args.roleName, args.privileges);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -936,7 +1454,7 @@ namespace {
args.roles,
args.privileges);
- status = authzManager->insertRoleDocument(txn, roleObjBuilder.done(), args.writeConcern);
+ status = insertRoleDocument(txn, roleObjBuilder.done(), args.writeConcern);
return appendCommandStatus(result, status);
}
@@ -988,7 +1506,7 @@ namespace {
if (args.hasPrivileges) {
BSONArray privileges;
- status = auth::privilegeVectorToBSONArray(args.privileges, &privileges);
+ status = privilegeVectorToBSONArray(args.privileges, &privileges);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -996,7 +1514,7 @@ namespace {
}
if (args.hasRoles) {
- updateSetBuilder.append("roles", auth::rolesVectorToBSONArray(args.roles));
+ updateSetBuilder.append("roles", rolesVectorToBSONArray(args.roles));
}
ServiceContext* serviceContext = txn->getClient()->getServiceContext();
@@ -1009,7 +1527,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1022,14 +1540,14 @@ namespace {
}
if (args.hasRoles) {
- status = auth::checkOkayToGrantRolesToRole(args.roleName, args.roles, authzManager);
+ status = checkOkayToGrantRolesToRole(args.roleName, args.roles, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
}
if (args.hasPrivileges) {
- status = auth::checkOkayToGrantPrivilegesToRole(args.roleName, args.privileges);
+ status = checkOkayToGrantPrivilegesToRole(args.roleName, args.privileges);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1040,10 +1558,10 @@ namespace {
args.hasRoles? &args.roles : NULL,
args.hasPrivileges? &args.privileges : NULL);
- status = authzManager->updateRoleDocument(txn,
- args.roleName,
- BSON("$set" << updateSetBuilder.done()),
- args.writeConcern);
+ status = updateRoleDocument(txn,
+ args.roleName,
+ BSON("$set" << updateSetBuilder.done()),
+ args.writeConcern);
// Must invalidate even on bad status - what if the write succeeded but the GLE failed?
authzManager->invalidateUserCache();
return appendCommandStatus(result, status);
@@ -1086,7 +1604,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- Status status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1113,7 +1631,7 @@ namespace {
" is a built-in role and cannot be modified."));
}
- status = auth::checkOkayToGrantPrivilegesToRole(roleName, privilegesToAdd);
+ status = checkOkayToGrantPrivilegesToRole(roleName, privilegesToAdd);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1161,7 +1679,7 @@ namespace {
roleName,
privilegesToAdd);
- status = authzManager->updateRoleDocument(
+ status = updateRoleDocument(
txn,
roleName,
updateBSONBuilder.done(),
@@ -1209,7 +1727,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- Status status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1286,7 +1804,7 @@ namespace {
BSONObjBuilder updateBSONBuilder;
updateObj.writeTo(&updateBSONBuilder);
- status = authzManager->updateRoleDocument(
+ status = updateRoleDocument(
txn,
roleName,
updateBSONBuilder.done(),
@@ -1357,7 +1875,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1370,7 +1888,7 @@ namespace {
}
// Check for cycles
- status = auth::checkOkayToGrantRolesToRole(roleName, rolesToAdd, authzManager);
+ status = checkOkayToGrantRolesToRole(roleName, rolesToAdd, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1393,10 +1911,10 @@ namespace {
roleName,
rolesToAdd);
- status = authzManager->updateRoleDocument(
+ status = updateRoleDocument(
txn,
roleName,
- BSON("$set" << BSON("roles" << auth::rolesVectorToBSONArray(directRoles))),
+ BSON("$set" << BSON("roles" << rolesVectorToBSONArray(directRoles))),
writeConcern);
// Must invalidate even on bad status - what if the write succeeded but the GLE failed?
authzManager->invalidateUserCache();
@@ -1441,7 +1959,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- Status status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1494,10 +2012,10 @@ namespace {
roleName,
rolesToRemove);
- status = authzManager->updateRoleDocument(
+ status = updateRoleDocument(
txn,
roleName,
- BSON("$set" << BSON("roles" << auth::rolesVectorToBSONArray(roles))),
+ BSON("$set" << BSON("roles" << rolesVectorToBSONArray(roles))),
writeConcern);
// Must invalidate even on bad status - what if the write succeeded but the GLE failed?
authzManager->invalidateUserCache();
@@ -1545,7 +2063,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- Status status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ Status status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1576,9 +2094,9 @@ namespace {
// Remove this role from all users
int nMatched;
- status = authzManager->updateAuthzDocuments(
+ status = updateAuthzDocuments(
txn,
- NamespaceString("admin.system.users"),
+ AuthorizationManager::usersCollectionNamespace,
BSON("roles" << BSON("$elemMatch" <<
BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME <<
roleName.getRole() <<
@@ -1606,9 +2124,9 @@ namespace {
}
// Remove this role from all other roles
- status = authzManager->updateAuthzDocuments(
+ status = updateAuthzDocuments(
txn,
- NamespaceString("admin.system.roles"),
+ AuthorizationManager::rolesCollectionNamespace,
BSON("roles" << BSON("$elemMatch" <<
BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME <<
roleName.getRole() <<
@@ -1639,7 +2157,7 @@ namespace {
audit::logDropRole(ClientBasic::getCurrent(),
roleName);
// Finally, remove the actual role document
- status = authzManager->removeRoleDocuments(
+ status = removeRoleDocuments(
txn,
BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME << roleName.getRole() <<
AuthorizationManager::ROLE_DB_FIELD_NAME << roleName.getDB()),
@@ -1718,14 +2236,14 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
// Remove these roles from all users
int nMatched;
- status = authzManager->updateAuthzDocuments(
+ status = updateAuthzDocuments(
txn,
AuthorizationManager::usersCollectionNamespace,
BSON("roles" << BSON(AuthorizationManager::ROLE_DB_FIELD_NAME << dbname)),
@@ -1751,7 +2269,7 @@ namespace {
// Remove these roles from all other roles
std::string sourceFieldName =
str::stream() << "roles." << AuthorizationManager::ROLE_DB_FIELD_NAME;
- status = authzManager->updateAuthzDocuments(
+ status = updateAuthzDocuments(
txn,
AuthorizationManager::rolesCollectionNamespace,
BSON(sourceFieldName << dbname),
@@ -1776,7 +2294,7 @@ namespace {
audit::logDropAllRolesFromDatabase(ClientBasic::getCurrent(), dbname);
// Finally, remove the actual role documents
- status = authzManager->removeRoleDocuments(
+ status = removeRoleDocuments(
txn,
BSON(AuthorizationManager::ROLE_DB_FIELD_NAME << dbname),
writeConcern,
@@ -1836,9 +2354,8 @@ namespace {
return appendCommandStatus(result, status);
}
- status =
- auth::requireAuthSchemaVersion26UpgradeOrFinal(txn,
- getGlobalAuthorizationManager());
+ status = requireAuthSchemaVersion26UpgradeOrFinal(txn,
+ getGlobalAuthorizationManager());
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -2110,10 +2627,10 @@ namespace {
if (update && usersToDrop->count(userName)) {
auditCreateOrUpdateUser(userObj, false);
- Status status = authzManager->updatePrivilegeDocument(txn,
- userName,
- userObj,
- writeConcern);
+ Status status = updatePrivilegeDocument(txn,
+ userName,
+ userObj,
+ writeConcern);
if (!status.isOK()) {
// Match the behavior of mongorestore to continue on failure
warning() << "Could not update user " << userName <<
@@ -2121,10 +2638,9 @@ namespace {
}
} else {
auditCreateOrUpdateUser(userObj, true);
- Status status = authzManager->insertPrivilegeDocument(txn,
- userName.getDB().toString(),
- userObj,
- writeConcern);
+ Status status = insertPrivilegeDocument(txn,
+ userObj,
+ writeConcern);
if (!status.isOK()) {
// Match the behavior of mongorestore to continue on failure
warning() << "Could not insert user " << userName <<
@@ -2155,10 +2671,10 @@ namespace {
if (update && rolesToDrop->count(roleName)) {
auditCreateOrUpdateRole(roleObj, false);
- Status status = authzManager->updateRoleDocument(txn,
- roleName,
- roleObj,
- writeConcern);
+ Status status = updateRoleDocument(txn,
+ roleName,
+ roleObj,
+ writeConcern);
if (!status.isOK()) {
// Match the behavior of mongorestore to continue on failure
warning() << "Could not update role " << roleName <<
@@ -2166,7 +2682,7 @@ namespace {
}
} else {
auditCreateOrUpdateRole(roleObj, true);
- Status status = authzManager->insertRoleDocument(txn, roleObj, writeConcern);
+ Status status = insertRoleDocument(txn, roleObj, writeConcern);
if (!status.isOK()) {
// Match the behavior of mongorestore to continue on failure
warning() << "Could not insert role " << roleName <<
@@ -2240,7 +2756,7 @@ namespace {
it != usersToDrop.end(); ++it) {
const UserName& userName = *it;
audit::logDropUser(ClientBasic::getCurrent(), userName);
- status = authzManager->removePrivilegeDocuments(
+ status = removePrivilegeDocuments(
txn,
BSON(AuthorizationManager::USER_NAME_FIELD_NAME <<
userName.getUser().toString() <<
@@ -2323,7 +2839,7 @@ namespace {
it != rolesToDrop.end(); ++it) {
const RoleName& roleName = *it;
audit::logDropRole(ClientBasic::getCurrent(), roleName);
- status = authzManager->removeRoleDocuments(
+ status = removeRoleDocuments(
txn,
BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME <<
roleName.getRole().toString() <<
@@ -2371,7 +2887,7 @@ namespace {
}
AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext);
- status = auth::requireAuthSchemaVersion26Final(txn, authzManager);
+ status = requireAuthSchemaVersion26Final(txn, authzManager);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
diff --git a/src/mongo/db/commands/user_management_commands.h b/src/mongo/db/commands/user_management_commands.h
index 5f21c719117..6b67b8f7891 100644
--- a/src/mongo/db/commands/user_management_commands.h
+++ b/src/mongo/db/commands/user_management_commands.h
@@ -35,7 +35,6 @@
#include "mongo/db/auth/privilege.h"
#include "mongo/db/auth/role_name.h"
#include "mongo/db/auth/user_name.h"
-#include "mongo/platform/unordered_set.h"
namespace mongo {
@@ -55,55 +54,6 @@ namespace auth {
*/
void redactPasswordData(mutablebson::Element parent);
- BSONArray roleSetToBSONArray(const unordered_set<RoleName>& roles);
-
- BSONArray rolesVectorToBSONArray(const std::vector<RoleName>& roles);
-
- Status privilegeVectorToBSONArray(const PrivilegeVector& privileges, BSONArray* result);
-
- /**
- * Used to get all current roles of the user identified by 'userName'.
- */
- Status getCurrentUserRoles(OperationContext* txn,
- AuthorizationManager* authzManager,
- const UserName& userName,
- unordered_set<RoleName>* roles);
-
- /**
- * Checks that every role in "rolesToAdd" exists, that adding each of those roles to "role"
- * will not result in a cycle to the role graph, and that every role being added comes from the
- * same database as the role it is being added to (or that the role being added to is from the
- * "admin" database.
- */
- Status checkOkayToGrantRolesToRole(const RoleName& role,
- const std::vector<RoleName> rolesToAdd,
- AuthorizationManager* authzManager);
-
- /**
- * Checks that every privilege being granted targets just the database the role is from, or that
- * the role is from the "admin" db.
- */
- Status checkOkayToGrantPrivilegesToRole(const RoleName& role,
- const PrivilegeVector& privileges);
-
- /**
- * Returns Status::OK() if the current Auth schema version is at least the auth schema version
- * for the MongoDB 2.6 and 3.0 MongoDB-CR/SCRAM mixed auth mode.
- * Returns an error otherwise.
- */
- Status requireAuthSchemaVersion26Final(OperationContext* txn,
- AuthorizationManager* authzManager);
-
- /**
- * Returns Status::OK() if the current Auth schema version is at least the auth schema version
- * for MongoDB 2.6 during the upgrade process.
- * Returns an error otherwise.
- */
- Status requireAuthSchemaVersion26UpgradeOrFinal(OperationContext* txn,
- AuthorizationManager* authzManager);
-
- void appendBSONObjToBSONArrayBuilder(BSONArrayBuilder* array, const BSONObj& obj);
-
//
// checkAuthorizedTo* methods
//
diff --git a/src/mongo/db/commands/user_management_commands_common.cpp b/src/mongo/db/commands/user_management_commands_common.cpp
index cfe634f142a..9e2210a92d5 100644
--- a/src/mongo/db/commands/user_management_commands_common.cpp
+++ b/src/mongo/db/commands/user_management_commands_common.cpp
@@ -40,7 +40,6 @@
#include "mongo/config.h"
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
-#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/resource_pattern.h"
#include "mongo/db/auth/user.h"
@@ -64,178 +63,6 @@ namespace auth {
}
}
- BSONArray roleSetToBSONArray(const unordered_set<RoleName>& roles) {
- BSONArrayBuilder rolesArrayBuilder;
- for (unordered_set<RoleName>::const_iterator it = roles.begin(); it != roles.end(); ++it) {
- const RoleName& role = *it;
- rolesArrayBuilder.append(
- BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME << role.getRole() <<
- AuthorizationManager::ROLE_DB_FIELD_NAME << role.getDB()));
- }
- return rolesArrayBuilder.arr();
- }
-
- BSONArray rolesVectorToBSONArray(const std::vector<RoleName>& roles) {
- BSONArrayBuilder rolesArrayBuilder;
- for (std::vector<RoleName>::const_iterator it = roles.begin(); it != roles.end(); ++it) {
- const RoleName& role = *it;
- rolesArrayBuilder.append(
- BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME << role.getRole() <<
- AuthorizationManager::ROLE_DB_FIELD_NAME << role.getDB()));
- }
- return rolesArrayBuilder.arr();
- }
-
- Status privilegeVectorToBSONArray(const PrivilegeVector& privileges, BSONArray* result) {
- BSONArrayBuilder arrBuilder;
- for (PrivilegeVector::const_iterator it = privileges.begin();
- it != privileges.end(); ++it) {
- const Privilege& privilege = *it;
-
- ParsedPrivilege parsedPrivilege;
- std::string errmsg;
- if (!ParsedPrivilege::privilegeToParsedPrivilege(privilege,
- &parsedPrivilege,
- &errmsg)) {
- return Status(ErrorCodes::FailedToParse, errmsg);
- }
- if (!parsedPrivilege.isValid(&errmsg)) {
- return Status(ErrorCodes::FailedToParse, errmsg);
- }
- arrBuilder.append(parsedPrivilege.toBSON());
- }
- *result = arrBuilder.arr();
- return Status::OK();
- }
-
- Status getCurrentUserRoles(OperationContext* txn,
- AuthorizationManager* authzManager,
- const UserName& userName,
- unordered_set<RoleName>* roles) {
- User* user;
- authzManager->invalidateUserByName(userName); // Need to make sure cache entry is up to date
- Status status = authzManager->acquireUser(txn, userName, &user);
- if (!status.isOK()) {
- return status;
- }
- RoleNameIterator rolesIt = user->getRoles();
- while (rolesIt.more()) {
- roles->insert(rolesIt.next());
- }
- authzManager->releaseUser(user);
- return Status::OK();
- }
-
- Status checkOkayToGrantRolesToRole(const RoleName& role,
- const std::vector<RoleName> rolesToAdd,
- AuthorizationManager* authzManager) {
- for (std::vector<RoleName>::const_iterator it = rolesToAdd.begin();
- it != rolesToAdd.end(); ++it) {
- const RoleName& roleToAdd = *it;
- if (roleToAdd == role) {
- return Status(ErrorCodes::InvalidRoleModification,
- mongoutils::str::stream() << "Cannot grant role " <<
- role.getFullName() << " to itself.");
- }
-
- if (role.getDB() != "admin" && roleToAdd.getDB() != role.getDB()) {
- return Status(ErrorCodes::InvalidRoleModification,
- str::stream() << "Roles on the \'" << role.getDB() <<
- "\' database cannot be granted roles from other databases");
- }
-
- BSONObj roleToAddDoc;
- Status status = authzManager->getRoleDescription(roleToAdd, false, &roleToAddDoc);
- if (status == ErrorCodes::RoleNotFound) {
- return Status(ErrorCodes::RoleNotFound,
- "Cannot grant nonexistent role " + roleToAdd.toString());
- }
- if (!status.isOK()) {
- return status;
- }
- std::vector<RoleName> indirectRoles;
- status = auth::parseRoleNamesFromBSONArray(
- BSONArray(roleToAddDoc["inheritedRoles"].Obj()),
- role.getDB(),
- &indirectRoles);
- if (!status.isOK()) {
- return status;
- }
-
- if (sequenceContains(indirectRoles, role)) {
- return Status(ErrorCodes::InvalidRoleModification,
- mongoutils::str::stream() << "Granting " <<
- roleToAdd.getFullName() << " to " << role.getFullName()
- << " would introduce a cycle in the role graph.");
- }
- }
- return Status::OK();
- }
-
- Status checkOkayToGrantPrivilegesToRole(const RoleName& role,
- const PrivilegeVector& privileges) {
- if (role.getDB() == "admin") {
- return Status::OK();
- }
-
- for (PrivilegeVector::const_iterator it = privileges.begin();
- it != privileges.end(); ++it) {
- const ResourcePattern& resource = (*it).getResourcePattern();
- if ((resource.isDatabasePattern() || resource.isExactNamespacePattern()) &&
- (resource.databaseToMatch() == role.getDB())) {
- continue;
- }
-
- return Status(ErrorCodes::InvalidRoleModification,
- str::stream() << "Roles on the \'" << role.getDB() <<
- "\' database cannot be granted privileges that target other "
- "databases or the cluster");
- }
-
- return Status::OK();
- }
-
- Status requireAuthSchemaVersion26Final(OperationContext* txn,
- AuthorizationManager* authzManager) {
- int foundSchemaVersion;
- Status status = authzManager->getAuthorizationVersion(txn, &foundSchemaVersion);
- if (!status.isOK()) {
- return status;
- }
-
- if (foundSchemaVersion < AuthorizationManager::schemaVersion26Final) {
- return Status(
- ErrorCodes::AuthSchemaIncompatible,
- str::stream() << "User and role management commands require auth data to have "
- "at least schema version " << AuthorizationManager::schemaVersion26Final <<
- " but found " << foundSchemaVersion);
- }
- return authzManager->writeAuthSchemaVersionIfNeeded(txn, foundSchemaVersion);
- }
-
- Status requireAuthSchemaVersion26UpgradeOrFinal(OperationContext* txn,
- AuthorizationManager* authzManager) {
- int foundSchemaVersion;
- Status status = authzManager->getAuthorizationVersion(txn, &foundSchemaVersion);
- if (!status.isOK()) {
- return status;
- }
-
- if (foundSchemaVersion < AuthorizationManager::schemaVersion26Upgrade) {
- return Status(
- ErrorCodes::AuthSchemaIncompatible,
- str::stream() << "The usersInfo and rolesInfo commands require auth data to "
- "have at least schema version " <<
- AuthorizationManager::schemaVersion26Upgrade <<
- " but found " << foundSchemaVersion);
- }
- return Status::OK();
- }
-
- void appendBSONObjToBSONArrayBuilder(BSONArrayBuilder* array, const BSONObj& obj) {
- array->append(obj);
- }
-
Status checkAuthorizedToGrantRoles(AuthorizationSession* authzSession,
const std::vector<RoleName>& roles) {
for (size_t i = 0; i < roles.size(); ++i) {