void Pipeline::addRequiredPrivileges(Command* commandTemplate, const string& db, BSONObj cmdObj, vector<Privilege>* out) { NamespaceString inputNs(db, cmdObj.firstElement().str()); auto inputResource = ResourcePattern::forExactNamespace(inputNs); uassert(17138, mongoutils::str::stream() << "Invalid input namespace, " << inputNs.ns(), inputNs.isValid()); out->push_back(Privilege(inputResource, ActionType::find)); BSONObj pipeline = cmdObj.getObjectField("pipeline"); BSONForEach(stageElem, pipeline) { BSONObj stage = stageElem.embeddedObjectUserCheck(); if (str::equals(stage.firstElementFieldName(), "$out")) { NamespaceString outputNs(db, stage.firstElement().str()); uassert(17139, mongoutils::str::stream() << "Invalid $out target namespace, " << outputNs.ns(), outputNs.isValid()); ActionSet actions; actions.addAction(ActionType::remove); actions.addAction(ActionType::insert); if (shouldBypassDocumentValidationForCommand(cmdObj)) { actions.addAction(ActionType::bypassDocumentValidation); } out->push_back(Privilege(ResourcePattern::forExactNamespace(outputNs), actions)); } }
Status Pipeline::checkAuthForCommand(ClientBasic* client, const std::string& db, const BSONObj& cmdObj) { NamespaceString inputNs(db, cmdObj.firstElement().str()); auto inputResource = ResourcePattern::forExactNamespace(inputNs); uassert(17138, mongoutils::str::stream() << "Invalid input namespace, " << inputNs.ns(), inputNs.isValid()); std::vector<Privilege> privileges; if (dps::extractElementAtPath(cmdObj, "pipeline.0.$indexStats")) { Privilege::addPrivilegeToPrivilegeVector( &privileges, Privilege(ResourcePattern::forAnyNormalResource(), ActionType::indexStats)); } else if (dps::extractElementAtPath(cmdObj, "pipeline.0.$collStats")) { Privilege::addPrivilegeToPrivilegeVector(&privileges, Privilege(inputResource, ActionType::collStats)); } else { // If no source requiring an alternative permission scheme is specified then default to // requiring find() privileges on the given namespace. Privilege::addPrivilegeToPrivilegeVector(&privileges, Privilege(inputResource, ActionType::find)); } BSONObj pipeline = cmdObj.getObjectField("pipeline"); BSONForEach(stageElem, pipeline) { BSONObj stage = stageElem.embeddedObjectUserCheck(); StringData stageName = stage.firstElementFieldName(); if (stageName == "$out" && stage.firstElementType() == String) { NamespaceString outputNs(db, stage.firstElement().str()); uassert(17139, mongoutils::str::stream() << "Invalid $out target namespace, " << outputNs.ns(), outputNs.isValid()); ActionSet actions; actions.addAction(ActionType::remove); actions.addAction(ActionType::insert); if (shouldBypassDocumentValidationForCommand(cmdObj)) { actions.addAction(ActionType::bypassDocumentValidation); } Privilege::addPrivilegeToPrivilegeVector( &privileges, Privilege(ResourcePattern::forExactNamespace(outputNs), actions)); } else if (stageName == "$lookup" && stage.firstElementType() == Object) { NamespaceString fromNs(db, stage.firstElement()["from"].str()); Privilege::addPrivilegeToPrivilegeVector( &privileges, Privilege(ResourcePattern::forExactNamespace(fromNs), ActionType::find)); } else if (stageName == "$graphLookup" && stage.firstElementType() == Object) { NamespaceString fromNs(db, stage.firstElement()["from"].str()); Privilege::addPrivilegeToPrivilegeVector( &privileges, Privilege(ResourcePattern::forExactNamespace(fromNs), ActionType::find)); } }