summaryrefslogtreecommitdiff
path: root/src/mongo/db/catalog/coll_mod.cpp
diff options
context:
space:
mode:
authorNick Zolnierz <nicholas.zolnierz@mongodb.com>2020-04-09 10:45:06 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-04-27 13:47:14 +0000
commit3032eb8c2a10163bf727767efe2b73b8d60c9ecb (patch)
tree5e57608a4b1ee76158d2706c1dac6d1ce9e653e2 /src/mongo/db/catalog/coll_mod.cpp
parentb3ecf8bc6b2c787d672be1c31187f3f2b2d673cd (diff)
downloadmongo-3032eb8c2a10163bf727767efe2b73b8d60c9ecb.tar.gz
SERVER-45514 Reject document validators with encryption-related keywords if the validationAction is "warn" or validationLevel is "moderate"
Diffstat (limited to 'src/mongo/db/catalog/coll_mod.cpp')
-rw-r--r--src/mongo/db/catalog/coll_mod.cpp110
1 files changed, 56 insertions, 54 deletions
diff --git a/src/mongo/db/catalog/coll_mod.cpp b/src/mongo/db/catalog/coll_mod.cpp
index da5e601bdef..40d6b541f97 100644
--- a/src/mongo/db/catalog/coll_mod.cpp
+++ b/src/mongo/db/catalog/coll_mod.cpp
@@ -72,9 +72,9 @@ struct CollModRequest {
BSONElement indexHidden = {};
BSONElement viewPipeLine = {};
std::string viewOn = {};
- BSONElement collValidator = {};
- std::string collValidationAction = {};
- std::string collValidationLevel = {};
+ boost::optional<Collection::Validator> collValidator;
+ boost::optional<std::string> collValidationAction;
+ boost::optional<std::string> collValidationLevel;
bool recordPreImages = false;
};
@@ -191,15 +191,13 @@ StatusWith<CollModRequest> parseCollModRequest(OperationContext* opCtx,
ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo46) {
maxFeatureCompatibilityVersion = currentFCV;
}
- auto statusW = coll->parseValidator(opCtx,
- e.Obj(),
- MatchExpressionParser::kDefaultSpecialFeatures,
- maxFeatureCompatibilityVersion);
- if (!statusW.isOK()) {
- return statusW.getStatus();
+ cmr.collValidator = coll->parseValidator(opCtx,
+ e.Obj().getOwned(),
+ MatchExpressionParser::kDefaultSpecialFeatures,
+ maxFeatureCompatibilityVersion);
+ if (!cmr.collValidator->isOK()) {
+ return cmr.collValidator->getStatus();
}
-
- cmr.collValidator = e;
} else if (fieldName == "validationLevel" && !isView) {
auto status = coll->parseValidationLevel(e.String());
if (!status.isOK())
@@ -345,19 +343,22 @@ Status _collModInternal(OperationContext* opCtx,
auto oplogEntryObj = oplogEntryBuilder.obj();
// Save both states of the CollModRequest to allow writeConflictRetries.
- const CollModRequest cmrOld = statusW.getValue();
- CollModRequest cmrNew = statusW.getValue();
-
- if (!cmrOld.indexHidden.eoo()) {
-
+ CollModRequest cmrNew = std::move(statusW.getValue());
+ auto viewPipeline = cmrNew.viewPipeLine;
+ auto viewOn = cmrNew.viewOn;
+ auto indexExpireAfterSeconds = cmrNew.indexExpireAfterSeconds;
+ auto indexHidden = cmrNew.indexHidden;
+ auto idx = cmrNew.idx;
+
+ if (indexHidden) {
if (serverGlobalParams.featureCompatibility.getVersion() <
ServerGlobalParams::FeatureCompatibility::Version::kFullyUpgradedTo46 &&
- cmrOld.indexHidden.booleanSafe()) {
+ indexHidden.booleanSafe()) {
return Status(ErrorCodes::BadValue, "Hidden indexes can only be created with FCV 4.6");
}
if (coll->ns().isSystem())
return Status(ErrorCodes::BadValue, "Can't hide index on system collection");
- if (cmrOld.idx->isIdIndex())
+ if (idx->isIdIndex())
return Status(ErrorCodes::BadValue, "can't hide _id index");
}
@@ -367,11 +368,11 @@ Status _collModInternal(OperationContext* opCtx,
// Handle collMod on a view and return early. The View Catalog handles the creation of oplog
// entries for modifications on a view.
if (view) {
- if (!cmrOld.viewPipeLine.eoo())
- view->setPipeline(cmrOld.viewPipeLine);
+ if (viewPipeline)
+ view->setPipeline(viewPipeline);
- if (!cmrOld.viewOn.empty())
- view->setViewOn(NamespaceString(dbName, cmrOld.viewOn));
+ if (!viewOn.empty())
+ view->setViewOn(NamespaceString(dbName, viewOn));
ViewCatalog* catalog = ViewCatalog::get(db);
@@ -401,53 +402,51 @@ Status _collModInternal(OperationContext* opCtx,
// Handle collMod operation type appropriately.
- if (!cmrOld.indexExpireAfterSeconds.eoo() || !cmrOld.indexHidden.eoo()) {
+ if (indexExpireAfterSeconds || indexHidden) {
BSONElement newExpireSecs = {};
BSONElement oldExpireSecs = {};
BSONElement newHidden = {};
BSONElement oldHidden = {};
+
// TTL Index
- if (!cmrOld.indexExpireAfterSeconds.eoo()) {
- newExpireSecs = cmrOld.indexExpireAfterSeconds;
- oldExpireSecs = cmrOld.idx->infoObj().getField("expireAfterSeconds");
+ if (indexExpireAfterSeconds) {
+ newExpireSecs = indexExpireAfterSeconds;
+ oldExpireSecs = idx->infoObj().getField("expireAfterSeconds");
if (SimpleBSONElementComparator::kInstance.evaluate(oldExpireSecs !=
newExpireSecs)) {
// Change the value of "expireAfterSeconds" on disk.
DurableCatalog::get(opCtx)->updateTTLSetting(opCtx,
coll->getCatalogId(),
- cmrOld.idx->indexName(),
+ idx->indexName(),
newExpireSecs.safeNumberLong());
}
}
// User wants to hide or unhide index.
- if (!cmrOld.indexHidden.eoo()) {
- newHidden = cmrOld.indexHidden;
- oldHidden = cmrOld.idx->infoObj().getField("hidden");
+ if (indexHidden) {
+ newHidden = indexHidden;
+ oldHidden = idx->infoObj().getField("hidden");
// Make sure when we set 'hidden' to false, we can remove the hidden field from
// catalog.
if (SimpleBSONElementComparator::kInstance.evaluate(oldHidden != newHidden)) {
- DurableCatalog::get(opCtx)->updateHiddenSetting(opCtx,
- coll->getCatalogId(),
- cmrOld.idx->indexName(),
- newHidden.booleanSafe());
+ DurableCatalog::get(opCtx)->updateHiddenSetting(
+ opCtx, coll->getCatalogId(), idx->indexName(), newHidden.booleanSafe());
}
}
-
- indexCollModInfo = IndexCollModInfo{
- cmrOld.indexExpireAfterSeconds.eoo() ? boost::optional<Seconds>()
- : Seconds(newExpireSecs.safeNumberLong()),
- cmrOld.indexExpireAfterSeconds.eoo() ? boost::optional<Seconds>()
- : Seconds(oldExpireSecs.safeNumberLong()),
- cmrOld.indexHidden.eoo() ? boost::optional<bool>() : newHidden.booleanSafe(),
- cmrOld.indexHidden.eoo() ? boost::optional<bool>() : oldHidden.booleanSafe(),
- cmrNew.idx->indexName()};
+ indexCollModInfo =
+ IndexCollModInfo{!indexExpireAfterSeconds ? boost::optional<Seconds>()
+ : Seconds(newExpireSecs.safeNumberLong()),
+ !indexExpireAfterSeconds ? boost::optional<Seconds>()
+ : Seconds(oldExpireSecs.safeNumberLong()),
+ !indexHidden ? boost::optional<bool>() : newHidden.booleanSafe(),
+ !indexHidden ? boost::optional<bool>() : oldHidden.booleanSafe(),
+ cmrNew.idx->indexName()};
// Notify the index catalog that the definition of this index changed. This will
- // invalidate the idx pointer in cmrOld. On rollback of this WUOW, the idx pointer
- // in cmrNew will be invalidated and the idx pointer in cmrOld will be valid again.
- cmrNew.idx = coll->getIndexCatalog()->refreshEntry(opCtx, cmrOld.idx);
+ // invalidate the local idx pointer. On rollback of this WUOW, the idx pointer in
+ // cmrNew will be invalidated and the local var idx pointer will be valid again.
+ cmrNew.idx = coll->getIndexCatalog()->refreshEntry(opCtx, idx);
opCtx->recoveryUnit()->registerChange(std::make_unique<CollModResultChange>(
oldExpireSecs, newExpireSecs, oldHidden, newHidden, result));
@@ -457,13 +456,17 @@ Status _collModInternal(OperationContext* opCtx,
}
}
- // The Validator, ValidationAction and ValidationLevel are already parsed and must be OK.
- if (!cmrNew.collValidator.eoo())
- invariant(coll->setValidator(opCtx, cmrNew.collValidator.Obj()));
- if (!cmrNew.collValidationAction.empty())
- invariant(coll->setValidationAction(opCtx, cmrNew.collValidationAction));
- if (!cmrNew.collValidationLevel.empty())
- invariant(coll->setValidationLevel(opCtx, cmrNew.collValidationLevel));
+ if (cmrNew.collValidator) {
+ coll->setValidator(opCtx, std::move(*cmrNew.collValidator));
+ }
+ if (cmrNew.collValidationAction)
+ uassertStatusOKWithContext(
+ coll->setValidationAction(opCtx, *cmrNew.collValidationAction),
+ "Failed to set validationAction");
+ if (cmrNew.collValidationLevel) {
+ uassertStatusOKWithContext(coll->setValidationLevel(opCtx, *cmrNew.collValidationLevel),
+ "Failed to set validationLevel");
+ }
if (cmrNew.recordPreImages != oldCollOptions.recordPreImages) {
coll->setRecordPreImages(opCtx, cmrNew.recordPreImages);
@@ -471,7 +474,6 @@ Status _collModInternal(OperationContext* opCtx,
// Only observe non-view collMods, as view operations are observed as operations on the
// system.views collection.
-
auto* const opObserver = opCtx->getServiceContext()->getOpObserver();
opObserver->onCollMod(
opCtx, nss, coll->uuid(), oplogEntryObj, oldCollOptions, indexCollModInfo);