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:
Ata E Husain Bohra 2022-04-21 14:56:09 -07:00 committed by GitHub
parent 98b82f1ac3
commit 5b5b45c7cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 167 additions and 124 deletions

View File

@ -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);

View File

@ -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);
}
};

View File

@ -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) {

View File

@ -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);
}
};

View File

@ -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);