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
31 changes: 31 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ set(util_source_files

src/util/exception_location_helpers.hpp

src/util/file_operations_helpers.hpp
src/util/file_operations_helpers.cpp

src/util/hex_value_fwd.hpp
src/util/hex_value.hpp
src/util/hex_value.cpp

src/util/flag_set_fwd.hpp
src/util/flag_set.hpp

Expand Down Expand Up @@ -436,6 +443,10 @@ set(binsrv_source_files
src/binsrv/basic_logger.hpp
src/binsrv/basic_logger.cpp

src/binsrv/basic_keyring_fwd.hpp
src/binsrv/basic_keyring.hpp
src/binsrv/basic_keyring.cpp

src/binsrv/basic_storage_backend_fwd.hpp
src/binsrv/basic_storage_backend.hpp
src/binsrv/basic_storage_backend.cpp
Expand All @@ -447,12 +458,22 @@ set(binsrv_source_files
src/binsrv/cout_logger.hpp
src/binsrv/cout_logger.cpp

src/binsrv/encryption_config_fwd.hpp
src/binsrv/encryption_config.hpp
src/binsrv/encryption_config.cpp

src/binsrv/encryption_format_type_fwd.hpp
src/binsrv/encryption_format_type.hpp

src/binsrv/exception_handling_helpers.hpp
src/binsrv/exception_handling_helpers.cpp

src/binsrv/file_logger.hpp
src/binsrv/file_logger.cpp

src/binsrv/file_keyring.hpp
src/binsrv/file_keyring.cpp

src/binsrv/filesystem_storage_backend.hpp
src/binsrv/filesystem_storage_backend.cpp

Expand All @@ -465,6 +486,16 @@ set(binsrv_source_files
src/binsrv/logger_factory.hpp
src/binsrv/logger_factory.cpp

src/binsrv/keyring_factory.hpp
src/binsrv/keyring_factory.cpp

src/binsrv/keyring_record_collection_fwd.hpp
src/binsrv/keyring_record_collection.hpp
src/binsrv/keyring_record_collection.cpp

src/binsrv/keyring_record_fwd.hpp
src/binsrv/keyring_record.hpp

src/binsrv/main_config_fwd.hpp
src/binsrv/main_config.hpp
src/binsrv/main_config.cpp
Expand Down
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,11 @@ The Percona Binary Log Server configuration file has the following format.
"uri": "https://key_id:secret@192.168.0.100:9000/binsrv-bucket/vault",
"fs_buffer_directory": "/tmp/binsrv",
"checkpoint_size": "128M",
"checkpoint_interval": "30s"
"checkpoint_interval": "30s",
"encryption": {
"format": "generic",
"keyring_uri": "file:///var/lib/pbs/keyring/keyring_data.json"
}
}
}
```
Expand Down Expand Up @@ -612,6 +616,36 @@ For example:
##### Checkpointing on S3
Please note that S3 API does not provide a way to append a portion of data to an existing object. Currently, in our S3 storage backend "append" operations are implemented as complete object overwrites meaning data re-uploads. Practically, if your typical binlog file size is '1G' and you set `<storage.checkpoint_size>` to '256M', you will upload '256M + 512M + 768M + 1024M = 2560M' (about 2.5 times more then your binlog file size in this example). So, keep balance between the value of this parameter and your typical binlog size. Similar concerns can be raised regarding enabling `<storage.checkpoint_interval>`.

#### \<storage.encryption\> section
If this section is present, then all the binlog data files will be encrypted before written to the storage.
- `<storage.encryption.format>` - specifies the encryption format (currently only `generic` is supported).
- `<storage.encryption.keyring_uri>` - specifies location of the keyring JSON data file (currently only 'file://' scheme is supported meaning that the file should be taken from the local file sytem from the path specified in this URI, e.g. `file:///var/lib/pbs/keyring/keyring_data.json`).

##### Keyring file format
```json
{
"version": 1,
"keys": [
{
"id": "alpha",
"algorithm": "AES-128-ECB",
"data_hex": "00112233445566778899AABBCCDDEEFF"
},
{
"id": "beta",
"algorithm": "AES-256-GCM",
"data_hex": "00112233445566778899AABBCCDDEEFFFFEEDDCCBBAA998877665544332211"
}
]
}
```
Keyring JSON file should represent a top-level JSON object with the following keys.
- `version` - currently should always be equal to `1`.
- `keys` - should be an array of objects tith the following keys
- `id` - a unique string identifier of the key in the keyring.
- `algorithm` - the name of the symmetric cypher which should be used with this key (e.g `AES-256-GCM`).
- `data_hex` - key bytes in hex format (typically `16`, `24`, or `32` bytes, meaning `32`, `48`, or `64` characters)

### Resuming previous operation

Running the utility for the second time (in any mode) results in resuming streaming from the position at which the previous run finished.
Expand Down
15 changes: 15 additions & 0 deletions keyring_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": 1,
"keys": [
{
"id": "alpha",
"algorithm": "AES-128-ECB",
"data_hex": "00112233445566778899AABBCCDDEEFF"
},
{
"id": "beta",
"algorithm": "AES-256-GCM",
"data_hex": "00112233445566778899AABBCCDDEEFFFFEEDDCCBBAA998877665544332211"
}
]
}
6 changes: 5 additions & 1 deletion main_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
"uri": "file:///home/user/vault",
"fs_buffer_directory": "/tmp/binsrv",
"checkpoint_size": "2M",
"checkpoint_interval": "30s"
"checkpoint_interval": "30s",
"encryption": {
"format": "generic",
"keyring_uri": "file:///home/user/keyring/keyring/keyring_data.json"
}
}
}
26 changes: 26 additions & 0 deletions src/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@

#include "app_version.hpp"

#include "binsrv/basic_keyring.hpp"
#include "binsrv/basic_logger.hpp"
// needed for encryption_format_type's operator <<
#include "binsrv/encryption_format_type.hpp" // IWYU pragma: keep
#include "binsrv/exception_handling_helpers.hpp"
#include "binsrv/keyring_factory.hpp"
#include "binsrv/log_severity.hpp"
#include "binsrv/logger_factory.hpp"
#include "binsrv/main_config.hpp"
Expand Down Expand Up @@ -248,6 +252,15 @@ void log_replication_config_info(
}
}

void log_encryption_config_info(
binsrv::basic_logger &logger,
const binsrv::encryption_config &encryption_config) {
log_config_param<"format">(logger, encryption_config,
"binlog storage encryption format");
log_config_param<"keyring_uri">(logger, encryption_config,
"binlog storage encryption keyring URI");
}

void log_storage_config_info(binsrv::basic_logger &logger,
const binsrv::storage_config &storage_config) {

Expand All @@ -263,6 +276,10 @@ void log_storage_config_info(binsrv::basic_logger &logger,
logger, storage_config, "binlog storage backend checkpointing size");
log_config_param<"checkpoint_interval">(
logger, storage_config, "binlog storage backend checkpointing interval");
const auto &optional_encryption_config{storage_config.get<"encryption">()};
if (optional_encryption_config.has_value()) {
log_encryption_config_info(logger, *optional_encryption_config);
}
}

void log_storage_info(binsrv::basic_logger &logger,
Expand Down Expand Up @@ -1310,6 +1327,15 @@ int main(int argc, char *argv[]) {
const auto verify_checksum{replication_config.get<"verify_checksum">()};
const auto replication_mode{replication_config.get<"mode">()};
const auto optional_rewrite_config{replication_config.get<"rewrite">()};
const auto &optional_encryption_config{storage_config.get<"encryption">()};

binsrv::basic_keyring_ptr keyring;
if (optional_encryption_config.has_value()) {
keyring = binsrv::keyring_factory::create(
optional_encryption_config->get<"keyring_uri">());
logger->log(binsrv::log_severity::info,
"initialized keyring: " + keyring->get_description());
}

binsrv::storage storage{storage_config,
binsrv::storage_construction_mode_type::streaming,
Expand Down
35 changes: 35 additions & 0 deletions src/binsrv/basic_keyring.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) 2023-2024 Percona and/or its affiliates.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 2.0,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License, version 2.0, for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#include "binsrv/basic_keyring.hpp"

#include <string>
#include <string_view>

#include "binsrv/keyring_record_fwd.hpp"

namespace binsrv {

basic_keyring::~basic_keyring() = default;

[[nodiscard]] const keyring_record &
basic_keyring::get_key(std::string_view key_id) {
return do_get_key(key_id);
}
[[nodiscard]] std::string basic_keyring::get_description() const {
return do_get_description();
}

} // namespace binsrv
48 changes: 48 additions & 0 deletions src/binsrv/basic_keyring.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2023-2024 Percona and/or its affiliates.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 2.0,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License, version 2.0, for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#ifndef BINSRV_BASIC_KEYRING_HPP
#define BINSRV_BASIC_KEYRING_HPP

#include "binsrv/basic_keyring_fwd.hpp" // IWYU pragma: export

#include "binsrv/keyring_record_fwd.hpp"

#include <string>

namespace binsrv {

class [[nodiscard]] basic_keyring {
public:
basic_keyring() = default;
basic_keyring(const basic_keyring &) = delete;
basic_keyring(basic_keyring &&) noexcept = delete;
basic_keyring &operator=(const basic_keyring &) = delete;
basic_keyring &operator=(basic_keyring &&) = delete;

virtual ~basic_keyring();

[[nodiscard]] const keyring_record &get_key(std::string_view key_id);
[[nodiscard]] std::string get_description() const;

private:
[[nodiscard]] virtual const keyring_record &
do_get_key(std::string_view key_id) = 0;
[[nodiscard]] virtual std::string do_get_description() const = 0;
};

} // namespace binsrv

#endif // BINSRV_BASIC_KEYRING_HPP
29 changes: 29 additions & 0 deletions src/binsrv/basic_keyring_fwd.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2023-2024 Percona and/or its affiliates.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 2.0,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License, version 2.0, for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#ifndef BINSRV_BASIC_KEYRING_FWD_HPP
#define BINSRV_BASIC_KEYRING_FWD_HPP

#include <memory>

namespace binsrv {

class basic_keyring;

using basic_keyring_ptr = std::shared_ptr<basic_keyring>;

} // namespace binsrv

#endif // BINSRV_BASIC_KEYRING_FWD_HPP
2 changes: 2 additions & 0 deletions src/binsrv/basic_logger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ namespace binsrv {
basic_logger::basic_logger(log_severity min_level) noexcept
: min_level_{min_level} {}

basic_logger::~basic_logger() = default;

void basic_logger::log(log_severity level, std::string_view message) {
if (level >= min_level_) {
// the length of the longest log severity label
Expand Down
2 changes: 1 addition & 1 deletion src/binsrv/basic_logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class [[nodiscard]] basic_logger {
basic_logger(basic_logger &&) = delete;
basic_logger &operator=(basic_logger &&) = delete;

virtual ~basic_logger() = default;
virtual ~basic_logger();

[[nodiscard]] log_severity get_min_level() const noexcept {
return min_level_;
Expand Down
33 changes: 33 additions & 0 deletions src/binsrv/encryption_config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) 2023-2026 Percona and/or its affiliates.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 2.0,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License, version 2.0, for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

#include "binsrv/encryption_config.hpp"

#include <stdexcept>

#include "binsrv/encryption_format_type.hpp"

#include "util/exception_location_helpers.hpp"

namespace binsrv {

void encryption_config::validate() const {
if (get<"format">() != encryption_format_type::generic) {
util::exception_location().raise<std::invalid_argument>(
"error validating storage encryption config: unsupported format");
}
}

} // namespace binsrv
Loading
Loading