void SASLServerMechanismRegistry::advertiseMechanismNamesForUser(OperationContext* opCtx, const BSONObj& isMasterCmd, BSONObjBuilder* builder) { BSONElement saslSupportedMechs = isMasterCmd["saslSupportedMechs"]; if (saslSupportedMechs.type() == BSONType::String) { UserName userName = uassertStatusOK(UserName::parse(saslSupportedMechs.String())); // Authenticating the __system@local user to the admin database on mongos is required // by the auth passthrough test suite. if (getTestCommandsEnabled() && userName.getUser() == internalSecurity.user->getName().getUser() && userName.getDB() == "admin") { userName = internalSecurity.user->getName(); } AuthorizationManager* authManager = AuthorizationManager::get(opCtx->getServiceContext()); UserHandle user; const auto swUser = authManager->acquireUser(opCtx, userName); if (!swUser.isOK()) { auto& status = swUser.getStatus(); if (status.code() == ErrorCodes::UserNotFound) { log() << "Supported SASL mechanisms requested for unknown user '" << userName << "'"; return; } uassertStatusOK(status); } user = std::move(swUser.getValue()); BSONArrayBuilder mechanismsBuilder; const auto& mechList = _getMapRef(userName.getDB()); for (const auto& factoryIt : mechList) { SecurityPropertySet properties = factoryIt->properties(); if (!properties.hasAllProperties(SecurityPropertySet{SecurityProperty::kNoPlainText, SecurityProperty::kMutualAuth}) && userName.getDB() != "$external") { continue; } auto mechanismEnabled = _mechanismSupportedByConfig(factoryIt->mechanismName()); if (!mechanismEnabled && userName == internalSecurity.user->getName()) { mechanismEnabled = factoryIt->isInternalAuthMech(); } if (mechanismEnabled && factoryIt->canMakeMechanismForUser(user.get())) { mechanismsBuilder << factoryIt->mechanismName(); } } builder->appendArray("saslSupportedMechs", mechanismsBuilder.arr()); } }
void NoopWriter::_writeNoop(OperationContext* opCtx) { // Use GlobalLock + lockMMAPV1Flush instead of DBLock to allow return when the lock is not // available. It may happen when the primary steps down and a shared global lock is acquired. Lock::GlobalLock lock( opCtx, MODE_IX, Date_t::now() + Milliseconds(1), Lock::InterruptBehavior::kLeaveUnlocked); if (!lock.isLocked()) { LOG(1) << "Global lock is not available skipping noopWrite"; return; } opCtx->lockState()->lockMMAPV1Flush(); auto replCoord = ReplicationCoordinator::get(opCtx); // Its a proxy for being a primary if (!replCoord->canAcceptWritesForDatabase(opCtx, "admin")) { LOG(1) << "Not a primary, skipping the noop write"; return; } auto lastAppliedOpTime = replCoord->getMyLastAppliedOpTime(); // _lastKnownOpTime is not protected by lock as its used only by one thread. if (lastAppliedOpTime != _lastKnownOpTime) { LOG(1) << "Not scheduling a noop write. Last known OpTime: " << _lastKnownOpTime << " != last primary OpTime: " << lastAppliedOpTime; } else { if (writePeriodicNoops.load()) { const auto logLevel = getTestCommandsEnabled() ? 0 : 1; LOG(logLevel) << "Writing noop to oplog as there has been no writes to this replica set in over " << _writeInterval; writeConflictRetry( opCtx, "writeNoop", NamespaceString::kRsOplogNamespace.ns(), [&opCtx] { WriteUnitOfWork uow(opCtx); opCtx->getClient()->getServiceContext()->getOpObserver()->onOpMessage(opCtx, kMsgObj); uow.commit(); }); } } _lastKnownOpTime = replCoord->getMyLastAppliedOpTime(); LOG(1) << "Set last known op time to " << _lastKnownOpTime; }
bool CurrentOpCommandBase::run(OperationContext* opCtx, const std::string& dbName, const BSONObj& cmdObj, BSONObjBuilder& result) { // Convert the currentOp command spec into an equivalent aggregation command. This will be // of the form {aggregate:1, pipeline: [{$currentOp: {idleConnections: $all, allUsers: // !$ownOps, truncateOps: true}}, {$match: {<filter>}}, {$group: {_id: null, inprog: {$push: // "$$ROOT"}}}], cursor:{}} std::vector<BSONObj> pipeline; // {$currentOp: {idleConnections: $all, allUsers: !$ownOps, truncateOps: true}} BSONObjBuilder currentOpBuilder; BSONObjBuilder currentOpSpecBuilder(currentOpBuilder.subobjStart("$currentOp")); // If test commands are enabled, then we allow the currentOp commands to specify whether or not // to truncate long operations via the '$truncateOps' parameter. Otherwise, we always truncate // operations to match the behaviour of the legacy currentOp command. const bool truncateOps = !getTestCommandsEnabled() || !cmdObj[kTruncateOps] || cmdObj[kTruncateOps].trueValue(); currentOpSpecBuilder.append("idleConnections", cmdObj[kAll].trueValue()); currentOpSpecBuilder.append("allUsers", !cmdObj[kOwnOps].trueValue()); currentOpSpecBuilder.append("truncateOps", truncateOps); currentOpSpecBuilder.doneFast(); pipeline.push_back(currentOpBuilder.obj()); // {$match: {<user-defined filter>}} BSONObjBuilder matchBuilder; BSONObjBuilder matchSpecBuilder(matchBuilder.subobjStart("$match")); size_t idx = 0; for (const auto& elt : cmdObj) { const auto fieldName = elt.fieldNameStringData(); if (0 == idx++ || kCurOpCmdParams.count(fieldName) || isGenericArgument(fieldName)) { continue; } matchSpecBuilder.append(elt); } matchSpecBuilder.doneFast(); pipeline.push_back(matchBuilder.obj()); // Perform any required modifications to the pipeline before adding the final $group stage. modifyPipeline(&pipeline); // {$group: {_id: null, inprog: {$push: "$$ROOT"}}} BSONObjBuilder groupBuilder; BSONObjBuilder groupSpecBuilder(groupBuilder.subobjStart("$group")); groupSpecBuilder.append("_id", 0); BSONObjBuilder inprogSpecBuilder(groupSpecBuilder.subobjStart("inprog")); inprogSpecBuilder.append("$push", "$$ROOT"); inprogSpecBuilder.doneFast(); groupSpecBuilder.doneFast(); pipeline.push_back(groupBuilder.obj()); // Pipeline is complete; create an AggregationRequest for $currentOp. const AggregationRequest request(NamespaceString::makeCollectionlessAggregateNSS("admin"), std::move(pipeline)); // Run the pipeline and obtain a CursorResponse. auto aggResults = uassertStatusOK(runAggregation(opCtx, request)); if (aggResults.getBatch().empty()) { result.append("inprog", BSONArray()); } else { result.append(aggResults.getBatch().front()["inprog"]); } // Make any final custom additions to the response object. appendToResponse(&result); return true; }