summaryrefslogtreecommitdiff
path: root/src/mongo/db/auth
diff options
context:
space:
mode:
authorSpencer T Brody <spencer@mongodb.com>2014-02-06 14:16:40 -0500
committerSpencer T Brody <spencer@mongodb.com>2014-02-07 15:41:33 -0500
commit75d912c25ab2a2aabaab73b22a6cafddeb6c4906 (patch)
tree4cd664b59d85c1d09580994c3c6fd661004c6892 /src/mongo/db/auth
parent8ca048383099f4e0c70f79d2bccdcebd1c1df33c (diff)
downloadmongo-75d912c25ab2a2aabaab73b22a6cafddeb6c4906.tar.gz
Move some code out of auth_helpers.cpp back to the AuthorizationManager
Diffstat (limited to 'src/mongo/db/auth')
-rw-r--r--src/mongo/db/auth/authorization_manager.cpp105
1 files changed, 102 insertions, 3 deletions
diff --git a/src/mongo/db/auth/authorization_manager.cpp b/src/mongo/db/auth/authorization_manager.cpp
index 95fe058f2eb..318952e82cd 100644
--- a/src/mongo/db/auth/authorization_manager.cpp
+++ b/src/mongo/db/auth/authorization_manager.cpp
@@ -913,6 +913,24 @@ namespace {
const BSONObj& oldUserDoc,
const BSONObj& writeConcern) {
+ uassert(17387,
+ mongoutils::str::stream() << "While preparing to upgrade user doc from the 2.4 "
+ "user data schema to the 2.6 schema, found a user doc with a "
+ "\"credentials\" field, indicating that the doc already has the new "
+ "schema. Make sure that all documents in admin.system.users have the same "
+ "user data schema and that the version document in admin.system.version "
+ "indicates the correct schema version. User doc found: " <<
+ oldUserDoc.toString(),
+ !oldUserDoc.hasField("credentials"));
+
+ uassert(17386,
+ mongoutils::str::stream() << "While preparing to upgrade user doc from "
+ "the 2.4 user data schema to the 2.6 schema, found a user doc "
+ "that doesn't conform to the 2.4 *or* 2.6 schema. Doc found: "
+ << oldUserDoc.toString(),
+ oldUserDoc.hasField("user") &&
+ (oldUserDoc.hasField("userSource") || oldUserDoc.hasField("pwd")));
+
std::string oldUserSource;
uassertStatusOK(bsonExtractStringFieldWithDefault(
oldUserDoc,
@@ -923,9 +941,90 @@ namespace {
if (oldUserSource == "local")
return; // Skips users from "local" database, which cannot be upgraded.
- BSONObj query;
- BSONObj update;
- auth::getUpdateToUpgradeUser(sourceDB, oldUserDoc, &query, &update);
+ const std::string oldUserName = oldUserDoc["user"].String();
+ BSONObj query = BSON("_id" << oldUserSource + "." + oldUserName);
+
+ BSONObjBuilder updateBuilder;
+ {
+ BSONObjBuilder toSetBuilder(updateBuilder.subobjStart("$set"));
+ toSetBuilder << "user" << oldUserName << "db" << oldUserSource;
+ BSONElement pwdElement = oldUserDoc["pwd"];
+ if (!pwdElement.eoo()) {
+ toSetBuilder << "credentials" << BSON("MONGODB-CR" << pwdElement.String());
+ }
+ else if (oldUserSource == "$external") {
+ toSetBuilder << "credentials" << BSON("external" << true);
+ }
+ }
+ {
+ BSONObjBuilder pushAllBuilder(updateBuilder.subobjStart("$pushAll"));
+ BSONArrayBuilder rolesBuilder(pushAllBuilder.subarrayStart("roles"));
+
+ const bool readOnly = oldUserDoc["readOnly"].trueValue();
+ const BSONElement rolesElement = oldUserDoc["roles"];
+ if (readOnly) {
+ // Handles the cases where there is a truthy readOnly field, which is a 2.2-style
+ // read-only user.
+ if (sourceDB == "admin") {
+ rolesBuilder << BSON("role" << "readAnyDatabase" << "db" << "admin");
+ }
+ else {
+ rolesBuilder << BSON("role" << "read" << "db" << sourceDB);
+ }
+ }
+ else if (rolesElement.eoo()) {
+ // Handles the cases where the readOnly field is absent or falsey, but the
+ // user is known to be 2.2-style because it lacks a roles array.
+ if (sourceDB == "admin") {
+ rolesBuilder << BSON("role" << "root" << "db" << "admin");
+ }
+ else {
+ rolesBuilder << BSON("role" << "dbOwner" << "db" << sourceDB);
+ }
+ }
+ else {
+ // Handles 2.4-style user documents, with roles arrays and (optionally, in admin db)
+ // otherDBRoles objects.
+ uassert(17252,
+ "roles field in v2.4 user documents must be an array",
+ rolesElement.type() == Array);
+ for (BSONObjIterator oldRoles(rolesElement.Obj());
+ oldRoles.more();
+ oldRoles.next()) {
+
+ BSONElement roleElement = *oldRoles;
+ rolesBuilder << BSON("role" << roleElement.String() << "db" << sourceDB);
+ }
+
+ BSONElement otherDBRolesElement = oldUserDoc["otherDBRoles"];
+ if (sourceDB == "admin" && !otherDBRolesElement.eoo()) {
+ uassert(17253,
+ "otherDBRoles field in v2.4 user documents must be an object.",
+ otherDBRolesElement.type() == Object);
+
+ for (BSONObjIterator otherDBs(otherDBRolesElement.Obj());
+ otherDBs.more();
+ otherDBs.next()) {
+
+ BSONElement otherDBRoles = *otherDBs;
+ if (otherDBRoles.fieldNameStringData() == "local")
+ continue;
+ uassert(17254,
+ "Member fields of otherDBRoles objects must be arrays.",
+ otherDBRoles.type() == Array);
+ for (BSONObjIterator oldRoles(otherDBRoles.Obj());
+ oldRoles.more();
+ oldRoles.next()) {
+
+ BSONElement roleElement = *oldRoles;
+ rolesBuilder << BSON("role" << roleElement.String() <<
+ "db" << otherDBRoles.fieldNameStringData());
+ }
+ }
+ }
+ }
+ }
+ BSONObj update = updateBuilder.obj();
uassertStatusOK(externalState->updateOne(
AuthorizationManager::usersAltCollectionNamespace,