[SERVER-53218] Inherit API Parameters from command for validator evaluation Created: 03/Dec/20  Updated: 29/Oct/23  Resolved: 18/Feb/21

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: 4.9.0

Type: Task Priority: Major - P3
Reporter: Nicholas Zolnierz Assignee: Arun Banala
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Backwards Compatibility: Fully Compatible
Sprint: Query Execution 2021-02-22
Participants:

 Description   

This was discovered under SERVER-51617, where the evaluation of a document validator for each insert/update command uses the ExpressionContext created at parse time of the validator. Currently, the validation is performed under a const context since access to the Collection object needs to be thread safe. This means that we can't just expose a 'reattachToOperationContext' sort of method, but may need to funnel through an OperationContext/ExpressionContext/APIParameters to the MatchExpression::matches and Expression::evaluate methods.



 Comments   
Comment by Githook User [ 17/Feb/21 ]

Author:

{'name': 'Arun Banala', 'email': 'arun.banala@mongodb.com', 'username': 'banarun'}

Message: SERVER-53218 Inherit API Parameters from command for validator evaluation
Branch: master
https://github.com/mongodb/mongo/commit/45e2b7620e47e367f940c838b44d8139de3b8205

Comment by Nicholas Zolnierz [ 03/Dec/20 ]

I don't think we want to this, but reparsing the expression for each insert fixed the issue:

diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp
index a7197aedf5..efc9904cba 100644
--- a/src/mongo/db/catalog/collection_impl.cpp
+++ b/src/mongo/db/catalog/collection_impl.cpp
@@ -440,8 +440,33 @@ Status CollectionImpl::checkValidation(OperationContext* opCtx, const BSONObj& d
         return Status::OK();
     }
 
-    if (validatorMatchExpr->matchesBSON(document))
-        return Status::OK();
+    // If the API parameters were set on the operation, then reparse the validator with the new
+    // parameters.
+    if (APIParameters::get(opCtx).getParamsPassed()) {
+        //  Before evaluating the match expression, inherit the API version parameters from
+        // the OperationContext.
+        auto expCtx = _validator.expCtxForFilter->copyWith(opCtx);
+
+        // If the validation action is "warn" or the level is "moderate", then disallow any
+        // encryption keywords. This is to prevent any plaintext data from showing up in the logs.
+        MatchExpressionParser::AllowedFeatureSet allowedFeatures =
+            MatchExpressionParser::kDefaultSpecialFeatures;
+        if (_validationAction == CollectionImpl::ValidationAction::WARN ||
+            _validationLevel == CollectionImpl::ValidationLevel::MODERATE)
+            allowedFeatures &= ~MatchExpressionParser::AllowedFeatures::kEncryptKeywords;
+
+        auto statusWithMatcher = MatchExpressionParser::parse(
+            _validator.validatorDoc, expCtx, ExtensionsCallbackNoop(), allowedFeatures);
+
+        if (!statusWithMatcher.isOK()) {
+            return statusWithMatcher.getStatus();
+        }
+        if (statusWithMatcher.getValue()->matchesBSON(document))
+            return Status::OK();
+    } else {
+        if (validatorMatchExpr->matchesBSON(document))
+            return Status::OK();
+    }

arun.banala and I also discussed better approaches to avoid reparsing (and the potential perf hit), most of which involved plumbing through a new parameter to the expression evaluation methods.

Generated at Thu Feb 08 05:30:16 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.