From 650871daad6b8f1de5d1d9cf6468b7c6f552c340 Mon Sep 17 00:00:00 2001 From: matt dannenberg Date: Tue, 8 Sep 2015 04:25:43 -0400 Subject: Revert "SERVER-20134 Restore the authSchemaUpgrade command" This reverts commit 7a3fa1f56d9cb121cae4d854f6ded2a12793077b. --- jstests/auth/auth_schema_upgrade.js | 86 -------- jstests/auth/lib/commands_lib.js | 19 -- jstests/multiVersion/libs/auth_helpers.js | 4 +- src/mongo/db/auth/action_types.txt | 1 - src/mongo/db/auth/role_graph_builtin_roles.cpp | 3 - .../db/auth/user_management_commands_parser.cpp | 42 ---- .../db/auth/user_management_commands_parser.h | 14 -- src/mongo/db/commands/user_management_commands.cpp | 222 --------------------- src/mongo/db/commands/user_management_commands.h | 1 - .../commands/user_management_commands_common.cpp | 8 - .../commands/cluster_user_management_commands.cpp | 95 --------- 11 files changed, 1 insertion(+), 494 deletions(-) delete mode 100644 jstests/auth/auth_schema_upgrade.js diff --git a/jstests/auth/auth_schema_upgrade.js b/jstests/auth/auth_schema_upgrade.js deleted file mode 100644 index 001e5c04a1b..00000000000 --- a/jstests/auth/auth_schema_upgrade.js +++ /dev/null @@ -1,86 +0,0 @@ -// Standalone test of authSchemaUpgrade -load('./jstests/multiVersion/libs/auth_helpers.js'); - -var setupCRUsers = function(conn){ - jsTest.log("setting up legacy users"); - var adminDB = conn.getDB('admin'); - - adminDB.system.version.update({_id:"authSchema"},{"currentVersion":3},{upsert:true}) - - adminDB.createUser({user: 'user1', pwd: 'pass', - roles: jsTest.adminUserRoles}); - assert(adminDB.auth({mechanism: 'MONGODB-CR', - user: 'user1', pwd: 'pass'})); - - adminDB.createUser({user: 'user2', pwd: 'pass', - roles: jsTest.adminUserRoles}); - assert(adminDB.auth({mechanism: 'MONGODB-CR', - user: 'user2', pwd: 'pass'})); - - // Add $external no-op user to verify that it does not affect - // authSchemaUpgrade SERVER-18475 - adminDB.getSiblingDB('$external').createUser({user: "evil", roles: []}); - - jsTest.log("Verifying user documents before upgrading"); - - // We haven't run authSchemaUpgrade so there shouldn't be - // any stored SCRAM-SHA-1 credentials. - verifyUserDoc(adminDB, 'user1', true, false); - verifyUserDoc(adminDB, 'user2', true, false); - verifyUserDoc(adminDB.getSiblingDB('$external'), "evil", false, false, true); - - adminDB.updateUser('user1', {pwd: 'newpass', - roles: jsTest.adminUserRoles}); - verifyAuth(adminDB, 'user1', 'newpass', true, true); - - verifyUserDoc(adminDB, 'user1', true, false); -} - -var verifySchemaUpgrade = function(adminDB) { - // All users should only have SCRAM credentials. - verifyUserDoc(adminDB, 'user1', false, true); - verifyUserDoc(adminDB, 'user2', false, true); - verifyUserDoc(adminDB.getSiblingDB('$external'), "evil", false, false, true); - - // After authSchemaUpgrade MONGODB-CR no longer works. - verifyAuth(adminDB, 'user1', 'newpass', false, true); - verifyAuth(adminDB, 'user2', 'pass', false, true); -} - -var runAndVerifySchemaUpgrade = function(conn){ - jsTest.log("run authSchemaUpgrade"); - var adminDB = conn.getDB('admin'); - - assert.commandWorked(adminDB.runCommand('authSchemaUpgrade')); - verifySchemaUpgrade(adminDB); -} - -var testAuthSchemaUpgrade = function(conn) { - setupCRUsers(conn); - runAndVerifySchemaUpgrade(conn); -} - -// Test authSchemaUpgrade and upgrade shards -var testUpgradeShards = function(mongos, shard) { - setupCRUsers(shard); - - assert.commandWorked(mongos.adminCommand({"authSchemaUpgrade":1,"upgradeShards":1})); - verifySchemaUpgrade(shard.getDB('admin')); -} - -jsTest.log('Test authSchemUpgrade standalone'); -var conn = MongoRunner.runMongod(); -testAuthSchemaUpgrade(conn); -MongoRunner.stopMongod(conn); - -jsTest.log('Test authSchemUpgrade sharded'); -var dopts = { smallfiles: "", nopreallocj: ""} -var st = new ShardingTest( - { shards: 1, - mongos: 1, - config: 1, - useHostname: false, // Needed when relying on the localhost exception - other: { shardOptions: dopts, configOptions: dopts, mongosOptions: { verbose: 1 } } } ); -testAuthSchemaUpgrade(st.s); -testUpgradeShards(st.s, st.shard0); -st.stop(); diff --git a/jstests/auth/lib/commands_lib.js b/jstests/auth/lib/commands_lib.js index f677f5a2ebc..2ce024ade88 100644 --- a/jstests/auth/lib/commands_lib.js +++ b/jstests/auth/lib/commands_lib.js @@ -373,25 +373,6 @@ var authCommandsLib = { { runOnDb: secondDbName, roles: {} } ] }, - { - testname: "authSchemaUpgrade", - command: {authSchemaUpgrade: 1}, - testcases: [ - { - runOnDb: adminDbName, - roles: { - userAdminAnyDatabase: 1, - root: 1, - __system: 1 - }, - privileges: [ - { resource: {cluster: true}, actions: ["authSchemaUpgrade"] } - ] - }, - { runOnDb: firstDbName, roles: {} }, - { runOnDb: secondDbName, roles: {} } - ] - }, { testname: "buildInfo", command: {buildInfo: 1}, diff --git a/jstests/multiVersion/libs/auth_helpers.js b/jstests/multiVersion/libs/auth_helpers.js index cebb2b03e5f..39566da3d1b 100644 --- a/jstests/multiVersion/libs/auth_helpers.js +++ b/jstests/multiVersion/libs/auth_helpers.js @@ -9,11 +9,10 @@ var getUserDoc = function(db, username){ // Verify that the user document for username in db // has MONGODB-CR credentials (or not) and SCRAM-SHA-1 // credentials (or not). -var verifyUserDoc = function(db, username, hasCR, hasSCRAM, hasExternal = false){ +var verifyUserDoc = function(db, username, hasCR, hasSCRAM){ var userDoc = getUserDoc(db, username); assert.eq(hasCR, 'MONGODB-CR' in userDoc.credentials); assert.eq(hasSCRAM, 'SCRAM-SHA-1' in userDoc.credentials); - assert.eq(hasExternal, 'external' in userDoc.credentials); } // Verify that that we can authenticate (or not) using MONGODB-CR @@ -23,5 +22,4 @@ var verifyAuth = function(db, username, password, passCR, passSCRAM){ user: username, pwd: password})); assert.eq(passSCRAM, db.auth({mechanism: 'SCRAM-SHA-1', user: username, pwd: password})); - db.logout(); } diff --git a/src/mongo/db/auth/action_types.txt b/src/mongo/db/auth/action_types.txt index 2d55b878687..0e2c2aed753 100644 --- a/src/mongo/db/auth/action_types.txt +++ b/src/mongo/db/auth/action_types.txt @@ -11,7 +11,6 @@ "auditLogRotate", # Not used for permissions checks, but to id the event in logs. "authCheck", # Not used for permissions checks, but to id the authorization-checking event in logs. "authenticate", # Not used for permission checks, but to id authentication events in logs. -"authSchemaUpgrade", "bypassDocumentValidation", # For bypassDocumentValidation command option. "changeCustomData", "changePassword", diff --git a/src/mongo/db/auth/role_graph_builtin_roles.cpp b/src/mongo/db/auth/role_graph_builtin_roles.cpp index 94e3b157346..eff0ce4f9fa 100644 --- a/src/mongo/db/auth/role_graph_builtin_roles.cpp +++ b/src/mongo/db/auth/role_graph_builtin_roles.cpp @@ -289,9 +289,6 @@ void addUserAdminAnyDbPrivileges(PrivilegeVector* privileges) { privileges, Privilege(ResourcePattern::forAnyNormalResource(), userAdminRoleActions)); Privilege::addPrivilegeToPrivilegeVector( privileges, Privilege(ResourcePattern::forClusterResource(), ActionType::listDatabases)); - Privilege::addPrivilegeToPrivilegeVector( - privileges, - Privilege(ResourcePattern::forClusterResource(), ActionType::authSchemaUpgrade)); Privilege::addPrivilegeToPrivilegeVector( privileges, Privilege(ResourcePattern::forClusterResource(), ActionType::invalidateUserCache)); diff --git a/src/mongo/db/auth/user_management_commands_parser.cpp b/src/mongo/db/auth/user_management_commands_parser.cpp index 54109d14bf7..82130e2a530 100644 --- a/src/mongo/db/auth/user_management_commands_parser.cpp +++ b/src/mongo/db/auth/user_management_commands_parser.cpp @@ -662,47 +662,5 @@ Status parseMergeAuthzCollectionsCommand(const BSONObj& cmdObj, return Status::OK(); } -Status parseAuthSchemaUpgradeCommand(const BSONObj& cmdObj, - const std::string& dbname, - AuthSchemaUpgradeArgs* parsedArgs) { - static const int minUpgradeSteps = 1; - static const int maxUpgradeSteps = 2; - - unordered_set validFieldNames; - validFieldNames.insert("authSchemaUpgrade"); - validFieldNames.insert("maxSteps"); - validFieldNames.insert("upgradeShards"); - validFieldNames.insert("writeConcern"); - - Status status = _checkNoExtraFields(cmdObj, "authSchemaUpgrade", validFieldNames); - if (!status.isOK()) { - return status; - } - - status = bsonExtractBooleanFieldWithDefault( - cmdObj, "upgradeShards", true, &parsedArgs->shouldUpgradeShards); - if (!status.isOK()) { - return status; - } - - long long steps; - status = bsonExtractIntegerFieldWithDefault(cmdObj, "maxSteps", maxUpgradeSteps, &steps); - if (!status.isOK()) - return status; - if (steps < minUpgradeSteps || steps > maxUpgradeSteps) { - return Status(ErrorCodes::BadValue, - mongoutils::str::stream() << "Legal values for \"maxSteps\" are at least " - << minUpgradeSteps << " and no more than " - << maxUpgradeSteps << "; found " << steps); - } - parsedArgs->maxSteps = static_cast(steps); - - status = _extractWriteConcern(cmdObj, &parsedArgs->writeConcern); - if (!status.isOK()) { - return status; - } - - return Status::OK(); -} } // namespace auth } // namespace mongo diff --git a/src/mongo/db/auth/user_management_commands_parser.h b/src/mongo/db/auth/user_management_commands_parser.h index 2bc278feecb..c55210e8978 100644 --- a/src/mongo/db/auth/user_management_commands_parser.h +++ b/src/mongo/db/auth/user_management_commands_parser.h @@ -223,19 +223,5 @@ struct MergeAuthzCollectionsArgs { Status parseMergeAuthzCollectionsCommand(const BSONObj& cmdObj, MergeAuthzCollectionsArgs* parsedArgs); -struct AuthSchemaUpgradeArgs { - int maxSteps = 3; - bool shouldUpgradeShards = true; - BSONObj writeConcern; -}; - -/** - * Takes a command object describing an invocation of the "authSchemaUpgrade" command and - * parses out the write concern, maximum steps to take and whether or not shard servers should - * also be upgraded, in the sharded deployment case. - */ -Status parseAuthSchemaUpgradeCommand(const BSONObj& cmdObj, - const std::string& dbname, - AuthSchemaUpgradeArgs* parsedArgs); } // namespace auth } // namespace mongo diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp index a5b1d2373b2..cb63736f7c0 100644 --- a/src/mongo/db/commands/user_management_commands.cpp +++ b/src/mongo/db/commands/user_management_commands.cpp @@ -2722,226 +2722,4 @@ public: } cmdMergeAuthzCollections; -/** - * Logs that the auth schema upgrade failed because of "status" and returns "status". - */ -Status logUpgradeFailed(const Status& status) { - log() << "Auth schema upgrade failed with " << status; - return status; -} - -/** - * Updates a single user document from MONGODB-CR to SCRAM credentials. - * - * Throws a DBException on errors. - */ -void updateUserCredentials(OperationContext* txn, - const StringData& sourceDB, - const BSONObj& userDoc, - const BSONObj& writeConcern) { - // Skip users in $external, SERVER-18475 - if (userDoc["db"].String() == "$external") { - return; - } - - BSONElement credentialsElement = userDoc["credentials"]; - uassert(18806, - mongoutils::str::stream() - << "While preparing to upgrade user doc from " - "2.6/3.0 user data schema to the 3.0+ SCRAM only schema, found a user doc " - "with missing or incorrectly formatted credentials: " << userDoc.toString(), - credentialsElement.type() == Object); - - BSONObj credentialsObj = credentialsElement.Obj(); - BSONElement mongoCRElement = credentialsObj["MONGODB-CR"]; - BSONElement scramElement = credentialsObj["SCRAM-SHA-1"]; - - // Ignore any user documents that already have SCRAM credentials. This should only - // occur if a previous authSchemaUpgrade was interrupted halfway. - if (!scramElement.eoo()) { - return; - } - - uassert(18744, - mongoutils::str::stream() - << "While preparing to upgrade user doc from " - "2.6/3.0 user data schema to the 3.0+ SCRAM only schema, found a user doc " - "missing MONGODB-CR credentials :" << userDoc.toString(), - !mongoCRElement.eoo()); - - std::string hashedPassword = mongoCRElement.String(); - - BSONObj query = BSON("_id" << userDoc["_id"].String()); - BSONObjBuilder updateBuilder; - { - BSONObjBuilder toSetBuilder(updateBuilder.subobjStart("$set")); - toSetBuilder << "credentials" - << BSON("SCRAM-SHA-1" << scram::generateCredentials( - hashedPassword, saslGlobalParams.scramIterationCount)); - } - - uassertStatusOK(updateOneAuthzDocument(txn, - NamespaceString("admin", "system.users"), - query, - updateBuilder.obj(), - true, - writeConcern)); -} - -/** Loop through all the user documents in the admin.system.users collection. - * For each user document: - * 1. Compute SCRAM credentials based on the MONGODB-CR hash - * 2. Remove the MONGODB-CR hash - * 3. Add SCRAM credentials to the user document credentials section - */ -Status updateCredentials(OperationContext* txn, const BSONObj& writeConcern) { - // Loop through and update the user documents in admin.system.users. - Status status = queryAuthzDocument( - txn, - NamespaceString("admin", "system.users"), - BSONObj(), - BSONObj(), - stdx::bind(updateUserCredentials, txn, "admin", stdx::placeholders::_1, writeConcern)); - if (!status.isOK()) - return logUpgradeFailed(status); - - // Update the schema version document. - status = - updateOneAuthzDocument(txn, - AuthorizationManager::versionCollectionNamespace, - AuthorizationManager::versionDocumentQuery, - BSON("$set" << BSON(AuthorizationManager::schemaVersionFieldName - << AuthorizationManager::schemaVersion28SCRAM)), - true, - writeConcern); - if (!status.isOK()) - return logUpgradeFailed(status); - - return Status::OK(); -} - -/** - * Performs one step in the process of upgrading the stored authorization data to the - * newest schema. - * - * On success, returns Status::OK(), and *isDone will indicate whether there are more - * steps to perform. - * - * If the authorization data is already fully upgraded, returns Status::OK and sets *isDone - * to true, so this is safe to call on a fully upgraded system. - * - * On failure, returns a status other than Status::OK(). In this case, is is typically safe - * to try again. - */ -Status upgradeAuthSchemaStep(OperationContext* txn, - AuthorizationManager* authzManager, - const BSONObj& writeConcern, - bool* isDone) { - int authzVersion; - Status status = authzManager->getAuthorizationVersion(txn, &authzVersion); - if (!status.isOK()) { - return status; - } - - switch (authzVersion) { - case AuthorizationManager::schemaVersion26Final: - case AuthorizationManager::schemaVersion28SCRAM: { - Status status = updateCredentials(txn, writeConcern); - if (status.isOK()) - *isDone = true; - return status; - } - default: - return Status(ErrorCodes::AuthSchemaIncompatible, - mongoutils::str::stream() - << "Do not know how to upgrade auth schema from version " - << authzVersion); - } -} - -/** - * Performs up to maxSteps steps in the process of upgrading the stored authorization data - * to the newest schema. Behaves as if by repeatedly calling upgradeSchemaStep up to - * maxSteps times until either it completes the upgrade or returns a non-OK status. - * - * Invalidates the user cache before the first step and after each attempted step. - * - * Returns Status::OK() to indicate that the upgrade process has completed successfully. - * Returns ErrorCodes::OperationIncomplete to indicate that progress was made, but that more - * steps must be taken to complete the process. Other returns indicate a failure to make - * progress performing the upgrade, and the specific code and message in the returned status - * may provide additional information. - */ -Status upgradeAuthSchema(OperationContext* txn, - AuthorizationManager* authzManager, - int maxSteps, - const BSONObj& writeConcern) { - if (maxSteps < 1) { - return Status(ErrorCodes::BadValue, - "Minimum value for maxSteps parameter to upgradeAuthSchema is 1"); - } - authzManager->invalidateUserCache(); - for (int i = 0; i < maxSteps; ++i) { - bool isDone; - Status status = upgradeAuthSchemaStep(txn, authzManager, writeConcern, &isDone); - authzManager->invalidateUserCache(); - if (!status.isOK() || isDone) { - return status; - } - } - return Status(ErrorCodes::OperationIncomplete, - mongoutils::str::stream() << "Auth schema upgrade incomplete after " << maxSteps - << " successful steps."); -} - -class CmdAuthSchemaUpgrade : public Command { -public: - CmdAuthSchemaUpgrade() : Command("authSchemaUpgrade") {} - - virtual bool slaveOk() const { - return false; - } - - virtual bool adminOnly() const { - return true; - } - - virtual bool isWriteCommandForConfigServer() const { - return true; - } - - virtual void help(stringstream& ss) const { - ss << "Upgrades the auth data storage schema"; - } - - virtual Status checkAuthForCommand(ClientBasic* client, - const std::string& dbname, - const BSONObj& cmdObj) { - return auth::checkAuthForAuthSchemaUpgradeCommand(client); - } - - virtual bool run(OperationContext* txn, - const string& dbname, - BSONObj& cmdObj, - int options, - string& errmsg, - BSONObjBuilder& result) { - auth::AuthSchemaUpgradeArgs parsedArgs; - Status status = auth::parseAuthSchemaUpgradeCommand(cmdObj, dbname, &parsedArgs); - if (!status.isOK()) { - return appendCommandStatus(result, status); - } - - ServiceContext* serviceContext = txn->getClient()->getServiceContext(); - AuthorizationManager* authzManager = AuthorizationManager::get(serviceContext); - - stdx::lock_guard lk(getAuthzDataMutex(serviceContext)); - - status = upgradeAuthSchema(txn, authzManager, parsedArgs.maxSteps, parsedArgs.writeConcern); - if (status.isOK()) - result.append("done", true); - return appendCommandStatus(result, status); - } - -} cmdAuthSchemaUpgrade; } // namespace mongo diff --git a/src/mongo/db/commands/user_management_commands.h b/src/mongo/db/commands/user_management_commands.h index 8ae4e233db9..63c7a7d8d6c 100644 --- a/src/mongo/db/commands/user_management_commands.h +++ b/src/mongo/db/commands/user_management_commands.h @@ -141,7 +141,6 @@ Status checkAuthForGetUserCacheGenerationCommand(ClientBasic* client); Status checkAuthForMergeAuthzCollectionsCommand(ClientBasic* client, const BSONObj& cmdObj); -Status checkAuthForAuthSchemaUpgradeCommand(ClientBasic* client); } // namespace auth } // namespace mongo diff --git a/src/mongo/db/commands/user_management_commands_common.cpp b/src/mongo/db/commands/user_management_commands_common.cpp index 09445c5aea7..64aee9eca51 100644 --- a/src/mongo/db/commands/user_management_commands_common.cpp +++ b/src/mongo/db/commands/user_management_commands_common.cpp @@ -522,14 +522,6 @@ Status checkAuthForMergeAuthzCollectionsCommand(ClientBasic* client, const BSONO return Status::OK(); } -Status checkAuthForAuthSchemaUpgradeCommand(ClientBasic* client) { - AuthorizationSession* authzSession = AuthorizationSession::get(client); - if (!authzSession->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(), - ActionType::authSchemaUpgrade)) { - return Status(ErrorCodes::Unauthorized, "Not authorized to run authSchemaUpgrade command."); - } - return Status::OK(); -} } // namespace auth } // namespace mongo diff --git a/src/mongo/s/commands/cluster_user_management_commands.cpp b/src/mongo/s/commands/cluster_user_management_commands.cpp index d3072c8db5a..75fca86dc7a 100644 --- a/src/mongo/s/commands/cluster_user_management_commands.cpp +++ b/src/mongo/s/commands/cluster_user_management_commands.cpp @@ -42,8 +42,6 @@ #include "mongo/db/commands.h" #include "mongo/db/jsobj.h" #include "mongo/s/catalog/catalog_manager.h" -#include "mongo/s/catalog/type_shard.h" -#include "mongo/s/client/shard_registry.h" #include "mongo/s/grid.h" namespace mongo { @@ -805,97 +803,4 @@ public: } cmdMergeAuthzCollections; -namespace { -/** - * Runs the authSchemaUpgrade on all shards, with the given maxSteps and writeConcern - * parameters. - * - * Upgrades each shard serially, and stops on first failure. Returned error indicates that - * failure. - */ -Status runUpgradeOnAllShards(OperationContext* txn, int maxSteps, const BSONObj& writeConcern) { - BSONObjBuilder cmdObjBuilder; - cmdObjBuilder.append("authSchemaUpgrade", 1); - cmdObjBuilder.append("maxSteps", maxSteps); - if (!writeConcern.isEmpty()) { - cmdObjBuilder.append("writeConcern", writeConcern); - } - const BSONObj cmdObj = cmdObjBuilder.done(); - - // Upgrade each shard in turn, stopping on first failure. - vector allShards; - Status status = grid.catalogManager()->getAllShards(txn, &allShards); - if (!status.isOK()) { - return status; - } - auto shardRegistry = grid.shardRegistry(); - for (const auto& shardEntry : allShards) { - auto cmdResult = shardRegistry->runCommandWithNotMasterRetries( - txn, shardEntry.getName(), "admin", cmdObj); - - if (!cmdResult.isOK()) { - return Status(status.code(), - str::stream() << "Failed to run authSchemaUpgrade on shard " - << shardEntry.getName() << causedBy(status)); - } - } - - return Status::OK(); -} -} // namespace - -class CmdAuthSchemaUpgrade : public Command { -public: - CmdAuthSchemaUpgrade() : Command("authSchemaUpgrade") {} - - virtual bool slaveOk() const { - return false; - } - - virtual bool adminOnly() const { - return true; - } - - virtual bool isWriteCommandForConfigServer() const { - return true; - } - - virtual void help(stringstream& ss) const { - ss << "Upgrades the auth data storage schema"; - } - - virtual Status checkAuthForCommand(ClientBasic* client, - const std::string& dbname, - const BSONObj& cmdObj) { - return auth::checkAuthForAuthSchemaUpgradeCommand(client); - } - - bool run(OperationContext* txn, - const string& dbname, - BSONObj& cmdObj, - int options, - string& errmsg, - BSONObjBuilder& result) { - // Run the authSchemaUpgrade command on the config servers - if (!grid.catalogManager(txn) - ->runUserManagementWriteCommand(txn, this->name, dbname, cmdObj, &result)) { - return false; - } - - auth::AuthSchemaUpgradeArgs parsedArgs; - Status status = auth::parseAuthSchemaUpgradeCommand(cmdObj, dbname, &parsedArgs); - if (!status.isOK()) { - return appendCommandStatus(result, status); - } - - // Optionally run the authSchemaUpgrade command on the individual shards - if (parsedArgs.shouldUpgradeShards) { - status = runUpgradeOnAllShards(txn, parsedArgs.maxSteps, parsedArgs.writeConcern); - if (!status.isOK()) - return appendCommandStatus(result, status); - } - return true; - } -} cmdAuthSchemaUpgrade; - } // namespace mongo -- cgit v1.2.1