prepare for argon2id
This commit is contained in:
@@ -90,6 +90,11 @@ private:
|
|||||||
return s3_config_;
|
return s3_config_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto read_file_bytes(const std::string &api_path,
|
||||||
|
std::size_t size, std::uint64_t offset,
|
||||||
|
data_buffer &data, bool encrypted,
|
||||||
|
stop_type &stop_requested) -> api_error;
|
||||||
|
|
||||||
[[nodiscard]] auto set_meta_key(const std::string &api_path,
|
[[nodiscard]] auto set_meta_key(const std::string &api_path,
|
||||||
api_meta_map &meta) -> api_error;
|
api_meta_map &meta) -> api_error;
|
||||||
|
|
||||||
|
@@ -68,6 +68,7 @@ inline constexpr std::string META_CHANGED{"changed"};
|
|||||||
inline constexpr std::string META_CREATION{"creation"};
|
inline constexpr std::string META_CREATION{"creation"};
|
||||||
inline constexpr std::string META_DIRECTORY{"directory"};
|
inline constexpr std::string META_DIRECTORY{"directory"};
|
||||||
inline constexpr std::string META_GID{"gid"};
|
inline constexpr std::string META_GID{"gid"};
|
||||||
|
inline constexpr std::string META_KDF{"kdf"};
|
||||||
inline constexpr std::string META_KEY{"key"};
|
inline constexpr std::string META_KEY{"key"};
|
||||||
inline constexpr std::string META_MODE{"mode"};
|
inline constexpr std::string META_MODE{"mode"};
|
||||||
inline constexpr std::string META_MODIFIED{"modified"};
|
inline constexpr std::string META_MODIFIED{"modified"};
|
||||||
@@ -78,11 +79,11 @@ inline constexpr std::string META_SOURCE{"source"};
|
|||||||
inline constexpr std::string META_UID{"uid"};
|
inline constexpr std::string META_UID{"uid"};
|
||||||
inline constexpr std::string META_WRITTEN{"written"};
|
inline constexpr std::string META_WRITTEN{"written"};
|
||||||
|
|
||||||
inline constexpr std::array<std::string, 16U> META_USED_NAMES = {
|
inline constexpr std::array<std::string, 17U> META_USED_NAMES = {
|
||||||
META_ACCESSED, META_ATTRIBUTES, META_BACKUP, META_CHANGED,
|
META_ACCESSED, META_ATTRIBUTES, META_BACKUP, META_CHANGED, META_CREATION,
|
||||||
META_CREATION, META_DIRECTORY, META_GID, META_KEY,
|
META_DIRECTORY, META_GID, META_KDF, META_KEY, META_MODE,
|
||||||
META_MODE, META_MODIFIED, META_OSXFLAGS, META_PINNED,
|
META_MODIFIED, META_OSXFLAGS, META_PINNED, META_SIZE, META_SOURCE,
|
||||||
META_SIZE, META_SOURCE, META_UID, META_WRITTEN,
|
META_UID, META_WRITTEN,
|
||||||
};
|
};
|
||||||
|
|
||||||
using api_meta_map = std::map<std::string, std::string>;
|
using api_meta_map = std::map<std::string, std::string>;
|
||||||
|
@@ -815,124 +815,6 @@ auto s3_provider::is_online() const -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
|
||||||
std::uint64_t offset, data_buffer &data,
|
|
||||||
stop_type &stop_requested) -> api_error {
|
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const auto &cfg{get_s3_config()};
|
|
||||||
auto is_encrypted{not cfg.encryption_token.empty()};
|
|
||||||
|
|
||||||
std::string key;
|
|
||||||
if (is_encrypted) {
|
|
||||||
auto res{get_item_meta(api_path, META_KEY, key)};
|
|
||||||
if (res != api_error::success) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto object_name{
|
|
||||||
utils::path::create_api_path(is_encrypted ? key : api_path),
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto read_bytes =
|
|
||||||
[this, &api_path, &cfg, &object_name,
|
|
||||||
&stop_requested](std::size_t read_size, std::size_t read_offset,
|
|
||||||
data_buffer &read_buffer) -> api_error {
|
|
||||||
auto res{api_error::error};
|
|
||||||
for (std::uint32_t idx{0U};
|
|
||||||
not(stop_requested || app_config::get_stop_requested()) &&
|
|
||||||
res != api_error::success &&
|
|
||||||
idx < get_config().get_retry_read_count() + 1U;
|
|
||||||
++idx) {
|
|
||||||
if (idx > 0U) {
|
|
||||||
read_buffer.clear();
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(1s);
|
|
||||||
}
|
|
||||||
|
|
||||||
curl::requests::http_get get{};
|
|
||||||
get.aws_service = "aws:amz:" + cfg.region + ":s3";
|
|
||||||
get.headers["response-content-type"] = "binary/octet-stream";
|
|
||||||
get.range = {{
|
|
||||||
.begin = read_offset,
|
|
||||||
.end = read_offset + read_size - 1U,
|
|
||||||
}};
|
|
||||||
get.response_handler = [&read_buffer](auto &&response_data,
|
|
||||||
long /*response_code*/) {
|
|
||||||
read_buffer = response_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
res = set_request_path(get, object_name);
|
|
||||||
if (res != api_error::success) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto notify_retry = [=](long response_code) {
|
|
||||||
auto msg =
|
|
||||||
fmt::format("read file bytes failed|offset|{}|size|{}|retry|{}",
|
|
||||||
std::to_string(read_offset),
|
|
||||||
std::to_string(read_size), std::to_string(idx + 1U));
|
|
||||||
if (response_code == 0) {
|
|
||||||
utils::error::raise_api_path_error(function_name, api_path,
|
|
||||||
api_error::comm_error, msg);
|
|
||||||
} else {
|
|
||||||
utils::error::raise_api_path_error(function_name, api_path,
|
|
||||||
response_code, msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
long response_code{};
|
|
||||||
if (not get_comm().make_request(get, response_code, stop_requested)) {
|
|
||||||
notify_retry(response_code);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response_code < http_error_codes::ok ||
|
|
||||||
response_code >= http_error_codes::multiple_choices) {
|
|
||||||
notify_retry(response_code);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = api_error::success;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (not is_encrypted) {
|
|
||||||
return read_bytes(size, offset, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string temp;
|
|
||||||
auto res{get_item_meta(api_path, META_SIZE, temp)};
|
|
||||||
if (res != api_error::success) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
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),
|
|
||||||
[&](data_buffer &ct_buffer, std::uint64_t start_offset,
|
|
||||||
std::uint64_t end_offset) -> bool {
|
|
||||||
return read_bytes((end_offset - start_offset + 1U),
|
|
||||||
start_offset,
|
|
||||||
ct_buffer) == api_error::success;
|
|
||||||
},
|
|
||||||
total_size, data)
|
|
||||||
? api_error::success
|
|
||||||
: api_error::decryption_error;
|
|
||||||
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
utils::error::raise_error(function_name, e, "exception occurred");
|
|
||||||
}
|
|
||||||
|
|
||||||
return api_error::error;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto s3_provider::remove_directory_impl(const std::string &api_path)
|
auto s3_provider::remove_directory_impl(const std::string &api_path)
|
||||||
-> api_error {
|
-> api_error {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
@@ -1085,7 +967,40 @@ auto s3_provider::start(api_item_added_callback api_item_added,
|
|||||||
|
|
||||||
event_system::instance().raise<service_start_begin>(function_name,
|
event_system::instance().raise<service_start_begin>(function_name,
|
||||||
"s3_provider");
|
"s3_provider");
|
||||||
|
const auto &cfg{get_s3_config()};
|
||||||
|
|
||||||
auto ret = base_provider::start(api_item_added, mgr);
|
auto ret = base_provider::start(api_item_added, mgr);
|
||||||
|
if (ret && not cfg.encryption_token.empty()) {
|
||||||
|
std::string kdf_str;
|
||||||
|
auto res = get_item_meta("/", META_KDF, kdf_str);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
kdf_ = nlohmann::json::parse(kdf_str).get<kdf_config>();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
utils::error::raise_api_path_error(function_name, "/", res,
|
||||||
|
"get item meta failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
key_ = utils::encryption::recreate_key<utils::hash::hash_256_t>(
|
||||||
|
cfg.encryption_token, kdf);
|
||||||
|
} else {
|
||||||
|
base_provider::stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
event_system::instance().raise<service_start_end>(function_name,
|
event_system::instance().raise<service_start_end>(function_name,
|
||||||
"s3_provider");
|
"s3_provider");
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1165,4 +1080,131 @@ auto s3_provider::upload_file_impl(const std::string &api_path,
|
|||||||
|
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||||
|
std::uint64_t offset, data_buffer &data,
|
||||||
|
stop_type &stop_requested) -> api_error {
|
||||||
|
return read_file_bytes(api_path, size, offset, data,
|
||||||
|
not get_s3_config().encryption_token.empty(),
|
||||||
|
stop_requested);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
||||||
|
std::uint64_t offset, data_buffer &data,
|
||||||
|
bool encrypted, stop_type &stop_requested)
|
||||||
|
-> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const auto &cfg{get_s3_config()};
|
||||||
|
|
||||||
|
std::string key;
|
||||||
|
if (encrypted) {
|
||||||
|
auto res{get_item_meta(api_path, META_KEY, key)};
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto object_name{
|
||||||
|
utils::path::create_api_path(encrypted ? key : api_path),
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto read_bytes =
|
||||||
|
[this, &api_path, &cfg, &object_name,
|
||||||
|
&stop_requested](std::size_t read_size, std::size_t read_offset,
|
||||||
|
data_buffer &read_buffer) -> api_error {
|
||||||
|
auto res{api_error::error};
|
||||||
|
for (std::uint32_t idx{0U};
|
||||||
|
not(stop_requested || app_config::get_stop_requested()) &&
|
||||||
|
res != api_error::success &&
|
||||||
|
idx < get_config().get_retry_read_count() + 1U;
|
||||||
|
++idx) {
|
||||||
|
if (idx > 0U) {
|
||||||
|
read_buffer.clear();
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(1s);
|
||||||
|
}
|
||||||
|
|
||||||
|
curl::requests::http_get get{};
|
||||||
|
get.aws_service = "aws:amz:" + cfg.region + ":s3";
|
||||||
|
get.headers["response-content-type"] = "binary/octet-stream";
|
||||||
|
get.range = {{
|
||||||
|
.begin = read_offset,
|
||||||
|
.end = read_offset + read_size - 1U,
|
||||||
|
}};
|
||||||
|
get.response_handler = [&read_buffer](auto &&response_data,
|
||||||
|
long /*response_code*/) {
|
||||||
|
read_buffer = response_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
res = set_request_path(get, object_name);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto notify_retry = [=](long response_code) {
|
||||||
|
auto msg =
|
||||||
|
fmt::format("read file bytes failed|offset|{}|size|{}|retry|{}",
|
||||||
|
std::to_string(read_offset),
|
||||||
|
std::to_string(read_size), std::to_string(idx + 1U));
|
||||||
|
if (response_code == 0) {
|
||||||
|
utils::error::raise_api_path_error(function_name, api_path,
|
||||||
|
api_error::comm_error, msg);
|
||||||
|
} else {
|
||||||
|
utils::error::raise_api_path_error(function_name, api_path,
|
||||||
|
response_code, msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
long response_code{};
|
||||||
|
if (not get_comm().make_request(get, response_code, stop_requested)) {
|
||||||
|
notify_retry(response_code);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response_code < http_error_codes::ok ||
|
||||||
|
response_code >= http_error_codes::multiple_choices) {
|
||||||
|
notify_retry(response_code);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (not encrypted) {
|
||||||
|
return read_bytes(size, offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string temp;
|
||||||
|
auto res{get_item_meta(api_path, META_SIZE, temp)};
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
[&](data_buffer &ct_buffer, std::uint64_t start_offset,
|
||||||
|
std::uint64_t end_offset) -> bool {
|
||||||
|
return read_bytes((end_offset - start_offset + 1U),
|
||||||
|
start_offset,
|
||||||
|
ct_buffer) == api_error::success;
|
||||||
|
},
|
||||||
|
total_size, data)
|
||||||
|
? api_error::success
|
||||||
|
: api_error::decryption_error;
|
||||||
|
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
utils::error::raise_error(function_name, e, "exception occurred");
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::error;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
Reference in New Issue
Block a user