summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/crypto/fle_crypto.cpp23
-rw-r--r--src/mongo/crypto/fle_crypto.h9
-rw-r--r--src/mongo/crypto/fle_crypto_test.cpp2
-rw-r--r--src/mongo/db/commands/fle2_compact.cpp11
-rw-r--r--src/mongo/db/commands/fle2_compact.h6
-rw-r--r--src/mongo/db/s/SConscript3
-rw-r--r--src/mongo/db/s/cleanup_structured_encryption_data_coordinator.cpp75
-rw-r--r--src/mongo/db/s/cleanup_structured_encryption_data_coordinator.h94
-rw-r--r--src/mongo/db/s/cleanup_structured_encryption_data_coordinator.idl90
-rw-r--r--src/mongo/db/s/sharding_ddl_coordinator.idl1
-rw-r--r--src/mongo/db/s/sharding_ddl_coordinator_service.cpp5
-rw-r--r--src/mongo/db/s/shardsvr_cleanup_structured_encryption_data_command.cpp159
-rw-r--r--src/mongo/s/commands/SConscript1
-rw-r--r--src/mongo/s/commands/cluster_fle2_cleanup_cmd.cpp123
14 files changed, 593 insertions, 9 deletions
diff --git a/src/mongo/crypto/fle_crypto.cpp b/src/mongo/crypto/fle_crypto.cpp
index 90ac49484db..35a18f29f07 100644
--- a/src/mongo/crypto/fle_crypto.cpp
+++ b/src/mongo/crypto/fle_crypto.cpp
@@ -4150,14 +4150,23 @@ std::vector<CompactionToken> CompactionHelpers::parseCompactionTokens(BSONObj co
void CompactionHelpers::validateCompactionTokens(const EncryptedFieldConfig& efc,
BSONObj compactionTokens) {
+ _validateTokens(efc, compactionTokens, "Compaction"_sd);
+}
+
+void CompactionHelpers::validateCleanupTokens(const EncryptedFieldConfig& efc,
+ BSONObj cleanupTokens) {
+ _validateTokens(efc, cleanupTokens, "Cleanup"_sd);
+}
+
+void CompactionHelpers::_validateTokens(const EncryptedFieldConfig& efc,
+ BSONObj tokens,
+ StringData cmd) {
for (const auto& field : efc.getFields()) {
- const auto& tokenElement = compactionTokens.getField(field.getPath());
- uassert(
- 6346806,
- str::stream()
- << "Compaction tokens object is missing compaction token for the encrypted path '"
- << field.getPath() << "'",
- !tokenElement.eoo());
+ const auto& tokenElement = tokens.getField(field.getPath());
+ uassert(7294900,
+ str::stream() << cmd << " tokens object is missing " << cmd
+ << " token for the encrypted path '" << field.getPath() << "'",
+ !tokenElement.eoo());
}
}
diff --git a/src/mongo/crypto/fle_crypto.h b/src/mongo/crypto/fle_crypto.h
index 4e82a75d6e6..866b21a3f9a 100644
--- a/src/mongo/crypto/fle_crypto.h
+++ b/src/mongo/crypto/fle_crypto.h
@@ -1326,6 +1326,15 @@ public:
* in the encrypted field config
*/
static void validateCompactionTokens(const EncryptedFieldConfig& efc, BSONObj compactionTokens);
+
+ /**
+ * Validates the compaction tokens BSON contains an element for each field
+ * in the encrypted field config
+ */
+ static void validateCleanupTokens(const EncryptedFieldConfig& efc, BSONObj cleanupTokens);
+
+private:
+ static void _validateTokens(const EncryptedFieldConfig& efc, BSONObj tokens, StringData cmd);
};
/**
diff --git a/src/mongo/crypto/fle_crypto_test.cpp b/src/mongo/crypto/fle_crypto_test.cpp
index 8b5f54e392d..5b328ef3dd4 100644
--- a/src/mongo/crypto/fle_crypto_test.cpp
+++ b/src/mongo/crypto/fle_crypto_test.cpp
@@ -2842,7 +2842,7 @@ TEST(CompactionHelpersTest, validateCompactionTokensTest) {
// validate fails until all fields are present
ASSERT_THROWS_CODE(CompactionHelpers::validateCompactionTokens(efc, builder.asTempObj()),
DBException,
- 6346806);
+ 7294900);
// validate doesn't care about the value, so this is fine
builder.append(field.getPath(), "foo");
diff --git a/src/mongo/db/commands/fle2_compact.cpp b/src/mongo/db/commands/fle2_compact.cpp
index 60516d19330..7e5aa58e7d8 100644
--- a/src/mongo/db/commands/fle2_compact.cpp
+++ b/src/mongo/db/commands/fle2_compact.cpp
@@ -38,7 +38,6 @@
#include "mongo/crypto/encryption_fields_gen.h"
#include "mongo/crypto/fle_stats.h"
#include "mongo/db/catalog/collection_catalog.h"
-#include "mongo/db/commands/fle2_compact_gen.h"
#include "mongo/db/commands/server_status.h"
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/pipeline/aggregate_command_gen.h"
@@ -487,6 +486,16 @@ void validateCompactRequest(const CompactStructuredEncryptionData& request, cons
CompactionHelpers::validateCompactionTokens(efc, request.getCompactionTokens());
}
+void validateCleanupRequest(const CleanupStructuredEncryptionData& request, const Collection& edc) {
+ uassert(7294901,
+ "Target namespace is not an encrypted collection",
+ edc.getCollectionOptions().encryptedFieldConfig);
+
+ // Validate the request contains a compaction token for each encrypted field
+ const auto& efc = edc.getCollectionOptions().encryptedFieldConfig.value();
+ CompactionHelpers::validateCleanupTokens(efc, request.getCleanupTokens());
+}
+
const PrfBlock& FLECompactESCDeleteSet::at(size_t index) const {
if (index >= size()) {
throw std::out_of_range("out of range");
diff --git a/src/mongo/db/commands/fle2_compact.h b/src/mongo/db/commands/fle2_compact.h
index 3fdabcdb3d6..08f0f4bc0bf 100644
--- a/src/mongo/db/commands/fle2_compact.h
+++ b/src/mongo/db/commands/fle2_compact.h
@@ -30,6 +30,7 @@
#pragma once
#include "mongo/base/status_with.h"
+#include "mongo/db/commands/fle2_cleanup_gen.h"
#include "mongo/db/commands/fle2_compact_gen.h"
#include "mongo/db/fle_crud.h"
@@ -52,6 +53,11 @@ struct EncryptedStateCollectionsNamespaces {
*/
void validateCompactRequest(const CompactStructuredEncryptionData& request, const Collection& edc);
+/**
+ * Validate a compact request has the right encryption tokens.
+ */
+void validateCleanupRequest(const CleanupStructuredEncryptionData& request, const Collection& edc);
+
void processFLECompactV2(OperationContext* opCtx,
const CompactStructuredEncryptionData& request,
GetTxnCallback getTxn,
diff --git a/src/mongo/db/s/SConscript b/src/mongo/db/s/SConscript
index 5d39f886d20..6d3f3566c38 100644
--- a/src/mongo/db/s/SConscript
+++ b/src/mongo/db/s/SConscript
@@ -457,6 +457,8 @@ env.Library(
'auto_split_vector_command.cpp',
'check_sharding_index_command.cpp',
'cleanup_orphaned_cmd.cpp',
+ 'cleanup_structured_encryption_data_coordinator.cpp',
+ 'cleanup_structured_encryption_data_coordinator.idl',
'clone_catalog_data_command.cpp',
'cluster_abort_transaction_cmd_d.cpp',
'cluster_commit_transaction_cmd_d.cpp',
@@ -555,6 +557,7 @@ env.Library(
'shardsvr_check_metadata_consistency_command.cpp',
'shardsvr_check_metadata_consistency_participant_command.cpp',
'shardsvr_cleanup_reshard_collection_command.cpp',
+ 'shardsvr_cleanup_structured_encryption_data_command.cpp',
'shardsvr_collmod_command.cpp',
'shardsvr_collmod_participant_command.cpp',
'shardsvr_index_catalog_test_commands.cpp',
diff --git a/src/mongo/db/s/cleanup_structured_encryption_data_coordinator.cpp b/src/mongo/db/s/cleanup_structured_encryption_data_coordinator.cpp
new file mode 100644
index 00000000000..55633d214df
--- /dev/null
+++ b/src/mongo/db/s/cleanup_structured_encryption_data_coordinator.cpp
@@ -0,0 +1,75 @@
+/**
+ * Copyright (C) 2023-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/s/cleanup_structured_encryption_data_coordinator.h"
+
+#include "mongo/base/checked_cast.h"
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/crypto/fle_options_gen.h"
+#include "mongo/db/catalog/collection_catalog.h"
+#include "mongo/db/commands/create_gen.h"
+#include "mongo/db/commands/rename_collection_gen.h"
+#include "mongo/db/dbdirectclient.h"
+#include "mongo/db/drop_gen.h"
+#include "mongo/db/persistent_task_store.h"
+#include "mongo/logv2/log.h"
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kSharding
+
+
+namespace mongo {
+
+boost::optional<BSONObj> CleanupStructuredEncryptionDataCoordinator::reportForCurrentOp(
+ MongoProcessInterface::CurrentOpConnectionsMode connMode,
+ MongoProcessInterface::CurrentOpSessionsMode sessionMode) noexcept {
+
+ return boost::none;
+}
+
+ExecutorFuture<void> CleanupStructuredEncryptionDataCoordinator::_runImpl(
+ std::shared_ptr<executor::ScopedTaskExecutor> executor,
+ const CancellationToken& token) noexcept {
+ return ExecutorFuture<void>(**executor)
+ .then(_buildPhaseHandler(Phase::kRenameEcocForCleanup,
+ [this, anchor = shared_from_this()]() {
+ // TODO
+ }))
+ .then(_buildPhaseHandler(Phase::kCleanupStructuredEncryptionData,
+ [this, anchor = shared_from_this()]() {
+ // TODO
+ }))
+ .then(_buildPhaseHandler(Phase::kDropTempCollection, [this, anchor = shared_from_this()] {
+ // TODO
+ }));
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/s/cleanup_structured_encryption_data_coordinator.h b/src/mongo/db/s/cleanup_structured_encryption_data_coordinator.h
new file mode 100644
index 00000000000..311169e14f8
--- /dev/null
+++ b/src/mongo/db/s/cleanup_structured_encryption_data_coordinator.h
@@ -0,0 +1,94 @@
+/**
+ * Copyright (C) 2023-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include <boost/optional.hpp>
+#include <memory>
+
+#include "mongo/bson/bsonobj.h"
+#include "mongo/db/commands/fle2_compact.h"
+#include "mongo/db/namespace_string.h"
+#include "mongo/db/s/cleanup_structured_encryption_data_coordinator_gen.h"
+#include "mongo/db/s/sharding_ddl_coordinator.h"
+
+namespace mongo {
+
+class CleanupStructuredEncryptionDataCoordinator final
+ : public RecoverableShardingDDLCoordinator<CleanupStructuredEncryptionDataState,
+ CleanupStructuredEncryptionDataPhaseEnum> {
+public:
+ static constexpr auto kStateContext = "CleanupStructuredEncryptionDataState"_sd;
+ using StateDoc = CleanupStructuredEncryptionDataState;
+ using Phase = CleanupStructuredEncryptionDataPhaseEnum;
+
+ CleanupStructuredEncryptionDataCoordinator(ShardingDDLCoordinatorService* service,
+ const BSONObj& doc)
+ : RecoverableShardingDDLCoordinator(
+ service, "CleanupStructuredEncryptionDataCoordinator", doc) {}
+
+ boost::optional<BSONObj> reportForCurrentOp(
+ MongoProcessInterface::CurrentOpConnectionsMode connMode,
+ MongoProcessInterface::CurrentOpSessionsMode sessionMode) noexcept final;
+
+ CleanupStructuredEncryptionDataCommandReply getResponse(OperationContext* opCtx) {
+ getCompletionFuture().get(opCtx);
+ invariant(_response);
+ return *_response;
+ }
+
+ void checkIfOptionsConflict(const BSONObj& stateDoc) const final {}
+
+private:
+ StringData serializePhase(const Phase& phase) const override {
+ return CleanupStructuredEncryptionDataPhase_serializer(phase);
+ }
+
+ ExecutorFuture<void> _runImpl(std::shared_ptr<executor::ScopedTaskExecutor> executor,
+ const CancellationToken& token) noexcept final;
+
+private:
+ // The response to the cleanup command
+ boost::optional<CleanupStructuredEncryptionDataCommandReply> _response;
+
+ // Whether to skip the cleanup operation
+ bool _skipCompact{false};
+
+ // The UUID of the temporary collection that the ECOC was renamed to
+ boost::optional<UUID> _ecocRenameUuid;
+
+ // Stats for the ESC
+ ECStats _escStats;
+
+ // Stats for the ECOC
+ ECOCStats _ecocStats;
+};
+
+
+} // namespace mongo
diff --git a/src/mongo/db/s/cleanup_structured_encryption_data_coordinator.idl b/src/mongo/db/s/cleanup_structured_encryption_data_coordinator.idl
new file mode 100644
index 00000000000..9860a803675
--- /dev/null
+++ b/src/mongo/db/s/cleanup_structured_encryption_data_coordinator.idl
@@ -0,0 +1,90 @@
+# Copyright (C) 2023-present MongoDB, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the Server Side Public License, version 1,
+# as published by MongoDB, Inc.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# Server Side Public License for more details.
+#
+# You should have received a copy of the Server Side Public License
+# along with this program. If not, see
+# <http://www.mongodb.com/licensing/server-side-public-license>.
+#
+# As a special exception, the copyright holders give permission to link the
+# code of portions of this program with the OpenSSL library under certain
+# conditions as described in each individual source file and distribute
+# linked combinations including the program with the OpenSSL library. You
+# must comply with the Server Side Public License in all respects for
+# all of the code used other than as permitted herein. If you modify file(s)
+# with this exception, you may extend this exception to your version of the
+# file(s), but you are not obligated to do so. If you do not wish to do so,
+# delete this exception statement from your version. If you delete this
+# exception statement from all source files in the program, then also delete
+# it in the license file.
+#
+
+global:
+ cpp_namespace: "mongo"
+
+imports:
+ - "mongo/db/basic_types.idl"
+ - "mongo/db/commands/fle2_cleanup.idl"
+ - "mongo/db/s/sharding_ddl_coordinator.idl"
+
+enums:
+ CleanupStructuredEncryptionDataPhase:
+ description: "The current phase of the cleanupStructuredEncryptionData pipeline"
+ type: string
+ values:
+ kUnset: "unset"
+ kRenameEcocForCleanup: "rename-collections-for-cleanup"
+ kCleanupStructuredEncryptionData: "cleanup-structured-encryption-data"
+ kDropTempCollection: "drop-temp-collection"
+
+structs:
+ CleanupStructuredEncryptionDataState:
+ description: "Represents the state of the cleanupStructuredEncryptionData pipeline
+ for protocol version 2"
+ strict: false
+ chained_structs:
+ ShardingDDLCoordinatorMetadata: ShardingDDLCoordinatorMetadata
+ fields:
+ phase:
+ description: "Current phase"
+ type: CleanupStructuredEncryptionDataPhase
+ default: kUnset
+ skipCleanup:
+ description: "Whether to skip the cleanup operation"
+ type: bool
+ default: false
+ escNss:
+ description: "Collection containing insertions metadata"
+ type: namespacestring
+ ecocNss:
+ description: "Collection containing cleanup metadata to perform cleanup with"
+ type: namespacestring
+ ecocUuid:
+ description: "UUID of the collection identified by ecocNss"
+ type: uuid
+ optional: true
+ ecocRenameNss:
+ description: "Temporary name to use while performing cleanup"
+ type: namespacestring
+ ecocRenameUuid:
+ description: "UUID of the collection identified by ecocRenameNss"
+ type: uuid
+ optional: true
+ cleanupTokens:
+ description: "Cleanup tokens for the cleanup operation"
+ type: object_owned
+ escStats:
+ description: "Statistics for the ESC collection"
+ type: ECStats
+ optional: true
+ ecocStats:
+ description: "Statistics for the temporary ECOC collection"
+ type: ECOCStats
+ optional: true
diff --git a/src/mongo/db/s/sharding_ddl_coordinator.idl b/src/mongo/db/s/sharding_ddl_coordinator.idl
index 4d874dbac8d..914551be35f 100644
--- a/src/mongo/db/s/sharding_ddl_coordinator.idl
+++ b/src/mongo/db/s/sharding_ddl_coordinator.idl
@@ -69,6 +69,7 @@ enums:
kCompactStructuredEncryptionDataPre70Compatible: "compactStructuredEncryptionData_V2"
# TODO SERVER-68373 remove once 7.0 becomes last LTS
kCompactStructuredEncryptionDataPre61Compatible: "compactStructuredEncryptionData"
+ kCleanupStructuredEncryptionData: "cleanupStructuredEncryptionData"
types:
ForwardableOperationMetadata:
diff --git a/src/mongo/db/s/sharding_ddl_coordinator_service.cpp b/src/mongo/db/s/sharding_ddl_coordinator_service.cpp
index 5f6cc209b0f..f196e8bf590 100644
--- a/src/mongo/db/s/sharding_ddl_coordinator_service.cpp
+++ b/src/mongo/db/s/sharding_ddl_coordinator_service.cpp
@@ -33,6 +33,7 @@
#include "mongo/base/checked_cast.h"
#include "mongo/db/dbdirectclient.h"
#include "mongo/db/pipeline/aggregate_command_gen.h"
+#include "mongo/db/s/cleanup_structured_encryption_data_coordinator.h"
#include "mongo/db/s/collmod_coordinator.h"
#include "mongo/db/s/compact_structured_encryption_data_coordinator.h"
#include "mongo/db/s/create_collection_coordinator.h"
@@ -109,6 +110,10 @@ std::shared_ptr<ShardingDDLCoordinator> constructShardingDDLCoordinatorInstance(
return std::make_shared<CompactStructuredEncryptionDataCoordinator>(
service, std::move(initialState));
break;
+ case DDLCoordinatorTypeEnum::kCleanupStructuredEncryptionData:
+ return std::make_shared<CleanupStructuredEncryptionDataCoordinator>(
+ service, std::move(initialState));
+ break;
default:
uasserted(ErrorCodes::BadValue,
str::stream()
diff --git a/src/mongo/db/s/shardsvr_cleanup_structured_encryption_data_command.cpp b/src/mongo/db/s/shardsvr_cleanup_structured_encryption_data_command.cpp
new file mode 100644
index 00000000000..14574183083
--- /dev/null
+++ b/src/mongo/db/s/shardsvr_cleanup_structured_encryption_data_command.cpp
@@ -0,0 +1,159 @@
+/**
+ * Copyright (C) 2023-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+
+#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/catalog/collection_catalog.h"
+#include "mongo/db/catalog_raii.h"
+#include "mongo/db/commands.h"
+#include "mongo/db/commands/feature_compatibility_version.h"
+#include "mongo/db/commands/fle2_cleanup_gen.h"
+#include "mongo/db/s/cleanup_structured_encryption_data_coordinator.h"
+#include "mongo/db/s/cleanup_structured_encryption_data_coordinator_gen.h"
+#include "mongo/db/server_feature_flags_gen.h"
+#include "mongo/logv2/log.h"
+#include "mongo/s/cluster_commands_helpers.h"
+
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kCommand
+
+
+namespace mongo {
+namespace {
+
+class _shardsvrCleanupStructuredEncryptionDataCommand final
+ : public TypedCommand<_shardsvrCleanupStructuredEncryptionDataCommand> {
+public:
+ using Request = CleanupStructuredEncryptionData;
+ using Reply = typename Request::Reply;
+
+ _shardsvrCleanupStructuredEncryptionDataCommand()
+ : TypedCommand("_shardsvrCleanupStructuredEncryptionData"_sd) {}
+
+ bool skipApiVersionCheck() const final {
+ // Internal command (server to server).
+ return true;
+ }
+
+ std::string help() const final {
+ return "Internal command. Do not call directly. Cleans up an ECOC collection.";
+ }
+
+ bool adminOnly() const final {
+ return false;
+ }
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const final {
+ return AllowedOnSecondary::kNever;
+ }
+
+ std::set<StringData> sensitiveFieldNames() const final {
+ return {CleanupStructuredEncryptionData::kCleanupTokensFieldName};
+ }
+
+ class Invocation final : public InvocationBase {
+ public:
+ using InvocationBase::InvocationBase;
+
+ Reply typedRun(OperationContext* opCtx) {
+
+ CurOp::get(opCtx)->debug().shouldOmitDiagnosticInformation = true;
+
+ auto cleanupCoordinator =
+ [&]() -> std::shared_ptr<ShardingDDLCoordinatorService::Instance> {
+ FixedFCVRegion fixedFcvRegion(opCtx);
+
+ auto cleanup = makeRequest(opCtx);
+ return ShardingDDLCoordinatorService::getService(opCtx)->getOrCreateInstance(
+ opCtx, cleanup.toBSON());
+ }();
+
+ return checked_pointer_cast<CleanupStructuredEncryptionDataCoordinator>(
+ cleanupCoordinator)
+ ->getResponse(opCtx);
+ }
+
+ private:
+ CleanupStructuredEncryptionDataState makeRequest(OperationContext* opCtx) {
+ const auto& req = request();
+ const auto& nss = req.getNamespace();
+
+ AutoGetCollection baseColl(opCtx, nss, MODE_IX);
+ uassert(ErrorCodes::NamespaceNotFound,
+ str::stream() << "Unknown collection: " << nss.toStringForErrorMsg(),
+ baseColl.getCollection());
+
+ validateCleanupRequest(req, *(baseColl.getCollection().get()));
+
+ auto namespaces =
+ uassertStatusOK(EncryptedStateCollectionsNamespaces::createFromDataCollection(
+ *(baseColl.getCollection().get())));
+
+ AutoGetCollection ecocColl(opCtx, namespaces.ecocNss, MODE_IX);
+ AutoGetCollection ecocTempColl(opCtx, namespaces.ecocRenameNss, MODE_IX);
+
+ CleanupStructuredEncryptionDataState cleanup;
+
+ if (ecocColl.getCollection()) {
+ cleanup.setEcocUuid(ecocColl->uuid());
+ }
+ if (ecocTempColl.getCollection()) {
+ cleanup.setEcocRenameUuid(ecocTempColl->uuid());
+ }
+
+ cleanup.setShardingDDLCoordinatorMetadata(
+ {{nss, DDLCoordinatorTypeEnum::kCleanupStructuredEncryptionData}});
+ cleanup.setEscNss(namespaces.escNss);
+ cleanup.setEcocNss(namespaces.ecocNss);
+ cleanup.setEcocRenameNss(namespaces.ecocRenameNss);
+ cleanup.setCleanupTokens(req.getCleanupTokens().getOwned());
+
+ return cleanup;
+ }
+
+ NamespaceString ns() const override {
+ return request().getNamespace();
+ }
+
+ bool supportsWriteConcern() const override {
+ return true;
+ }
+
+ void doCheckAuthorization(OperationContext* opCtx) const override {
+ uassert(ErrorCodes::Unauthorized,
+ "Unauthorized",
+ AuthorizationSession::get(opCtx->getClient())
+ ->isAuthorizedForActionsOnResource(ResourcePattern::forClusterResource(),
+ ActionType::internal));
+ }
+ };
+
+} shardsvrCleanupStructuredEncryptionDataCommand;
+
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/s/commands/SConscript b/src/mongo/s/commands/SConscript
index 00c6ec73e35..35d64a7435e 100644
--- a/src/mongo/s/commands/SConscript
+++ b/src/mongo/s/commands/SConscript
@@ -58,6 +58,7 @@ env.Library(
'cluster_filemd5_cmd.cpp',
'cluster_find_and_modify_cmd.cpp',
'cluster_find_cmd_s.cpp',
+ 'cluster_fle2_cleanup_cmd.cpp',
'cluster_fle2_compact_cmd.cpp',
'cluster_fle2_get_count_info_cmd.cpp',
'cluster_fsync_cmd.cpp',
diff --git a/src/mongo/s/commands/cluster_fle2_cleanup_cmd.cpp b/src/mongo/s/commands/cluster_fle2_cleanup_cmd.cpp
new file mode 100644
index 00000000000..ea596a2b398
--- /dev/null
+++ b/src/mongo/s/commands/cluster_fle2_cleanup_cmd.cpp
@@ -0,0 +1,123 @@
+/**
+ * Copyright (C) 2022-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/commands.h"
+#include "mongo/db/commands/fle2_cleanup_gen.h"
+#include "mongo/s/cluster_commands_helpers.h"
+#include "mongo/s/grid.h"
+
+namespace mongo {
+namespace {
+
+class ClusterCleanupStructuredEncryptionDataCmd final
+ : public TypedCommand<ClusterCleanupStructuredEncryptionDataCmd> {
+public:
+ using Request = CleanupStructuredEncryptionData;
+ using Reply = CleanupStructuredEncryptionData::Reply;
+
+ class Invocation final : public InvocationBase {
+ public:
+ using InvocationBase::InvocationBase;
+
+ Reply typedRun(OperationContext* opCtx);
+
+ private:
+ bool supportsWriteConcern() const final {
+ return false;
+ }
+
+ void doCheckAuthorization(OperationContext* opCtx) const final {
+ auto* as = AuthorizationSession::get(opCtx->getClient());
+ uassert(ErrorCodes::Unauthorized,
+ "Not authorized to cleanup structured encryption data",
+ as->isAuthorizedForActionsOnResource(
+ ResourcePattern::forExactNamespace(request().getNamespace()),
+ ActionType::cleanupStructuredEncryptionData));
+ }
+
+ NamespaceString ns() const final {
+ return request().getNamespace();
+ }
+ };
+
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const final {
+ return BasicCommand::AllowedOnSecondary::kNever;
+ }
+
+ bool adminOnly() const final {
+ return false;
+ }
+
+ std::set<StringData> sensitiveFieldNames() const final {
+ return {CleanupStructuredEncryptionData::kCleanupTokensFieldName};
+ }
+} clusterCleanupStructuredEncryptionDataCmd;
+
+using Cmd = ClusterCleanupStructuredEncryptionDataCmd;
+Cmd::Reply Cmd::Invocation::typedRun(OperationContext* opCtx) {
+ CurOp::get(opCtx)->debug().shouldOmitDiagnosticInformation = true;
+
+ auto nss = request().getNamespace();
+ const auto dbInfo =
+ uassertStatusOK(Grid::get(opCtx)->catalogCache()->getDatabase(opCtx, nss.db()));
+
+ // Rewrite command verb to _shardSvrCleanupStructuredEnccryptionData.
+ auto cmd = request().toBSON({});
+ BSONObjBuilder req;
+ for (const auto& elem : cmd) {
+ if (elem.fieldNameStringData() == Request::kCommandName) {
+ req.appendAs(elem, "_shardsvrCleanupStructuredEncryptionData");
+ } else {
+ req.append(elem);
+ }
+ }
+
+ auto response = uassertStatusOK(
+ executeCommandAgainstDatabasePrimary(
+ opCtx,
+ nss.db(),
+ dbInfo,
+ CommandHelpers::appendMajorityWriteConcern(req.obj(), opCtx->getWriteConcern()),
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly),
+ Shard::RetryPolicy::kIdempotent)
+ .swResponse);
+
+ BSONObjBuilder result;
+ CommandHelpers::filterCommandReplyForPassthrough(response.data, &result);
+
+ auto reply = result.obj();
+ uassertStatusOK(getStatusFromCommandResult(reply));
+ return Reply::parse(IDLParserContext{Request::kCommandName}, reply.removeField("ok"_sd));
+}
+
+} // namespace
+} // namespace mongo