Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/common/dbpa_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class DBPS_EXPORT DataBatchProtectionAgentInterface {
// (e.g., as a serialized map/JSON field).
virtual void init(
std::string column_name,
std::map<std::string, std::string> connection_config,
std::map<std::string, std::string> configuration_map,
std::string app_context,
std::string column_key_id,
Type::type datatype,
Expand All @@ -110,7 +110,7 @@ class DBPS_EXPORT DataBatchProtectionAgentInterface {
std::optional<std::map<std::string, std::string>> column_encryption_metadata)
{
column_name_ = std::move(column_name);
connection_config_ = std::move(connection_config);
configuration_map_ = std::move(configuration_map);
app_context_ = std::move(app_context);
column_key_id_ = std::move(column_key_id);
datatype_ = datatype;
Expand Down Expand Up @@ -150,7 +150,7 @@ class DBPS_EXPORT DataBatchProtectionAgentInterface {

protected:
std::string column_name_;
std::map<std::string, std::string> connection_config_;
std::map<std::string, std::string> configuration_map_;
std::string app_context_; // includes user_id
std::optional<std::map<std::string, std::string>> column_encryption_metadata_;

Expand Down
4 changes: 2 additions & 2 deletions src/common/dbpa_local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ const std::map<std::string, std::string>& LocalDecryptionResult::error_fields()

void LocalDataBatchProtectionAgent::init(
std::string column_name,
std::map<std::string, std::string> connection_config,
std::map<std::string, std::string> configuration_map,
std::string app_context,
std::string column_key_id,
Type::type datatype,
Expand All @@ -126,7 +126,7 @@ void LocalDataBatchProtectionAgent::init(
// Call the base class init to store the configuration
DataBatchProtectionAgentInterface::init(
std::move(column_name),
std::move(connection_config),
std::move(configuration_map),
std::move(app_context),
std::move(column_key_id),
datatype,
Expand Down
2 changes: 1 addition & 1 deletion src/common/dbpa_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class DBPS_EXPORT LocalDataBatchProtectionAgent : public DataBatchProtectionAgen
// DataBatchProtectionAgentInterface implementation
void init(
std::string column_name,
std::map<std::string, std::string> connection_config,
std::map<std::string, std::string> configuration_map,
std::string app_context,
std::string column_key_id,
Type::type datatype,
Expand Down
26 changes: 13 additions & 13 deletions src/common/dbpa_local_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ class LocalDataBatchProtectionAgentTest : public ::testing::Test {
TEST_F(LocalDataBatchProtectionAgentTest, SuccessfulEncryption) {
LocalDataBatchProtectionAgent agent;

std::map<std::string, std::string> connection_config;
std::map<std::string, std::string> configuration_map = {};
std::string app_context = R"({"user_id": "test_user"})";

EXPECT_NO_THROW(agent.init("test_column", connection_config, app_context, "test_key",
EXPECT_NO_THROW(agent.init("test_column", configuration_map, app_context, "test_key",
Type::UNDEFINED, std::nullopt, CompressionCodec::UNCOMPRESSED, std::nullopt));

std::vector<uint8_t> test_data = {1, 2, 3, 4};
Expand All @@ -59,10 +59,10 @@ TEST_F(LocalDataBatchProtectionAgentTest, SuccessfulEncryption) {
TEST_F(LocalDataBatchProtectionAgentTest, SuccessfulEncryptionCompressedDictionary) {
LocalDataBatchProtectionAgent agent;

std::map<std::string, std::string> connection_config;
std::map<std::string, std::string> configuration_map = {};
std::string app_context = R"({"user_id": "test_user"})";

EXPECT_NO_THROW(agent.init("test_column", connection_config, app_context, "test_key",
EXPECT_NO_THROW(agent.init("test_column", configuration_map, app_context, "test_key",
Type::BYTE_ARRAY, std::nullopt, CompressionCodec::GZIP, std::nullopt));

// GZIP compressed data for strings "apple" and "banana"
Expand All @@ -84,10 +84,10 @@ TEST_F(LocalDataBatchProtectionAgentTest, SuccessfulEncryptionCompressedDictiona
TEST_F(LocalDataBatchProtectionAgentTest, SuccessfulDecryption) {
LocalDataBatchProtectionAgent agent;

std::map<std::string, std::string> connection_config;
std::map<std::string, std::string> configuration_map = {};
std::string app_context = R"({"user_id": "test_user"})";

EXPECT_NO_THROW(agent.init("test_column", connection_config, app_context, "test_key",
EXPECT_NO_THROW(agent.init("test_column", configuration_map, app_context, "test_key",
Type::UNDEFINED, std::nullopt, CompressionCodec::UNCOMPRESSED, DBPS_ENCRYPTION_METADATA));

std::vector<uint8_t> test_data = {1, 2, 3, 4};
Expand All @@ -103,10 +103,10 @@ TEST_F(LocalDataBatchProtectionAgentTest, SuccessfulDecryption) {
TEST_F(LocalDataBatchProtectionAgentTest, RoundTripEncryptDecrypt) {
LocalDataBatchProtectionAgent encrypt_agent;

std::map<std::string, std::string> connection_config;
std::map<std::string, std::string> configuration_map = {};
std::string app_context = R"({"user_id": "test_user"})";

EXPECT_NO_THROW(encrypt_agent.init("test_column", connection_config, app_context, "test_key",
EXPECT_NO_THROW(encrypt_agent.init("test_column", configuration_map, app_context, "test_key",
Type::UNDEFINED, std::nullopt, CompressionCodec::UNCOMPRESSED, std::nullopt));

// Original data to encrypt
Expand All @@ -132,7 +132,7 @@ TEST_F(LocalDataBatchProtectionAgentTest, RoundTripEncryptDecrypt) {

// Create a new agent for decryption with the encryption_metadata from the encryption result
LocalDataBatchProtectionAgent decrypt_agent;
EXPECT_NO_THROW(decrypt_agent.init("test_column", connection_config, app_context, "test_key",
EXPECT_NO_THROW(decrypt_agent.init("test_column", configuration_map, app_context, "test_key",
Type::UNDEFINED, std::nullopt, CompressionCodec::UNCOMPRESSED, encryption_metadata));

// Decrypt the ciphertext
Expand Down Expand Up @@ -183,21 +183,21 @@ TEST_F(LocalDataBatchProtectionAgentTest, DecryptWithoutInit) {
TEST_F(LocalDataBatchProtectionAgentTest, MissingUserId) {
LocalDataBatchProtectionAgent agent;

std::map<std::string, std::string> connection_config;
std::map<std::string, std::string> configuration_map = {};
std::string app_context = R"({"role": "admin"})";

EXPECT_THROW(agent.init("test_column", connection_config, app_context, "test_key",
EXPECT_THROW(agent.init("test_column", configuration_map, app_context, "test_key",
Type::BYTE_ARRAY, std::nullopt, CompressionCodec::UNCOMPRESSED, std::nullopt), DBPSException);
}

// Test missing page_encoding in encoding_attributes
TEST_F(LocalDataBatchProtectionAgentTest, MissingPageEncoding) {
LocalDataBatchProtectionAgent agent;

std::map<std::string, std::string> connection_config;
std::map<std::string, std::string> configuration_map = {};
std::string app_context = R"({"user_id": "test_user"})";

EXPECT_NO_THROW(agent.init("test_column", connection_config, app_context, "test_key",
EXPECT_NO_THROW(agent.init("test_column", configuration_map, app_context, "test_key",
Type::BYTE_ARRAY, std::nullopt, CompressionCodec::UNCOMPRESSED, std::nullopt));

std::vector<uint8_t> test_data = {1, 2, 3, 4};
Expand Down
65 changes: 17 additions & 48 deletions src/common/dbpa_remote.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "../client/dbps_api_client.h"
#include "../client/httplib_pool_registry.h"
#include "../client/httplib_pooled_client.h"
#include "dbpa_utils.h"
#include "enum_utils.h"
#include <iostream>

Expand Down Expand Up @@ -167,7 +168,7 @@ RemoteDataBatchProtectionAgent::RemoteDataBatchProtectionAgent(std::shared_ptr<H

void RemoteDataBatchProtectionAgent::init(
std::string column_name,
std::map<std::string, std::string> connection_config,
std::map<std::string, std::string> configuration_map,
std::string app_context,
std::string column_key_id,
Type::type datatype,
Expand All @@ -182,7 +183,7 @@ void RemoteDataBatchProtectionAgent::init(
// Call the base class init to store the configuration
DataBatchProtectionAgentInterface::init(
std::move(column_name),
std::move(connection_config),
std::move(configuration_map),
std::move(app_context),
std::move(column_key_id),
datatype,
Expand Down Expand Up @@ -212,7 +213,7 @@ void RemoteDataBatchProtectionAgent::init(
// The API client constructor does not attempt a HTTP connection with the server. The first Get/Post call creates the HTTP connection.
if (!api_client_) {
// given that there is no API client, instantiate a new one with a new HTTP client.
auto http_client = InstantiateHttpClient(); //uses connection_config_
auto http_client = InstantiateHttpClient(); //uses configuration_map_
api_client_ = std::make_unique<DBPSApiClient>(http_client);
} else {
std::cerr << "INFO: RemoteDataBatchProtectionAgent::init() - Using existing API client" << std::endl;
Expand Down Expand Up @@ -366,24 +367,24 @@ void RemoteDataBatchProtectionAgent::UpdateEncryptionMetadata(std::optional<std:
column_encryption_metadata_ = std::move(encryption_metadata);
}

std::optional<nlohmann::json> RemoteDataBatchProtectionAgent::LoadConnectionConfigFile(const std::map<std::string, std::string>& connection_config) const {
const std::string error_trace = "ERROR: RemoteDataBatchProtectionAgent::LoadConnectionConfigFile() - ";
auto config_file_it = connection_config.find(k_connection_config_key_);
if (config_file_it == connection_config.end()) {
std::optional<nlohmann::json> RemoteDataBatchProtectionAgent::LoadConfigFile(const std::string& config_file_key) const {
const std::string error_trace = "ERROR: RemoteDataBatchProtectionAgent::LoadConfigFile() - ";
auto config_file_it = configuration_map_.find(config_file_key);
if (config_file_it == configuration_map_.end()) {
std::cerr << error_trace
<< "connection_config does not provide " << k_connection_config_key_ << std::endl;
<< "configuration_map does not provide " << config_file_key << std::endl;
return std::nullopt;
}
auto config_file_path = config_file_it->second;
if (!std::filesystem::exists(config_file_path)) {
std::cerr << error_trace << k_connection_config_key_ << " [" << config_file_path
std::cerr << error_trace << config_file_key << " [" << config_file_path
<< "] does not exist" << std::endl;
return std::nullopt;
}

std::ifstream config_file(config_file_path);
if (!config_file.is_open()) {
std::cerr << error_trace << k_connection_config_key_ << " [" << config_file_path
std::cerr << error_trace << config_file_key << " [" << config_file_path
<< "] could not be opened" << std::endl;
return std::nullopt;
}
Expand All @@ -393,7 +394,7 @@ std::optional<nlohmann::json> RemoteDataBatchProtectionAgent::LoadConnectionConf
config_file.close();

if (config_file_contents.empty()) {
std::cerr << error_trace << k_connection_config_key_ << " [" << config_file_path
std::cerr << error_trace << config_file_key << " [" << config_file_path
<< "] is empty" << std::endl;
return std::nullopt;
}
Expand All @@ -402,19 +403,19 @@ std::optional<nlohmann::json> RemoteDataBatchProtectionAgent::LoadConnectionConf
auto json = nlohmann::json::parse(config_file_contents);
return json;
} catch (const nlohmann::json::exception& e) {
std::cerr << error_trace << k_connection_config_key_ << " [" << config_file_path
std::cerr << error_trace << config_file_key << " [" << config_file_path
<< "] is not a valid JSON file: " << e.what() << std::endl;
return std::nullopt;
}
}

std::shared_ptr<HttpClientInterface> RemoteDataBatchProtectionAgent::InstantiateHttpClient() {
auto config_json_opt = LoadConnectionConfigFile(connection_config_);
auto config_json_opt = LoadConfigFile(k_connection_config_key_);
auto server_url_opt = config_json_opt ? ExtractServerUrl(*config_json_opt) : std::nullopt;
if (!server_url_opt || server_url_opt->empty()) {
std::cerr << "ERROR: RemoteDataBatchProtectionAgent::InstantiateHttpClient() - No server_url provided in connection_config." << std::endl;
std::cerr << "ERROR: RemoteDataBatchProtectionAgent::InstantiateHttpClient() - No server_url provided in " << k_connection_config_key_ << "." << std::endl;
initialized_ = "Agent not properly initialized - server_url missing";
throw DBPSException("No server_url provided in connection_config");
throw DBPSException("No server_url provided in " + k_connection_config_key_);
}
server_url_ = *server_url_opt;
std::cerr << "INFO: RemoteDataBatchProtectionAgent::init() - server_url extracted: [" << server_url_ << "]" << std::endl;
Expand Down Expand Up @@ -475,7 +476,7 @@ static long long get_int_or_default(const nlohmann::json& config_json, const cha
return val.get<long long>();
}

//Extract pool config from connection_config. Expected format is a set of key-values pairs which are top level in the file
// Extract pool config from connection_config json. Expected format is a set of key-values pairs which are top level in the file
// there is no nesting
HttplibPoolRegistry::PoolConfig RemoteDataBatchProtectionAgent::ExtractPoolConfig(const nlohmann::json& config_json) {
HttplibPoolRegistry::PoolConfig pool_config;
Expand Down Expand Up @@ -511,35 +512,3 @@ std::size_t RemoteDataBatchProtectionAgent::ExtractNumWorkerThreads(const nlohma
return static_cast<std::size_t>(
get_int_or_default(config_json, "connection_pool.num_worker_threads", 0));
}

std::optional<std::string> RemoteDataBatchProtectionAgent::ExtractUserId(const std::string& app_context) const {
try {
auto json = nlohmann::json::parse(app_context);
if (json.contains("user_id") && json["user_id"].is_string()) {
std::string user_id = json["user_id"];
if (!user_id.empty()) {
return user_id;
}
}
} catch (const nlohmann::json::exception& e) {
std::cerr << "ERROR: RemoteDataBatchProtectionAgent::ExtractUserId() - Failed to parse app_context JSON: " << e.what() << std::endl;
}
return std::nullopt;
}

std::optional<Format::type> RemoteDataBatchProtectionAgent::ExtractPageEncoding(const std::map<std::string, std::string>& encoding_attributes) const {
auto it = encoding_attributes.find("page_encoding");
if (it != encoding_attributes.end()) {
const std::string& encoding_str = it->second;
auto format_opt = to_format_enum(encoding_str);
if (format_opt.has_value()) {
return format_opt.value();
} else {
std::cerr << "ERROR: RemoteDataBatchProtectionAgent::ExtractPageEncoding() - Unknown page_encoding: " << encoding_str << std::endl;
return std::nullopt;
}
}
// Return nullopt if page_encoding not found
std::cerr << "ERROR: RemoteDataBatchProtectionAgent::ExtractPageEncoding() - page_encoding not found." << std::endl;
return std::nullopt;
}
29 changes: 13 additions & 16 deletions src/common/dbpa_remote.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class DBPS_EXPORT RemoteDecryptionResult : public DecryptionResult {
*/
class DBPS_EXPORT RemoteDataBatchProtectionAgent : public DataBatchProtectionAgentInterface {
public:
// Constructor (default). Creates API_client during init() using server_url from connection_config
// Constructor (default). Creates API_client during init() using server_url from the connection_config file.
RemoteDataBatchProtectionAgent() = default;

// Constructor with HTTP client passed. Creates API_client immediately on the contructor.
Expand All @@ -107,7 +107,7 @@ class DBPS_EXPORT RemoteDataBatchProtectionAgent : public DataBatchProtectionAge
// DataBatchProtectionAgentInterface implementation
void init(
std::string column_name,
std::map<std::string, std::string> connection_config,
std::map<std::string, std::string> configuration_map,
std::string app_context,
std::string column_key_id,
Type::type datatype,
Expand Down Expand Up @@ -135,29 +135,26 @@ class DBPS_EXPORT RemoteDataBatchProtectionAgent : public DataBatchProtectionAge
std::optional<std::string> initialized_;
std::string server_url_;
std::string user_id_;
std::string k_connection_config_key_ = "connection_config_file_path";
inline static const std::string k_connection_config_key_ = "connection_config_file_path";

// Helper methods for configuration parsing

// Extract pool config from connection_config
// assumes all values in connection_config are optional, and will use default values if any not present.
// Load and parse the config file in the configuration_map.
std::optional<nlohmann::json> LoadConfigFile(const std::string& config_file_key) const;

// Extract pool config from the connection_config json. Values are optional, and will use default values if not present.
HttplibPoolRegistry::PoolConfig ExtractPoolConfig(const nlohmann::json& config_json);

// Extract number of worker threads for pooled client; defaults to 0 (auto)
std::size_t ExtractNumWorkerThreads(const nlohmann::json& config_json) const;

private:
// Helper methods for configuration parsing

// Load and parse the connection config file specified in connection_config
std::optional<nlohmann::json> LoadConnectionConfigFile(const std::map<std::string, std::string>& connection_config) const;
// Extract server_url from parsed JSON config such as {"server_url": "http://localhost:8080"}
std::optional<std::string> ExtractServerUrl(const nlohmann::json& config_json) const;

private:
// Instantiate a new HTTP client using the connection config file
std::shared_ptr<HttpClientInterface> InstantiateHttpClient();

// Extract server_url from parsed JSON config such as {"server_url": "http://localhost:8080"}
std::optional<std::string> ExtractServerUrl(const nlohmann::json& config_json) const;

std::optional<std::string> ExtractUserId(const std::string& app_context) const;
std::optional<Format::type> ExtractPageEncoding(const std::map<std::string, std::string>& encoding_attributes) const;

// Client instance
std::unique_ptr<DBPSApiClient> api_client_;
};
Expand Down
Loading