diff options
author | Mathias Stearn <mathias@10gen.com> | 2017-06-26 16:22:29 -0400 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2017-07-13 16:53:12 -0400 |
commit | c4883a9d289a01e8e4f45ccac7f19f59f2892c42 (patch) | |
tree | e853e7ce79e6c07b2390d5f64940f4a49d24924d | |
parent | b32c49eadcfab7c7e321a4d539e770d2a70e9730 (diff) | |
download | mongo-c4883a9d289a01e8e4f45ccac7f19f59f2892c42.tar.gz |
SERVER-29731 Auth checks get access to document sequences
-rw-r--r-- | src/mongo/db/commands.cpp | 43 | ||||
-rw-r--r-- | src/mongo/db/commands.h | 111 | ||||
-rw-r--r-- | src/mongo/db/commands/SConscript | 16 | ||||
-rw-r--r-- | src/mongo/db/commands/apply_ops_cmd_common.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/commands/explain_cmd.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/commands/write_commands/write_commands.cpp | 35 | ||||
-rw-r--r-- | src/mongo/db/commands/write_commands/write_commands_common.cpp | 49 | ||||
-rw-r--r-- | src/mongo/db/commands/write_commands/write_commands_common.h | 4 | ||||
-rw-r--r-- | src/mongo/db/ops/write_ops_document_stream_integration_test.cpp | 35 | ||||
-rw-r--r-- | src/mongo/db/service_entry_point_mongod.cpp | 2 | ||||
-rw-r--r-- | src/mongo/s/commands/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_explain_cmd.cpp | 3 | ||||
-rw-r--r-- | src/mongo/s/commands/cluster_write_cmd.cpp | 12 | ||||
-rw-r--r-- | src/mongo/s/commands/strategy.cpp | 2 |
14 files changed, 180 insertions, 138 deletions
diff --git a/src/mongo/db/commands.cpp b/src/mongo/db/commands.cpp index 2ba830fb4de..8b54dc93534 100644 --- a/src/mongo/db/commands.cpp +++ b/src/mongo/db/commands.cpp @@ -250,15 +250,20 @@ void Command::appendOperationTime(BSONObjBuilder& result, LogicalTime operationT result.append("operationTime", operationTime.asTimestamp()); } -Status Command::checkAuthForOperation(OperationContext* opCtx, - const std::string& dbname, - const BSONObj& cmdObj) { +Status BasicCommand::checkAuthForRequest(OperationContext* opCtx, const OpMsgRequest& request) { + uassertNoDocumentSequences(request); + return checkAuthForOperation(opCtx, request.getDatabase().toString(), request.body); +} + +Status BasicCommand::checkAuthForOperation(OperationContext* opCtx, + const std::string& dbname, + const BSONObj& cmdObj) { return checkAuthForCommand(opCtx->getClient(), dbname, cmdObj); } -Status Command::checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) { +Status BasicCommand::checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj) { std::vector<Privilege> privileges; this->addRequiredPrivileges(dbname, cmdObj, &privileges); if (AuthorizationSession::get(client)->isAuthorizedForPrivileges(privileges)) @@ -279,19 +284,19 @@ BSONObj Command::getRedactedCopyForLogging(const BSONObj& cmdObj) { static Status _checkAuthorizationImpl(Command* c, OperationContext* opCtx, - const std::string& dbname, - const BSONObj& cmdObj) { + const OpMsgRequest& request) { namespace mmb = mutablebson; auto client = opCtx->getClient(); + auto dbname = request.getDatabase(); if (c->adminOnly() && dbname != "admin") { return Status(ErrorCodes::Unauthorized, str::stream() << c->getName() << " may only be run against the admin database."); } if (AuthorizationSession::get(client)->getAuthorizationManager().isAuthEnabled()) { - Status status = c->checkAuthForOperation(opCtx, dbname, cmdObj); + Status status = c->checkAuthForRequest(opCtx, request); if (status == ErrorCodes::Unauthorized) { - mmb::Document cmdToLog(cmdObj, mmb::Document::kInPlaceDisabled); + mmb::Document cmdToLog(request.body, mmb::Document::kInPlaceDisabled); c->redactForLogging(&cmdToLog); return Status(ErrorCodes::Unauthorized, str::stream() << "not authorized on " << dbname << " to execute command " @@ -311,14 +316,13 @@ static Status _checkAuthorizationImpl(Command* c, Status Command::checkAuthorization(Command* c, OperationContext* opCtx, - const std::string& dbname, - const BSONObj& cmdObj) { - namespace mmb = mutablebson; - Status status = _checkAuthorizationImpl(c, opCtx, dbname, cmdObj); + const OpMsgRequest& request) { + Status status = _checkAuthorizationImpl(c, opCtx, request); if (!status.isOK()) { log(LogComponent::kAccessControl) << status; } - audit::logCommandAuthzCheck(opCtx->getClient(), dbname, cmdObj, c, status.code()); + audit::logCommandAuthzCheck( + opCtx->getClient(), request.getDatabase().toString(), request.body, c, status.code()); return status; } @@ -364,13 +368,16 @@ bool Command::isUserManagementCommand(const std::string& name) { return userManagementCommands.count(name); } -bool BasicCommand::enhancedRun(OperationContext* opCtx, - const OpMsgRequest& request, - BSONObjBuilder& result) { +void BasicCommand::uassertNoDocumentSequences(const OpMsgRequest& request) { uassert(40472, str::stream() << "The " << getName() << " command does not support document sequences.", request.sequences.empty()); +} +bool BasicCommand::enhancedRun(OperationContext* opCtx, + const OpMsgRequest& request, + BSONObjBuilder& result) { + uassertNoDocumentSequences(request); return run(opCtx, request.getDatabase().toString(), request.body, result); } diff --git a/src/mongo/db/commands.h b/src/mongo/db/commands.h index ab0ec1c7bfd..5eb48f794f9 100644 --- a/src/mongo/db/commands.h +++ b/src/mongo/db/commands.h @@ -171,13 +171,10 @@ public: BSONObjBuilder* out) const = 0; /** - * Checks if the client associated with the given OperationContext, "opCtx", is authorized to - * run - * this command on database "dbname" with the invocation described by "cmdObj". + * Checks if the client associated with the given OperationContext is authorized to run this + * command. */ - virtual Status checkAuthForOperation(OperationContext* opCtx, - const std::string& dbname, - const BSONObj& cmdObj) = 0; + virtual Status checkAuthForRequest(OperationContext* opCtx, const OpMsgRequest& request) = 0; /** * Redacts "cmdObj" in-place to a form suitable for writing to logs. @@ -243,26 +240,6 @@ public: * Increment counter for how many times this command has failed. */ virtual void incrementCommandsFailed() = 0; - -private: - /** - * Checks if the given client is authorized to run this command on database "dbname" - * with the invocation described by "cmdObj". - * - * NOTE: Implement checkAuthForOperation that takes an OperationContext* instead. - */ - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) = 0; - - /** - * Appends to "*out" the privileges required to run this command on database "dbname" with - * the invocation described by "cmdObj". New commands shouldn't implement this, they should - * implement checkAuthForOperation (which takes an OperationContext*), instead. - */ - virtual void addRequiredPrivileges(const std::string& dbname, - const BSONObj& cmdObj, - std::vector<Privilege>* out) = 0; }; /** @@ -333,10 +310,6 @@ public: ExplainOptions::Verbosity verbosity, BSONObjBuilder* out) const override; - Status checkAuthForOperation(OperationContext* opCtx, - const std::string& dbname, - const BSONObj& cmdObj) override; - void redactForLogging(mutablebson::Document* cmdObj) override; BSONObj getRedactedCopyForLogging(const BSONObj& cmdObj) override; @@ -472,9 +445,8 @@ public: * authorized. */ static Status checkAuthorization(Command* c, - OperationContext* client, - const std::string& dbname, - const BSONObj& cmdObj); + OperationContext* opCtx, + const OpMsgRequest& request); /** * Appends passthrough fields from a cmdObj to a given request. @@ -536,17 +508,6 @@ public: static BSONObj filterCommandReplyForPassthrough(const BSONObj& reply); private: - Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) override; - - void addRequiredPrivileges(const std::string& dbname, - const BSONObj& cmdObj, - std::vector<Privilege>* out) override { - // The default implementation of addRequiredPrivileges should never be hit. - fassertFailed(16940); - } - // Counters for how many times this command has been executed and failed Counter64 _commandsExecuted; Counter64 _commandsFailed; @@ -567,12 +528,9 @@ class BasicCommand : public Command { public: using Command::Command; - /** - * Calls run() as defined below. - */ - bool enhancedRun(OperationContext* opCtx, - const OpMsgRequest& request, - BSONObjBuilder& result) final; + // + // Interface for subclasses to implement + // /** * run the given command @@ -584,6 +542,59 @@ public: const std::string& db, const BSONObj& cmdObj, BSONObjBuilder& result) = 0; + + /** + * Checks if the client associated with the given OperationContext is authorized to run this + * command. Default implementation defers to checkAuthForCommand. + */ + virtual Status checkAuthForOperation(OperationContext* opCtx, + const std::string& dbname, + const BSONObj& cmdObj); + +private: + // + // Deprecated virtual methods. + // + + /** + * Checks if the given client is authorized to run this command on database "dbname" + * with the invocation described by "cmdObj". + * + * NOTE: Implement checkAuthForOperation that takes an OperationContext* instead. + */ + virtual Status checkAuthForCommand(Client* client, + const std::string& dbname, + const BSONObj& cmdObj); + + /** + * Appends to "*out" the privileges required to run this command on database "dbname" with + * the invocation described by "cmdObj". New commands shouldn't implement this, they should + * implement checkAuthForOperation (which takes an OperationContext*), instead. + */ + virtual void addRequiredPrivileges(const std::string& dbname, + const BSONObj& cmdObj, + std::vector<Privilege>* out) { + // The default implementation of addRequiredPrivileges should never be hit. + fassertFailed(16940); + } + + // + // Methods provided for subclasses if they implement above interface. + // + + /** + * Calls run(). + */ + bool enhancedRun(OperationContext* opCtx, + const OpMsgRequest& request, + BSONObjBuilder& result) final; + + /** + * Calls checkAuthForOperation. + */ + Status checkAuthForRequest(OperationContext* opCtx, const OpMsgRequest& request) final; + + void uassertNoDocumentSequences(const OpMsgRequest& request); }; /** diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript index 6c711a48810..ed571c55ca3 100644 --- a/src/mongo/db/commands/SConscript +++ b/src/mongo/db/commands/SConscript @@ -35,6 +35,18 @@ env.Library( ) env.Library( + target="write_commands_common", + source=[ + "write_commands/write_commands_common.cpp", + ], + LIBDEPS=[ + '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/db/commands', + '$BUILD_DIR/mongo/db/ops/write_ops_parsers', + ], +) + +env.Library( target="core", source=[ "authentication_commands.cpp", @@ -52,7 +64,6 @@ env.Library( "parameters.cpp", "rename_collection_common.cpp", "user_management_commands_common.cpp", - "write_commands/write_commands_common.cpp", ], LIBDEPS=[ '$BUILD_DIR/mongo/client/clientdriver', @@ -205,7 +216,8 @@ env.Library( 'current_op_common', 'dcommands_fcv', 'dcommands_fsync', - 'killcursors_common' + 'killcursors_common', + 'write_commands_common', ], ) diff --git a/src/mongo/db/commands/apply_ops_cmd_common.cpp b/src/mongo/db/commands/apply_ops_cmd_common.cpp index 55b463abc04..06628e63fd5 100644 --- a/src/mongo/db/commands/apply_ops_cmd_common.cpp +++ b/src/mongo/db/commands/apply_ops_cmd_common.cpp @@ -79,7 +79,7 @@ Status checkOperationAuthorization(OperationContext* opCtx, return Status(ErrorCodes::FailedToParse, "Unrecognized command in op"); } - return Command::checkAuthorization(command, opCtx, dbname, o); + return Command::checkAuthorization(command, opCtx, OpMsgRequest::fromDBAndBody(dbname, o)); } if (opType == "i"_sd) { diff --git a/src/mongo/db/commands/explain_cmd.cpp b/src/mongo/db/commands/explain_cmd.cpp index c2b3893c15e..d0a218a2e1a 100644 --- a/src/mongo/db/commands/explain_cmd.cpp +++ b/src/mongo/db/commands/explain_cmd.cpp @@ -117,7 +117,8 @@ public: return Status(ErrorCodes::CommandNotFound, ss); } - return commToExplain->checkAuthForOperation(opCtx, dbname, explainObj); + return commToExplain->checkAuthForRequest( + opCtx, OpMsgRequest::fromDBAndBody(dbname, std::move(explainObj))); } virtual bool run(OperationContext* opCtx, diff --git a/src/mongo/db/commands/write_commands/write_commands.cpp b/src/mongo/db/commands/write_commands/write_commands.cpp index 2c9d5a37c8f..695e5cd3710 100644 --- a/src/mongo/db/commands/write_commands/write_commands.cpp +++ b/src/mongo/db/commands/write_commands/write_commands.cpp @@ -73,10 +73,9 @@ void redactTooLongLog(mutablebson::Document* cmdObj, StringData fieldName) { Status checkAuthForWriteCommand(Client* client, BatchedCommandRequest::BatchType batchType, - NamespaceString ns, - const BSONObj& cmdObj) { + const OpMsgRequest& request) { Status status = - auth::checkAuthForWriteCommand(AuthorizationSession::get(client), batchType, ns, cmdObj); + auth::checkAuthForWriteCommand(AuthorizationSession::get(client), batchType, request); if (!status.isOK()) { LastError::get(client).setLastError(status.code(), status.reason()); } @@ -232,13 +231,9 @@ public: help << "insert documents"; } - Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) final { - return checkAuthForWriteCommand(client, - BatchedCommandRequest::BatchType_Insert, - NamespaceString(parseNs(dbname, cmdObj)), - cmdObj); + Status checkAuthForRequest(OperationContext* opCtx, const OpMsgRequest& request) final { + return checkAuthForWriteCommand( + opCtx->getClient(), BatchedCommandRequest::BatchType_Insert, request); } void runImpl(OperationContext* opCtx, @@ -267,13 +262,9 @@ public: help << "update documents"; } - Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) final { - return checkAuthForWriteCommand(client, - BatchedCommandRequest::BatchType_Update, - NamespaceString(parseNs(dbname, cmdObj)), - cmdObj); + Status checkAuthForRequest(OperationContext* opCtx, const OpMsgRequest& request) final { + return checkAuthForWriteCommand( + opCtx->getClient(), BatchedCommandRequest::BatchType_Update, request); } void runImpl(OperationContext* opCtx, @@ -338,13 +329,9 @@ public: help << "delete documents"; } - Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) final { - return checkAuthForWriteCommand(client, - BatchedCommandRequest::BatchType_Delete, - NamespaceString(parseNs(dbname, cmdObj)), - cmdObj); + Status checkAuthForRequest(OperationContext* opCtx, const OpMsgRequest& request) final { + return checkAuthForWriteCommand( + opCtx->getClient(), BatchedCommandRequest::BatchType_Delete, request); } void runImpl(OperationContext* opCtx, diff --git a/src/mongo/db/commands/write_commands/write_commands_common.cpp b/src/mongo/db/commands/write_commands/write_commands_common.cpp index 9a5eb5d6cd8..98acc3dd66b 100644 --- a/src/mongo/db/commands/write_commands/write_commands_common.cpp +++ b/src/mongo/db/commands/write_commands/write_commands_common.cpp @@ -44,6 +44,7 @@ namespace mongo { namespace auth { namespace { +using write_ops::Delete; using write_ops::Insert; using write_ops::Update; using write_ops::UpdateOpEntry; @@ -51,17 +52,9 @@ using write_ops::UpdateOpEntry; /** * Helper to determine whether or not there are any upserts in the batch */ -bool containsUpserts(const BSONObj& writeCmdObj) { - BSONElement updatesEl = writeCmdObj[Update::kUpdatesFieldName]; - if (updatesEl.type() != Array) { - return false; - } - - for (const auto& updateEl : updatesEl.Array()) { - if (!updateEl.isABSONObj()) - continue; - - if (updateEl.Obj()[UpdateOpEntry::kUpsertFieldName].trueValue()) +bool containsUpserts(const std::vector<UpdateOpEntry>& updates) { + for (auto&& update : updates) { + if (update.getUpsert()) return true; } @@ -73,26 +66,18 @@ bool containsUpserts(const BSONObj& writeCmdObj) { * * TODO: Remove when we have parsing hooked before authorization. */ -StatusWith<NamespaceString> getIndexedNss(const BSONObj& writeCmdObj) { - BSONElement documentsEl = writeCmdObj[Insert::kDocumentsFieldName]; - if (documentsEl.type() != Array) { - return {ErrorCodes::FailedToParse, "index write batch is invalid"}; - } - - BSONObjIterator it(documentsEl.Obj()); - if (!it.more()) { +StatusWith<NamespaceString> getIndexedNss(const std::vector<BSONObj>& documentsToInsert) { + if (documentsToInsert.empty()) { return {ErrorCodes::FailedToParse, "index write batch is empty"}; } - BSONElement indexDescEl = it.next(); - - const std::string nsToIndex = indexDescEl["ns"].str(); + const std::string nsToIndex = documentsToInsert.front()["ns"].str(); if (nsToIndex.empty()) { return {ErrorCodes::FailedToParse, "index write batch contains an invalid index descriptor"}; } - if (it.more()) { + if (documentsToInsert.size() != 1) { return {ErrorCodes::FailedToParse, "index write batches may only contain a single index descriptor"}; } @@ -104,21 +89,23 @@ StatusWith<NamespaceString> getIndexedNss(const BSONObj& writeCmdObj) { Status checkAuthForWriteCommand(AuthorizationSession* authzSession, BatchedCommandRequest::BatchType cmdType, - const NamespaceString& cmdNSS, - const BSONObj& cmdObj) { + const OpMsgRequest& request) { std::vector<Privilege> privileges; ActionSet actionsOnCommandNSS; - if (shouldBypassDocumentValidationForCommand(cmdObj)) { + if (shouldBypassDocumentValidationForCommand(request.body)) { actionsOnCommandNSS.addAction(ActionType::bypassDocumentValidation); } + NamespaceString cmdNSS; if (cmdType == BatchedCommandRequest::BatchType_Insert) { - if (!cmdNSS.isSystemDotIndexes()) { + auto op = Insert::parse(IDLParserErrorContext("insert"), request); + cmdNSS = op.getNamespace(); + if (!op.getNamespace().isSystemDotIndexes()) { actionsOnCommandNSS.addAction(ActionType::insert); } else { // Special-case indexes until we have a command - const auto swNssToIndex = getIndexedNss(cmdObj); + const auto swNssToIndex = getIndexedNss(op.getDocuments()); if (!swNssToIndex.isOK()) { return swNssToIndex.getStatus(); } @@ -128,14 +115,18 @@ Status checkAuthForWriteCommand(AuthorizationSession* authzSession, Privilege(ResourcePattern::forExactNamespace(nssToIndex), ActionType::createIndex)); } } else if (cmdType == BatchedCommandRequest::BatchType_Update) { + auto op = Update::parse(IDLParserErrorContext("update"), request); + cmdNSS = op.getNamespace(); actionsOnCommandNSS.addAction(ActionType::update); // Upsert also requires insert privs - if (containsUpserts(cmdObj)) { + if (containsUpserts(op.getUpdates())) { actionsOnCommandNSS.addAction(ActionType::insert); } } else { fassert(17251, cmdType == BatchedCommandRequest::BatchType_Delete); + auto op = Delete::parse(IDLParserErrorContext("delete"), request); + cmdNSS = op.getNamespace(); actionsOnCommandNSS.addAction(ActionType::remove); } diff --git a/src/mongo/db/commands/write_commands/write_commands_common.h b/src/mongo/db/commands/write_commands/write_commands_common.h index 8f8206d3c70..897ee283fe1 100644 --- a/src/mongo/db/commands/write_commands/write_commands_common.h +++ b/src/mongo/db/commands/write_commands/write_commands_common.h @@ -32,6 +32,7 @@ #include "mongo/db/jsobj.h" #include "mongo/db/namespace_string.h" #include "mongo/s/write_ops/batched_command_request.h" +#include "mongo/util/net/op_msg.h" /** * Contains common functionality shared between the batch write commands in mongos and mongod. @@ -42,8 +43,7 @@ namespace auth { Status checkAuthForWriteCommand(AuthorizationSession* authzSession, BatchedCommandRequest::BatchType cmdType, - const NamespaceString& cmdNSS, - const BSONObj& cmdObj); + const OpMsgRequest& request); } // namespace auth } // namespace mongo diff --git a/src/mongo/db/ops/write_ops_document_stream_integration_test.cpp b/src/mongo/db/ops/write_ops_document_stream_integration_test.cpp index adfc5842e3d..3ef382f3ef4 100644 --- a/src/mongo/db/ops/write_ops_document_stream_integration_test.cpp +++ b/src/mongo/db/ops/write_ops_document_stream_integration_test.cpp @@ -66,4 +66,39 @@ TEST(WriteOpsDocSeq, InsertDocStreamWorks) { ASSERT_EQ(conn->count(ns.ns()), 5u); } +TEST(WriteOpsDocSeq, InsertDocStreamWorksWithSystemDotIndexes) { + std::string errMsg; + auto conn = std::unique_ptr<DBClientBase>( + unittest::getFixtureConnectionString().connect("integration_test", errMsg)); + uassert(ErrorCodes::SocketException, errMsg, conn); + + NamespaceString ns("test", "doc_seq"); + conn->dropCollection(ns.ns()); + ASSERT_EQ(conn->count(ns.ns()), 0u); + + OpMsgRequest request; + request.body = BSON("insert" + << "system.indexes" + << "$db" + << ns.db()); + request.sequences = {{"documents", + { + BSON("ns" << ns.ns() << "key" << BSON("x" << 1) << "name" + << "my_special_index"), + }}}; + + const auto reply = conn->runCommand(std::move(request)); + ASSERT_EQ(int(reply->getProtocol()), int(rpc::Protocol::kOpMsg)); + auto body = reply->getCommandReply(); + ASSERT_OK(getStatusFromCommandResult(body)); + ASSERT_EQ(body["n"].Int(), 1); + + auto indexes = conn->getIndexSpecs(ns.ns()); + ASSERT_EQ(indexes.size(), 2u); // my_special_index + _id + + indexes.sort([](auto&& l, auto&& r) { return l["name"].String() < r["name"].String(); }); + ASSERT_EQ(indexes.front()["name"].String(), "_id_"); + ASSERT_EQ(indexes.back()["name"].String(), "my_special_index"); +} + } // namespace mongo diff --git a/src/mongo/db/service_entry_point_mongod.cpp b/src/mongo/db/service_entry_point_mongod.cpp index 0491274939f..67790e417fc 100644 --- a/src/mongo/db/service_entry_point_mongod.cpp +++ b/src/mongo/db/service_entry_point_mongod.cpp @@ -573,7 +573,7 @@ void execCommandDatabase(OperationContext* opCtx, OperationContextSession sessionTxnState(opCtx); ImpersonationSessionGuard guard(opCtx); - uassertStatusOK(Command::checkAuthorization(command, opCtx, dbname, request.body)); + uassertStatusOK(Command::checkAuthorization(command, opCtx, request)); repl::ReplicationCoordinator* replCoord = repl::ReplicationCoordinator::get(opCtx->getClient()->getServiceContext()); diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript index 58588b5a7b7..eceafa93e4f 100644 --- a/src/mongo/s/commands/SConscript +++ b/src/mongo/s/commands/SConscript @@ -87,6 +87,7 @@ env.Library( '$BUILD_DIR/mongo/db/commands/apply_ops_cmd_common', '$BUILD_DIR/mongo/db/commands/killcursors_common', '$BUILD_DIR/mongo/db/ftdc/ftdc_server', + '$BUILD_DIR/mongo/db/commands/write_commands_common', '$BUILD_DIR/mongo/db/pipeline/aggregation', '$BUILD_DIR/mongo/db/views/views', '$BUILD_DIR/mongo/rpc/client_metadata', diff --git a/src/mongo/s/commands/cluster_explain_cmd.cpp b/src/mongo/s/commands/cluster_explain_cmd.cpp index 6397a2d3f07..0b7897f416c 100644 --- a/src/mongo/s/commands/cluster_explain_cmd.cpp +++ b/src/mongo/s/commands/cluster_explain_cmd.cpp @@ -102,7 +102,8 @@ public: return Status(ErrorCodes::CommandNotFound, ss); } - return commToExplain->checkAuthForOperation(opCtx, dbname, explainObj); + return commToExplain->checkAuthForRequest( + opCtx, OpMsgRequest::fromDBAndBody(dbname, std::move(explainObj))); } virtual bool run(OperationContext* opCtx, diff --git a/src/mongo/s/commands/cluster_write_cmd.cpp b/src/mongo/s/commands/cluster_write_cmd.cpp index b0c5e248c8f..1f1ad290f47 100644 --- a/src/mongo/s/commands/cluster_write_cmd.cpp +++ b/src/mongo/s/commands/cluster_write_cmd.cpp @@ -76,17 +76,13 @@ public: return true; } - virtual Status checkAuthForCommand(Client* client, - const std::string& dbname, - const BSONObj& cmdObj) { - Status status = auth::checkAuthForWriteCommand(AuthorizationSession::get(client), - _writeType, - NamespaceString(parseNs(dbname, cmdObj)), - cmdObj); + Status checkAuthForRequest(OperationContext* opCtx, const OpMsgRequest& request) final { + Status status = auth::checkAuthForWriteCommand( + AuthorizationSession::get(opCtx->getClient()), _writeType, request); // TODO: Remove this when we standardize GLE reporting from commands if (!status.isOK()) { - LastError::get(client).setLastError(status.code(), status.reason()); + LastError::get(opCtx->getClient()).setLastError(status.code(), status.reason()); } return status; diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp index 915809a03aa..eb7d7a53b34 100644 --- a/src/mongo/s/commands/strategy.cpp +++ b/src/mongo/s/commands/strategy.cpp @@ -179,7 +179,7 @@ void execCommandClient(OperationContext* opCtx, topLevelFields[fieldName]++ == 0); } - Status status = Command::checkAuthorization(c, opCtx, dbname, request.body); + Status status = Command::checkAuthorization(c, opCtx, request); if (!status.isOK()) { Command::appendCommandStatus(result, status); return; |