From baaa005e325590f32e7010c47ef4adbed64e671d Mon Sep 17 00:00:00 2001 From: offa Date: Mon, 18 Dec 2023 17:14:15 +0100 Subject: [PATCH 1/5] Add Http support to disable certificate verification (#114) and configure timeouts (#171) --- src/HTTP.cxx | 11 +++++++++++ src/HTTP.h | 4 ++++ test/HttpTest.cxx | 21 +++++++++++++++++++++ test/mock/CprMock.cxx | 5 +++++ test/mock/CprMock.h | 1 + 5 files changed, 42 insertions(+) diff --git a/src/HTTP.cxx b/src/HTTP.cxx index cf579aa..1418130 100644 --- a/src/HTTP.cxx +++ b/src/HTTP.cxx @@ -122,6 +122,17 @@ namespace influxdb::transports } } + void HTTP::setVerifyCertificate(bool verify) + { + session.SetVerifySsl(verify); + } + + void HTTP::setTimeout(std::chrono::milliseconds timeout) + { + session.SetTimeout(timeout); + session.SetConnectTimeout(timeout); + } + std::string HTTP::execute(const std::string& cmd) { session.SetUrl(cpr::Url{endpointUrl + "/query"}); diff --git a/src/HTTP.h b/src/HTTP.h index 66ccf02..09ab729 100644 --- a/src/HTTP.h +++ b/src/HTTP.h @@ -31,6 +31,7 @@ #include "Transport.h" #include #include +#include #include namespace influxdb::transports @@ -71,6 +72,9 @@ namespace influxdb::transports /// Sets proxy void setProxy(const Proxy& proxy) override; + void setVerifyCertificate(bool verify); + void setTimeout(std::chrono::milliseconds timeout); + private: std::string endpointUrl; std::string databaseName; diff --git a/test/HttpTest.cxx b/test/HttpTest.cxx index 3344105..bdfd46d 100644 --- a/test/HttpTest.cxx +++ b/test/HttpTest.cxx @@ -251,6 +251,27 @@ namespace influxdb::test http.setProxy(Proxy{"https://auth-proxy-server:1234", Proxy::Auth{"abc", "def"}}); } + TEST_CASE("Set certificate verification", "[HttpTest]") + { + auto http = createHttp(); + + REQUIRE_CALL(sessionMock, SetVerifySsl(_)).WITH(bool{_1} == false); + http.setVerifyCertificate(false); + + REQUIRE_CALL(sessionMock, SetVerifySsl(_)).WITH(bool{_1} == true); + http.setVerifyCertificate(true); + } + + TEST_CASE("Set timeout sets timeouts", "[HttpTest]") + { + constexpr std::chrono::seconds timeout{3}; + auto http = createHttp(); + + REQUIRE_CALL(sessionMock, SetTimeout(_)).WITH(_1.ms == timeout); + REQUIRE_CALL(sessionMock, SetConnectTimeout(_)).WITH(_1.ms == timeout); + http.setTimeout(timeout); + } + TEST_CASE("Execute sets parameters", "[HttpTest]") { auto http = createHttp(); diff --git a/test/mock/CprMock.cxx b/test/mock/CprMock.cxx index 9a53bac..dc136d2 100644 --- a/test/mock/CprMock.cxx +++ b/test/mock/CprMock.cxx @@ -85,6 +85,11 @@ namespace cpr influxdb::test::sessionMock.SetProxyAuth(std::move(proxy_auth)); } + void Session::SetVerifySsl(const VerifySsl& verify) + { + influxdb::test::sessionMock.SetVerifySsl(verify); + } + void Session::SetParameters(Parameters&& parameters) { influxdb::test::sessionMock.SetParameters(ParametersSpy::toMap(parameters)); diff --git a/test/mock/CprMock.h b/test/mock/CprMock.h index 210572d..92575bd 100644 --- a/test/mock/CprMock.h +++ b/test/mock/CprMock.h @@ -45,6 +45,7 @@ namespace influxdb::test MAKE_MOCK1(SetAuth, void(const cpr::Authentication&)); MAKE_MOCK1(SetProxies, void(cpr::Proxies&&)); MAKE_MOCK1(SetProxyAuth, void(cpr::ProxyAuthentication&&)); + MAKE_MOCK1(SetVerifySsl, void(const cpr::VerifySsl&)); }; extern SessionMock sessionMock; From f849556acc1db4f481316087a9c51cf3a66946f0 Mon Sep 17 00:00:00 2001 From: offa Date: Mon, 18 Dec 2023 17:17:24 +0100 Subject: [PATCH 2/5] Add new API for transport configuration (#216) --- include/InfluxDBBuilder.h | 54 ++++++++++++++++++++++++++++ src/CMakeLists.txt | 1 + src/InfluxDBBuilder.cxx | 74 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 include/InfluxDBBuilder.h create mode 100644 src/InfluxDBBuilder.cxx diff --git a/include/InfluxDBBuilder.h b/include/InfluxDBBuilder.h new file mode 100644 index 0000000..50ca304 --- /dev/null +++ b/include/InfluxDBBuilder.h @@ -0,0 +1,54 @@ +// MIT License +// +// Copyright (c) 2020-2023 offa +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef INFLUXDATA_INFLUXDBBUILDER_H +#define INFLUXDATA_INFLUXDBBUILDER_H + +#include "InfluxDB.h" +#include "Transport.h" +#include "Proxy.h" +#include "influxdb_export.h" +#include + +namespace influxdb +{ + class INFLUXDB_EXPORT InfluxDBBuilder + { + public: + std::unique_ptr connect(); + + InfluxDBBuilder&& setBasicAuthentication(const std::string& user, const std::string& pass); + InfluxDBBuilder&& setAuthToken(const std::string& token); + InfluxDBBuilder&& setProxy(const Proxy& proxy); + InfluxDBBuilder&& setTimeout(std::chrono::milliseconds timeout); + InfluxDBBuilder&& setVerifyCertificate(bool verify); + + static InfluxDBBuilder http(const std::string& url); + + private: + explicit InfluxDBBuilder(std::unique_ptr impl); + + std::unique_ptr transport; + }; +} + +#endif // INFLUXDATA_INFLUXDBBUILDER_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3c58bd2..8763f48 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,7 @@ add_library(InfluxDB-Core OBJECT InfluxDB.cxx Point.cxx InfluxDBFactory.cxx + InfluxDBBuilder.cxx Proxy.cxx ) target_include_directories(InfluxDB-Core PUBLIC diff --git a/src/InfluxDBBuilder.cxx b/src/InfluxDBBuilder.cxx new file mode 100644 index 0000000..d4e284a --- /dev/null +++ b/src/InfluxDBBuilder.cxx @@ -0,0 +1,74 @@ +// MIT License +// +// Copyright (c) 2020-2023 offa +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#include "InfluxDBBuilder.h" +#include "HTTP.h" + +namespace influxdb +{ + InfluxDBBuilder::InfluxDBBuilder(std::unique_ptr impl) + : transport(std::move(impl)) + { + } + + std::unique_ptr InfluxDBBuilder::connect() + { + return std::make_unique(std::move(transport)); + } + + InfluxDBBuilder&& InfluxDBBuilder::setBasicAuthentication(const std::string& user, const std::string& pass) + { + dynamic_cast(*transport).setBasicAuthentication(user, pass); + return std::move(*this); + } + + InfluxDBBuilder&& InfluxDBBuilder::setAuthToken(const std::string& token) + { + dynamic_cast(*transport).setAuthToken(token); + return std::move(*this); + } + + InfluxDBBuilder&& InfluxDBBuilder::setProxy(const Proxy& proxy) + { + dynamic_cast(*transport).setProxy(proxy); + return std::move(*this); + } + + InfluxDBBuilder&& InfluxDBBuilder::setTimeout(std::chrono::milliseconds timeout) + { + dynamic_cast(*transport).setTimeout(timeout); + return std::move(*this); + } + + InfluxDBBuilder&& InfluxDBBuilder::setVerifyCertificate(bool verify) + { + dynamic_cast(*transport).setVerifyCertificate(verify); + return std::move(*this); + } + + InfluxDBBuilder InfluxDBBuilder::http(const std::string& url) + { + return InfluxDBBuilder{std::make_unique(url)}; + } + + +} From 55bbc07ef46afec9bb982ab853fbf5c0e3522716 Mon Sep 17 00:00:00 2001 From: offa Date: Thu, 1 Feb 2024 16:49:09 +0100 Subject: [PATCH 3/5] Add system tests for transport API (#216) --- test/system/HttpAuthST.cxx | 26 ++++++++++++++++++++++++++ test/system/InfluxDBST.cxx | 22 ++++++++++++++++++++++ test/system/SystemTest.h | 8 ++++++-- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/test/system/HttpAuthST.cxx b/test/system/HttpAuthST.cxx index aa0ce3f..9525ea9 100644 --- a/test/system/HttpAuthST.cxx +++ b/test/system/HttpAuthST.cxx @@ -21,6 +21,7 @@ // SOFTWARE. #include "SystemTest.h" +#include "InfluxDBBuilder.h" namespace influxdb::test { @@ -43,4 +44,29 @@ namespace influxdb::test CHECK_THAT(response, ContainsSubstring(user.name)); } } + + TEST_CASE("Http authentication methods", "[HttpAuthTest]") + { + using Catch::Matchers::ContainsSubstring; + + const auto user = getUserFromEnv(); + + SECTION("Authenticate through factory") + { + auto db = InfluxDBFactory::Get("http://" + (user.name + ":" + user.pass + "@") + getHostFromEnv() + ":8086?db=ignore"); + + const auto response = db->execute("show users"); + CHECK_THAT(response, ContainsSubstring(user.name)); + } + + SECTION("Authenticate through builder") + { + auto db = InfluxDBBuilder::http("http://" + getHostFromEnv() + ":8086?db=ignore") + .setBasicAuthentication(user.name, user.pass) + .connect(); + + const auto response = db->execute("show users"); + CHECK_THAT(response, ContainsSubstring(user.name)); + } + } } diff --git a/test/system/InfluxDBST.cxx b/test/system/InfluxDBST.cxx index 46b15de..50a9a9c 100644 --- a/test/system/InfluxDBST.cxx +++ b/test/system/InfluxDBST.cxx @@ -21,6 +21,7 @@ // SOFTWARE. #include "SystemTest.h" +#include "InfluxDBBuilder.h" namespace influxdb::test { @@ -38,6 +39,27 @@ namespace influxdb::test } } + TEST_CASE("Connection configuration", "[InfluxDBST]") + { + using namespace Catch::Matchers; + + SECTION("Connect through factory") + { + auto db = InfluxDBFactory::Get("http://" + getHostFromEnv() + ":8086?db=ignore"); + const auto response = db->execute("show databases"); + CHECK(response.empty() == false); + } + + SECTION("Connect through builder") + { + auto db = InfluxDBBuilder::http("http://" + getHostFromEnv() + ":8086?db=ignore") + .setTimeout(std::chrono::seconds{5}) + .connect(); + const auto response = db->execute("show databases"); + CHECK(response.empty() == false); + } + } + TEST_CASE("InfluxDB system test", "[InfluxDBST]") { using namespace Catch::Matchers; diff --git a/test/system/SystemTest.h b/test/system/SystemTest.h index bccb969..67f07b6 100644 --- a/test/system/SystemTest.h +++ b/test/system/SystemTest.h @@ -61,10 +61,14 @@ namespace influxdb::test return {*user, *pass}; } + inline std::string getHostFromEnv() + { + return getEnv("INFLUXDBCXX_SYSTEMTEST_HOST").value_or("localhost"); + } + inline std::unique_ptr configure(const std::string& db, std::optional user = {}) { - const auto host = getEnv("INFLUXDBCXX_SYSTEMTEST_HOST").value_or("localhost"); const std::string authString{user ? (user->name + ":" + user->pass + "@") : ""}; - return InfluxDBFactory::Get("http://" + authString + host + ":8086?db=" + db); + return InfluxDBFactory::Get("http://" + authString + getHostFromEnv() + ":8086?db=" + db); } } From 5f840651054c9537c6f4477eb8dc3cbf0acd90f6 Mon Sep 17 00:00:00 2001 From: offa Date: Thu, 1 Feb 2024 17:20:47 +0100 Subject: [PATCH 4/5] Update transport docs (#220) --- README.md | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 4a88844..93f1860 100644 --- a/README.md +++ b/README.md @@ -120,15 +120,7 @@ const auto response = influxdb->execute("SHOW DATABASES"); ## Transports -An underlying transport is fully configurable by passing an URI: -``` -[protocol]://[username:password@]host:port[?db=database] - -# Auth token: -[protocol]://[token@]host:port[?db=database] -``` -
-List of supported transport is following: +Supported transports: | Name | Dependency | URI protocol | Sample URI | | ----------- |:-----------:|:--------------:| -------------------------------------:| @@ -137,9 +129,36 @@ List of supported transport is following: | UDP | boost | `udp` | `udp://localhost:8094` | | Unix socket | boost | `unix` | `unix:///tmp/telegraf.sock` | - i) boost is needed to support queries. +### Configuration by URI + +An underlying transport is configurable by passing an URI. `[protocol]` determines the actual transport type: + +```cpp +auto influxdb = influxdb::InfluxDBFactory::Get("http://localhost:8086?db=test"); +``` + +URI Format: + +``` +[protocol]://[username:password@]host:port[?db=database] + +# Auth token: +[protocol]://[token@]host:port[?db=database] +``` + +### Additional transport configuration *(HTTP only)* + +The HTTP transport supports additional configurations beyond the limited URI parameters: + +```cpp +auto influxdb = InfluxDBBuilder::http("http://localhost:8086?db=test") + .setTimeout(std::chrono::seconds{20}) + .setAuthToken("") + .connect(); +``` + ## InfluxDB v2.x compatibility From 50faea555e742bb8c25a88d050e19b74f4e722bd Mon Sep 17 00:00:00 2001 From: offa Date: Sun, 4 Feb 2024 14:24:28 +0100 Subject: [PATCH 5/5] Update date --- include/InfluxDBBuilder.h | 2 +- src/InfluxDBBuilder.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/InfluxDBBuilder.h b/include/InfluxDBBuilder.h index 50ca304..7acafe3 100644 --- a/include/InfluxDBBuilder.h +++ b/include/InfluxDBBuilder.h @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2020-2023 offa +// Copyright (c) 2020-2024 offa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal diff --git a/src/InfluxDBBuilder.cxx b/src/InfluxDBBuilder.cxx index d4e284a..1706cb7 100644 --- a/src/InfluxDBBuilder.cxx +++ b/src/InfluxDBBuilder.cxx @@ -1,6 +1,6 @@ // MIT License // -// Copyright (c) 2020-2023 offa +// Copyright (c) 2020-2024 offa // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal