diff options
author | Gabriel Russell <gabriel.russell@mongodb.com> | 2017-08-15 10:56:11 -0400 |
---|---|---|
committer | Gabriel Russell <gabriel.russell@mongodb.com> | 2017-09-21 15:41:06 -0400 |
commit | 305f4366320ba2538f077c28d0f3ea6979277c48 (patch) | |
tree | 683be295499125aa86147bab7f1e018111ba5b7f | |
parent | 8beb002326a5fdd82c694497b7ebcb52a593a3d3 (diff) | |
download | mongo-305f4366320ba2538f077c28d0f3ea6979277c48.tar.gz |
SERVER-30430 Gate session use on featureCompatibilityVersion
12 files changed, 210 insertions, 2 deletions
diff --git a/jstests/noPassthrough/logical_session_feature_compatibility.js b/jstests/noPassthrough/logical_session_feature_compatibility.js new file mode 100644 index 00000000000..f060e499ecf --- /dev/null +++ b/jstests/noPassthrough/logical_session_feature_compatibility.js @@ -0,0 +1,107 @@ +(function() { + 'use strict'; + var cases = [ + { + name: "endSessions", + cmd: {endSessions: []}, + }, + { + name: "killAllSessions", + cmd: {killSessions: []}, + }, + { + name: "killAllSessionsByPattern", + cmd: {killAllSessionsByPattern: []}, + }, + { + name: "killSessions", + cmd: {killSessions: []}, + }, + { + name: "refreshLogicalSessionCacheNow", + cmd: {refreshLogicalSessionCacheNow: 1}, + }, + { + name: "refreshSessions", + cmd: {refreshSessions: []}, + }, + { + name: "startSession", + cmd: {startSession: 1}, + }, + ]; + + var casesLength = cases.length; + var testCases = function(compatibilityVersion, errorCode) { + assert.commandWorked( + admin.adminCommand({setFeatureCompatibilityVersion: compatibilityVersion})); + for (var i = 0; i < casesLength; i++) { + var testCase = cases[i]; + var result = admin.runCommand(testCase.cmd); + + if (!errorCode) { + assert.commandWorked(result, + "failed test that we can run " + testCase.name + + " under featureCompatibilityVersion 3.6"); + + } else { + assert.commandFailedWithCode(result, + errorCode, + "failed test that we can't run " + testCase.name + + " under featureCompatibilityVersion 3.4"); + } + } + }; + + // First verify the commands without auth, in feature compatibility version 3.6. + + var conn = MongoRunner.runMongod({nojournal: ""}); + var admin = conn.getDB("admin"); + + testCases("3.6"); + + // Second verify the commands without auth, in feature compatibility version 3.4. + + testCases("3.4", ErrorCodes.InvalidOptions); + + // Third, verify the commands with auth, in feature compatibility version 3.6 + + MongoRunner.stopMongod(conn); + + conn = MongoRunner.runMongod({auth: "", nojournal: ""}); + admin = conn.getDB("admin"); + admin.createUser({user: 'user0', pwd: 'password', roles: ["root"]}); + admin.auth("user0", "password"); + + testCases("3.6"); + + // Third, verify the commands with auth, in feature compatibility version 3.4 + + testCases("3.4", ErrorCodes.InvalidOptions); + + MongoRunner.stopMongod(conn); + + // Verify that sessions are vivified for ops that have lsids when fcv is 3.4 + + var conn = MongoRunner.runMongod({nojournal: ""}); + var admin = conn.getDB("admin"); + + assert.commandWorked(admin.adminCommand({setFeatureCompatibilityVersion: "3.6"})); + + for (var i = 0; i < 11; i++) { + admin.runCommand({"insert": "test", "documents": [{a: 1}], "lsid": {"id": UUID()}}); + } + + admin.adminCommand({setFeatureCompatibilityVersion: "3.4"}); + + for (var i = 0; i < 13; i++) { + admin.runCommand({"insert": "test", "documents": [{a: 2}], "lsid": {"id": UUID()}}); + } + + admin.adminCommand({setFeatureCompatibilityVersion: "3.6"}); + + admin.runCommand({refreshLogicalSessionCacheNow: 1}); + + assert.eq(admin.system.sessions.find().count(), 11); + +})(); diff --git a/src/mongo/db/commands/end_sessions_command.cpp b/src/mongo/db/commands/end_sessions_command.cpp index 6a07059f472..895663a538c 100644 --- a/src/mongo/db/commands/end_sessions_command.cpp +++ b/src/mongo/db/commands/end_sessions_command.cpp @@ -60,6 +60,11 @@ public: const std::string& dbname, const BSONObj& cmdObj) override { + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return SessionsCommandFCV34Status(getName()); + } + // It is always ok to run this command, as long as you are authenticated // as some user, if auth is enabled. AuthorizationSession* authSession = AuthorizationSession::get(opCtx->getClient()); @@ -77,6 +82,11 @@ public: const BSONObj& cmdObj, BSONObjBuilder& result) override { + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return appendCommandStatus(result, SessionsCommandFCV34Status(getName())); + } + auto lsCache = LogicalSessionCache::get(opCtx); auto cmd = EndSessionsCmdFromClient::parse("EndSessionsCmdFromClient"_sd, cmdObj); diff --git a/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp b/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp index 48387e69e88..c4147529484 100644 --- a/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp +++ b/src/mongo/db/commands/kill_all_sessions_by_pattern_command.cpp @@ -72,11 +72,18 @@ public: Status checkAuthForOperation(OperationContext* opCtx, const std::string& dbname, const BSONObj& cmdObj) override { + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return SessionsCommandFCV34Status(getName()); + } + AuthorizationSession* authSession = AuthorizationSession::get(opCtx->getClient()); if (!authSession->isAuthorizedForPrivilege( Privilege{ResourcePattern::forClusterResource(), ActionType::killAnySession})) { return Status(ErrorCodes::Unauthorized, "Unauthorized"); } + return Status::OK(); } @@ -84,6 +91,12 @@ public: const std::string& db, const BSONObj& cmdObj, BSONObjBuilder& result) override { + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return appendCommandStatus(result, SessionsCommandFCV34Status(getName())); + } + IDLParserErrorContext ctx("KillAllSessionsByPatternCmd"); auto ksc = KillAllSessionsByPatternCmd::parse(ctx, cmdObj); diff --git a/src/mongo/db/commands/kill_all_sessions_command.cpp b/src/mongo/db/commands/kill_all_sessions_command.cpp index ba200c4e443..aeeffacc732 100644 --- a/src/mongo/db/commands/kill_all_sessions_command.cpp +++ b/src/mongo/db/commands/kill_all_sessions_command.cpp @@ -72,11 +72,18 @@ public: Status checkAuthForOperation(OperationContext* opCtx, const std::string& dbname, const BSONObj& cmdObj) override { + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return SessionsCommandFCV34Status(getName()); + } + AuthorizationSession* authSession = AuthorizationSession::get(opCtx->getClient()); if (!authSession->isAuthorizedForPrivilege( Privilege{ResourcePattern::forClusterResource(), ActionType::killAnySession})) { return Status(ErrorCodes::Unauthorized, "Unauthorized"); } + return Status::OK(); } @@ -84,6 +91,12 @@ public: const std::string& db, const BSONObj& cmdObj, BSONObjBuilder& result) override { + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return appendCommandStatus(result, SessionsCommandFCV34Status(getName())); + } + IDLParserErrorContext ctx("KillAllSessionsCmd"); auto ksc = KillAllSessionsCmd::parse(ctx, cmdObj); diff --git a/src/mongo/db/commands/kill_sessions_command.cpp b/src/mongo/db/commands/kill_sessions_command.cpp index 6460863d599..c8b67f8f695 100644 --- a/src/mongo/db/commands/kill_sessions_command.cpp +++ b/src/mongo/db/commands/kill_sessions_command.cpp @@ -101,6 +101,12 @@ public: Status checkAuthForOperation(OperationContext* opCtx, const std::string& dbname, const BSONObj& cmdObj) override { + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return SessionsCommandFCV34Status(getName()); + } + return Status::OK(); } @@ -108,6 +114,12 @@ public: const std::string& db, const BSONObj& cmdObj, BSONObjBuilder& result) override { + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return appendCommandStatus(result, SessionsCommandFCV34Status(getName())); + } + IDLParserErrorContext ctx("KillSessionsCmd"); auto ksc = KillSessionsCmdFromClient::parse(ctx, cmdObj); diff --git a/src/mongo/db/commands/refresh_logical_session_cache_now.cpp b/src/mongo/db/commands/refresh_logical_session_cache_now.cpp index f1b61473cda..cb607f13b82 100644 --- a/src/mongo/db/commands/refresh_logical_session_cache_now.cpp +++ b/src/mongo/db/commands/refresh_logical_session_cache_now.cpp @@ -32,6 +32,7 @@ #include "mongo/db/client.h" #include "mongo/db/commands.h" #include "mongo/db/logical_session_cache.h" +#include "mongo/db/logical_session_id_helpers.h" #include "mongo/db/operation_context.h" namespace mongo { @@ -64,6 +65,12 @@ public: Status checkAuthForOperation(OperationContext* opCtx, const std::string& dbname, const BSONObj& cmdObj) override { + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return SessionsCommandFCV34Status(getName()); + } + return Status::OK(); } @@ -71,6 +78,12 @@ public: const std::string& db, const BSONObj& cmdObj, BSONObjBuilder& result) override { + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return appendCommandStatus(result, SessionsCommandFCV34Status(getName())); + } + auto cache = LogicalSessionCache::get(opCtx); auto client = opCtx->getClient(); diff --git a/src/mongo/db/commands/refresh_sessions_command.cpp b/src/mongo/db/commands/refresh_sessions_command.cpp index 2d938ddb75e..452894bd24f 100644 --- a/src/mongo/db/commands/refresh_sessions_command.cpp +++ b/src/mongo/db/commands/refresh_sessions_command.cpp @@ -34,6 +34,7 @@ #include "mongo/db/commands.h" #include "mongo/db/jsobj.h" #include "mongo/db/logical_session_cache.h" +#include "mongo/db/logical_session_id_helpers.h" #include "mongo/db/operation_context.h" #include "mongo/db/refresh_sessions_gen.h" @@ -60,6 +61,12 @@ public: Status checkAuthForOperation(OperationContext* opCtx, const std::string& dbname, const BSONObj& cmdObj) override { + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return SessionsCommandFCV34Status(getName()); + } + // It is always ok to run this command, as long as you are authenticated // as some user, if auth is enabled. AuthorizationSession* authSession = AuthorizationSession::get(opCtx->getClient()); @@ -76,6 +83,12 @@ public: const std::string& db, const BSONObj& cmdObj, BSONObjBuilder& result) override { + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return appendCommandStatus(result, SessionsCommandFCV34Status(getName())); + } + IDLParserErrorContext ctx("RefreshSessionsCmdFromClient"); auto cmd = RefreshSessionsCmdFromClient::parse(ctx, cmdObj); auto res = diff --git a/src/mongo/db/commands/refresh_sessions_command_internal.cpp b/src/mongo/db/commands/refresh_sessions_command_internal.cpp index 2010ca2350b..1ce8702a1db 100644 --- a/src/mongo/db/commands/refresh_sessions_command_internal.cpp +++ b/src/mongo/db/commands/refresh_sessions_command_internal.cpp @@ -34,6 +34,7 @@ #include "mongo/db/commands.h" #include "mongo/db/jsobj.h" #include "mongo/db/logical_session_cache.h" +#include "mongo/db/logical_session_id_helpers.h" #include "mongo/db/operation_context.h" #include "mongo/db/refresh_sessions_gen.h" diff --git a/src/mongo/db/commands/start_session_command.cpp b/src/mongo/db/commands/start_session_command.cpp index 63fe696057d..05341a93c2f 100644 --- a/src/mongo/db/commands/start_session_command.cpp +++ b/src/mongo/db/commands/start_session_command.cpp @@ -66,8 +66,12 @@ public: Status checkAuthForOperation(OperationContext* opCtx, const std::string& dbname, const BSONObj& cmdObj) override { - // Anybody may start a session. The command body below checks - // that only a single user is logged in. + + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return SessionsCommandFCV34Status(getName()); + } + return Status::OK(); } @@ -76,6 +80,11 @@ public: const BSONObj& cmdObj, BSONObjBuilder& result) override { + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return appendCommandStatus(result, SessionsCommandFCV34Status(getName())); + } + auto client = opCtx->getClient(); ServiceContext* serviceContext = client->getServiceContext(); diff --git a/src/mongo/db/initialize_operation_session_info.cpp b/src/mongo/db/initialize_operation_session_info.cpp index fbfe8bffe30..0bd3c600bd5 100644 --- a/src/mongo/db/initialize_operation_session_info.cpp +++ b/src/mongo/db/initialize_operation_session_info.cpp @@ -33,6 +33,7 @@ #include "mongo/db/logical_session_cache.h" #include "mongo/db/logical_session_id_helpers.h" #include "mongo/db/operation_context.h" +#include "mongo/db/server_options.h" namespace mongo { @@ -44,6 +45,11 @@ void initializeOperationSessionInfo(OperationContext* opCtx, return; } + if (serverGlobalParams.featureCompatibility.version.load() == + ServerGlobalParams::FeatureCompatibility::Version::k34) { + return; + } + auto osi = OperationSessionInfoFromClient::parse("OperationSessionInfo"_sd, requestBody); if (osi.getSessionId()) { diff --git a/src/mongo/db/logical_session_id_helpers.cpp b/src/mongo/db/logical_session_id_helpers.cpp index e3de10a12b7..7f89ca518df 100644 --- a/src/mongo/db/logical_session_id_helpers.cpp +++ b/src/mongo/db/logical_session_id_helpers.cpp @@ -33,6 +33,7 @@ #include "mongo/db/auth/authorization_session.h" #include "mongo/db/auth/user.h" #include "mongo/db/auth/user_name.h" +#include "mongo/db/commands/feature_compatibility_version_command_parser.h" #include "mongo/db/logical_session_cache.h" #include "mongo/db/operation_context.h" @@ -184,4 +185,12 @@ LogicalSessionIdSet makeLogicalSessionIds(const std::vector<LogicalSessionFromCl return lsids; } +Status SessionsCommandFCV34Status(StringData command) { + StringBuilder sb; + sb << command; + sb << " is not available in featureCompatibilityVersion 3.4. See "; + sb << feature_compatibility_version::kDochubLink << " ."; + return {ErrorCodes::InvalidOptions, sb.str()}; +} + } // namespace mongo diff --git a/src/mongo/db/logical_session_id_helpers.h b/src/mongo/db/logical_session_id_helpers.h index a913ac3c769..9735706330b 100644 --- a/src/mongo/db/logical_session_id_helpers.h +++ b/src/mongo/db/logical_session_id_helpers.h @@ -70,4 +70,6 @@ LogicalSessionIdSet makeLogicalSessionIds(const std::vector<LogicalSessionFromCl OperationContext* opCtx, std::initializer_list<Privilege> allowSpoof = {}); +Status SessionsCommandFCV34Status(StringData command); + } // namespace mongo |