Restart tests carry forward encryption knobs value (#7497)

Previously to get around the issue that EKP is not present when restart test switching encryption from on to off and read encrypted data, EKP was made to start in simulation regardless of encryption knob. This PR revert that change, and instead force restart test not to change encryption knob, by passing previous encryption knob through restartInfo.ini file. Also since we don't allow downgrading an encrypted cluster to previous version, disable encryption in downgrade tests.

Also adding an assert to allow reading encrypted mutations only if encryption knob is on. We may reconsider allowing switching encryption on/off for existing cluster, but for now we don't allow it.
This commit is contained in:
Yi Wu 2022-07-14 14:45:17 -07:00 committed by GitHub
parent 598457b872
commit 7d7ce0909f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 54 additions and 17 deletions

View File

@ -622,7 +622,7 @@ void checkBetterSingletons(ClusterControllerData* self) {
} }
WorkerDetails newEKPWorker; WorkerDetails newEKPWorker;
if (SERVER_KNOBS->ENABLE_ENCRYPTION || g_network->isSimulated()) { if (SERVER_KNOBS->ENABLE_ENCRYPTION) {
newEKPWorker = findNewProcessForSingleton(self, ProcessClass::EncryptKeyProxy, id_used); newEKPWorker = findNewProcessForSingleton(self, ProcessClass::EncryptKeyProxy, id_used);
} }
@ -636,7 +636,7 @@ void checkBetterSingletons(ClusterControllerData* self) {
} }
ProcessClass::Fitness bestFitnessForEKP; ProcessClass::Fitness bestFitnessForEKP;
if (SERVER_KNOBS->ENABLE_ENCRYPTION || g_network->isSimulated()) { if (SERVER_KNOBS->ENABLE_ENCRYPTION) {
bestFitnessForEKP = findBestFitnessForSingleton(self, newEKPWorker, ProcessClass::EncryptKeyProxy); bestFitnessForEKP = findBestFitnessForSingleton(self, newEKPWorker, ProcessClass::EncryptKeyProxy);
} }
@ -661,7 +661,7 @@ void checkBetterSingletons(ClusterControllerData* self) {
} }
bool ekpHealthy = true; bool ekpHealthy = true;
if (SERVER_KNOBS->ENABLE_ENCRYPTION || g_network->isSimulated()) { if (SERVER_KNOBS->ENABLE_ENCRYPTION) {
ekpHealthy = isHealthySingleton<EncryptKeyProxyInterface>( ekpHealthy = isHealthySingleton<EncryptKeyProxyInterface>(
self, newEKPWorker, ekpSingleton, bestFitnessForEKP, self->recruitingEncryptKeyProxyID); self, newEKPWorker, ekpSingleton, bestFitnessForEKP, self->recruitingEncryptKeyProxyID);
} }
@ -685,7 +685,7 @@ void checkBetterSingletons(ClusterControllerData* self) {
} }
Optional<Standalone<StringRef>> currEKPProcessId, newEKPProcessId; Optional<Standalone<StringRef>> currEKPProcessId, newEKPProcessId;
if (SERVER_KNOBS->ENABLE_ENCRYPTION || g_network->isSimulated()) { if (SERVER_KNOBS->ENABLE_ENCRYPTION) {
currEKPProcessId = ekpSingleton.interface.get().locality.processId(); currEKPProcessId = ekpSingleton.interface.get().locality.processId();
newEKPProcessId = newEKPWorker.interf.locality.processId(); newEKPProcessId = newEKPWorker.interf.locality.processId();
} }
@ -697,7 +697,7 @@ void checkBetterSingletons(ClusterControllerData* self) {
newPids.emplace_back(newBMProcessId); newPids.emplace_back(newBMProcessId);
} }
if (SERVER_KNOBS->ENABLE_ENCRYPTION || g_network->isSimulated()) { if (SERVER_KNOBS->ENABLE_ENCRYPTION) {
currPids.emplace_back(currEKPProcessId); currPids.emplace_back(currEKPProcessId);
newPids.emplace_back(newEKPProcessId); newPids.emplace_back(newEKPProcessId);
} }
@ -712,7 +712,7 @@ void checkBetterSingletons(ClusterControllerData* self) {
} }
// if the knob is disabled, the EKP coloc counts should have no affect on the coloc counts check below // if the knob is disabled, the EKP coloc counts should have no affect on the coloc counts check below
if (!SERVER_KNOBS->ENABLE_ENCRYPTION && !g_network->isSimulated()) { if (!SERVER_KNOBS->ENABLE_ENCRYPTION) {
ASSERT(currColocMap[currEKPProcessId] == 0); ASSERT(currColocMap[currEKPProcessId] == 0);
ASSERT(newColocMap[newEKPProcessId] == 0); ASSERT(newColocMap[newEKPProcessId] == 0);
} }
@ -1271,7 +1271,7 @@ ACTOR Future<Void> registerWorker(RegisterWorkerRequest req,
self, w, currSingleton, registeringSingleton, self->recruitingBlobManagerID); self, w, currSingleton, registeringSingleton, self->recruitingBlobManagerID);
} }
if ((SERVER_KNOBS->ENABLE_ENCRYPTION || g_network->isSimulated()) && req.encryptKeyProxyInterf.present()) { if (SERVER_KNOBS->ENABLE_ENCRYPTION && req.encryptKeyProxyInterf.present()) {
auto currSingleton = EncryptKeyProxySingleton(self->db.serverInfo->get().encryptKeyProxy); auto currSingleton = EncryptKeyProxySingleton(self->db.serverInfo->get().encryptKeyProxy);
auto registeringSingleton = EncryptKeyProxySingleton(req.encryptKeyProxyInterf); auto registeringSingleton = EncryptKeyProxySingleton(req.encryptKeyProxyInterf);
haltRegisteringOrCurrentSingleton<EncryptKeyProxyInterface>( haltRegisteringOrCurrentSingleton<EncryptKeyProxyInterface>(
@ -2525,7 +2525,7 @@ ACTOR Future<Void> clusterControllerCore(ClusterControllerFullInterface interf,
state Future<ErrorOr<Void>> error = errorOr(actorCollection(self.addActor.getFuture())); state Future<ErrorOr<Void>> error = errorOr(actorCollection(self.addActor.getFuture()));
// EncryptKeyProxy is necessary for TLog recovery, recruit it as the first process // EncryptKeyProxy is necessary for TLog recovery, recruit it as the first process
if (SERVER_KNOBS->ENABLE_ENCRYPTION || g_network->isSimulated()) { if (SERVER_KNOBS->ENABLE_ENCRYPTION) {
self.addActor.send(monitorEncryptKeyProxy(&self)); self.addActor.send(monitorEncryptKeyProxy(&self));
} }
self.addActor.send(clusterWatchDatabase( self.addActor.send(clusterWatchDatabase(

View File

@ -506,6 +506,12 @@ private:
OpHeader* h, OpHeader* h,
bool* isZeroFilled, bool* isZeroFilled,
int* zeroFillSize) { int* zeroFillSize) {
// Metadata op types to be excluded from encryption.
static std::unordered_set<OpType> metaOps = { OpSnapshotEnd, OpSnapshotAbort, OpCommit, OpRollback };
if (metaOps.count((OpType)h->op) == 0) {
// It is not supported to open an encrypted store as unencrypted, or vice-versa.
ASSERT_EQ(h->op == OpEncrypted, self->enableEncryption);
}
state int remainingBytes = h->len1 + h->len2 + 1; state int remainingBytes = h->len1 + h->len2 + 1;
if (h->op == OpEncrypted) { if (h->op == OpEncrypted) {
// encryption header, plus the real (encrypted) op type // encryption header, plus the real (encrypted) op type

View File

@ -260,6 +260,9 @@ class TestConfig {
if (attrib == "disableRemoteKVS") { if (attrib == "disableRemoteKVS") {
disableRemoteKVS = strcmp(value.c_str(), "true") == 0; disableRemoteKVS = strcmp(value.c_str(), "true") == 0;
} }
if (attrib == "disableEncryption") {
disableEncryption = strcmp(value.c_str(), "true") == 0;
}
if (attrib == "restartInfoLocation") { if (attrib == "restartInfoLocation") {
isFirstTestInRestart = true; isFirstTestInRestart = true;
} }
@ -297,6 +300,8 @@ public:
bool disableHostname = false; bool disableHostname = false;
// remote key value store is a child process spawned by the SS process to run the storage engine // remote key value store is a child process spawned by the SS process to run the storage engine
bool disableRemoteKVS = false; bool disableRemoteKVS = false;
// 7.2 cannot be downgraded to 7.1 or below after enabling encryption-at-rest.
bool disableEncryption = false;
// Storage Engine Types: Verify match with SimulationConfig::generateNormalConfig // Storage Engine Types: Verify match with SimulationConfig::generateNormalConfig
// 0 = "ssd" // 0 = "ssd"
// 1 = "memory" // 1 = "memory"
@ -358,6 +363,7 @@ public:
.add("disableTss", &disableTss) .add("disableTss", &disableTss)
.add("disableHostname", &disableHostname) .add("disableHostname", &disableHostname)
.add("disableRemoteKVS", &disableRemoteKVS) .add("disableRemoteKVS", &disableRemoteKVS)
.add("disableEncryption", &disableEncryption)
.add("simpleConfig", &simpleConfig) .add("simpleConfig", &simpleConfig)
.add("generateFearless", &generateFearless) .add("generateFearless", &generateFearless)
.add("datacenters", &datacenters) .add("datacenters", &datacenters)
@ -1091,10 +1097,15 @@ ACTOR Future<Void> restartSimulatedSystem(std::vector<Future<Void>>* systemActor
INetworkConnections::net()->parseMockDNSFromString(mockDNSStr); INetworkConnections::net()->parseMockDNSFromString(mockDNSStr);
} }
} }
auto& g_knobs = IKnobCollection::getMutableGlobalKnobCollection();
if (testConfig.disableRemoteKVS) { if (testConfig.disableRemoteKVS) {
IKnobCollection::getMutableGlobalKnobCollection().setKnob("remote_kv_store", g_knobs.setKnob("remote_kv_store", KnobValueRef::create(bool{ false }));
KnobValueRef::create(bool{ false })); TraceEvent(SevDebug, "DisableRemoteKVS");
TraceEvent(SevDebug, "DisaableRemoteKVS").log(); }
if (testConfig.disableEncryption) {
g_knobs.setKnob("enable_encryption", KnobValueRef::create(bool{ false }));
g_knobs.setKnob("enable_tlog_encryption", KnobValueRef::create(bool{ false }));
TraceEvent(SevDebug, "DisableEncryption");
} }
*pConnString = conn; *pConnString = conn;
*pTesterCount = testerCount; *pTesterCount = testerCount;
@ -1860,10 +1871,15 @@ void setupSimulatedSystem(std::vector<Future<Void>>* systemActors,
if (testConfig.configureLocked) { if (testConfig.configureLocked) {
startingConfigString += " locked"; startingConfigString += " locked";
} }
auto& g_knobs = IKnobCollection::getMutableGlobalKnobCollection();
if (testConfig.disableRemoteKVS) { if (testConfig.disableRemoteKVS) {
IKnobCollection::getMutableGlobalKnobCollection().setKnob("remote_kv_store", g_knobs.setKnob("remote_kv_store", KnobValueRef::create(bool{ false }));
KnobValueRef::create(bool{ false })); TraceEvent(SevDebug, "DisableRemoteKVS");
TraceEvent(SevDebug, "DisaableRemoteKVS").log(); }
if (testConfig.disableEncryption) {
g_knobs.setKnob("enable_encryption", KnobValueRef::create(bool{ false }));
g_knobs.setKnob("enable_tlog_encryption", KnobValueRef::create(bool{ false }));
TraceEvent(SevDebug, "DisableEncryption");
} }
auto configDBType = testConfig.getConfigDBType(); auto configDBType = testConfig.getConfigDBType();
for (auto kv : startingConfigJSON) { for (auto kv : startingConfigJSON) {

View File

@ -817,7 +817,7 @@ ACTOR static Future<JsonBuilderObject> processStatusFetcher(
roles.addRole("blob_manager", db->get().blobManager.get()); roles.addRole("blob_manager", db->get().blobManager.get());
} }
if ((SERVER_KNOBS->ENABLE_ENCRYPTION || g_network->isSimulated()) && db->get().encryptKeyProxy.present()) { if (SERVER_KNOBS->ENABLE_ENCRYPTION && db->get().encryptKeyProxy.present()) {
roles.addRole("encrypt_key_proxy", db->get().encryptKeyProxy.get()); roles.addRole("encrypt_key_proxy", db->get().encryptKeyProxy.get());
} }

View File

@ -2121,6 +2121,10 @@ int main(int argc, char* argv[]) {
} }
} }
} }
g_knobs.setKnob("enable_encryption",
KnobValue::create(ini.GetBoolValue("META", "enableEncryption", false)));
g_knobs.setKnob("enable_tlog_encryption",
KnobValue::create(ini.GetBoolValue("META", "enableTLogEncryption", false)));
} }
setupAndRun(dataFolder, opts.testFile, opts.restarting, (isRestoring >= 1), opts.whitelistBinPaths); setupAndRun(dataFolder, opts.testFile, opts.restarting, (isRestoring >= 1), opts.whitelistBinPaths);
g_simulator.run(); g_simulator.run();

View File

@ -24,6 +24,7 @@
#pragma once #pragma once
#include "fdbclient/CommitTransaction.h" #include "fdbclient/CommitTransaction.h"
#include "fdbserver/Knobs.h"
#include "flow/BlobCipher.h" #include "flow/BlobCipher.h"
struct EncryptedMutationMessage { struct EncryptedMutationMessage {
@ -96,6 +97,7 @@ struct EncryptedMutationMessage {
Arena& arena, Arena& arena,
const std::unordered_map<BlobCipherDetails, Reference<BlobCipherKey>>& cipherKeys, const std::unordered_map<BlobCipherDetails, Reference<BlobCipherKey>>& cipherKeys,
StringRef* buf = nullptr) { StringRef* buf = nullptr) {
ASSERT(SERVER_KNOBS->ENABLE_ENCRYPTION);
EncryptedMutationMessage msg; EncryptedMutationMessage msg;
ar >> msg; ar >> msg;
auto textCipherItr = cipherKeys.find(msg.header.cipherTextDetails); auto textCipherItr = cipherKeys.find(msg.header.cipherTextDetails);

View File

@ -1172,7 +1172,10 @@ std::map<std::string, std::function<void(const std::string&)>> testSpecGlobalKey
{ "disableTss", [](const std::string& value) { TraceEvent("TestParserTest").detail("ParsedDisableTSS", ""); } }, { "disableTss", [](const std::string& value) { TraceEvent("TestParserTest").detail("ParsedDisableTSS", ""); } },
{ "disableHostname", { "disableHostname",
[](const std::string& value) { TraceEvent("TestParserTest").detail("ParsedDisableHostname", ""); } }, [](const std::string& value) { TraceEvent("TestParserTest").detail("ParsedDisableHostname", ""); } },
{ "disableRemoteKVS", [](const std::string& value) { TraceEvent("TestParserTest").detail("ParsedRemoteKVS", ""); } } { "disableRemoteKVS",
[](const std::string& value) { TraceEvent("TestParserTest").detail("ParsedRemoteKVS", ""); } },
{ "disableEncryption",
[](const std::string& value) { TraceEvent("TestParserTest").detail("ParsedRemoteKVS", ""); } }
}; };
std::map<std::string, std::function<void(const std::string& value, TestSpec* spec)>> testSpecTestKeys = { std::map<std::string, std::function<void(const std::string& value, TestSpec* spec)>> testSpecTestKeys = {

View File

@ -2380,7 +2380,7 @@ struct ConsistencyCheckWorkload : TestWorkload {
} }
// Check EncryptKeyProxy // Check EncryptKeyProxy
if ((SERVER_KNOBS->ENABLE_ENCRYPTION || g_network->isSimulated()) && db.encryptKeyProxy.present() && if (SERVER_KNOBS->ENABLE_ENCRYPTION && db.encryptKeyProxy.present() &&
(!nonExcludedWorkerProcessMap.count(db.encryptKeyProxy.get().address()) || (!nonExcludedWorkerProcessMap.count(db.encryptKeyProxy.get().address()) ||
nonExcludedWorkerProcessMap[db.encryptKeyProxy.get().address()].processClass.machineClassFitness( nonExcludedWorkerProcessMap[db.encryptKeyProxy.get().address()].processClass.machineClassFitness(
ProcessClass::EncryptKeyProxy) > fitnessLowerBound)) { ProcessClass::EncryptKeyProxy) > fitnessLowerBound)) {

View File

@ -19,6 +19,7 @@
*/ */
#include "fdbclient/NativeAPI.actor.h" #include "fdbclient/NativeAPI.actor.h"
#include "fdbserver/Knobs.h"
#include "fdbserver/TesterInterface.actor.h" #include "fdbserver/TesterInterface.actor.h"
#include "fdbserver/workloads/workloads.actor.h" #include "fdbserver/workloads/workloads.actor.h"
#include "fdbrpc/simulator.h" #include "fdbrpc/simulator.h"
@ -67,6 +68,9 @@ struct SaveAndKillWorkload : TestWorkload {
ini.SetValue("META", "tssMode", format("%d", g_simulator.tssMode).c_str()); ini.SetValue("META", "tssMode", format("%d", g_simulator.tssMode).c_str());
ini.SetValue("META", "mockDNS", INetworkConnections::net()->convertMockDNSToString().c_str()); ini.SetValue("META", "mockDNS", INetworkConnections::net()->convertMockDNSToString().c_str());
ini.SetBoolValue("META", "enableEncryption", SERVER_KNOBS->ENABLE_ENCRYPTION);
ini.SetBoolValue("META", "enableTLogEncryption", SERVER_KNOBS->ENABLE_TLOG_ENCRYPTION);
std::vector<ISimulator::ProcessInfo*> processes = g_simulator.getAllProcesses(); std::vector<ISimulator::ProcessInfo*> processes = g_simulator.getAllProcesses();
std::map<NetworkAddress, ISimulator::ProcessInfo*> rebootingProcesses = g_simulator.currentlyRebootingProcesses; std::map<NetworkAddress, ISimulator::ProcessInfo*> rebootingProcesses = g_simulator.currentlyRebootingProcesses;
std::map<std::string, ISimulator::ProcessInfo*> allProcessesMap; std::map<std::string, ISimulator::ProcessInfo*> allProcessesMap;

View File

@ -2,6 +2,7 @@
extraMachineCountDC = 2 extraMachineCountDC = 2
maxTLogVersion=6 maxTLogVersion=6
disableHostname=true disableHostname=true
disableEncryption=true
storageEngineExcludeTypes=[4] storageEngineExcludeTypes=[4]
[[test]] [[test]]

View File

@ -2,6 +2,7 @@ storageEngineExcludeTypes=-1,-2,3
maxTLogVersion=6 maxTLogVersion=6
disableTss=true disableTss=true
disableHostname=true disableHostname=true
disableEncryption=true
testTitle=Clogged testTitle=Clogged
clearAfterTest=false clearAfterTest=false