mirror of
https://github.com/apple/foundationdb.git
synced 2025-06-01 10:45:56 +08:00
encryption as a tenant property
This commit is contained in:
parent
2b6f349649
commit
26d233c0f8
@ -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));
|
||||
|
||||
|
@ -117,6 +117,7 @@ struct ClientDBInfo {
|
||||
Optional<Value> forward;
|
||||
std::vector<VersionHistory> history;
|
||||
UID clusterId;
|
||||
bool isEncryptionEnabled;
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -47,13 +47,14 @@ struct TenantMapEntry {
|
||||
Key prefix;
|
||||
TenantState tenantState = TenantState::READY;
|
||||
Optional<TenantGroupName> tenantGroup;
|
||||
bool encrypted;
|
||||
|
||||
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;
|
||||
@ -72,7 +73,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);
|
||||
|
@ -96,7 +96,8 @@ Future<Void> checkTenantMode(Transaction tr) {
|
||||
ACTOR template <class Transaction>
|
||||
Future<std::pair<Optional<TenantMapEntry>, bool>> createTenantTransaction(Transaction tr,
|
||||
TenantNameRef name,
|
||||
TenantMapEntry tenantEntry) {
|
||||
TenantMapEntry tenantEntry,
|
||||
bool encrypted) {
|
||||
ASSERT(tenantEntry.id >= 0);
|
||||
|
||||
if (name.startsWith("\xff"_sr)) {
|
||||
@ -129,6 +130,7 @@ Future<std::pair<Optional<TenantMapEntry>, bool>> createTenantTransaction(Transa
|
||||
}
|
||||
|
||||
tenantEntry.tenantState = TenantState::READY;
|
||||
tenantEntry.encrypted = encrypted;
|
||||
TenantMetadata::tenantMap.set(tr, name, tenantEntry);
|
||||
if (tenantEntry.tenantGroup.present()) {
|
||||
TenantMetadata::tenantGroupTenantIndex.insert(tr, Tuple::makeTuple(tenantEntry.tenantGroup.get(), name));
|
||||
@ -156,6 +158,7 @@ Future<int64_t> getNextTenantId(Transaction tr) {
|
||||
ACTOR template <class DB>
|
||||
Future<Optional<TenantMapEntry>> createTenant(Reference<DB> db,
|
||||
TenantName name,
|
||||
bool encrypted,
|
||||
TenantMapEntry tenantEntry = TenantMapEntry()) {
|
||||
state Reference<typename DB::TransactionT> tr = db->createTransaction();
|
||||
|
||||
@ -188,7 +191,7 @@ Future<Optional<TenantMapEntry>> createTenant(Reference<DB> db,
|
||||
}
|
||||
|
||||
state std::pair<Optional<TenantMapEntry>, bool> newTenant =
|
||||
wait(createTenantTransaction(tr, name, tenantEntry));
|
||||
wait(createTenantTransaction(tr, name, tenantEntry, encrypted));
|
||||
|
||||
if (newTenant.second) {
|
||||
ASSERT(newTenant.first.present());
|
||||
|
@ -113,7 +113,8 @@ private:
|
||||
TenantNameRef tenantName,
|
||||
std::vector<std::pair<Standalone<StringRef>, Optional<Value>>> configMutations,
|
||||
int64_t tenantId,
|
||||
std::map<TenantGroupName, int>* tenantGroupNetTenantDelta) {
|
||||
std::map<TenantGroupName, int>* tenantGroupNetTenantDelta,
|
||||
bool encrypted) {
|
||||
state TenantMapEntry tenantEntry;
|
||||
tenantEntry.setId(tenantId);
|
||||
|
||||
@ -126,7 +127,7 @@ private:
|
||||
}
|
||||
|
||||
std::pair<Optional<TenantMapEntry>, bool> entry =
|
||||
wait(TenantAPI::createTenantTransaction(&ryw->getTransaction(), tenantName, tenantEntry));
|
||||
wait(TenantAPI::createTenantTransaction(&ryw->getTransaction(), tenantName, tenantEntry, encrypted));
|
||||
|
||||
return Void();
|
||||
}
|
||||
@ -140,7 +141,13 @@ private:
|
||||
|
||||
std::vector<Future<Void>> createFutures;
|
||||
for (auto const& [tenant, config] : tenants) {
|
||||
createFutures.push_back(createTenant(ryw, tenant, config, nextId++, tenantGroupNetTenantDelta));
|
||||
createFutures.push_back(
|
||||
createTenant(ryw,
|
||||
tenant,
|
||||
config,
|
||||
nextId++,
|
||||
tenantGroupNetTenantDelta,
|
||||
ryw->getTransactionState()->cx->clientInfo->get().isEncryptionEnabled));
|
||||
}
|
||||
|
||||
TenantMetadata::lastTenantId.set(&ryw->getTransaction(), nextId - 1);
|
||||
|
@ -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 = db->serverInfo->get().encryptKeyProxy.present();
|
||||
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 != db->serverInfo->get().encryptKeyProxy.present()) {
|
||||
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", db->serverInfo->get().encryptKeyProxy.present())
|
||||
.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 = db->serverInfo->get().encryptKeyProxy.present();
|
||||
clientInfo.commitProxies = req.commitProxies;
|
||||
clientInfo.grvProxies = req.grvProxies;
|
||||
clientInfo.tenantMode = db->config.tenantMode;
|
||||
|
@ -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, false);
|
||||
|
||||
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, false);
|
||||
|
||||
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, false);
|
||||
bool newTenant = tenantCache.update(tenantName, tenant);
|
||||
ASSERT(!newTenant);
|
||||
keepCount++;
|
||||
|
@ -4172,11 +4172,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, false)),
|
||||
std::make_pair("tenant2"_sr, TenantMapEntry(2, TenantState::READY, false)),
|
||||
std::make_pair("tenant3"_sr, TenantMapEntry(3, TenantState::READY, false)),
|
||||
std::make_pair("tenant4"_sr, TenantMapEntry(4, TenantState::READY, false)),
|
||||
std::make_pair("tenant6"_sr, TenantMapEntry(6, TenantState::READY, false))
|
||||
};
|
||||
TenantPrefixIndex index;
|
||||
index.createNewVersion(1);
|
||||
|
@ -1638,7 +1638,7 @@ ACTOR Future<Void> runTests(Reference<AsyncVar<Optional<struct ClusterController
|
||||
entry.tenantGroup = "TestTenantGroup"_sr;
|
||||
}
|
||||
TraceEvent("CreatingTenant").detail("Tenant", tenant).detail("TenantGroup", entry.tenantGroup);
|
||||
tenantFutures.push_back(success(TenantAPI::createTenant(cx.getReference(), tenant, entry)));
|
||||
tenantFutures.push_back(success(TenantAPI::createTenant(cx.getReference(), tenant, false, entry)));
|
||||
}
|
||||
|
||||
wait(waitForAll(tenantFutures));
|
||||
|
@ -212,7 +212,7 @@ struct BlobGranuleCorrectnessWorkload : TestWorkload {
|
||||
fmt::print("Setting up blob granule range for tenant {0}\n", name.printable());
|
||||
}
|
||||
|
||||
Optional<TenantMapEntry> entry = wait(TenantAPI::createTenant(cx.getReference(), name));
|
||||
Optional<TenantMapEntry> entry = wait(TenantAPI::createTenant(cx.getReference(), name, false));
|
||||
ASSERT(entry.present());
|
||||
|
||||
if (BGW_DEBUG) {
|
||||
|
@ -240,7 +240,8 @@ struct FuzzApiCorrectnessWorkload : TestWorkload {
|
||||
if (i < self->numTenants) {
|
||||
TenantMapEntry entry;
|
||||
entry.tenantGroup = self->getTenantGroup(i);
|
||||
tenantFutures.push_back(::success(TenantAPI::createTenant(cx.getReference(), tenantName, entry)));
|
||||
tenantFutures.push_back(
|
||||
::success(TenantAPI::createTenant(cx.getReference(), tenantName, false, entry)));
|
||||
self->createdTenants.insert(tenantName);
|
||||
}
|
||||
}
|
||||
|
@ -38,10 +38,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 {
|
||||
@ -155,8 +156,10 @@ struct TenantManagementWorkload : TestWorkload {
|
||||
wait(tr->commit());
|
||||
} else if (operationType == OperationType::MANAGEMENT_DATABASE) {
|
||||
ASSERT(tenantsToCreate.size() == 1);
|
||||
wait(success(TenantAPI::createTenant(
|
||||
cx.getReference(), tenantsToCreate.begin()->first, tenantsToCreate.begin()->second)));
|
||||
wait(success(TenantAPI::createTenant(cx.getReference(),
|
||||
tenantsToCreate.begin()->first,
|
||||
SERVER_KNOBS->ENABLE_ENCRYPTION,
|
||||
tenantsToCreate.begin()->second)));
|
||||
} else if (operationType == OperationType::MANAGEMENT_TRANSACTION) {
|
||||
tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS);
|
||||
int64_t _nextId = wait(TenantAPI::getNextTenantId(tr));
|
||||
@ -165,7 +168,8 @@ struct TenantManagementWorkload : TestWorkload {
|
||||
std::vector<Future<Void>> createFutures;
|
||||
for (auto [tenant, entry] : tenantsToCreate) {
|
||||
entry.setId(nextId++);
|
||||
createFutures.push_back(success(TenantAPI::createTenantTransaction(tr, tenant, entry)));
|
||||
createFutures.push_back(
|
||||
success(TenantAPI::createTenantTransaction(tr, tenant, entry, SERVER_KNOBS->ENABLE_ENCRYPTION)));
|
||||
}
|
||||
TenantMetadata::lastTenantId.set(tr, nextId - 1);
|
||||
wait(waitForAll(createFutures));
|
||||
@ -241,8 +245,8 @@ 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);
|
||||
self->createdTenants[tenantItr->first] = TenantData(
|
||||
entry.get().id, tenantItr->second.tenantGroup, true, SERVER_KNOBS->ENABLE_ENCRYPTION);
|
||||
|
||||
// If this tenant has a tenant group, create or update the entry for it
|
||||
if (tenantItr->second.tenantGroup.present()) {
|
||||
@ -551,10 +555,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));
|
||||
@ -569,7 +575,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;
|
||||
}
|
||||
@ -991,6 +997,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 == SERVER_KNOBS->ENABLE_ENCRYPTION);
|
||||
|
||||
checkTenants.push_back(checkTenantContents(cx, self, dataItr->first, localItr->second));
|
||||
lastTenant = dataItr->first;
|
||||
|
Loading…
x
Reference in New Issue
Block a user