/* * This file is a part of the LinkAhead Project. * * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com> * Copyright (C) 2021-2024 IndiScale GmbH <info@indiscale.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. * */ #ifndef LINKAHEAD_CONFIGURATION_H #define LINKAHEAD_CONFIGURATION_H #include "linkahead/authentication.h" // for Authenticator, PlainPassw... #include "linkahead/certificate_provider.h" // for CertificateProvider, path #include "linkahead/exceptions.h" // for ConfigurationError #include "linkahead/utility.h" // for load_json_file #include <google/protobuf/arena.h> // for Arena #include <google/protobuf/extension_set.h> // for Arena #include <grpcpp/security/credentials.h> // for ChannelCredentials #include <filesystem> // for path, exists #include <iosfwd> // for ostream #include <memory> // for shared_ptr, unique_ptr #include <string> // for string namespace linkahead::configuration { using google::protobuf::Arena; using grpc::ChannelCredentials; using linkahead::authentication::Authenticator; using linkahead::authentication::PlainPasswordAuthenticator; using linkahead::exceptions::ConfigurationError; using linkahead::utility::JsonValue; using linkahead::utility::load_json_file; using std::filesystem::exists; using std::filesystem::path; const std::string logger_name = "linkahead::configuration"; /** * @brief Configuration of the LinkAhead connection. */ class ConnectionConfiguration { private: std::string host; int port; public: ConnectionConfiguration(std::string host, int port); virtual ~ConnectionConfiguration() = default; friend auto operator<<(std::ostream &out, const ConnectionConfiguration &configuration) -> std::ostream &; [[nodiscard]] auto virtual ToString() const -> std::string = 0; [[nodiscard]] auto GetHost() const -> std::string; [[nodiscard]] auto GetPort() const -> int; [[nodiscard]] auto virtual GetChannelCredentials() const -> std::shared_ptr<ChannelCredentials> = 0; }; class InsecureConnectionConfiguration : public ConnectionConfiguration { private: std::shared_ptr<ChannelCredentials> credentials; public: InsecureConnectionConfiguration(const std::string &host, int port); [[nodiscard]] auto GetChannelCredentials() const -> std::shared_ptr<ChannelCredentials> override; [[nodiscard]] auto ToString() const -> std::string override; }; class TlsConnectionConfiguration : public ConnectionConfiguration { private: std::shared_ptr<ChannelCredentials> credentials; std::string certificate_provider; public: TlsConnectionConfiguration(const std::string &host, int port); TlsConnectionConfiguration(const std::string &host, int port, const Authenticator &authenticator); TlsConnectionConfiguration(const std::string &host, int port, const CertificateProvider &certificate_provider); TlsConnectionConfiguration(const std::string &host, int port, const CertificateProvider &certificate_provider, const Authenticator &authenticator); [[nodiscard]] auto GetChannelCredentials() const -> std::shared_ptr<ChannelCredentials> override; [[nodiscard]] auto ToString() const -> std::string override; }; /** * Reads the configuration file and keeps the configuration. Singleton. * * Currently, this class can only read a single configuration file. No merging * or overwriting is supported. */ class ConfigurationManager { public: static ConfigurationManager &GetInstance(); ; /** * See mReset. */ inline static auto Reset() noexcept -> int { return GetInstance().mReset(); } /** * See mClear. */ inline static auto Clear() noexcept -> int { return GetInstance().mClear(); } /** * See mLoadSingleJSONConfiguration. */ inline static auto LoadSingleJSONConfiguration(const path &json_file) -> void { GetInstance().mLoadSingleJSONConfiguration(json_file); } /** * See mGetConnectionConfiguration. */ inline static auto GetConnectionConfiguration(const std::string &name) -> std::unique_ptr<ConnectionConfiguration> { return GetInstance().mGetConnectionConfiguration(name); } /** * Return the ConnectionConfiguration for the default connection. */ inline static auto GetDefaultConnectionConfiguration() -> std::unique_ptr<ConnectionConfiguration> { return GetInstance().mGetConnectionConfiguration(GetInstance().mGetDefaultConnectionName()); } /** * See mGetDefaultConnectionName. */ inline static auto GetDefaultConnectionName() -> std::string { return GetInstance().mGetDefaultConnectionName(); } ConfigurationManager(ConfigurationManager const &) = delete; void operator=(ConfigurationManager const &) = delete; inline static auto GetArena() -> Arena * { return &GetInstance().arena; } private: Arena arena; JsonValue json_configuration; static ConfigurationManager mInstance; inline ConfigurationManager() : json_configuration(nullptr){ // InitializeDefaults(); }; /** * Initialize this ConfigurationManager with the defaults. * * Currently, this means, that the ConfigurationManager attempts to load the * first existing file from the LIBLINKAHEAD_CONFIGURATION_FILES_PRECEDENCE list * of file locations. */ auto InitializeDefaults() -> int; /** * Reset this ConfigurationManager. * * The current configuration is deleted and a new configuration is being * loaded via InitializeDefaults. */ auto mReset() noexcept -> int; /** * Clear this ConfigurationManager. * * Afterwards, this ConfigurationManager is uninitilized. * * In contrast to mReset, this method only deletes the current configuration * but does not load a new one via InitializeDefaults. */ auto mClear() noexcept -> int; /** * Load a configuration from a json file. */ auto mLoadSingleJSONConfiguration(const path &json_file) -> void; /** * Return the ConnectionConfiguration for the connection of the given name. */ auto mGetConnectionConfiguration(const std::string &name) const -> std::unique_ptr<ConnectionConfiguration>; /** * Return the ConnectionConfiguration for the default connection. */ auto mGetDefaultConnectionName() const -> std::string; }; } // namespace linkahead::configuration #endif