[EaR]: Update KMS APIs to split encryption keys endpoints (#9017)
* [EaR]: Update KMS APIs to split encryption keys endpoints Description diff-1: Address review comments Major changes proposed: 1. Extend fdbserver to allow parsing two endpoints for encryption at-rest support: getEncrypitonKeys, getLatestEncryptionKeys 2. Update RESTKmsConnector to do the following: 2.1. Split the getLatest and getCipher requests. 2.2. "domain_id" for point lookup marked as 'optional' Testing devRunCorrectness - 100K
This commit is contained in:
parent
d4cbe20d5f
commit
f673fce975
|
@ -1062,6 +1062,7 @@ void ServerKnobs::initialize(Randomize randomize, ClientKnobs* clientKnobs, IsSi
|
|||
// NOTE: Care must be taken when attempting to update below configurations for a up/running FDB cluster.
|
||||
init( REST_KMS_CONNECTOR_DISCOVER_KMS_URL_FILE, "");
|
||||
init( REST_KMS_CONNECTOR_GET_ENCRYPTION_KEYS_ENDPOINT, "");
|
||||
init( REST_KMS_CONNECTOR_GET_LATEST_ENCRYPTION_KEYS_ENDPOINT, "");
|
||||
init( REST_KMS_CONNECTOR_GET_BLOB_METADATA_ENDPOINT, "");
|
||||
// Details to fetch validation token from a localhost file
|
||||
// acceptable format: "<token_name1>#<absolute_file_path1>,<token_name2>#<absolute_file_path2>,.."
|
||||
|
|
|
@ -1024,6 +1024,7 @@ public:
|
|||
bool REST_KMS_CONNECTOR_REFRESH_KMS_URLS;
|
||||
double REST_KMS_CONNECTOR_REFRESH_KMS_URLS_INTERVAL_SEC;
|
||||
std::string REST_KMS_CONNECTOR_GET_ENCRYPTION_KEYS_ENDPOINT;
|
||||
std::string REST_KMS_CONNECTOR_GET_LATEST_ENCRYPTION_KEYS_ENDPOINT;
|
||||
std::string REST_KMS_CONNECTOR_GET_BLOB_METADATA_ENDPOINT;
|
||||
|
||||
// Idempotency ids
|
||||
|
|
|
@ -77,9 +77,6 @@ const char* TOKEN_NAME_FILE_SEP = "#";
|
|||
const char* TOKEN_TUPLE_SEP = ",";
|
||||
const char DISCOVER_URL_FILE_URL_SEP = '\n';
|
||||
|
||||
const char* QUERY_MODE_LOOKUP_BY_DOMAIN_ID = "lookupByDomainId";
|
||||
const char* QUERY_MODE_LOOKUP_BY_KEY_ID = "lookupByKeyId";
|
||||
|
||||
const char* BLOB_METADATA_DETAILS_TAG = "blob_metadata_details";
|
||||
const char* BLOB_METADATA_DOMAIN_ID_TAG = "domain_id";
|
||||
const char* BLOB_METADATA_BASE_LOCATION_TAG = "base_location";
|
||||
|
@ -615,7 +612,7 @@ StringRef getEncryptKeysByKeyIdsRequestBody(Reference<RESTKmsConnectorCtx> ctx,
|
|||
// "cipher_key_details" = [
|
||||
// {
|
||||
// "base_cipher_id" : <cipherKeyId>
|
||||
// "encrypt_domain_id" : <domainId>
|
||||
// "encrypt_domain_id" : <domainId> // Optional
|
||||
// },
|
||||
// {
|
||||
// ....
|
||||
|
@ -637,9 +634,6 @@ StringRef getEncryptKeysByKeyIdsRequestBody(Reference<RESTKmsConnectorCtx> ctx,
|
|||
rapidjson::Document doc;
|
||||
doc.SetObject();
|
||||
|
||||
// Append 'query_mode' object
|
||||
addQueryModeSection(ctx, doc, QUERY_MODE_LOOKUP_BY_KEY_ID);
|
||||
|
||||
// Append 'cipher_key_details' as json array
|
||||
rapidjson::Value keyIdDetails(rapidjson::kArrayType);
|
||||
for (const auto& detail : req.encryptKeyInfos) {
|
||||
|
@ -651,11 +645,13 @@ StringRef getEncryptKeysByKeyIdsRequestBody(Reference<RESTKmsConnectorCtx> ctx,
|
|||
baseKeyId.SetUint64(detail.baseCipherId);
|
||||
keyIdDetail.AddMember(key, baseKeyId, doc.GetAllocator());
|
||||
|
||||
// Add 'encrypt_domain_id'
|
||||
key.SetString(ENCRYPT_DOMAIN_ID_TAG, doc.GetAllocator());
|
||||
rapidjson::Value domainId;
|
||||
domainId.SetInt64(detail.domainId);
|
||||
keyIdDetail.AddMember(key, domainId, doc.GetAllocator());
|
||||
if (detail.domainId.present()) {
|
||||
// Add 'encrypt_domain_id'
|
||||
key.SetString(ENCRYPT_DOMAIN_ID_TAG, doc.GetAllocator());
|
||||
rapidjson::Value domainId;
|
||||
domainId.SetInt64(detail.domainId.get());
|
||||
keyIdDetail.AddMember(key, domainId, doc.GetAllocator());
|
||||
}
|
||||
|
||||
// push above object to the array
|
||||
keyIdDetails.PushBack(keyIdDetail, doc.GetAllocator());
|
||||
|
@ -812,9 +808,6 @@ StringRef getEncryptKeysByDomainIdsRequestBody(Reference<RESTKmsConnectorCtx> ct
|
|||
rapidjson::Document doc;
|
||||
doc.SetObject();
|
||||
|
||||
// Append 'query_mode' object
|
||||
addQueryModeSection(ctx, doc, QUERY_MODE_LOOKUP_BY_DOMAIN_ID);
|
||||
|
||||
// Append 'cipher_key_details' as json array
|
||||
addLatestDomainDetailsToDoc(doc, CIPHER_KEY_DETAILS_TAG, ENCRYPT_DOMAIN_ID_TAG, req.encryptDomainIds);
|
||||
|
||||
|
@ -849,7 +842,7 @@ ACTOR Future<Void> fetchEncryptionKeysByDomainIds(Reference<RESTKmsConnectorCtx>
|
|||
f = &parseEncryptCipherResponse;
|
||||
|
||||
Standalone<VectorRef<EncryptCipherKeyDetailsRef>> result = wait(kmsRequestImpl(
|
||||
ctx, SERVER_KNOBS->REST_KMS_CONNECTOR_GET_ENCRYPTION_KEYS_ENDPOINT, requestBodyRef, std::move(f)));
|
||||
ctx, SERVER_KNOBS->REST_KMS_CONNECTOR_GET_LATEST_ENCRYPTION_KEYS_ENDPOINT, requestBodyRef, std::move(f)));
|
||||
reply.cipherKeyDetails = result;
|
||||
reply.arena.dependsOn(result.arena());
|
||||
req.reply.send(reply);
|
||||
|
|
|
@ -123,13 +123,15 @@ ACTOR Future<Void> ekLookupByIds(Reference<SimKmsConnectorContext> ctx,
|
|||
for (const auto& item : req.encryptKeyInfos) {
|
||||
const auto& itr = ctx->simEncryptKeyStore.find(item.baseCipherId);
|
||||
if (itr != ctx->simEncryptKeyStore.end()) {
|
||||
// TODO: Relax assert if EKP APIs are updated to make 'domain_id' optional for encryption keys point lookups
|
||||
ASSERT(item.domainId.present());
|
||||
rep.cipherKeyDetails.emplace_back_deep(
|
||||
rep.arena, item.domainId, itr->first, StringRef(itr->second.get()->key), refAtTS, expAtTS);
|
||||
rep.arena, item.domainId.get(), itr->first, StringRef(itr->second.get()->key), refAtTS, expAtTS);
|
||||
|
||||
if (dbgKIdTrace.present()) {
|
||||
// {encryptDomainId, baseCipherId} forms a unique tuple across encryption domains
|
||||
dbgKIdTrace.get().detail(
|
||||
getEncryptDbgTraceKey(ENCRYPT_DBG_TRACE_RESULT_PREFIX, item.domainId, itr->first), "");
|
||||
getEncryptDbgTraceKey(ENCRYPT_DBG_TRACE_RESULT_PREFIX, item.domainId.get(), itr->first), "");
|
||||
}
|
||||
} else {
|
||||
success = false;
|
||||
|
|
|
@ -117,7 +117,7 @@ enum {
|
|||
OPT_METRICSPREFIX, OPT_LOGGROUP, OPT_LOCALITY, OPT_IO_TRUST_SECONDS, OPT_IO_TRUST_WARN_ONLY, OPT_FILESYSTEM, OPT_PROFILER_RSS_SIZE, OPT_KVFILE,
|
||||
OPT_TRACE_FORMAT, OPT_WHITELIST_BINPATH, OPT_BLOB_CREDENTIAL_FILE, OPT_CONFIG_PATH, OPT_USE_TEST_CONFIG_DB, OPT_NO_CONFIG_DB, OPT_FAULT_INJECTION, OPT_PROFILER, OPT_PRINT_SIMTIME,
|
||||
OPT_FLOW_PROCESS_NAME, OPT_FLOW_PROCESS_ENDPOINT, OPT_IP_TRUSTED_MASK, OPT_KMS_CONN_DISCOVERY_URL_FILE, OPT_KMS_CONNECTOR_TYPE, OPT_KMS_CONN_VALIDATION_TOKEN_DETAILS,
|
||||
OPT_KMS_CONN_GET_ENCRYPTION_KEYS_ENDPOINT, OPT_KMS_CONN_GET_BLOB_METADATA_ENDPOINT, OPT_NEW_CLUSTER_KEY, OPT_AUTHZ_PUBLIC_KEY_FILE, OPT_USE_FUTURE_PROTOCOL_VERSION
|
||||
OPT_KMS_CONN_GET_ENCRYPTION_KEYS_ENDPOINT, OPT_KMS_CONN_GET_LATEST_ENCRYPTION_KEYS_ENDPOINT, OPT_KMS_CONN_GET_BLOB_METADATA_ENDPOINT, OPT_NEW_CLUSTER_KEY, OPT_AUTHZ_PUBLIC_KEY_FILE, OPT_USE_FUTURE_PROTOCOL_VERSION
|
||||
};
|
||||
|
||||
CSimpleOpt::SOption g_rgOptions[] = {
|
||||
|
@ -218,6 +218,7 @@ CSimpleOpt::SOption g_rgOptions[] = {
|
|||
{ OPT_KMS_CONNECTOR_TYPE, "--kms-connector-type", SO_REQ_SEP },
|
||||
{ OPT_KMS_CONN_VALIDATION_TOKEN_DETAILS, "--kms-conn-validation-token-details", SO_REQ_SEP },
|
||||
{ OPT_KMS_CONN_GET_ENCRYPTION_KEYS_ENDPOINT, "--kms-conn-get-encryption-keys-endpoint", SO_REQ_SEP },
|
||||
{ OPT_KMS_CONN_GET_LATEST_ENCRYPTION_KEYS_ENDPOINT, "--kms-conn-get-latest-encryption-keys-endpoint", SO_REQ_SEP },
|
||||
{ OPT_KMS_CONN_GET_BLOB_METADATA_ENDPOINT, "--kms-conn-get-blob-metadata-endpoint", SO_REQ_SEP },
|
||||
{ OPT_USE_FUTURE_PROTOCOL_VERSION, "--use-future-protocol-version", SO_REQ_SEP },
|
||||
TLS_OPTION_FLAGS,
|
||||
|
@ -1708,6 +1709,10 @@ private:
|
|||
knobs.emplace_back("rest_kms_connector_get_encryption_keys_endpoint", args.OptionArg());
|
||||
break;
|
||||
}
|
||||
case OPT_KMS_CONN_GET_LATEST_ENCRYPTION_KEYS_ENDPOINT: {
|
||||
knobs.emplace_back("rest_kms_connector_get_latest_encryption_keys_endpoint", args.OptionArg());
|
||||
break;
|
||||
}
|
||||
case OPT_KMS_CONN_GET_BLOB_METADATA_ENDPOINT: {
|
||||
knobs.emplace_back("rest_kms_connector_get_blob_metadata_endpoint", args.OptionArg());
|
||||
break;
|
||||
|
|
|
@ -127,15 +127,23 @@ struct KmsConnLookupEKsByKeyIdsRep {
|
|||
|
||||
struct KmsConnLookupKeyIdsReqInfo {
|
||||
constexpr static FileIdentifier file_identifier = 3092256;
|
||||
EncryptCipherDomainId domainId;
|
||||
// Encryption at-rest relies on partioning database to define encryption domains, one such possible domain is
|
||||
// "Tenants". It is possible that KMS assigned 'baseCipherId' embedded 'encryption domain information', hence, make
|
||||
// the field optional.
|
||||
Optional<EncryptCipherDomainId> domainId;
|
||||
EncryptCipherBaseKeyId baseCipherId;
|
||||
|
||||
KmsConnLookupKeyIdsReqInfo() : domainId(INVALID_ENCRYPT_DOMAIN_ID), baseCipherId(INVALID_ENCRYPT_CIPHER_KEY_ID) {}
|
||||
explicit KmsConnLookupKeyIdsReqInfo(const EncryptCipherDomainId dId, const EncryptCipherBaseKeyId bCId)
|
||||
explicit KmsConnLookupKeyIdsReqInfo(const Optional<EncryptCipherDomainId> dId, const EncryptCipherBaseKeyId bCId)
|
||||
: domainId(dId), baseCipherId(bCId) {}
|
||||
|
||||
bool operator==(const KmsConnLookupKeyIdsReqInfo& info) const {
|
||||
return domainId == info.domainId && baseCipherId == info.baseCipherId;
|
||||
if (domainId.present()) {
|
||||
if (!info.domainId.present() || domainId.get() != info.domainId.get()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return baseCipherId == info.baseCipherId;
|
||||
}
|
||||
|
||||
template <class Ar>
|
||||
|
|
Loading…
Reference in New Issue