broken build
Some checks failed
BlockStorage/repertory/pipeline/head There was a failure building this commit
Some checks failed
BlockStorage/repertory/pipeline/head There was a failure building this commit
This commit is contained in:
@@ -24,6 +24,8 @@
|
||||
|
||||
#include "providers/base_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/encryption.hpp"
|
||||
#include "utils/hash.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class app_config;
|
||||
@@ -48,6 +50,9 @@ public:
|
||||
|
||||
private:
|
||||
s3_config s3_config_;
|
||||
bool legacy_bucket_{true};
|
||||
utils::encryption::kdf_config master_kdf_cfg_;
|
||||
utils::hash::hash_256_t master_key_;
|
||||
|
||||
private:
|
||||
[[nodiscard]] auto add_if_not_found(api_file &file,
|
||||
@@ -66,8 +71,8 @@ private:
|
||||
api_meta_map &meta)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto decrypt_object_name(std::string &object_name) const
|
||||
-> api_error;
|
||||
[[nodiscard]] auto decrypt_object_name(std::string &object_name,
|
||||
bool &uses_kdf) const -> api_error;
|
||||
|
||||
[[nodiscard]] auto get_last_modified(bool directory,
|
||||
const std::string &api_path,
|
||||
@@ -95,6 +100,9 @@ private:
|
||||
data_buffer &data, bool encrypted,
|
||||
stop_type &stop_requested) -> api_error;
|
||||
|
||||
[[nodiscard]] auto search_keys_for_kdf(std::string_view encryption_token)
|
||||
-> bool;
|
||||
|
||||
[[nodiscard]] auto set_meta_key(const std::string &api_path,
|
||||
api_meta_map &meta) -> api_error;
|
||||
|
||||
|
@@ -927,6 +927,92 @@ auto s3_provider::rename_file(const std::string & /* from_api_path */,
|
||||
return api_error::not_implemented;
|
||||
}
|
||||
|
||||
auto s3_provider::search_keys_for_kdf(std::string_view encryption_token)
|
||||
-> bool {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
auto grab_more{true};
|
||||
std::string token{};
|
||||
while (grab_more) {
|
||||
std::string response_data{};
|
||||
long response_code{};
|
||||
if (not get_object_list(response_data, response_code, "/", prefix, token)) {
|
||||
throw utils::error::create_exception(function_name,
|
||||
{"failed to get object list"});
|
||||
}
|
||||
|
||||
if (response_code == http_error_codes::not_found) {
|
||||
throw utils::error::create_exception(function_name,
|
||||
{"failed to get object list"});
|
||||
}
|
||||
|
||||
if (response_code != http_error_codes::ok) {
|
||||
throw utils::error::create_exception(function_name,
|
||||
{"failed to get object list"});
|
||||
}
|
||||
|
||||
pugi::xml_document doc;
|
||||
auto parse_res{doc.load_string(response_data.c_str())};
|
||||
if (parse_res.status != pugi::xml_parse_status::status_ok) {
|
||||
throw utils::error::create_exception(function_name,
|
||||
{"failed to get object list"});
|
||||
}
|
||||
|
||||
grab_more = doc.select_node("/ListBucketResult/IsTruncated")
|
||||
.node()
|
||||
.text()
|
||||
.as_bool();
|
||||
if (grab_more) {
|
||||
token = doc.select_node("/ListBucketResult/NextContinuationToken")
|
||||
.node()
|
||||
.text()
|
||||
.as_string();
|
||||
}
|
||||
|
||||
node_list = doc.select_nodes("/ListBucketResult/Contents");
|
||||
for (const auto &node : node_list) {
|
||||
auto object_name{
|
||||
node.node().select_node("Key").node().text().as_string()),
|
||||
};
|
||||
if (object_name == "/")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
data_buffer buffer;
|
||||
if (not utils::collection::from_hex_string(object_name, buffer)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
kdf_config cfg;
|
||||
if (not kdf_config::from_header(buffer, cfg)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cfg.unique_id = 0U;
|
||||
cfg.seal();
|
||||
|
||||
master_kdf_cfg_ = cfg;
|
||||
if (not utils::encryption::recreate_key_argon2id(
|
||||
encryption_token, master_kdf_cfg_, master_key_)) {
|
||||
throw utils::error::create_exception(
|
||||
function_name, {"failed to recreate master key from kdf"});
|
||||
}
|
||||
|
||||
auto res =
|
||||
set_item_meta("/", META_KDF, nlohmann::json(master_kdf_cfg_).dump());
|
||||
if (res == api_error::success) {
|
||||
legacy_bucket_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
throw utils::error::create_exception(function_name,
|
||||
{"failed to set meta kdf"});
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto s3_provider::set_meta_key(const std::string &api_path, api_meta_map &meta)
|
||||
-> api_error {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
@@ -949,9 +1035,20 @@ auto s3_provider::set_meta_key(const std::string &api_path, api_meta_map &meta)
|
||||
}
|
||||
|
||||
data_buffer result;
|
||||
utils::encryption::encrypt_data(
|
||||
cfg.encryption_token,
|
||||
*(utils::string::split(api_path, '/', false).end() - 1U), result);
|
||||
if (legacy_bucket_) {
|
||||
utils::encryption::encrypt_data(
|
||||
cfg.encryption_token,
|
||||
*(utils::string::split(api_path, '/', false).end() - 1U), result);
|
||||
} else {
|
||||
auto [key, cfg] = master_kdf_cfg_.create_subkey(
|
||||
utils::encryption::kdf_context::path, id, master_key_);
|
||||
|
||||
utils::encryption::encrypt_data(
|
||||
key, *(utils::string::split(api_path, '/', false).end() - 1U), result);
|
||||
|
||||
auto hdr = cfg.to_header();
|
||||
result.insert(result.begin(), hdr.begin(), hdr.end());
|
||||
}
|
||||
|
||||
meta[META_KEY] = utils::path::create_api_path(
|
||||
utils::path::combine(utils::path::create_api_path(encrypted_parent_path),
|
||||
@@ -976,27 +1073,44 @@ auto s3_provider::start(api_item_added_callback api_item_added,
|
||||
ret == res == api_error::success;
|
||||
if (ret) {
|
||||
if (kdf_str.empty()) {
|
||||
if (not search_keys_for_kdf()) {
|
||||
kdf_.seal();
|
||||
res = set_item_meta("/", META_KDF, nlohmann::json(kdf_).dump());
|
||||
ret == res == api_error::success;
|
||||
if (not ret) {
|
||||
utils::error::raise_api_path_error(function_name, "/", res,
|
||||
"set item meta failed");
|
||||
try {
|
||||
if (not search_keys_for_kdf(cfg.encryption_token)) {
|
||||
if (get_directory_item_count("/") == 0U) {
|
||||
legacy_bucket_ = false;
|
||||
master_kdf_cfg_.seal();
|
||||
master_key_ =
|
||||
utils::encryption::generate_key<utils::hash::hash_256_t>(
|
||||
cfg.encryption_token, master_kdf_cfg_);
|
||||
|
||||
auto res = set_item_meta("/", META_KDF,
|
||||
nlohmann::json(master_kdf_cfg_).dump());
|
||||
ret == res == api_error::success;
|
||||
if (not ret) {
|
||||
utils::error::raise_api_path_error(function_name, "/", res,
|
||||
"set kdf in meta failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
utils::error::raise_error(function_name, e, "exception occurred");
|
||||
ret = false;
|
||||
}
|
||||
} else {
|
||||
kdf_ = nlohmann::json::parse(kdf_str).get<kdf_config>();
|
||||
master_kdf_cfg_ =
|
||||
nlohmann::json::parse(kdf_str).get<utils::encryption::kdf_config>();
|
||||
if (not utils::encryption::recreate_key_argon2id(
|
||||
cfg.encryption_token, master_kdf_cfg_, master_key_)) {
|
||||
ret = false;
|
||||
utils::error::raise_error(function_name,
|
||||
"failed to recreate master key from kdf");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
utils::error::raise_api_path_error(function_name, "/", res,
|
||||
"get item meta failed");
|
||||
"get kdf from meta failed");
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
key_ = utils::encryption::recreate_key<utils::hash::hash_256_t>(
|
||||
cfg.encryption_token, kdf);
|
||||
} else {
|
||||
if (not ret) {
|
||||
base_provider::stop();
|
||||
}
|
||||
}
|
||||
@@ -1060,10 +1174,24 @@ auto s3_provider::upload_file_impl(const std::string &api_path,
|
||||
}
|
||||
|
||||
if (is_encrypted && file_size > 0U) {
|
||||
put_file.reader = std::make_shared<utils::encryption::encrypting_reader>(
|
||||
object_name, source_path,
|
||||
[]() -> bool { return app_config::get_stop_requested(); },
|
||||
cfg.encryption_token, std::nullopt, -1);
|
||||
if (legacy_bucket_) {
|
||||
put_file.reader = std::make_shared<utils::encryption::encrypting_reader>(
|
||||
object_name, source_path,
|
||||
[]() -> bool { return app_config::get_stop_requested(); },
|
||||
cfg.encryption_token, std::nullopt, -1);
|
||||
} else {
|
||||
put_file.reader = std::make_shared<utils::encryption::encrypting_reader>(
|
||||
object_name, source_path,
|
||||
[]() -> bool { return app_config::get_stop_requested(); },
|
||||
master_key_, master_kdf_cfg_, std::nullopt, -1);
|
||||
|
||||
res = set_item_meta(
|
||||
"/", META_KDF,
|
||||
nlohmann::json(*put_file.reader->get_kdf_config_for_data()).dump());
|
||||
if (res == api_error::success) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long response_code{};
|
||||
@@ -1185,11 +1313,30 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||
return res;
|
||||
}
|
||||
|
||||
utils::hash::hash_256_t key;
|
||||
if (legacy_bucket_) {
|
||||
key = utils::encryption::generate_key<utils::hash::hash_256_t>(
|
||||
cfg.encryption_token);
|
||||
} else {
|
||||
res = get_item_meta(api_path, META_KDF, temp);
|
||||
if (res != api_error::success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (not utils::encryption::recreate_key_argon2id(
|
||||
cfg.encryption_token,
|
||||
nlohmann::json::parse(temp).get<utils::encryption::kdf_config>(),
|
||||
key)) {
|
||||
throw utils::error::create_exception(
|
||||
function_name, {"failed to recreate data key from kdf"});
|
||||
return api_error::error;
|
||||
}
|
||||
}
|
||||
|
||||
auto total_size{utils::string::to_uint64(temp)};
|
||||
return utils::encryption::read_encrypted_range(
|
||||
{.begin = offset, .end = offset + size - 1U},
|
||||
utils::encryption::generate_key<utils::hash::hash_256_t>(
|
||||
cfg.encryption_token),
|
||||
{.begin = offset, .end = offset + size - 1U}, key,
|
||||
not legacy_bucket_,
|
||||
[&](data_buffer &ct_buffer, std::uint64_t start_offset,
|
||||
std::uint64_t end_offset) -> bool {
|
||||
return read_bytes((end_offset - start_offset + 1U),
|
||||
@@ -1206,5 +1353,4 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||
|
||||
return api_error::error;
|
||||
}
|
||||
|
||||
} // namespace repertory
|
||||
|
Reference in New Issue
Block a user