/* * Copyright (C) 2018 ScyllaDB * */ /* * SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0 */ #pragma once #include #include #include #include #include #include #include #include "../../bytes.hh" class service_set; namespace replica { class database; } namespace db { class config; class extensions; } namespace cql3 { class query_processor; } namespace service { class storage_service; class migration_manager; } namespace sstables { class sstable; } namespace encryption { inline const sstring KEY_PROVIDER = "key_provider"; inline const sstring SECRET_KEY_PROVIDER_FACTORY_CLASS = "secret_key_provider_factory_class"; inline const sstring SECRET_KEY_FILE = "secret_key_file"; inline const sstring SYSTEM_KEY_FILE = "system_key_file"; inline const sstring CIPHER_ALGORITHM = "cipher_algorithm"; inline const sstring SECRET_KEY_STRENGTH = "secret_key_strength"; inline const sstring HOST_NAME = "kmip_host"; inline const sstring TEMPLATE_NAME = "template_name"; inline const sstring KEY_NAMESPACE = "key_namespace"; bytes base64_decode(const sstring&, size_t off = 0, size_t n = sstring::npos); sstring base64_encode(const bytes&, size_t off = 0, size_t n = bytes::npos); bytes calculate_md5(const bytes&, size_t off = 0, size_t n = bytes::npos); bytes calculate_sha256(const bytes&, size_t off = 0, size_t n = bytes::npos); bytes calculate_sha256(bytes_view); bytes hmac_sha256(bytes_view msg, bytes_view key); future> read_text_file_fully(const std::string&); future<> write_text_file_fully(const std::string&, temporary_buffer); future<> write_text_file_fully(const std::string&, const std::string&); std::optional parse_expiry(std::optional); class symmetric_key; struct key_info; using options = std::map; using opt_bytes = std::optional; using key_ptr = shared_ptr; /** * wrapper for "options" (map) to provide an * interface returning empty optionals for * non-available values. Makes query simpler * and allows .value_or(...)-statements, which * are neat for default values. * * In the long run one could contemplate * using non-std maps with similar built-in * functionality for all our various configs * in the system, but for now we are firmly * entrenched in map */ template class map_wrapper { const Map& _options; public: using mapped_type = typename Map::mapped_type; using key_type = typename Map::key_type; map_wrapper(const Map& opts) : _options(opts) {} std::optional operator()(const key_type& k) const { auto i = _options.find(k); if (i != _options.end()) { return i->second; } return std::nullopt; } }; using opt_wrapper = map_wrapper; key_info get_key_info(const options&); class encryption_context; class key_provider { public: virtual ~key_provider() {} virtual future> key(const key_info&, opt_bytes = {}) = 0; virtual future<> validate() const { return make_ready_future<>(); } virtual bool should_delay_read(const opt_bytes&) const { return false; } private: friend std::ostream& operator<<(std::ostream&, const key_provider&); virtual void print(std::ostream&) const = 0; }; std::ostream& operator<<(std::ostream&, const key_provider&); } template <> struct fmt::formatter : fmt::ostream_formatter {}; namespace encryption { class key_provider_factory { public: virtual ~key_provider_factory() {} virtual shared_ptr get_provider(encryption_context& c, const options&) = 0; }; class encryption_config; class system_key; class kmip_host; class kms_host; class gcp_host; class azure_host; /** * Context is a singleton object, shared across shards. I.e. even though there are obvious mutating * calls in it, it guarantees thread/shard safety. * * Why is this not a sharded thingamajing? Because its own instance methods need to send itself * as a shard-safe object forwards, and thus need to know that same shard, which breaks the circle of * ownership and stuff. */ class encryption_context { public: virtual ~encryption_context() = default; virtual shared_ptr get_provider(const options&) = 0; virtual shared_ptr get_system_key(const sstring&) = 0; virtual shared_ptr get_kmip_host(const sstring&) = 0; virtual shared_ptr get_kms_host(const sstring&) = 0; virtual shared_ptr get_gcp_host(const sstring&) = 0; virtual shared_ptr get_azure_host(const sstring&) = 0; virtual shared_ptr get_cached_provider(const sstring& id) const = 0; virtual void cache_provider(const sstring& id, shared_ptr) = 0; virtual const encryption_config& config() const = 0; virtual shared_ptr get_config_encryption_key() const = 0; virtual sharded& get_query_processor() const = 0; virtual sharded& get_storage_service() const = 0; virtual sharded& get_database() const = 0; virtual sharded& get_migration_manager() const = 0; sstring maybe_decrypt_config_value(const sstring&) const; virtual future<> start() = 0; virtual future<> stop() = 0; }; future> register_extensions(const db::config&, std::unique_ptr, db::extensions&, const ::service_set&); // for testing std::string encryption_provider(const sstables::sstable&); }