Merge pull request #7714 from sfc-gh-nwijetunga/nim/tenant-encryption-property

Encryption as a tenant property
This commit is contained in:
Nim Wijetunga 2022-07-29 11:30:19 -07:00 committed by GitHub
commit 3e45b6657c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 53 additions and 25 deletions

View File

@ -628,8 +628,9 @@ def tenants(logger):
assert(len(json_output) == 2)
assert('tenant' in json_output)
assert(json_output['type'] == 'success')
assert(len(json_output['tenant']) == 3)
assert(len(json_output['tenant']) == 4)
assert('id' in json_output['tenant'])
assert('encrypted' in json_output['tenant'])
assert('prefix' in json_output['tenant'])
assert(len(json_output['tenant']['prefix']) == 2)
assert('base64' in json_output['tenant']['prefix'])
@ -649,8 +650,9 @@ def tenants(logger):
assert(len(json_output) == 2)
assert('tenant' in json_output)
assert(json_output['type'] == 'success')
assert(len(json_output['tenant']) == 4)
assert(len(json_output['tenant']) == 5)
assert('id' in json_output['tenant'])
assert('encrypted' in json_output['tenant'])
assert('prefix' in json_output['tenant'])
assert(json_output['tenant']['tenant_state'] == 'ready')
assert('tenant_group' in json_output['tenant'])

View File

@ -71,11 +71,15 @@ TenantState TenantMapEntry::stringToTenantState(std::string stateStr) {
}
TenantMapEntry::TenantMapEntry() {}
TenantMapEntry::TenantMapEntry(int64_t id, TenantState tenantState) : tenantState(tenantState) {
TenantMapEntry::TenantMapEntry(int64_t id, TenantState tenantState, bool encrypted)
: tenantState(tenantState), encrypted(encrypted) {
setId(id);
}
TenantMapEntry::TenantMapEntry(int64_t id, TenantState tenantState, Optional<TenantGroupName> tenantGroup)
: tenantState(tenantState), tenantGroup(tenantGroup) {
TenantMapEntry::TenantMapEntry(int64_t id,
TenantState tenantState,
Optional<TenantGroupName> tenantGroup,
bool encrypted)
: tenantState(tenantState), tenantGroup(tenantGroup), encrypted(encrypted) {
setId(id);
}
@ -88,6 +92,7 @@ void TenantMapEntry::setId(int64_t id) {
std::string TenantMapEntry::toJson(int apiVersion) const {
json_spirit::mObject tenantEntry;
tenantEntry["id"] = id;
tenantEntry["encrypted"] = encrypted;
if (apiVersion >= 720 || apiVersion == Database::API_VERSION_LATEST) {
json_spirit::mObject prefixObject;
@ -133,12 +138,12 @@ void TenantMapEntry::configure(Standalone<StringRef> parameter, Optional<Value>
}
TEST_CASE("/fdbclient/TenantMapEntry/Serialization") {
TenantMapEntry entry1(1, TenantState::READY);
TenantMapEntry entry1(1, TenantState::READY, false);
ASSERT(entry1.prefix == "\x00\x00\x00\x00\x00\x00\x00\x01"_sr);
TenantMapEntry entry2 = TenantMapEntry::decode(entry1.encode());
ASSERT(entry1.id == entry2.id && entry1.prefix == entry2.prefix);
TenantMapEntry entry3(std::numeric_limits<int64_t>::max(), TenantState::READY);
TenantMapEntry entry3(std::numeric_limits<int64_t>::max(), TenantState::READY, false);
ASSERT(entry3.prefix == "\x7f\xff\xff\xff\xff\xff\xff\xff"_sr);
TenantMapEntry entry4 = TenantMapEntry::decode(entry3.encode());
ASSERT(entry3.id == entry4.id && entry3.prefix == entry4.prefix);
@ -149,7 +154,7 @@ TEST_CASE("/fdbclient/TenantMapEntry/Serialization") {
int64_t maxPlusOne = std::min<uint64_t>(UINT64_C(1) << bits, std::numeric_limits<int64_t>::max());
int64_t id = deterministicRandom()->randomInt64(min, maxPlusOne);
TenantMapEntry entry(id, TenantState::READY);
TenantMapEntry entry(id, TenantState::READY, false);
int64_t bigEndianId = bigEndian64(id);
ASSERT(entry.id == id && entry.prefix == StringRef(reinterpret_cast<uint8_t*>(&bigEndianId), 8));

View File

@ -117,6 +117,7 @@ struct ClientDBInfo {
Optional<Value> forward;
std::vector<VersionHistory> history;
UID clusterId;
bool isEncryptionEnabled = false;
TenantMode tenantMode;
@ -130,7 +131,7 @@ struct ClientDBInfo {
if constexpr (!is_fb_function<Archive>) {
ASSERT(ar.protocolVersion().isValid());
}
serializer(ar, grvProxies, commitProxies, id, forward, history, tenantMode, clusterId);
serializer(ar, grvProxies, commitProxies, id, forward, history, tenantMode, clusterId, isEncryptionEnabled);
}
};

View File

@ -48,13 +48,14 @@ struct TenantMapEntry {
Key prefix;
TenantState tenantState = TenantState::READY;
Optional<TenantGroupName> tenantGroup;
bool encrypted = false;
constexpr static int PREFIX_SIZE = sizeof(id);
public:
TenantMapEntry();
TenantMapEntry(int64_t id, TenantState tenantState);
TenantMapEntry(int64_t id, TenantState tenantState, Optional<TenantGroupName> tenantGroup);
TenantMapEntry(int64_t id, TenantState tenantState, bool encrypted);
TenantMapEntry(int64_t id, TenantState tenantState, Optional<TenantGroupName> tenantGroup, bool encrypted);
void setId(int64_t id);
std::string toJson(int apiVersion) const;
@ -69,7 +70,7 @@ public:
template <class Ar>
void serialize(Ar& ar) {
serializer(ar, id, tenantState, tenantGroup);
serializer(ar, id, tenantState, tenantGroup, encrypted);
if constexpr (Ar::isDeserializing) {
if (id >= 0) {
prefix = idToPrefix(id);

View File

@ -116,6 +116,7 @@ private:
std::map<TenantGroupName, int>* tenantGroupNetTenantDelta) {
state TenantMapEntry tenantEntry;
tenantEntry.setId(tenantId);
tenantEntry.encrypted = ryw->getTransactionState()->cx->clientInfo->get().isEncryptionEnabled;
for (auto const& [name, value] : configMutations) {
tenantEntry.configure(name, value);

View File

@ -248,6 +248,7 @@ ACTOR Future<Void> clusterWatchDatabase(ClusterControllerData* cluster,
dbInfo.latencyBandConfig = db->serverInfo->get().latencyBandConfig;
dbInfo.myLocality = db->serverInfo->get().myLocality;
dbInfo.client = ClientDBInfo();
dbInfo.client.isEncryptionEnabled = SERVER_KNOBS->ENABLE_ENCRYPTION;
dbInfo.client.tenantMode = db->config.tenantMode;
dbInfo.client.clusterId = db->serverInfo->get().client.clusterId;
@ -1011,7 +1012,8 @@ void clusterRegisterMaster(ClusterControllerData* self, RegisterMasterRequest co
// Construct the client information
if (db->clientInfo->get().commitProxies != req.commitProxies ||
db->clientInfo->get().grvProxies != req.grvProxies ||
db->clientInfo->get().tenantMode != db->config.tenantMode || db->clientInfo->get().clusterId != req.clusterId) {
db->clientInfo->get().tenantMode != db->config.tenantMode || db->clientInfo->get().clusterId != req.clusterId ||
db->clientInfo->get().isEncryptionEnabled != SERVER_KNOBS->ENABLE_ENCRYPTION) {
TraceEvent("PublishNewClientInfo", self->id)
.detail("Master", dbInfo.master.id())
.detail("GrvProxies", db->clientInfo->get().grvProxies)
@ -1021,11 +1023,13 @@ void clusterRegisterMaster(ClusterControllerData* self, RegisterMasterRequest co
.detail("TenantMode", db->clientInfo->get().tenantMode.toString())
.detail("ReqTenantMode", db->config.tenantMode.toString())
.detail("ClusterId", db->clientInfo->get().clusterId)
.detail("EncryptionEnabled", SERVER_KNOBS->ENABLE_ENCRYPTION)
.detail("ReqClusterId", req.clusterId);
isChanged = true;
// TODO why construct a new one and not just copy the old one and change proxies + id?
ClientDBInfo clientInfo;
clientInfo.id = deterministicRandom()->randomUniqueID();
clientInfo.isEncryptionEnabled = SERVER_KNOBS->ENABLE_ENCRYPTION;
clientInfo.commitProxies = req.commitProxies;
clientInfo.grvProxies = req.grvProxies;
clientInfo.tenantMode = db->config.tenantMode;

View File

@ -393,6 +393,7 @@ ACTOR Future<Void> leaderRegister(LeaderElectionRegInterface interf, Key key) {
notify[i].send(newInfo);
notify.clear();
ClientDBInfo outInfo;
outInfo.isEncryptionEnabled = SERVER_KNOBS->ENABLE_ENCRYPTION;
outInfo.id = deterministicRandom()->randomUniqueID();
outInfo.forward = req.conn.toString();
clientData.clientInfo->set(CachedSerialization<ClientDBInfo>(outInfo));
@ -632,6 +633,7 @@ ACTOR Future<Void> leaderServer(LeaderElectionRegInterface interf,
Optional<LeaderInfo> forward = regs.getForward(req.clusterKey);
if (forward.present()) {
ClientDBInfo info;
info.isEncryptionEnabled = SERVER_KNOBS->ENABLE_ENCRYPTION;
info.id = deterministicRandom()->randomUniqueID();
info.forward = forward.get().serializedInfo;
req.reply.send(CachedSerialization<ClientDBInfo>(info));

View File

@ -217,7 +217,7 @@ public:
for (uint16_t i = 0; i < tenantCount; i++) {
TenantName tenantName(format("%s_%08d", "ddtc_test_tenant", tenantNumber + i));
TenantMapEntry tenant(tenantNumber + i, TenantState::READY);
TenantMapEntry tenant(tenantNumber + i, TenantState::READY, SERVER_KNOBS->ENABLE_ENCRYPTION);
tenantCache.insert(tenantName, tenant);
}
@ -245,7 +245,7 @@ public:
for (uint16_t i = 0; i < tenantCount; i++) {
TenantName tenantName(format("%s_%08d", "ddtc_test_tenant", tenantNumber + i));
TenantMapEntry tenant(tenantNumber + i, TenantState::READY);
TenantMapEntry tenant(tenantNumber + i, TenantState::READY, SERVER_KNOBS->ENABLE_ENCRYPTION);
tenantCache.insert(tenantName, tenant);
}
@ -259,7 +259,7 @@ public:
if (tenantOrdinal % staleTenantFraction != 0) {
TenantName tenantName(format("%s_%08d", "ddtc_test_tenant", tenantOrdinal));
TenantMapEntry tenant(tenantOrdinal, TenantState::READY);
TenantMapEntry tenant(tenantOrdinal, TenantState::READY, SERVER_KNOBS->ENABLE_ENCRYPTION);
bool newTenant = tenantCache.update(tenantName, tenant);
ASSERT(!newTenant);
keepCount++;

View File

@ -4262,11 +4262,11 @@ bool rangeIntersectsAnyTenant(TenantPrefixIndex& prefixIndex, KeyRangeRef range,
TEST_CASE("/fdbserver/storageserver/rangeIntersectsAnyTenant") {
std::map<TenantName, TenantMapEntry> entries = {
std::make_pair("tenant0"_sr, TenantMapEntry(0, TenantState::READY)),
std::make_pair("tenant2"_sr, TenantMapEntry(2, TenantState::READY)),
std::make_pair("tenant3"_sr, TenantMapEntry(3, TenantState::READY)),
std::make_pair("tenant4"_sr, TenantMapEntry(4, TenantState::READY)),
std::make_pair("tenant6"_sr, TenantMapEntry(6, TenantState::READY))
std::make_pair("tenant0"_sr, TenantMapEntry(0, TenantState::READY, SERVER_KNOBS->ENABLE_ENCRYPTION)),
std::make_pair("tenant2"_sr, TenantMapEntry(2, TenantState::READY, SERVER_KNOBS->ENABLE_ENCRYPTION)),
std::make_pair("tenant3"_sr, TenantMapEntry(3, TenantState::READY, SERVER_KNOBS->ENABLE_ENCRYPTION)),
std::make_pair("tenant4"_sr, TenantMapEntry(4, TenantState::READY, SERVER_KNOBS->ENABLE_ENCRYPTION)),
std::make_pair("tenant6"_sr, TenantMapEntry(6, TenantState::READY, SERVER_KNOBS->ENABLE_ENCRYPTION))
};
TenantPrefixIndex index;
index.createNewVersion(1);

View File

@ -1640,6 +1640,7 @@ ACTOR Future<Void> runTests(Reference<AsyncVar<Optional<struct ClusterController
if (deterministicRandom()->coinflip()) {
entry.tenantGroup = "TestTenantGroup"_sr;
}
entry.encrypted = SERVER_KNOBS->ENABLE_ENCRYPTION;
TraceEvent("CreatingTenant").detail("Tenant", tenant).detail("TenantGroup", entry.tenantGroup);
tenantFutures.push_back(success(TenantAPI::createTenant(cx.getReference(), tenant, entry)));
}

View File

@ -24,6 +24,7 @@
#include <sstream>
#include "fdbclient/FDBOptions.g.h"
#include "fdbserver/Knobs.h"
#include "fdbserver/TesterInterface.actor.h"
#include "fdbclient/GenericManagementAPI.actor.h"
#include "fdbclient/TenantManagement.actor.h"
@ -240,6 +241,7 @@ struct FuzzApiCorrectnessWorkload : TestWorkload {
if (i < self->numTenants) {
TenantMapEntry entry;
entry.tenantGroup = self->getTenantGroup(i);
entry.encrypted = SERVER_KNOBS->ENABLE_ENCRYPTION;
tenantFutures.push_back(::success(TenantAPI::createTenant(cx.getReference(), tenantName, entry)));
self->createdTenants.insert(tenantName);
}

View File

@ -40,10 +40,11 @@ struct TenantManagementWorkload : TestWorkload {
int64_t id;
Optional<TenantGroupName> tenantGroup;
bool empty;
bool encrypted;
TenantData() : id(-1), empty(true) {}
TenantData(int64_t id, Optional<TenantGroupName> tenantGroup, bool empty)
: id(id), tenantGroup(tenantGroup), empty(empty) {}
TenantData(int64_t id, Optional<TenantGroupName> tenantGroup, bool empty, bool encrypted)
: id(id), tenantGroup(tenantGroup), empty(empty), encrypted(encrypted) {}
};
struct TenantGroupData {
@ -209,6 +210,11 @@ struct TenantManagementWorkload : TestWorkload {
TenantMapEntry entry;
entry.tenantGroup = self->chooseTenantGroup(true);
if (operationType == OperationType::SPECIAL_KEYS) {
entry.encrypted = SERVER_KNOBS->ENABLE_ENCRYPTION;
} else {
entry.encrypted = deterministicRandom()->coinflip();
}
if (self->createdTenants.count(tenant)) {
alreadyExists = true;
@ -266,7 +272,7 @@ struct TenantManagementWorkload : TestWorkload {
// Update our local tenant state to include the newly created one
self->maxId = entry.get().id;
self->createdTenants[tenantItr->first] =
TenantData(entry.get().id, tenantItr->second.tenantGroup, true);
TenantData(entry.get().id, tenantItr->second.tenantGroup, true, tenantItr->second.encrypted);
// If this tenant has a tenant group, create or update the entry for it
if (tenantItr->second.tenantGroup.present()) {
@ -582,10 +588,12 @@ struct TenantManagementWorkload : TestWorkload {
std::string tenantStateStr;
std::string base64TenantGroup;
std::string printableTenantGroup;
bool encrypted;
jsonDoc.get("id", id);
jsonDoc.get("prefix.base64", base64Prefix);
jsonDoc.get("prefix.printable", printablePrefix);
jsonDoc.get("prefix.encrypted", encrypted);
prefix = base64::decoder::from_string(base64Prefix);
ASSERT(prefix == unprintable(printablePrefix));
@ -600,7 +608,7 @@ struct TenantManagementWorkload : TestWorkload {
tenantGroup = TenantGroupNameRef(tenantGroupStr);
}
TenantMapEntry entry(id, TenantState::READY, tenantGroup);
TenantMapEntry entry(id, TenantState::READY, tenantGroup, encrypted);
ASSERT(entry.prefix == prefix);
return entry;
}
@ -1127,6 +1135,7 @@ struct TenantManagementWorkload : TestWorkload {
ASSERT(localItr != self->createdTenants.end());
ASSERT(dataItr->first == localItr->first);
ASSERT(dataItr->second.tenantGroup == localItr->second.tenantGroup);
ASSERT(dataItr->second.encrypted == localItr->second.encrypted);
checkTenants.push_back(checkTenantContents(cx, self, dataItr->first, localItr->second));
lastTenant = dataItr->first;