diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 0e4d0dae38b5689372a0424a590fe16504fc3b87..773ab811d26dc9dfe299eef504c2c9e584c83882 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -22,6 +22,7 @@ set(libcaosdb_INCL ${CMAKE_CURRENT_BINARY_DIR}/constants.h ${CMAKE_CURRENT_SOURCE_DIR}/connection.h + ${CMAKE_CURRENT_SOURCE_DIR}/authentication.h ${CMAKE_CURRENT_SOURCE_DIR}/utils.h ) diff --git a/include/authentication.h b/include/authentication.h new file mode 100644 index 0000000000000000000000000000000000000000..25f56550e1bb89eaf986d0f115cf2b01e3ec4a12 --- /dev/null +++ b/include/authentication.h @@ -0,0 +1,82 @@ +/* + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2021 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 AUTHENTICATION_H +#define AUTHENTICATION_H +/** + * @file authentication.h + * @author Timm Fitschen + * @date 2021-06-28 + * @brief Configuration and setup of the client authentication. + */ +#include <string> +#include <iosfwd> +#include <memory> +#include <grpc/grpc.h> +#include <grpcpp/security/credentials.h> +#include "utils.h" + +namespace caosdb { +namespace authentication { +using grpc::MetadataCredentialsPlugin; +using grpc::string_ref; +using grpc::AuthContext; +using grpc::Status; +using caosdb::utils::base64_encode; + +/** + * @brief Abstract base class for authenticators. + */ +class Authenticator { +public: + virtual auto getCallCredentials() const -> std::shared_ptr<grpc::CallCredentials> = 0; +}; + +/** + * @brief Implementation of a MetadataCredentialsPlugin which my be created by + * any implementation of the Authenticator class. Only intended for internal + * use. + */ +class MetadataCredentialsPluginImpl : public MetadataCredentialsPlugin { +private: + std::string key; + std::string value; +public: + MetadataCredentialsPluginImpl(std::string key, std::string value); + + Status GetMetadata( + string_ref service_url, string_ref method_name, + const AuthContext& channel_auth_context, + std::multimap<grpc::string, grpc::string>* metadata) override; +}; + +class PlainPasswordAuthenticator : public Authenticator { +private: + std::string basic; +public: + PlainPasswordAuthenticator(const std::string& username, const std::string& password); + + auto getCallCredentials() const -> std::shared_ptr<grpc::CallCredentials> override; + +}; +} // namespace authentication +} // namespace caosdb +#endif diff --git a/include/connection.h b/include/connection.h index 5e3909596e65038f9f4cd5a69c7a658d981babf1..abe12af13d6e5f4decadf0b2d8bf81a9022c7c22 100644 --- a/include/connection.h +++ b/include/connection.h @@ -29,6 +29,7 @@ */ #include <string> #include <iosfwd> +#include "authentication.h" #include <memory> #include <grpc/grpc.h> #include <grpcpp/channel.h> @@ -51,6 +52,7 @@ namespace caosdb { using caosdb::info::v1alpha1::GeneralInfoService; using caosdb::info::v1alpha1::VersionInfo; using grpc::ChannelCredentials; +using caosdb::authentication::Authenticator; class CACertificateProvider { public: @@ -115,6 +117,10 @@ public: SslCaosDBConnectionConfig( const std::string &host, int port, const std::shared_ptr<CACertificateProvider> &cacert); + SslCaosDBConnectionConfig( + const std::string &host, int port, + const std::shared_ptr<CACertificateProvider> &cacert, + const std::shared_ptr<Authenticator> &authenticator); [[nodiscard]] auto getChannelCredentials() const -> std::shared_ptr<ChannelCredentials> override; [[nodiscard]] auto toString() const -> std::string override; diff --git a/include/utils.h b/include/utils.h index e4746664bfd544bb095a961c45bf61baf2802b71..4d7e3ea1a60026342ecac9676825ee0711356262 100644 --- a/include/utils.h +++ b/include/utils.h @@ -62,5 +62,13 @@ inline auto get_env_var(const std::string &key, const std::string &fall_back) } } +/** + * @brief + * @todo use boost-beast's implementation + */ +inline auto base64_encode(const std::string& plain) -> std::string { + return plain; +} + } // namespace caosdb::utils #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 49f850005698c5a18c2956a4689e50fc06249209..9b793ce6025d3c35b6f6736a687307668387cca4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,6 +22,7 @@ # add all source files to this list set(libcaosdb_SRC src/utils.cpp + src/authentication.cpp src/connection.cpp ) diff --git a/src/authentication.cpp b/src/authentication.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b7f47b755ae592a56b3dbf9b1c7c4068d15e825 --- /dev/null +++ b/src/authentication.cpp @@ -0,0 +1,57 @@ +/* + * This file is a part of the CaosDB Project. + * + * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2021 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/>. + * + */ +#include <string> +#include <memory> +#include "authentication.h" +#include <grpcpp/impl/codegen/status.h> +#include <grpcpp/impl/codegen/string_ref.h> +#include <map> +#include <utility> + +namespace caosdb::authentication { +using grpc::MetadataCredentialsPlugin; +using grpc::string_ref; +using grpc::AuthContext; +using grpc::Status; +using caosdb::utils::base64_encode; + +MetadataCredentialsPluginImpl::MetadataCredentialsPluginImpl(std::string key, std::string value) : key(std::move(key)), value(std::move(value)) {}; + +auto MetadataCredentialsPluginImpl::GetMetadata( + string_ref /*service_url*/, string_ref /*method_name*/, + const AuthContext& /*channel_auth_context*/, + std::multimap<grpc::string, grpc::string>* metadata) -> Status { + + metadata->insert(std::make_pair(this->key, this->value)); + return Status::OK; + }; + +PlainPasswordAuthenticator::PlainPasswordAuthenticator(const std::string& username, const std::string& password) { + this->basic = "Basic " + base64_encode(username + ":" + password); + }; + + auto PlainPasswordAuthenticator::getCallCredentials() const -> std::shared_ptr<grpc::CallCredentials> { + auto call_creds = grpc::MetadataCredentialsFromPlugin(std::unique_ptr<grpc::MetadataCredentialsPlugin>( + new MetadataCredentialsPluginImpl("authentication", this->basic))); + return call_creds; + }; + +} // namespace caosdb::authentication diff --git a/src/connection.cpp b/src/connection.cpp index 4ece7f61135f9413bf0e2e54becf494a174c43ef..5505fb85e31fbea95ac4176747a55ff89c9f47c8 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -22,6 +22,7 @@ #include "connection.h" #include "utils.h" +#include "authentication.h" #include <grpcpp/create_channel.h> #include <grpcpp/impl/codegen/client_context.h> #include <grpcpp/impl/codegen/status.h> @@ -41,6 +42,7 @@ using caosdb::utils::load_string_file; using grpc::InsecureChannelCredentials; using grpc::SslCredentials; using grpc::SslCredentialsOptions; +using caosdb::authentication::Authenticator; PemFileCACertProvider::PemFileCACertProvider(const std::string &path) { this->cacert = load_string_file(path); @@ -101,6 +103,18 @@ SslCaosDBConnectionConfig::SslCaosDBConnectionConfig( this->credentials = SslCredentials(options); } +SslCaosDBConnectionConfig::SslCaosDBConnectionConfig( + const std::string &host, int port, + const std::shared_ptr<CACertificateProvider> &cacert, + const std::shared_ptr<Authenticator> &authenticator) + : CaosDBConnectionConfig(host, port) { + + SslCredentialsOptions options; + options.pem_root_certs = cacert->getCACertPem(); + this->credentials = grpc::CompositeChannelCredentials(SslCredentials(options), authenticator->getCallCredentials()); + +} + auto SslCaosDBConnectionConfig::getChannelCredentials() const -> std::shared_ptr<ChannelCredentials> { return this->credentials;