summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCheahuychou Mao <mao.cheahuychou@gmail.com>2021-01-29 15:36:29 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-02-02 10:02:35 +0000
commit8baad6fdb799b24bbc999089773698a10bfeaecc (patch)
tree0bb2f389723bcd8434ece650fffb050b1dbed8f1
parent739d938be8bb992190b01004f39eecc2658c5c38 (diff)
downloadmongo-8baad6fdb799b24bbc999089773698a10bfeaecc.tar.gz
SERVER-54084 Add server parameter tenantMigrationDisableX509Auth to enable keyfile auth testing
-rw-r--r--jstests/replsets/tenant_migration_ssl_configuration.js286
-rw-r--r--src/mongo/db/commands/tenant_migration_donor_cmds.cpp25
-rw-r--r--src/mongo/db/commands/tenant_migration_donor_cmds.idl4
-rw-r--r--src/mongo/db/commands/tenant_migration_recipient_cmds.cpp37
-rw-r--r--src/mongo/db/commands/tenant_migration_recipient_cmds.idl2
-rw-r--r--src/mongo/db/repl/repl_server_parameters.idl9
-rw-r--r--src/mongo/db/repl/tenant_migration_donor_service.cpp69
-rw-r--r--src/mongo/db/repl/tenant_migration_donor_service.h7
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp40
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_service.cpp48
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_service.h21
-rw-r--r--src/mongo/db/repl/tenant_migration_recipient_service_test.cpp156
-rw-r--r--src/mongo/db/repl/tenant_migration_state_machine.idl8
13 files changed, 516 insertions, 196 deletions
diff --git a/jstests/replsets/tenant_migration_ssl_configuration.js b/jstests/replsets/tenant_migration_ssl_configuration.js
index 96363e89b1c..ebab8c01041 100644
--- a/jstests/replsets/tenant_migration_ssl_configuration.js
+++ b/jstests/replsets/tenant_migration_ssl_configuration.js
@@ -1,5 +1,6 @@
/**
- * Test that tenant migration commands require certificate fields and SSL to be enabled.
+ * Test that tenant migration commands only require and use certificate fields, and require SSL to
+ * to be enabled when 'tenantMigrationDisableX509Auth' server parameter is false (default).
*
* @tags: [requires_fcv_47, requires_majority_read_concern, incompatible_with_eft]
*/
@@ -14,11 +15,17 @@ const kTenantId = "testTenantId";
const kReadPreference = {
mode: "primary"
};
-const kMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForTest();
+const kValidMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForTest();
+const kExpiredMigrationCertificates = {
+ donorCertificateForRecipient: TenantMigrationUtil.getCertificateAndPrivateKey(
+ "jstests/libs/rs0_tenant_migration_expired.pem"),
+ recipientCertificateForDonor: TenantMigrationUtil.getCertificateAndPrivateKey(
+ "jstests/libs/rs1_tenant_migration_expired.pem")
+};
(() => {
- jsTest.log("Test that certificate fields are required fields for donorStartMigration and " +
- "recipientSyncData");
+ jsTest.log(
+ "Test that certificate fields are required when tenantMigrationDisableX509Auth=false");
const tenantMigrationTest = new TenantMigrationTest({name: jsTestName()});
if (!tenantMigrationTest.isFeatureFlagEnabled()) {
jsTestLog("Skipping test because the tenant migrations feature flag is disabled");
@@ -28,32 +35,32 @@ const kMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForT
const donorPrimary = tenantMigrationTest.getDonorPrimary();
const recipientPrimary = tenantMigrationTest.getRecipientPrimary();
- jsTest.log(
- "Test that 'donorCertificateForRecipient' is a required field for donorStartMigration");
+ jsTest.log("Test that donorStartMigration requires 'donorCertificateForRecipient' when " +
+ "tenantMigrationDisableX509Auth=false");
assert.commandFailedWithCode(donorPrimary.adminCommand({
donorStartMigration: 1,
migrationId: UUID(),
recipientConnectionString: tenantMigrationTest.getRecipientRst().getURL(),
tenantId: kTenantId,
readPreference: kReadPreference,
- recipientCertificateForDonor: kMigrationCertificates.recipientCertificateForDonor,
+ recipientCertificateForDonor: kValidMigrationCertificates.recipientCertificateForDonor,
}),
- 40414);
+ ErrorCodes.InvalidOptions);
- jsTest.log(
- "Test that 'recipientCertificateForDonor' is a required field for donorStartMigration");
+ jsTest.log("Test that donorStartMigration requires 'recipientCertificateForDonor' when " +
+ "tenantMigrationDisableX509Auth=false");
assert.commandFailedWithCode(donorPrimary.adminCommand({
donorStartMigration: 1,
migrationId: UUID(),
recipientConnectionString: tenantMigrationTest.getRecipientRst().getURL(),
tenantId: kTenantId,
readPreference: kReadPreference,
- donorCertificateForRecipient: kMigrationCertificates.donorCertificateForRecipient,
+ donorCertificateForRecipient: kValidMigrationCertificates.donorCertificateForRecipient,
}),
- 40414);
+ ErrorCodes.InvalidOptions);
- jsTest.log(
- "Test that 'recipientCertificateForDonor' is a required field for recipientSyncData");
+ jsTest.log("Test that recipientSyncData requires 'recipientCertificateForDonor' when " +
+ "tenantMigrationDisableX509Auth=false");
assert.commandFailedWithCode(recipientPrimary.adminCommand({
recipientSyncData: 1,
migrationId: UUID(),
@@ -61,10 +68,10 @@ const kMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForT
tenantId: kTenantId,
readPreference: kReadPreference
}),
- 40414);
+ ErrorCodes.InvalidOptions);
- jsTest.log(
- "Test that 'recipientCertificateForDonor' is a required field for recipientForgetMigration");
+ jsTest.log("Test that recipientForgetMigration requires 'recipientCertificateForDonor' when " +
+ "tenantMigrationDisableX509Auth=false");
assert.commandFailedWithCode(recipientPrimary.adminCommand({
recipientForgetMigration: 1,
migrationId: UUID(),
@@ -72,13 +79,14 @@ const kMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForT
tenantId: kTenantId,
readPreference: kReadPreference
}),
- 40414);
+ ErrorCodes.InvalidOptions);
tenantMigrationTest.stop();
})();
(() => {
- jsTest.log("Test that donorStartMigration fails if SSL is not enabled on the donor");
+ jsTest.log("Test that donorStartMigration fails if SSL is not enabled on the donor and " +
+ "tenantMigrationDisableX509Auth=false");
const donorRst = new ReplSetTest({nodes: 1, name: "donor"});
donorRst.startSet();
donorRst.initiate();
@@ -98,8 +106,8 @@ const kMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForT
recipientConnectionString: tenantMigrationTest.getRecipientRst().getURL(),
tenantId: kTenantId,
readPreference: kReadPreference,
- donorCertificateForRecipient: kMigrationCertificates.donorCertificateForRecipient,
- recipientCertificateForDonor: kMigrationCertificates.recipientCertificateForDonor,
+ donorCertificateForRecipient: kValidMigrationCertificates.donorCertificateForRecipient,
+ recipientCertificateForDonor: kValidMigrationCertificates.recipientCertificateForDonor,
}),
ErrorCodes.IllegalOperation);
@@ -108,7 +116,8 @@ const kMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForT
})();
(() => {
- jsTest.log("Test that recipientSyncData fails if SSL is not enabled on the recipient");
+ jsTest.log("Test that recipientSyncData fails if SSL is not enabled on the recipient and " +
+ "tenantMigrationDisableX509Auth=false");
const recipientRst = new ReplSetTest({nodes: 1, name: "recipient"});
recipientRst.startSet();
recipientRst.initiate();
@@ -128,7 +137,7 @@ const kMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForT
donorConnectionString: tenantMigrationTest.getDonorRst().getURL(),
tenantId: kTenantId,
readPreference: kReadPreference,
- recipientCertificateForDonor: kMigrationCertificates.recipientCertificateForDonor,
+ recipientCertificateForDonor: kValidMigrationCertificates.recipientCertificateForDonor,
}),
ErrorCodes.IllegalOperation);
@@ -137,7 +146,8 @@ const kMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForT
})();
(() => {
- jsTest.log("Test that donorStartMigration fails if SSL is not enabled on the recipient");
+ jsTest.log("Test that donorStartMigration fails if SSL is not enabled on the recipient and " +
+ "tenantMigrationDisableX509Auth=false");
const recipientRst = new ReplSetTest({nodes: 1, name: "recipient"});
recipientRst.startSet();
recipientRst.initiate();
@@ -157,8 +167,8 @@ const kMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForT
recipientConnectionString: tenantMigrationTest.getRecipientRst().getURL(),
tenantId: kTenantId,
readPreference: kReadPreference,
- donorCertificateForRecipient: kMigrationCertificates.donorCertificateForRecipient,
- recipientCertificateForDonor: kMigrationCertificates.recipientCertificateForDonor,
+ donorCertificateForRecipient: kValidMigrationCertificates.donorCertificateForRecipient,
+ recipientCertificateForDonor: kValidMigrationCertificates.recipientCertificateForDonor,
};
const stateRes = assert.commandWorked(TenantMigrationUtil.runTenantMigrationCommand(
@@ -174,4 +184,228 @@ const kMigrationCertificates = TenantMigrationUtil.makeMigrationCertificatesForT
recipientRst.stopSet();
tenantMigrationTest.stop();
})();
+
+(() => {
+ jsTest.log("Test that recipientSyncData doesn't require 'recipientCertificateForDonor' when " +
+ "tenantMigrationDisableX509Auth=true");
+ const migrationX509Options = TenantMigrationUtil.makeX509OptionsForTest();
+ const recipientRst = new ReplSetTest({
+ nodes: 1,
+ name: "recipient",
+ nodeOptions: Object.assign(migrationX509Options.recipient,
+ {setParameter: {tenantMigrationDisableX509Auth: true}})
+ });
+
+ recipientRst.startSet();
+ recipientRst.initiate();
+
+ const tenantMigrationTest = new TenantMigrationTest({name: jsTestName(), recipientRst});
+ if (!tenantMigrationTest.isFeatureFlagEnabled()) {
+ jsTestLog("Skipping test because the tenant migrations feature flag is disabled");
+ recipientRst.stopSet();
+ return;
+ }
+
+ const recipientPrimary = tenantMigrationTest.getRecipientPrimary();
+
+ assert.commandWorked(recipientPrimary.adminCommand({
+ recipientSyncData: 1,
+ migrationId: UUID(),
+ donorConnectionString: tenantMigrationTest.getDonorRst().getURL(),
+ tenantId: kTenantId,
+ readPreference: kReadPreference
+ }));
+
+ recipientRst.stopSet();
+ tenantMigrationTest.stop();
+})();
+
+(() => {
+ jsTest.log(
+ "Test that recipientForgetMigration doesn't require 'recipientCertificateForDonor' when " +
+ "tenantMigrationDisableX509Auth=true");
+ const migrationX509Options = TenantMigrationUtil.makeX509OptionsForTest();
+ const recipientRst = new ReplSetTest({
+ nodes: 1,
+ name: "recipient",
+ nodeOptions: Object.assign(migrationX509Options.recipient,
+ {setParameter: {tenantMigrationDisableX509Auth: true}})
+ });
+
+ recipientRst.startSet();
+ recipientRst.initiate();
+
+ const tenantMigrationTest = new TenantMigrationTest({name: jsTestName(), recipientRst});
+ if (!tenantMigrationTest.isFeatureFlagEnabled()) {
+ jsTestLog("Skipping test because the tenant migrations feature flag is disabled");
+ recipientRst.stopSet();
+ return;
+ }
+
+ const recipientPrimary = tenantMigrationTest.getRecipientPrimary();
+
+ assert.commandWorked(recipientPrimary.adminCommand({
+ recipientForgetMigration: 1,
+ migrationId: UUID(),
+ donorConnectionString: tenantMigrationTest.getDonorRst().getURL(),
+ tenantId: kTenantId,
+ readPreference: kReadPreference
+ }));
+
+ recipientRst.stopSet();
+ tenantMigrationTest.stop();
+})();
+
+(() => {
+ jsTest.log("Test that donorStartMigration doesn't require certificate fields when " +
+ "tenantMigrationDisableX509Auth=true");
+ const migrationX509Options = TenantMigrationUtil.makeX509OptionsForTest();
+ const donorRst = new ReplSetTest({
+ nodes: 1,
+ name: "donor",
+ nodeOptions: Object.assign(migrationX509Options.donor,
+ {setParameter: {tenantMigrationDisableX509Auth: true}})
+ });
+ const recipientRst = new ReplSetTest({
+ nodes: 1,
+ name: "recipient",
+ nodeOptions: Object.assign(migrationX509Options.recipient,
+ {setParameter: {tenantMigrationDisableX509Auth: true}})
+ });
+
+ donorRst.startSet();
+ donorRst.initiate();
+
+ recipientRst.startSet();
+ recipientRst.initiate();
+
+ const tenantMigrationTest =
+ new TenantMigrationTest({name: jsTestName(), donorRst, recipientRst});
+ if (!tenantMigrationTest.isFeatureFlagEnabled()) {
+ jsTestLog("Skipping test because the tenant migrations feature flag is disabled");
+ donorRst.stopSet();
+ recipientRst.stopSet();
+ return;
+ }
+
+ const migrationId = UUID();
+ const donorStartMigrationCmdObj = {
+ donorStartMigration: 1,
+ migrationId: migrationId,
+ recipientConnectionString: tenantMigrationTest.getRecipientRst().getURL(),
+ tenantId: kTenantId,
+ readPreference: kReadPreference
+ };
+ const stateRes = assert.commandWorked(TenantMigrationUtil.runTenantMigrationCommand(
+ donorStartMigrationCmdObj,
+ donorRst,
+ false /* retryOnRetryableErrors */,
+ TenantMigrationUtil.isMigrationCompleted /* shouldStopFunc */));
+ assert.eq(stateRes.state, TenantMigrationTest.State.kCommitted);
+ assert.commandWorked(
+ donorRst.getPrimary().adminCommand({donorForgetMigration: 1, migrationId: migrationId}));
+})();
+
+(() => {
+ jsTest.log("Test that tenant migration doesn't fail if SSL is not enabled on the donor and " +
+ "the recipient and tenantMigrationDisableX509Auth=true");
+
+ const donorRst = new ReplSetTest({
+ nodes: 1,
+ name: "donor",
+ nodeOptions: {setParameter: {tenantMigrationDisableX509Auth: true}}
+ });
+ const recipientRst = new ReplSetTest({
+ nodes: 1,
+ name: "recipient",
+ nodeOptions: {setParameter: {tenantMigrationDisableX509Auth: true}}
+ });
+
+ donorRst.startSet();
+ donorRst.initiate();
+
+ recipientRst.startSet();
+ recipientRst.initiate();
+
+ const tenantMigrationTest =
+ new TenantMigrationTest({name: jsTestName(), donorRst, recipientRst});
+ if (!tenantMigrationTest.isFeatureFlagEnabled()) {
+ jsTestLog("Skipping test because the tenant migrations feature flag is disabled");
+ donorRst.stopSet();
+ recipientRst.stopSet();
+ return;
+ }
+
+ const donorStartMigrationCmdObj = {
+ donorStartMigration: 1,
+ migrationId: UUID(),
+ recipientConnectionString: tenantMigrationTest.getRecipientRst().getURL(),
+ tenantId: kTenantId,
+ readPreference: kReadPreference
+ };
+
+ const stateRes = assert.commandWorked(TenantMigrationUtil.runTenantMigrationCommand(
+ donorStartMigrationCmdObj,
+ donorRst,
+ false /* retryOnRetryableErrors */,
+ TenantMigrationUtil.isMigrationCompleted /* shouldStopFunc */));
+ assert.eq(stateRes.state, TenantMigrationTest.State.kCommitted);
+
+ donorRst.stopSet();
+ recipientRst.stopSet();
+ tenantMigrationTest.stop();
+})();
+
+(() => {
+ jsTest.log(
+ "Test that input certificate fields are not used when tenantMigrationDisableX509Auth=true");
+ const migrationX509Options = TenantMigrationUtil.makeX509OptionsForTest();
+ const donorRst = new ReplSetTest({
+ nodes: 1,
+ name: "donor",
+ nodeOptions: Object.assign(migrationX509Options.donor,
+ {setParameter: {tenantMigrationDisableX509Auth: true}})
+ });
+ const recipientRst = new ReplSetTest({
+ nodes: 1,
+ name: "recipient",
+ nodeOptions: Object.assign(migrationX509Options.recipient,
+ {setParameter: {tenantMigrationDisableX509Auth: true}})
+ });
+
+ donorRst.startSet();
+ donorRst.initiate();
+
+ recipientRst.startSet();
+ recipientRst.initiate();
+
+ const tenantMigrationTest =
+ new TenantMigrationTest({name: jsTestName(), donorRst, recipientRst});
+ if (!tenantMigrationTest.isFeatureFlagEnabled()) {
+ jsTestLog("Skipping test because the tenant migrations feature flag is disabled");
+ donorRst.stopSet();
+ recipientRst.stopSet();
+ return;
+ }
+
+ const donorStartMigrationCmdObj = {
+ donorStartMigration: 1,
+ migrationId: UUID(),
+ recipientConnectionString: tenantMigrationTest.getRecipientRst().getURL(),
+ tenantId: kTenantId,
+ readPreference: kReadPreference,
+ donorCertificateForRecipient: kExpiredMigrationCertificates.donorCertificateForRecipient,
+ recipientCertificateForDonor: kExpiredMigrationCertificates.recipientCertificateForDonor,
+ };
+ const stateRes = assert.commandWorked(TenantMigrationUtil.runTenantMigrationCommand(
+ donorStartMigrationCmdObj,
+ donorRst,
+ false /* retryOnRetryableErrors */,
+ TenantMigrationUtil.isMigrationCompleted /* shouldStopFunc */));
+ assert.eq(stateRes.state, TenantMigrationTest.State.kCommitted);
+
+ donorRst.stopSet();
+ recipientRst.stopSet();
+ tenantMigrationTest.stop();
+})();
})();
diff --git a/src/mongo/db/commands/tenant_migration_donor_cmds.cpp b/src/mongo/db/commands/tenant_migration_donor_cmds.cpp
index add2ef18e6a..1570f370213 100644
--- a/src/mongo/db/commands/tenant_migration_donor_cmds.cpp
+++ b/src/mongo/db/commands/tenant_migration_donor_cmds.cpp
@@ -64,13 +64,24 @@ public:
const auto& cmd = request();
- const TenantMigrationDonorDocument stateDoc(
- cmd.getMigrationId(),
- cmd.getRecipientConnectionString().toString(),
- cmd.getReadPreference(),
- cmd.getTenantId().toString(),
- cmd.getDonorCertificateForRecipient(),
- cmd.getRecipientCertificateForDonor());
+ TenantMigrationDonorDocument stateDoc(cmd.getMigrationId(),
+ cmd.getRecipientConnectionString().toString(),
+ cmd.getReadPreference(),
+ cmd.getTenantId().toString());
+
+ if (!repl::tenantMigrationDisableX509Auth) {
+ uassert(ErrorCodes::InvalidOptions,
+ str::stream() << "'" << Request::kDonorCertificateForRecipientFieldName
+ << "' is a required field",
+ cmd.getDonorCertificateForRecipient());
+ uassert(ErrorCodes::InvalidOptions,
+ str::stream() << "'" << Request::kRecipientCertificateForDonorFieldName
+ << "' is a required field",
+ cmd.getRecipientCertificateForDonor());
+ stateDoc.setDonorCertificateForRecipient(cmd.getDonorCertificateForRecipient());
+ stateDoc.setRecipientCertificateForDonor(cmd.getRecipientCertificateForDonor());
+ }
+
const auto stateDocBson = stateDoc.toBSON();
auto donorService =
diff --git a/src/mongo/db/commands/tenant_migration_donor_cmds.idl b/src/mongo/db/commands/tenant_migration_donor_cmds.idl
index f81b718cffa..3ba8a06ecca 100644
--- a/src/mongo/db/commands/tenant_migration_donor_cmds.idl
+++ b/src/mongo/db/commands/tenant_migration_donor_cmds.idl
@@ -80,11 +80,15 @@ commands:
The SSL certificate and private key that the donor should use to authenticate to the
recipient.
type: TenantMigrationPEMPayload
+ # TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
+ optional: true
recipientCertificateForDonor:
description: >-
The SSL certificate and private key that the recipient should use to authenticate to the
donor.
type: TenantMigrationPEMPayload
+ # TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
+ optional: true
donorForgetMigration:
description: "Parser for the 'donorForgetMigration' command."
diff --git a/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp b/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
index c963bb35017..0dc4c19db20 100644
--- a/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
+++ b/src/mongo/db/commands/tenant_migration_recipient_cmds.cpp
@@ -64,14 +64,20 @@ public:
const auto& cmd = request();
- const TenantMigrationRecipientDocument stateDoc(
- cmd.getMigrationId(),
- cmd.getDonorConnectionString().toString(),
- cmd.getTenantId().toString(),
- cmd.getReadPreference(),
- cmd.getRecipientCertificateForDonor());
- const auto stateDocBson = stateDoc.toBSON();
+ TenantMigrationRecipientDocument stateDoc(cmd.getMigrationId(),
+ cmd.getDonorConnectionString().toString(),
+ cmd.getTenantId().toString(),
+ cmd.getReadPreference());
+
+ if (!repl::tenantMigrationDisableX509Auth) {
+ uassert(ErrorCodes::InvalidOptions,
+ str::stream() << "'" << Request::kRecipientCertificateForDonorFieldName
+ << "' is a required field",
+ cmd.getRecipientCertificateForDonor());
+ stateDoc.setRecipientCertificateForDonor(cmd.getRecipientCertificateForDonor());
+ }
+ const auto stateDocBson = stateDoc.toBSON();
if (MONGO_unlikely(returnResponseOkForRecipientSyncDataCmd.shouldFail())) {
LOGV2(4879608,
@@ -169,12 +175,17 @@ public:
// recipientSyncData. But even if that's the case, we still need to create an instance
// and persist a state document that's marked garbage collectable (which is done by the
// main chain).
- const TenantMigrationRecipientDocument stateDoc(
- cmd.getMigrationId(),
- cmd.getDonorConnectionString().toString(),
- cmd.getTenantId().toString(),
- cmd.getReadPreference(),
- cmd.getRecipientCertificateForDonor());
+ TenantMigrationRecipientDocument stateDoc(cmd.getMigrationId(),
+ cmd.getDonorConnectionString().toString(),
+ cmd.getTenantId().toString(),
+ cmd.getReadPreference());
+ if (!repl::tenantMigrationDisableX509Auth) {
+ uassert(ErrorCodes::InvalidOptions,
+ str::stream() << "'" << Request::kRecipientCertificateForDonorFieldName
+ << "' is a required field",
+ cmd.getRecipientCertificateForDonor());
+ stateDoc.setRecipientCertificateForDonor(cmd.getRecipientCertificateForDonor());
+ }
auto recipientInstance = repl::TenantMigrationRecipientService::Instance::getOrCreate(
opCtx, recipientService, stateDoc.toBSON());
diff --git a/src/mongo/db/commands/tenant_migration_recipient_cmds.idl b/src/mongo/db/commands/tenant_migration_recipient_cmds.idl
index a3c4fb991d2..71a5eb68f7b 100644
--- a/src/mongo/db/commands/tenant_migration_recipient_cmds.idl
+++ b/src/mongo/db/commands/tenant_migration_recipient_cmds.idl
@@ -79,6 +79,8 @@ structs:
The SSL certificate and private key that the recipient should use to authenticate to the
donor.
type: TenantMigrationPEMPayload
+ # TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
+ optional: true
commands:
recipientSyncData:
diff --git a/src/mongo/db/repl/repl_server_parameters.idl b/src/mongo/db/repl/repl_server_parameters.idl
index a1c56d2c6f7..e58efd020c0 100644
--- a/src/mongo/db/repl/repl_server_parameters.idl
+++ b/src/mongo/db/repl/repl_server_parameters.idl
@@ -444,6 +444,15 @@ server_parameters:
validator:
gte: 1
+ # TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
+ tenantMigrationDisableX509Auth:
+ description: >-
+ Disable x509 authentication for all ingoing and outgoing tenant migrations.
+ set_at: [ startup ]
+ cpp_vartype: bool
+ cpp_varname: tenantMigrationDisableX509Auth
+ default: false
+
feature_flags:
featureFlagTenantMigrations:
description: >-
diff --git a/src/mongo/db/repl/tenant_migration_donor_service.cpp b/src/mongo/db/repl/tenant_migration_donor_service.cpp
index 19e6ed500bf..9e42924363d 100644
--- a/src/mongo/db/repl/tenant_migration_donor_service.cpp
+++ b/src/mongo/db/repl/tenant_migration_donor_service.cpp
@@ -129,7 +129,9 @@ TenantMigrationDonorService::Instance::Instance(ServiceContext* const serviceCon
_stateDoc(tenant_migration_access_blocker::parseDonorStateDocument(initialState)),
_instanceName(kServiceName + "-" + _stateDoc.getTenantId()),
_recipientUri(
- uassertStatusOK(MongoURI::parse(_stateDoc.getRecipientConnectionString().toString()))) {
+ uassertStatusOK(MongoURI::parse(_stateDoc.getRecipientConnectionString().toString()))),
+ _sslMode(repl::tenantMigrationDisableX509Auth ? transport::kGlobalSSLMode
+ : transport::kEnableSSL) {
_recipientCmdExecutor = _makeRecipientCmdExecutor();
_recipientCmdExecutor->startup();
@@ -192,20 +194,31 @@ TenantMigrationDonorService::Instance::_makeRecipientCmdExecutor() {
auto hookList = std::make_unique<rpc::EgressMetadataHookList>();
auto connPoolOptions = executor::ConnectionPool::Options();
-#ifdef MONGO_CONFIG_SSL
- uassert(ErrorCodes::IllegalOperation,
- "Cannot run tenant migration as SSL is not enabled",
- getSSLGlobalParams().sslMode.load() != SSLParams::SSLMode_disabled);
auto donorCertificate = _stateDoc.getDonorCertificateForRecipient();
- auto donorSSLClusterPEMPayload = donorCertificate.getCertificate().toString() + "\n" +
- donorCertificate.getPrivateKey().toString();
- connPoolOptions.transientSSLParams =
- TransientSSLParams{_recipientUri.connectionString(), std::move(donorSSLClusterPEMPayload)};
+ auto recipientCertificate = _stateDoc.getRecipientCertificateForDonor();
+ if (donorCertificate) {
+ invariant(!repl::tenantMigrationDisableX509Auth);
+ invariant(recipientCertificate);
+ invariant(_sslMode == transport::kEnableSSL);
+#ifdef MONGO_CONFIG_SSL
+ uassert(ErrorCodes::IllegalOperation,
+ "Cannot run tenant migration with x509 authentication as SSL is not enabled",
+ getSSLGlobalParams().sslMode.load() != SSLParams::SSLMode_disabled);
+ auto donorSSLClusterPEMPayload = donorCertificate->getCertificate().toString() + "\n" +
+ donorCertificate->getPrivateKey().toString();
+ connPoolOptions.transientSSLParams = TransientSSLParams{
+ _recipientUri.connectionString(), std::move(donorSSLClusterPEMPayload)};
#else
- // If SSL is not supported, the donorStartMigration command should have failed certificate field
- // validation.
- MONGO_UNREACHABLE;
+ // If SSL is not supported, the donorStartMigration command should have failed certificate
+ // field validation.
+ MONGO_UNREACHABLE;
#endif
+ } else {
+ invariant(repl::tenantMigrationDisableX509Auth);
+ invariant(!recipientCertificate);
+ invariant(_sslMode == transport::kGlobalSSLMode);
+ }
+
return std::make_shared<executor::ThreadPoolTaskExecutor>(
std::make_unique<ThreadPool>(threadPoolOptions),
executor::makeNetworkInterface(
@@ -359,7 +372,7 @@ TenantMigrationDonorService::Instance::_fetchAndStoreRecipientClusterTimeKeyDocs
executor::RemoteCommandRequest::kNoTimeout, /* getMoreNetworkTimeout */
RemoteCommandRetryScheduler::makeRetryPolicy<ErrorCategory::RetriableError>(
kMaxRecipientKeyDocsFindAttempts, executor::RemoteCommandRequest::kNoTimeout),
- transport::kEnableSSL);
+ _sslMode);
uassertStatusOK(fetcher->schedule());
{
@@ -596,7 +609,7 @@ ExecutorFuture<void> TenantMigrationDonorService::Instance::_sendCommandToRecipi
rpc::makeEmptyMetadata(),
nullptr,
kRecipientSyncDataTimeout);
- request.sslMode = transport::kEnableSSL;
+ request.sslMode = _sslMode;
return (_recipientCmdExecutor)
->scheduleRemoteCommand(std::move(request),
@@ -629,13 +642,17 @@ ExecutorFuture<void> TenantMigrationDonorService::Instance::_sendRecipientSyncDa
const auto cmdObj = [&] {
auto donorConnString =
repl::ReplicationCoordinator::get(opCtx)->getConfig().getConnectionString();
+
RecipientSyncData request;
request.setDbName(NamespaceString::kAdminDb);
- request.setMigrationRecipientCommonData({_stateDoc.getId(),
- donorConnString.toString(),
- _stateDoc.getTenantId().toString(),
- _stateDoc.getReadPreference(),
- _stateDoc.getRecipientCertificateForDonor()});
+
+ MigrationRecipientCommonData commonData(_stateDoc.getId(),
+ donorConnString.toString(),
+ _stateDoc.getTenantId().toString(),
+ _stateDoc.getReadPreference());
+ commonData.setRecipientCertificateForDonor(_stateDoc.getRecipientCertificateForDonor());
+ request.setMigrationRecipientCommonData(commonData);
+
request.setReturnAfterReachingDonorTimestamp(_stateDoc.getBlockTimestamp());
return request.toBSON(BSONObj());
}();
@@ -652,13 +669,17 @@ ExecutorFuture<void> TenantMigrationDonorService::Instance::_sendRecipientForget
auto donorConnString =
repl::ReplicationCoordinator::get(opCtx)->getConfig().getConnectionString();
+
RecipientForgetMigration request;
request.setDbName(NamespaceString::kAdminDb);
- request.setMigrationRecipientCommonData({_stateDoc.getId(),
- donorConnString.toString(),
- _stateDoc.getTenantId().toString(),
- _stateDoc.getReadPreference(),
- _stateDoc.getRecipientCertificateForDonor()});
+
+ MigrationRecipientCommonData commonData(_stateDoc.getId(),
+ donorConnString.toString(),
+ _stateDoc.getTenantId().toString(),
+ _stateDoc.getReadPreference());
+ commonData.setRecipientCertificateForDonor(_stateDoc.getRecipientCertificateForDonor());
+ request.setMigrationRecipientCommonData(commonData);
+
return _sendCommandToRecipient(executor, recipientTargeterRS, request.toBSON(BSONObj()));
}
diff --git a/src/mongo/db/repl/tenant_migration_donor_service.h b/src/mongo/db/repl/tenant_migration_donor_service.h
index 8854b736987..3c33846cc54 100644
--- a/src/mongo/db/repl/tenant_migration_donor_service.h
+++ b/src/mongo/db/repl/tenant_migration_donor_service.h
@@ -149,8 +149,9 @@ public:
const NamespaceString _stateDocumentsNS = NamespaceString::kTenantMigrationDonorsNamespace;
/**
- * Makes a task executor for executing commands against the recipient on an SSL connection
- * that uses the migration certificate.
+ * Makes a task executor for executing commands against the recipient. If the server
+ * parameter 'tenantMigrationDisableX509Auth' is false, configures the executor to use the
+ * migration certificate to establish an SSL connection to the recipient.
*/
std::shared_ptr<executor::ThreadPoolTaskExecutor> _makeRecipientCmdExecutor();
@@ -226,6 +227,8 @@ public:
TenantMigrationDonorDocument _stateDoc;
const std::string _instanceName;
const MongoURI _recipientUri;
+ // TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
+ const transport::ConnectSSLMode _sslMode;
// Task executor used for executing commands against the recipient.
std::shared_ptr<executor::TaskExecutor> _recipientCmdExecutor;
diff --git a/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp b/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp
index 5246696ed02..fff534b61c0 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_entry_helpers_test.cpp
@@ -113,8 +113,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
migrationUUID,
"donor-rs0/localhost:12345",
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ activeTenantAStateDoc.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), activeTenantAStateDoc));
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), activeTenantAStateDoc));
@@ -122,8 +122,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
TenantMigrationRecipientDocument stateDoc1(migrationUUID,
"donor-rs1/localhost:12345",
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ stateDoc1.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto status = insertStateDoc(opCtx.get(), stateDoc1);
ASSERT_EQUALS(ErrorCodes::ConflictingOperationInProgress, status.code());
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), activeTenantAStateDoc));
@@ -132,8 +132,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
TenantMigrationRecipientDocument stateDoc2(migrationUUID,
"donor-rs0/localhost:12345",
"tenantB",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ stateDoc2.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_THROWS_CODE(
insertStateDoc(opCtx.get(), stateDoc2), DBException, ErrorCodes::DuplicateKey);
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), activeTenantAStateDoc));
@@ -142,8 +142,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
TenantMigrationRecipientDocument stateDoc3(UUID::gen(),
"donor-rs0/localhost:12345",
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ stateDoc3.setRecipientCertificateForDonor(kRecipientPEMPayload);
status = insertStateDoc(opCtx.get(), stateDoc3);
ASSERT_EQUALS(ErrorCodes::ConflictingOperationInProgress, status.code());
ASSERT_FALSE(checkStateDocPersisted(opCtx.get(), stateDoc3));
@@ -152,8 +152,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest, AddTenantMigrationRecipientStat
TenantMigrationRecipientDocument stateDoc4(UUID::gen(),
"donor-rs0/localhost:12345",
"tenantB",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ stateDoc4.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), stateDoc4));
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), stateDoc4));
}
@@ -167,8 +167,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
migrationUUID,
"donor-rs0/localhost:12345",
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ inactiveTenantAStateDoc.setRecipientCertificateForDonor(kRecipientPEMPayload);
inactiveTenantAStateDoc.setExpireAt(Date_t::now());
ASSERT_OK(insertStateDoc(opCtx.get(), inactiveTenantAStateDoc));
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), inactiveTenantAStateDoc));
@@ -177,8 +177,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
TenantMigrationRecipientDocument stateDoc1(migrationUUID,
"donor-rs1/localhost:12345",
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ stateDoc1.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_THROWS_CODE(
insertStateDoc(opCtx.get(), stateDoc1), DBException, ErrorCodes::DuplicateKey);
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), inactiveTenantAStateDoc));
@@ -187,8 +187,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
TenantMigrationRecipientDocument stateDoc2(migrationUUID,
"donor-rs0/localhost:12345",
"tenantB",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ stateDoc2.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_THROWS_CODE(
insertStateDoc(opCtx.get(), stateDoc2), DBException, ErrorCodes::DuplicateKey);
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), inactiveTenantAStateDoc));
@@ -197,8 +197,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
TenantMigrationRecipientDocument stateDoc3(UUID::gen(),
"donor-rs0/localhost:12345",
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ stateDoc3.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), stateDoc3));
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), stateDoc3));
@@ -206,8 +206,8 @@ TEST_F(TenantMigrationRecipientEntryHelpersTest,
TenantMigrationRecipientDocument stateDoc4(UUID::gen(),
"donor-rs0/localhost:12345",
"tenantC",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ stateDoc4.setRecipientCertificateForDonor(kRecipientPEMPayload);
ASSERT_OK(insertStateDoc(opCtx.get(), stateDoc4));
ASSERT_TRUE(checkStateDocPersisted(opCtx.get(), stateDoc4));
}
diff --git a/src/mongo/db/repl/tenant_migration_recipient_service.cpp b/src/mongo/db/repl/tenant_migration_recipient_service.cpp
index 8d893821f25..4d61601a2bf 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_service.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_service.cpp
@@ -199,21 +199,27 @@ TenantMigrationRecipientService::Instance::Instance(
_donorConnectionString(_stateDoc.getDonorConnectionString().toString()),
_donorUri(uassertStatusOK(MongoURI::parse(_stateDoc.getDonorConnectionString().toString()))),
_readPreference(_stateDoc.getReadPreference()),
- _transientSSLParams([&]() -> TransientSSLParams {
+ _transientSSLParams([&]() -> boost::optional<TransientSSLParams> {
+ if (auto recipientCertificate = _stateDoc.getRecipientCertificateForDonor()) {
+ invariant(!repl::tenantMigrationDisableX509Auth);
#ifdef MONGO_CONFIG_SSL
- uassert(ErrorCodes::IllegalOperation,
- "Cannot run tenant migration as SSL is not enabled",
- getSSLGlobalParams().sslMode.load() != SSLParams::SSLMode_disabled);
- auto recipientCertificate = _stateDoc.getRecipientCertificateForDonor();
- auto recipientSSLClusterPEMPayload = recipientCertificate.getCertificate().toString() +
- "\n" + recipientCertificate.getPrivateKey().toString();
- return TransientSSLParams{_donorUri.connectionString(),
- std::move(recipientSSLClusterPEMPayload)};
+ uassert(ErrorCodes::IllegalOperation,
+ "Cannot run tenant migration with x509 authentication as SSL is not enabled",
+ getSSLGlobalParams().sslMode.load() != SSLParams::SSLMode_disabled);
+ auto recipientSSLClusterPEMPayload =
+ recipientCertificate->getCertificate().toString() + "\n" +
+ recipientCertificate->getPrivateKey().toString();
+ return TransientSSLParams{_donorUri.connectionString(),
+ std::move(recipientSSLClusterPEMPayload)};
#else
- // If SSL is not supported, the recipientSyncData command should have failed certificate
- // field validation.
- MONGO_UNREACHABLE;
+ // If SSL is not supported, the recipientSyncData command should have failed
+ // certificate field validation.
+ MONGO_UNREACHABLE;
#endif
+ } else {
+ invariant(repl::tenantMigrationDisableX509Auth);
+ return boost::none;
+ }
}()) {
}
@@ -323,7 +329,7 @@ std::unique_ptr<DBClientConnection> TenantMigrationRecipientService::Instance::_
0 /* socketTimeout */,
nullptr /* uri */,
nullptr /* apiParameters */,
- &_transientSSLParams);
+ _transientSSLParams ? &_transientSSLParams.get() : nullptr);
if (!swClientBase.isOK()) {
LOGV2_ERROR(4880400,
"Failed to connect to migration donor",
@@ -335,12 +341,20 @@ std::unique_ptr<DBClientConnection> TenantMigrationRecipientService::Instance::_
uassertStatusOK(swClientBase.getStatus());
}
+ auto clientBase = swClientBase.getValue().release();
+
// ConnectionString::connect() always returns a DBClientConnection in a unique_ptr of
// DBClientBase type.
- std::unique_ptr<DBClientConnection> client(
- checked_cast<DBClientConnection*>(swClientBase.getValue().release()));
-
- if (MONGO_likely(!skipTenantMigrationRecipientAuth.shouldFail())) {
+ std::unique_ptr<DBClientConnection> client(checked_cast<DBClientConnection*>(clientBase));
+
+ // Authenticate connection to the donor.
+ if (!_transientSSLParams) {
+ uassertStatusOK(
+ replAuthenticate(clientBase)
+ .withContext(str::stream()
+ << "TenantMigrationRecipientService failed to authenticate to "
+ << serverAddress));
+ } else if (MONGO_likely(!skipTenantMigrationRecipientAuth.shouldFail())) {
client->auth(auth::createInternalX509AuthDocument());
}
diff --git a/src/mongo/db/repl/tenant_migration_recipient_service.h b/src/mongo/db/repl/tenant_migration_recipient_service.h
index a5c4317924b..58d0197b6d9 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_service.h
+++ b/src/mongo/db/repl/tenant_migration_recipient_service.h
@@ -289,8 +289,10 @@ public:
SemiFuture<void> _markStateDocAsGarbageCollectable();
/**
- * Creates a client, connects it to the donor, and authenticates it using the migration
- * certificate. Throws a user assertion on failure.
+ * Creates a client, connects it to the donor. If '_transientSSLParams' is not none, uses
+ * the migration certificate to do SSL authentication. Otherwise, uses the default
+ * authentication mode. Throws a user assertion on failure.
+ *
*/
std::unique_ptr<DBClientConnection> _connectAndAuth(const HostAndPort& serverAddress,
StringData applicationName);
@@ -414,12 +416,15 @@ public:
// This data is provided in the initial state doc and never changes. We keep copies to
// avoid having to obtain the mutex to access them.
- const std::string _tenantId; // (R)
- const UUID _migrationUuid; // (R)
- const std::string _donorConnectionString; // (R)
- const MongoURI _donorUri; // (R)
- const ReadPreferenceSetting _readPreference; // (R)
- const TransientSSLParams _transientSSLParams; // (R)
+ const std::string _tenantId; // (R)
+ const UUID _migrationUuid; // (R)
+ const std::string _donorConnectionString; // (R)
+ const MongoURI _donorUri; // (R)
+ const ReadPreferenceSetting _readPreference; // (R)
+ // TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
+ // Transient SSL params created based on the state doc if the server parameter
+ // 'tenantMigrationDisableX509Auth' is false.
+ const boost::optional<TransientSSLParams> _transientSSLParams = boost::none; // (R)
std::shared_ptr<ReplicaSetMonitor> _donorReplicaSetMonitor; // (M)
diff --git a/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp b/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
index 62719125707..b6bdd2c83fb 100644
--- a/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
+++ b/src/mongo/db/repl/tenant_migration_recipient_service_test.cpp
@@ -414,8 +414,8 @@ TEST_F(TenantMigrationRecipientServiceTest, BasicTenantMigrationRecipientService
migrationUUID,
"donor-rs/localhost:12345",
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -439,8 +439,8 @@ TEST_F(TenantMigrationRecipientServiceTest, InstanceReportsErrorOnFailureWhilePe
migrationUUID,
"donor-rs/localhost:12345",
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly, TagSet::primaryOnly()));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -471,8 +471,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_P
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -519,8 +519,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_S
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::SecondaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::SecondaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -572,8 +572,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_P
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -627,8 +627,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
auto hangFp =
@@ -699,8 +699,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
auto hangFp =
@@ -766,8 +766,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::Nearest),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::Nearest));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
auto hangFp =
@@ -841,8 +841,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryPreferred),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
auto hangFp =
@@ -907,8 +907,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryPreferred),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Hang the migration before attempting to connect to clients.
auto hangFp =
@@ -978,8 +978,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_P
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryPreferred),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryPreferred));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -1021,8 +1021,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientConnection_B
migrationUUID,
"broken,connect,string,no,set,name",
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -1042,8 +1042,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
"localhost:12345",
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -1066,8 +1066,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientGetStartOpTi
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -1103,8 +1103,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -1145,8 +1145,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientGetStartOpTi
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -1189,8 +1189,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -1223,8 +1223,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance. Fail to populate the remote oplog mock.
auto opCtx = makeOperationContext();
@@ -1256,8 +1256,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientStartOplogFe
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto opCtx = makeOperationContext();
std::shared_ptr<TenantMigrationRecipientService::Instance> instance;
@@ -1309,8 +1309,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientStartsCloner
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto opCtx = makeOperationContext();
std::shared_ptr<TenantMigrationRecipientService::Instance> instance;
@@ -1362,8 +1362,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherFailsDuringOplogApplicat
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
MockRemoteDBServer* const _donorServer =
@@ -1416,8 +1416,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherResumesFromTopOfOplogBuf
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
// migration on startup and will resume oplog fetching from the appropriate optime.
@@ -1519,8 +1519,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogFetcherNoDocInBufferToResumeFro
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
// migration on startup and will attempt to resume oplog fetching from the appropriate optime.
@@ -1624,8 +1624,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierResumesFromLastNoOpOplog
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
// migration on startup and will attempt to resume oplog fetching from the appropriate optime.
@@ -1743,8 +1743,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierResumesFromStartDonorApp
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
// migration on startup and will attempt to resume oplog fetching from the appropriate optime.
@@ -1897,8 +1897,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// We skip cloning here as a way to simulate that the recipient service has detected an existing
// migration on startup and will resume oplog fetching from the appropriate optime.
@@ -2001,8 +2001,8 @@ TEST_F(TenantMigrationRecipientServiceTest, OplogApplierFails) {
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
MockRemoteDBServer* const _donorServer =
@@ -2065,8 +2065,8 @@ TEST_F(TenantMigrationRecipientServiceTest, StoppingApplierAllowsCompletion) {
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
MockRemoteDBServer* const _donorServer =
@@ -2118,8 +2118,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientAddResumeTok
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
MockRemoteDBServer* const _donorServer =
@@ -2218,8 +2218,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_BeforeRun)
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto fp = globalFailPointRegistry().find("pauseBeforeRunTenantMigrationRecipientInstance");
fp->setMode(FailPoint::alwaysOn);
@@ -2253,8 +2253,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_FailToIniti
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto opCtx = makeOperationContext();
auto instance = repl::TenantMigrationRecipientService::Instance::getOrCreate(
@@ -2285,8 +2285,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_WaitUntilSt
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
auto fp = globalFailPointRegistry().find("pauseAfterRunTenantMigrationRecipientInstance");
auto initialTimesEntered = fp->setMode(FailPoint::alwaysOn);
@@ -2365,8 +2365,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterStartO
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -2426,8 +2426,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterConsis
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
MockRemoteDBServer* const _donorServer =
@@ -2512,8 +2512,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_AfterFail)
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Skip the cloners in this test, so we provide an empty list of databases.
MockRemoteDBServer* const _donorServer =
@@ -2591,8 +2591,8 @@ TEST_F(TenantMigrationRecipientServiceTest, RecipientForgetMigration_FailToMarkG
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -2640,8 +2640,8 @@ TEST_F(TenantMigrationRecipientServiceTest, TenantMigrationRecipientServiceRecor
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Create and start the instance.
auto opCtx = makeOperationContext();
@@ -2672,8 +2672,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Add an FCV value as if it was from a previous attempt.
auto currentFCV = serverGlobalParams.featureCompatibility.getVersion();
@@ -2708,8 +2708,8 @@ TEST_F(TenantMigrationRecipientServiceTest,
migrationUUID,
replSet.getConnectionString(),
"tenantA",
- ReadPreferenceSetting(ReadPreference::PrimaryOnly),
- kRecipientPEMPayload);
+ ReadPreferenceSetting(ReadPreference::PrimaryOnly));
+ initialStateDocument.setRecipientCertificateForDonor(kRecipientPEMPayload);
// Add an FCV value as if it was from a previous attempt, making sure we set a different
// version from the one we currently have.
diff --git a/src/mongo/db/repl/tenant_migration_state_machine.idl b/src/mongo/db/repl/tenant_migration_state_machine.idl
index 6b458f3d8b5..31e4e4f60a4 100644
--- a/src/mongo/db/repl/tenant_migration_state_machine.idl
+++ b/src/mongo/db/repl/tenant_migration_state_machine.idl
@@ -113,11 +113,15 @@ structs:
The SSL certificate and private key that the donor should use to authenticate
to the recipient.
type: TenantMigrationPEMPayload
+ # TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
+ optional: true
recipientCertificateForDonor:
description: >-
The SSL certificate and private key that the recipient should use to
authenticate to the donor.
type: TenantMigrationPEMPayload
+ # TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
+ optional: true
tenantMigrationRecipientDocument:
description: "Represents an in-progress tenant migration on the migration recipient."
@@ -183,10 +187,12 @@ structs:
The SSL certificate and private key that the recipient should use to
authenticate to the donor.
type: TenantMigrationPEMPayload
+ # TODO (SERVER-54085): Remove server parameter tenantMigrationDisableX509Auth.
+ optional: true
recipientPrimaryStartingFCV:
description: >-
The featureCompatibilityVersion of the recipient as recorded at the beginning
of a migration attempt. Implicitly includes information on current upgrade or
downgrade state.
type: fcv_string
- optional: true \ No newline at end of file
+ optional: true