mirror of
https://github.com/apple/foundationdb.git
synced 2025-05-14 01:42:37 +08:00
Update EKPServer LookupKeysByKeyIds API (#6898)
* Update EKPServer LookupKeysByKeyIds API Description Major changes include: 1. Update EKPServer LookupKeysByKeyIds API to include 'encryptDomainId' as input along with 'baseCipherId' 2. Unify EKPServer response definition to return std::vector<EKPBaseCipherDetails> 3. Update SimKmsProxy interfaces as per above mentioned changes. Testing 1. Update EncryptKeyProxyTest simulation test. 2. Update SimEncyrptKeyProxy unit test
This commit is contained in:
parent
98b82f1ac3
commit
5b5b45c7cb
@ -37,6 +37,7 @@
|
||||
#include "flow/network.h"
|
||||
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <utility>
|
||||
|
||||
#include "flow/actorcompiler.h" // This must be the last #include.
|
||||
|
||||
@ -155,25 +156,26 @@ ACTOR Future<Void> getCipherKeysByBaseCipherKeyIds(Reference<EncryptKeyProxyData
|
||||
// Scan the cached cipher-keys and filter our baseCipherIds locally cached
|
||||
// for the rest, reachout to KMS to fetch the required details
|
||||
|
||||
std::vector<EncryptBaseCipherId> lookupCipherIds;
|
||||
state std::unordered_map<EncryptBaseCipherId, Standalone<StringRef>> cachedKeys;
|
||||
|
||||
for (EncryptBaseCipherId id : req.baseCipherIds) {
|
||||
const auto itr = ekpProxyData->baseCipherKeyIdCache.find(id);
|
||||
if (itr != ekpProxyData->baseCipherKeyIdCache.end()) {
|
||||
ASSERT(itr->second.isValid());
|
||||
cachedKeys.emplace(id, itr->second.baseCipherKey);
|
||||
} else {
|
||||
lookupCipherIds.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
ekpProxyData->baseCipherKeyIdCacheHits += cachedKeys.size();
|
||||
ekpProxyData->baseCipherKeyIdCacheMisses += lookupCipherIds.size();
|
||||
std::vector<std::pair<EncryptBaseCipherId, EncryptDomainId>> lookupCipherIds;
|
||||
state std::vector<EKPBaseCipherDetails> cachedCipherDetails;
|
||||
|
||||
state EKPGetBaseCipherKeysByIdsRequest keysByIds = req;
|
||||
state EKPGetBaseCipherKeysByIdsReply keyIdsReply;
|
||||
|
||||
for (const auto& item : req.baseCipherIds) {
|
||||
const auto itr = ekpProxyData->baseCipherKeyIdCache.find(item.first);
|
||||
if (itr != ekpProxyData->baseCipherKeyIdCache.end()) {
|
||||
ASSERT(itr->second.isValid());
|
||||
cachedCipherDetails.emplace_back(
|
||||
itr->second.domainId, itr->second.baseCipherId, itr->second.baseCipherKey, keyIdsReply.arena);
|
||||
} else {
|
||||
lookupCipherIds.emplace_back(std::make_pair(item.first, item.second));
|
||||
}
|
||||
}
|
||||
|
||||
ekpProxyData->baseCipherKeyIdCacheHits += cachedCipherDetails.size();
|
||||
ekpProxyData->baseCipherKeyIdCacheMisses += lookupCipherIds.size();
|
||||
|
||||
if (g_network->isSimulated()) {
|
||||
if (!lookupCipherIds.empty()) {
|
||||
try {
|
||||
@ -181,16 +183,17 @@ ACTOR Future<Void> getCipherKeysByBaseCipherKeyIds(Reference<EncryptKeyProxyData
|
||||
SimGetEncryptKeysByKeyIdsReply simKeyIdsReply =
|
||||
wait(simKmsInterface.encryptKeyLookupByKeyIds.getReply(simKeyIdsReq));
|
||||
|
||||
for (const auto& item : simKeyIdsReply.encryptKeyMap) {
|
||||
keyIdsReply.baseCipherMap.emplace(item.first, StringRef(keyIdsReply.arena, item.second));
|
||||
for (const auto& item : simKeyIdsReply.encryptKeyDetails) {
|
||||
keyIdsReply.baseCipherDetails.emplace_back(
|
||||
item.encryptDomainId, item.encryptKeyId, item.encryptKey, keyIdsReply.arena);
|
||||
}
|
||||
|
||||
// Record the fetched cipher details to the local cache for the future references
|
||||
// Note: cache warm-up is done after reponding to the caller
|
||||
|
||||
for (auto& item : simKeyIdsReply.encryptKeyMap) {
|
||||
for (auto& item : simKeyIdsReply.encryptKeyDetails) {
|
||||
// DomainId isn't available here, the caller must know the encryption domainId
|
||||
ekpProxyData->insertIntoBaseCipherIdCache(0, item.first, item.second);
|
||||
ekpProxyData->insertIntoBaseCipherIdCache(item.encryptDomainId, item.encryptKeyId, item.encryptKey);
|
||||
}
|
||||
} catch (Error& e) {
|
||||
if (!canReplyWith(e)) {
|
||||
@ -207,11 +210,11 @@ ACTOR Future<Void> getCipherKeysByBaseCipherKeyIds(Reference<EncryptKeyProxyData
|
||||
throw not_implemented();
|
||||
}
|
||||
|
||||
for (auto& item : cachedKeys) {
|
||||
keyIdsReply.baseCipherMap.emplace(item.first, item.second);
|
||||
}
|
||||
// Append cached cipherKeyDetails to the result-set
|
||||
keyIdsReply.baseCipherDetails.insert(
|
||||
keyIdsReply.baseCipherDetails.end(), cachedCipherDetails.begin(), cachedCipherDetails.end());
|
||||
|
||||
keyIdsReply.numHits = cachedKeys.size();
|
||||
keyIdsReply.numHits = cachedCipherDetails.size();
|
||||
keysByIds.reply.send(keyIdsReply);
|
||||
|
||||
return Void();
|
||||
@ -223,7 +226,7 @@ ACTOR Future<Void> getLatestCipherKeys(Reference<EncryptKeyProxyData> ekpProxyDa
|
||||
// Scan the cached cipher-keys and filter our baseCipherIds locally cached
|
||||
// for the rest, reachout to KMS to fetch the required details
|
||||
|
||||
state std::unordered_map<EncryptBaseCipherId, EKPBaseCipherDetails> cachedKeys;
|
||||
state std::vector<EKPBaseCipherDetails> cachedCipherDetails;
|
||||
state EKPGetLatestBaseCipherKeysRequest latestKeysReq = req;
|
||||
state EKPGetLatestBaseCipherKeysReply latestCipherReply;
|
||||
state Arena& arena = latestCipherReply.arena;
|
||||
@ -231,17 +234,17 @@ ACTOR Future<Void> getLatestCipherKeys(Reference<EncryptKeyProxyData> ekpProxyDa
|
||||
// First, check if the requested information is already cached by the server.
|
||||
// Ensure the cached information is within FLOW_KNOBS->ENCRYPT_CIPHER_KEY_CACHE_TTL time window.
|
||||
|
||||
std::vector<EncryptBaseCipherId> lookupCipherDomains;
|
||||
std::vector<EncryptDomainId> lookupCipherDomains;
|
||||
for (EncryptDomainId id : req.encryptDomainIds) {
|
||||
const auto itr = ekpProxyData->baseCipherDomainIdCache.find(id);
|
||||
if (itr != ekpProxyData->baseCipherDomainIdCache.end() && itr->second.isValid()) {
|
||||
cachedKeys.emplace(id, EKPBaseCipherDetails(itr->second.baseCipherId, itr->second.baseCipherKey, arena));
|
||||
cachedCipherDetails.emplace_back(id, itr->second.baseCipherId, itr->second.baseCipherKey, arena);
|
||||
} else {
|
||||
lookupCipherDomains.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
ekpProxyData->baseCipherDomainIdCacheHits += cachedKeys.size();
|
||||
ekpProxyData->baseCipherDomainIdCacheHits += cachedCipherDetails.size();
|
||||
ekpProxyData->baseCipherDomainIdCacheMisses += lookupCipherDomains.size();
|
||||
|
||||
if (g_network->isSimulated()) {
|
||||
@ -251,13 +254,12 @@ ACTOR Future<Void> getLatestCipherKeys(Reference<EncryptKeyProxyData> ekpProxyDa
|
||||
SimGetEncryptKeyByDomainIdReply simKeysByDomainIdRep =
|
||||
wait(simKmsInterface.encryptKeyLookupByDomainId.getReply(simKeysByDomainIdReq));
|
||||
|
||||
for (auto& item : simKeysByDomainIdRep.encryptKeyMap) {
|
||||
latestCipherReply.baseCipherDetailMap.emplace(
|
||||
item.first, EKPBaseCipherDetails(item.second.encryptKeyId, item.second.encryptKey, arena));
|
||||
for (auto& item : simKeysByDomainIdRep.encryptKeyDetails) {
|
||||
latestCipherReply.baseCipherDetails.emplace_back(
|
||||
item.encryptDomainId, item.encryptKeyId, item.encryptKey, arena);
|
||||
|
||||
// Record the fetched cipher details to the local cache for the future references
|
||||
ekpProxyData->insertIntoBaseDomainIdCache(
|
||||
item.first, item.second.encryptKeyId, item.second.encryptKey);
|
||||
ekpProxyData->insertIntoBaseDomainIdCache(item.encryptDomainId, item.encryptKeyId, item.encryptKey);
|
||||
}
|
||||
} catch (Error& e) {
|
||||
if (!canReplyWith(e)) {
|
||||
@ -274,12 +276,12 @@ ACTOR Future<Void> getLatestCipherKeys(Reference<EncryptKeyProxyData> ekpProxyDa
|
||||
throw not_implemented();
|
||||
}
|
||||
|
||||
for (auto& item : cachedKeys) {
|
||||
latestCipherReply.baseCipherDetailMap.emplace(
|
||||
item.first, EKPBaseCipherDetails(item.second.baseCipherId, item.second.baseCipherKey, arena));
|
||||
for (auto& item : cachedCipherDetails) {
|
||||
latestCipherReply.baseCipherDetails.emplace_back(
|
||||
item.encryptDomainId, item.baseCipherId, item.baseCipherKey, arena);
|
||||
}
|
||||
|
||||
latestCipherReply.numHits = cachedKeys.size();
|
||||
latestCipherReply.numHits = cachedCipherDetails.size();
|
||||
latestKeysReq.reply.send(latestCipherReply);
|
||||
|
||||
return Void();
|
||||
@ -300,12 +302,12 @@ ACTOR Future<Void> refreshEncryptionKeysUsingSimKms(Reference<EncryptKeyProxyDat
|
||||
req.encryptDomainIds.emplace_back(item.first);
|
||||
}
|
||||
SimGetEncryptKeyByDomainIdReply rep = wait(simKmsInterface.encryptKeyLookupByDomainId.getReply(req));
|
||||
for (auto& item : rep.encryptKeyMap) {
|
||||
ekpProxyData->insertIntoBaseDomainIdCache(item.first, item.second.encryptKeyId, item.second.encryptKey);
|
||||
for (auto& item : rep.encryptKeyDetails) {
|
||||
ekpProxyData->insertIntoBaseDomainIdCache(item.encryptDomainId, item.encryptKeyId, item.encryptKey);
|
||||
}
|
||||
|
||||
ekpProxyData->baseCipherKeysRefreshed += rep.encryptKeyMap.size();
|
||||
TraceEvent("RefreshEKs_Done", ekpProxyData->myId).detail("KeyCount", rep.encryptKeyMap.size());
|
||||
ekpProxyData->baseCipherKeysRefreshed += rep.encryptKeyDetails.size();
|
||||
TraceEvent("RefreshEKs_Done", ekpProxyData->myId).detail("KeyCount", rep.encryptKeyDetails.size());
|
||||
} catch (Error& e) {
|
||||
if (!canReplyWith(e)) {
|
||||
TraceEvent("RefreshEncryptionKeys_Error").error(e);
|
||||
|
@ -90,10 +90,26 @@ struct HaltEncryptKeyProxyRequest {
|
||||
}
|
||||
};
|
||||
|
||||
struct EKPBaseCipherDetails {
|
||||
constexpr static FileIdentifier file_identifier = 2149615;
|
||||
int64_t encryptDomainId;
|
||||
uint64_t baseCipherId;
|
||||
StringRef baseCipherKey;
|
||||
|
||||
EKPBaseCipherDetails() : encryptDomainId(0), baseCipherId(0), baseCipherKey(StringRef()) {}
|
||||
explicit EKPBaseCipherDetails(int64_t dId, uint64_t id, StringRef key, Arena& arena)
|
||||
: encryptDomainId(dId), baseCipherId(id), baseCipherKey(StringRef(arena, key)) {}
|
||||
|
||||
template <class Ar>
|
||||
void serialize(Ar& ar) {
|
||||
serializer(ar, encryptDomainId, baseCipherId, baseCipherKey);
|
||||
}
|
||||
};
|
||||
|
||||
struct EKPGetBaseCipherKeysByIdsReply {
|
||||
constexpr static FileIdentifier file_identifier = 9485259;
|
||||
Arena arena;
|
||||
std::unordered_map<uint64_t, StringRef> baseCipherMap;
|
||||
std::vector<EKPBaseCipherDetails> baseCipherDetails;
|
||||
int numHits;
|
||||
Optional<Error> error;
|
||||
|
||||
@ -101,18 +117,18 @@ struct EKPGetBaseCipherKeysByIdsReply {
|
||||
|
||||
template <class Ar>
|
||||
void serialize(Ar& ar) {
|
||||
serializer(ar, arena, baseCipherMap, numHits, error);
|
||||
serializer(ar, arena, baseCipherDetails, numHits, error);
|
||||
}
|
||||
};
|
||||
|
||||
struct EKPGetBaseCipherKeysByIdsRequest {
|
||||
constexpr static FileIdentifier file_identifier = 4930263;
|
||||
UID requesterID;
|
||||
std::vector<uint64_t> baseCipherIds;
|
||||
std::vector<std::pair<uint64_t, int64_t>> baseCipherIds;
|
||||
ReplyPromise<EKPGetBaseCipherKeysByIdsReply> reply;
|
||||
|
||||
EKPGetBaseCipherKeysByIdsRequest() : requesterID(deterministicRandom()->randomUniqueID()) {}
|
||||
explicit EKPGetBaseCipherKeysByIdsRequest(UID uid, const std::vector<uint64_t>& ids)
|
||||
explicit EKPGetBaseCipherKeysByIdsRequest(UID uid, const std::vector<std::pair<uint64_t, int64_t>>& ids)
|
||||
: requesterID(uid), baseCipherIds(ids) {}
|
||||
|
||||
template <class Ar>
|
||||
@ -121,35 +137,20 @@ struct EKPGetBaseCipherKeysByIdsRequest {
|
||||
}
|
||||
};
|
||||
|
||||
struct EKPBaseCipherDetails {
|
||||
constexpr static FileIdentifier file_identifier = 2149615;
|
||||
uint64_t baseCipherId;
|
||||
StringRef baseCipherKey;
|
||||
|
||||
EKPBaseCipherDetails() : baseCipherId(0), baseCipherKey(StringRef()) {}
|
||||
explicit EKPBaseCipherDetails(uint64_t id, StringRef key, Arena& arena)
|
||||
: baseCipherId(id), baseCipherKey(StringRef(arena, key)) {}
|
||||
|
||||
template <class Ar>
|
||||
void serialize(Ar& ar) {
|
||||
serializer(ar, baseCipherId, baseCipherKey);
|
||||
}
|
||||
};
|
||||
|
||||
struct EKPGetLatestBaseCipherKeysReply {
|
||||
constexpr static FileIdentifier file_identifier = 4831583;
|
||||
Arena arena;
|
||||
std::unordered_map<uint64_t, EKPBaseCipherDetails> baseCipherDetailMap;
|
||||
std::vector<EKPBaseCipherDetails> baseCipherDetails;
|
||||
int numHits;
|
||||
Optional<Error> error;
|
||||
|
||||
EKPGetLatestBaseCipherKeysReply() : numHits(0) {}
|
||||
explicit EKPGetLatestBaseCipherKeysReply(const std::unordered_map<uint64_t, EKPBaseCipherDetails>& cipherMap)
|
||||
: baseCipherDetailMap(cipherMap), numHits(0) {}
|
||||
explicit EKPGetLatestBaseCipherKeysReply(const std::vector<EKPBaseCipherDetails>& cipherDetails)
|
||||
: baseCipherDetails(cipherDetails), numHits(0) {}
|
||||
|
||||
template <class Ar>
|
||||
void serialize(Ar& ar) {
|
||||
serializer(ar, arena, baseCipherDetailMap, numHits, error);
|
||||
serializer(ar, arena, baseCipherDetails, numHits, error);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include "fdbrpc/sim_validation.h"
|
||||
#include "fdbserver/Knobs.h"
|
||||
@ -29,6 +30,7 @@
|
||||
#include "flow/IRandom.h"
|
||||
#include "flow/ITrace.h"
|
||||
#include "flow/StreamCipher.h"
|
||||
#include "flow/Trace.h"
|
||||
#include "flow/UnitTest.h"
|
||||
#include "flow/actorcompiler.h" // This must be the last #include.
|
||||
#include "flow/network.h"
|
||||
@ -73,11 +75,14 @@ ACTOR Future<Void> simEncryptKmsProxyCore(SimKmsProxyInterface interf) {
|
||||
state SimGetEncryptKeysByKeyIdsReply keysByIdsRep;
|
||||
|
||||
// Lookup corresponding EncryptKeyCtx for input keyId
|
||||
for (SimEncryptKeyId keyId : req.encryptKeyIds) {
|
||||
const auto& itr = kmsProxyCtx.simEncryptKeyStore.find(keyId);
|
||||
for (const auto& item : req.encryptKeyIds) {
|
||||
const auto& itr = kmsProxyCtx.simEncryptKeyStore.find(item.first);
|
||||
if (itr != kmsProxyCtx.simEncryptKeyStore.end()) {
|
||||
keysByIdsRep.encryptKeyMap.emplace(keyId,
|
||||
StringRef(keysByIdsRep.arena, itr->second.get()->key));
|
||||
keysByIdsRep.encryptKeyDetails.emplace_back(
|
||||
item.second,
|
||||
itr->first,
|
||||
StringRef(keysByIdsRep.arena, itr->second.get()->key),
|
||||
keysByIdsRep.arena);
|
||||
} else {
|
||||
success = false;
|
||||
break;
|
||||
@ -99,9 +104,8 @@ ACTOR Future<Void> simEncryptKmsProxyCore(SimKmsProxyInterface interf) {
|
||||
SimEncryptKeyId keyId = domainId % SERVER_KNOBS->SIM_KMS_MAX_KEYS;
|
||||
const auto& itr = kmsProxyCtx.simEncryptKeyStore.find(keyId);
|
||||
if (itr != kmsProxyCtx.simEncryptKeyStore.end()) {
|
||||
keysByDomainIdRep.encryptKeyMap.emplace(
|
||||
domainId,
|
||||
SimEncryptKeyDetails(keyId, StringRef(itr->second.get()->key), keysByDomainIdRep.arena));
|
||||
keysByDomainIdRep.encryptKeyDetails.emplace_back(
|
||||
domainId, keyId, StringRef(itr->second.get()->key), keysByDomainIdRep.arena);
|
||||
} else {
|
||||
success = false;
|
||||
break;
|
||||
@ -137,32 +141,41 @@ ACTOR Future<Void> testRunWorkload(SimKmsProxyInterface inf, uint32_t nEncryptio
|
||||
domainIdsReq.encryptDomainIds.push_back(i);
|
||||
}
|
||||
SimGetEncryptKeyByDomainIdReply domainIdsReply = wait(inf.encryptKeyLookupByDomainId.getReply(domainIdsReq));
|
||||
for (auto& element : domainIdsReply.encryptKeyMap) {
|
||||
domainIdKeyMap.emplace(element.first,
|
||||
std::make_unique<SimEncryptKeyCtx>(element.second.encryptKeyId,
|
||||
element.second.encryptKey.toString().c_str()));
|
||||
for (auto& element : domainIdsReply.encryptKeyDetails) {
|
||||
domainIdKeyMap.emplace(
|
||||
element.encryptDomainId,
|
||||
std::make_unique<SimEncryptKeyCtx>(element.encryptKeyId, element.encryptKey.toString().c_str()));
|
||||
}
|
||||
|
||||
// randomly pick any domainId and validate if lookupByKeyId result matches
|
||||
SimGetEncryptKeysByKeyIdsRequest keyIdsReq;
|
||||
state std::unordered_map<SimEncryptKeyId, StringRef> validationMap;
|
||||
std::unordered_map<SimEncryptKeyId, SimEncryptDomainId> idsToLookup;
|
||||
for (i = 0; i < maxIterations; i++) {
|
||||
state int idx = deterministicRandom()->randomInt(0, maxDomainIds);
|
||||
state SimEncryptKeyCtx* ctx = domainIdKeyMap[idx].get();
|
||||
keyIdsReq.encryptKeyIds.push_back(ctx->id);
|
||||
validationMap[ctx->id] = StringRef(ctx->key);
|
||||
idsToLookup.emplace(ctx->id, idx);
|
||||
}
|
||||
SimGetEncryptKeysByKeyIdsReply keyIdsReply = wait(inf.encryptKeyLookupByKeyIds.getReply(keyIdsReq));
|
||||
ASSERT(keyIdsReply.encryptKeyMap.size() == validationMap.size());
|
||||
for (const auto& element : keyIdsReply.encryptKeyMap) {
|
||||
ASSERT(validationMap[element.first].compare(element.second) == 0);
|
||||
|
||||
state SimGetEncryptKeysByKeyIdsRequest keyIdsReq;
|
||||
for (const auto& item : idsToLookup) {
|
||||
keyIdsReq.encryptKeyIds.emplace_back(std::make_pair(item.first, item.second));
|
||||
}
|
||||
state SimGetEncryptKeysByKeyIdsReply keyIdsReply = wait(inf.encryptKeyLookupByKeyIds.getReply(keyIdsReq));
|
||||
/* TraceEvent("Lookup")
|
||||
.detail("KeyIdReqSize", keyIdsReq.encryptKeyIds.size())
|
||||
.detail("KeyIdsRepSz", keyIdsReply.encryptKeyDetails.size())
|
||||
.detail("ValSz", validationMap.size()); */
|
||||
ASSERT(keyIdsReply.encryptKeyDetails.size() == validationMap.size());
|
||||
for (const auto& element : keyIdsReply.encryptKeyDetails) {
|
||||
ASSERT(validationMap[element.encryptDomainId].compare(element.encryptKey) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Verify unknown key access returns the error
|
||||
state SimGetEncryptKeysByKeyIdsRequest req;
|
||||
req.encryptKeyIds.push_back(maxEncryptionKeys + 1);
|
||||
req.encryptKeyIds.emplace_back(std::make_pair(maxEncryptionKeys + 1, 1));
|
||||
try {
|
||||
SimGetEncryptKeysByKeyIdsReply reply = wait(inf.encryptKeyLookupByKeyIds.getReply(req));
|
||||
} catch (Error& e) {
|
||||
|
@ -71,26 +71,43 @@ struct SimKmsProxyInterface {
|
||||
}
|
||||
};
|
||||
|
||||
struct SimEncryptKeyDetails {
|
||||
constexpr static FileIdentifier file_identifier = 1227025;
|
||||
SimEncryptDomainId encryptDomainId;
|
||||
SimEncryptKeyId encryptKeyId;
|
||||
StringRef encryptKey;
|
||||
|
||||
SimEncryptKeyDetails() {}
|
||||
explicit SimEncryptKeyDetails(SimEncryptDomainId domainId, SimEncryptKeyId keyId, StringRef key, Arena& arena)
|
||||
: encryptDomainId(domainId), encryptKeyId(keyId), encryptKey(StringRef(arena, key)) {}
|
||||
|
||||
template <class Ar>
|
||||
void serialize(Ar& ar) {
|
||||
serializer(ar, encryptDomainId, encryptKeyId, encryptKey);
|
||||
}
|
||||
};
|
||||
|
||||
struct SimGetEncryptKeysByKeyIdsReply {
|
||||
constexpr static FileIdentifier file_identifier = 2313778;
|
||||
Arena arena;
|
||||
std::unordered_map<SimEncryptKeyId, StringRef> encryptKeyMap;
|
||||
std::vector<SimEncryptKeyDetails> encryptKeyDetails;
|
||||
|
||||
SimGetEncryptKeysByKeyIdsReply() {}
|
||||
|
||||
template <class Ar>
|
||||
void serialize(Ar& ar) {
|
||||
serializer(ar, arena, encryptKeyMap);
|
||||
serializer(ar, arena, encryptKeyDetails);
|
||||
}
|
||||
};
|
||||
|
||||
struct SimGetEncryptKeysByKeyIdsRequest {
|
||||
constexpr static FileIdentifier file_identifier = 6913396;
|
||||
std::vector<SimEncryptKeyId> encryptKeyIds;
|
||||
std::vector<std::pair<SimEncryptKeyId, SimEncryptDomainId>> encryptKeyIds;
|
||||
ReplyPromise<SimGetEncryptKeysByKeyIdsReply> reply;
|
||||
|
||||
SimGetEncryptKeysByKeyIdsRequest() {}
|
||||
explicit SimGetEncryptKeysByKeyIdsRequest(const std::vector<SimEncryptKeyId>& keyIds) : encryptKeyIds(keyIds) {}
|
||||
explicit SimGetEncryptKeysByKeyIdsRequest(const std::vector<std::pair<SimEncryptKeyId, SimEncryptDomainId>>& keyIds)
|
||||
: encryptKeyIds(keyIds) {}
|
||||
|
||||
template <class Ar>
|
||||
void serialize(Ar& ar) {
|
||||
@ -98,31 +115,16 @@ struct SimGetEncryptKeysByKeyIdsRequest {
|
||||
}
|
||||
};
|
||||
|
||||
struct SimEncryptKeyDetails {
|
||||
constexpr static FileIdentifier file_identifier = 1227025;
|
||||
SimEncryptKeyId encryptKeyId;
|
||||
StringRef encryptKey;
|
||||
|
||||
SimEncryptKeyDetails() {}
|
||||
explicit SimEncryptKeyDetails(SimEncryptKeyId keyId, StringRef key, Arena& arena)
|
||||
: encryptKeyId(keyId), encryptKey(StringRef(arena, key)) {}
|
||||
|
||||
template <class Ar>
|
||||
void serialize(Ar& ar) {
|
||||
serializer(ar, encryptKeyId, encryptKey);
|
||||
}
|
||||
};
|
||||
|
||||
struct SimGetEncryptKeyByDomainIdReply {
|
||||
constexpr static FileIdentifier file_identifier = 3009025;
|
||||
Arena arena;
|
||||
std::unordered_map<SimEncryptDomainId, SimEncryptKeyDetails> encryptKeyMap;
|
||||
std::vector<SimEncryptKeyDetails> encryptKeyDetails;
|
||||
|
||||
SimGetEncryptKeyByDomainIdReply() {}
|
||||
|
||||
template <class Ar>
|
||||
void serialize(Ar& ar) {
|
||||
serializer(ar, arena, encryptKeyMap);
|
||||
serializer(ar, arena, encryptKeyDetails);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <boost/range/const_iterator.hpp>
|
||||
#include <utility>
|
||||
|
||||
#include "flow/actorcompiler.h" // This must be the last #include.
|
||||
|
||||
@ -76,10 +77,17 @@ struct EncryptKeyProxyTestWorkload : TestWorkload {
|
||||
if (rep.present()) {
|
||||
|
||||
ASSERT(!rep.get().error.present());
|
||||
ASSERT_EQ(rep.get().baseCipherDetailMap.size(), self->domainIds.size());
|
||||
ASSERT_EQ(rep.get().baseCipherDetails.size(), self->domainIds.size());
|
||||
|
||||
for (const uint64_t id : self->domainIds) {
|
||||
ASSERT(rep.get().baseCipherDetailMap.find(id) != rep.get().baseCipherDetailMap.end());
|
||||
bool found = false;
|
||||
for (const auto& item : rep.get().baseCipherDetails) {
|
||||
if (item.baseCipherId == id) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(found);
|
||||
}
|
||||
|
||||
// Ensure no hits reported by the cache.
|
||||
@ -127,10 +135,17 @@ struct EncryptKeyProxyTestWorkload : TestWorkload {
|
||||
ErrorOr<EKPGetLatestBaseCipherKeysReply> rep = wait(self->ekpInf.getLatestBaseCipherKeys.tryGetReply(req));
|
||||
if (rep.present()) {
|
||||
ASSERT(!rep.get().error.present());
|
||||
ASSERT_EQ(rep.get().baseCipherDetailMap.size(), self->domainIds.size());
|
||||
ASSERT_EQ(rep.get().baseCipherDetails.size(), self->domainIds.size());
|
||||
|
||||
for (const uint64_t id : self->domainIds) {
|
||||
ASSERT(rep.get().baseCipherDetailMap.find(id) != rep.get().baseCipherDetailMap.end());
|
||||
bool found = false;
|
||||
for (const auto& item : rep.get().baseCipherDetails) {
|
||||
if (item.baseCipherId == id) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(found);
|
||||
}
|
||||
|
||||
// Ensure desired cache-hit counts
|
||||
@ -165,16 +180,23 @@ struct EncryptKeyProxyTestWorkload : TestWorkload {
|
||||
EKPGetLatestBaseCipherKeysReply rep = wait(self->ekpInf.getLatestBaseCipherKeys.getReply(req));
|
||||
|
||||
ASSERT(!rep.error.present());
|
||||
ASSERT_EQ(rep.baseCipherDetailMap.size(), self->domainIds.size());
|
||||
ASSERT_EQ(rep.baseCipherDetails.size(), self->domainIds.size());
|
||||
for (const uint64_t id : self->domainIds) {
|
||||
ASSERT(rep.baseCipherDetailMap.find(id) != rep.baseCipherDetailMap.end());
|
||||
bool found = false;
|
||||
for (const auto& item : rep.baseCipherDetails) {
|
||||
if (item.baseCipherId == id) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(found);
|
||||
}
|
||||
|
||||
self->cipherIdMap.clear();
|
||||
self->cipherIds.clear();
|
||||
for (auto& item : rep.baseCipherDetailMap) {
|
||||
self->cipherIdMap.emplace(item.second.baseCipherId, StringRef(self->arena, item.second.baseCipherKey));
|
||||
self->cipherIds.emplace_back(item.second.baseCipherId);
|
||||
for (auto& item : rep.baseCipherDetails) {
|
||||
self->cipherIdMap.emplace(item.baseCipherId, StringRef(self->arena, item.baseCipherKey));
|
||||
self->cipherIds.emplace_back(item.baseCipherId);
|
||||
}
|
||||
|
||||
state int numIterations = deterministicRandom()->randomInt(512, 786);
|
||||
@ -184,28 +206,28 @@ struct EncryptKeyProxyTestWorkload : TestWorkload {
|
||||
|
||||
EKPGetBaseCipherKeysByIdsRequest req;
|
||||
for (int i = idx; i < nIds && i < self->cipherIds.size(); i++) {
|
||||
req.baseCipherIds.emplace_back(self->cipherIds[i]);
|
||||
req.baseCipherIds.emplace_back(std::make_pair(self->cipherIds[i], 1));
|
||||
}
|
||||
expectedHits = req.baseCipherIds.size();
|
||||
EKPGetBaseCipherKeysByIdsReply rep = wait(self->ekpInf.getBaseCipherKeysByIds.getReply(req));
|
||||
|
||||
ASSERT(!rep.error.present());
|
||||
ASSERT_EQ(rep.baseCipherMap.size(), expectedHits);
|
||||
ASSERT_EQ(rep.baseCipherDetails.size(), expectedHits);
|
||||
ASSERT_EQ(rep.numHits, expectedHits);
|
||||
// Valdiate the 'cipherKey' content against the one read while querying by domainIds
|
||||
for (auto& item : rep.baseCipherMap) {
|
||||
const auto itr = self->cipherIdMap.find(item.first);
|
||||
for (auto& item : rep.baseCipherDetails) {
|
||||
const auto itr = self->cipherIdMap.find(item.baseCipherId);
|
||||
ASSERT(itr != self->cipherIdMap.end());
|
||||
Standalone<StringRef> toCompare = self->cipherIdMap[item.first];
|
||||
if (toCompare.compare(item.second) != 0) {
|
||||
Standalone<StringRef> toCompare = self->cipherIdMap[item.baseCipherId];
|
||||
if (toCompare.compare(item.baseCipherKey) != 0) {
|
||||
TraceEvent("Mismatch")
|
||||
.detail("Id", item.first)
|
||||
.detail("Id", item.baseCipherId)
|
||||
.detail("CipherMapDataHash", XXH3_64bits(toCompare.begin(), toCompare.size()))
|
||||
.detail("CipherMapSize", toCompare.size())
|
||||
.detail("CipherMapValue", toCompare.toString())
|
||||
.detail("ReadDataHash", XXH3_64bits(item.second.begin(), item.second.size()))
|
||||
.detail("ReadValue", item.second.toString())
|
||||
.detail("ReadDataSize", item.second.size());
|
||||
.detail("ReadDataHash", XXH3_64bits(item.baseCipherKey.begin(), item.baseCipherKey.size()))
|
||||
.detail("ReadValue", item.baseCipherKey.toString())
|
||||
.detail("ReadDataSize", item.baseCipherKey.size());
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
@ -219,12 +241,15 @@ struct EncryptKeyProxyTestWorkload : TestWorkload {
|
||||
TraceEvent("SimLookupInvalidKeyId_Start").log();
|
||||
|
||||
// Prepare a lookup with valid and invalid keyIds - SimEncryptKmsProxy should throw encrypt_key_not_found()
|
||||
std::vector<uint64_t> baseCipherIds(self->cipherIds);
|
||||
baseCipherIds.emplace_back(SERVER_KNOBS->SIM_KMS_MAX_KEYS + 10);
|
||||
std::vector<std::pair<uint64_t, int64_t>> baseCipherIds;
|
||||
for (auto id : self->cipherIds) {
|
||||
baseCipherIds.emplace_back(std::make_pair(id, 1));
|
||||
}
|
||||
baseCipherIds.emplace_back(std::make_pair(SERVER_KNOBS->SIM_KMS_MAX_KEYS + 10, 1));
|
||||
EKPGetBaseCipherKeysByIdsRequest req(deterministicRandom()->randomUniqueID(), baseCipherIds);
|
||||
EKPGetBaseCipherKeysByIdsReply rep = wait(self->ekpInf.getBaseCipherKeysByIds.getReply(req));
|
||||
|
||||
ASSERT_EQ(rep.baseCipherMap.size(), 0);
|
||||
ASSERT_EQ(rep.baseCipherDetails.size(), 0);
|
||||
ASSERT(rep.error.present());
|
||||
ASSERT_EQ(rep.error.get().code(), error_code_encrypt_key_not_found);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user