You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by sz...@apache.org on 2022/08/22 20:13:05 UTC

[nifi-minifi-cpp] 03/05: MINIFICPP-1882 centos build default CA doesnt work on ubuntu

This is an automated email from the ASF dual-hosted git repository.

szaszm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git

commit c65d4cde89efb145c4ec2901792a2fb54f3ed3e1
Author: Martin Zink <ma...@apache.org>
AuthorDate: Mon Aug 22 21:37:49 2022 +0200

    MINIFICPP-1882 centos build default CA doesnt work on ubuntu
    
    Closes #1393
    Signed-off-by: Marton Szasz <sz...@apache.org>
---
 extensions/http-curl/client/HTTPClient.cpp         | 82 ++++++++++++----------
 extensions/http-curl/client/HTTPClient.h           |  3 +-
 .../http-curl/tests/unit/HTTPClientTests.cpp       |  8 +++
 3 files changed, 56 insertions(+), 37 deletions(-)

diff --git a/extensions/http-curl/client/HTTPClient.cpp b/extensions/http-curl/client/HTTPClient.cpp
index 185593c51..4cf455972 100644
--- a/extensions/http-curl/client/HTTPClient.cpp
+++ b/extensions/http-curl/client/HTTPClient.cpp
@@ -123,9 +123,8 @@ void HTTPClient::initialize(const std::string &method, const std::string url, co
   if (!url.empty()) {
     url_ = url;
   }
-  if (isSecure(url_) && ssl_context_service_ != nullptr) {
-    configure_secure_connection(http_session_);
-  }
+  if (isSecure(url_))
+    configure_secure_connection();
 }
 
 void HTTPClient::setDisablePeerVerification() {
@@ -387,41 +386,33 @@ int HTTPClient::onProgress(void *clientp, curl_off_t /*dltotal*/, curl_off_t dln
   return 0;
 }
 
-void HTTPClient::configure_secure_connection(CURL *http_session) {
-  logger_->log_debug("Using certificate file \"%s\"", ssl_context_service_->getCertificateFile());
-  logger_->log_debug("Using private key file \"%s\"", ssl_context_service_->getPrivateKeyFile());
-  logger_->log_debug("Using CA certificate file \"%s\"", ssl_context_service_->getCACertificate());
-#if 0  // Reenable this path once we change from the direct manipulation of the SSL context to using the cURL API
-  if (!ssl_context_service_->getCertificateFile().empty()) {
-    if (utils::StringUtils::endsWith(ssl_context_service_->getCertificateFile(), "p12", false)) {
-      curl_easy_setopt(http_session, CURLOPT_SSLCERTTYPE, "P12");
-    } else {
-      curl_easy_setopt(http_session, CURLOPT_SSLCERTTYPE, "PEM");
-    }
-    curl_easy_setopt(http_session, CURLOPT_SSLCERT, ssl_context_service_->getCertificateFile().c_str());
-  }
-  if (!ssl_context_service_->getPrivateKeyFile().empty()) {
-    if (utils::StringUtils::endsWith(ssl_context_service_->getPrivateKeyFile(), "p12", false)) {
-      curl_easy_setopt(http_session, CURLOPT_SSLKEYTYPE, "P12");
-    } else {
-      curl_easy_setopt(http_session, CURLOPT_SSLKEYTYPE, "PEM");
-    }
-    curl_easy_setopt(http_session, CURLOPT_SSLKEY, ssl_context_service_->getPrivateKeyFile().c_str());
-    curl_easy_setopt(http_session, CURLOPT_KEYPASSWD, ssl_context_service_->getPassphrase().c_str());
-  }
-  if (!ssl_context_service_->getCACertificate().empty()) {
-    curl_easy_setopt(http_session, CURLOPT_CAINFO, ssl_context_service_->getCACertificate().c_str());
+void HTTPClient::configure_secure_connection() {
+#ifdef OPENSSL_SUPPORT
+  if (ssl_context_service_) {
+    logger_->log_debug("Using certificate file \"%s\"", ssl_context_service_->getCertificateFile());
+    logger_->log_debug("Using private key file \"%s\"", ssl_context_service_->getPrivateKeyFile());
+    logger_->log_debug("Using CA certificate file \"%s\"", ssl_context_service_->getCACertificate());
+
+    curl_easy_setopt(http_session_, CURLOPT_SSL_CTX_FUNCTION, &configure_ssl_context);
+    curl_easy_setopt(http_session_, CURLOPT_SSL_CTX_DATA, static_cast<void *>(ssl_context_service_.get()));
+    curl_easy_setopt(http_session_, CURLOPT_CAINFO, nullptr);
+    curl_easy_setopt(http_session_, CURLOPT_CAPATH, nullptr);
   } else {
-    curl_easy_setopt(http_session, CURLOPT_CAINFO, nullptr);
+    static const auto default_ca_path = getDefaultCAPath();
+
+    if (default_ca_path)
+      logger_->log_debug("Using CA certificate file \"%s\"", default_ca_path->string());
+    else
+      logger_->log_error("Could not find valid CA certificate file");
+
+    curl_easy_setopt(http_session_, CURLOPT_SSL_CTX_FUNCTION, nullptr);
+    curl_easy_setopt(http_session_, CURLOPT_SSL_CTX_DATA, nullptr);
+    if (default_ca_path)
+      curl_easy_setopt(http_session_, CURLOPT_CAINFO, default_ca_path->string().c_str());
+    else
+      curl_easy_setopt(http_session_, CURLOPT_CAINFO, nullptr);
+    curl_easy_setopt(http_session_, CURLOPT_CAPATH, nullptr);
   }
-  curl_easy_setopt(http_session, CURLOPT_CAPATH, nullptr);
-#else
-#ifdef OPENSSL_SUPPORT
-  curl_easy_setopt(http_session, CURLOPT_SSL_CTX_FUNCTION, &configure_ssl_context);
-  curl_easy_setopt(http_session, CURLOPT_SSL_CTX_DATA, static_cast<void*>(ssl_context_service_.get()));
-  curl_easy_setopt(http_session, CURLOPT_CAINFO, 0);
-  curl_easy_setopt(http_session, CURLOPT_CAPATH, 0);
-#endif
 #endif
 }
 
@@ -465,6 +456,25 @@ std::string HTTPClient::replaceInvalidCharactersInHttpHeaderFieldName(std::strin
   return field_name;
 }
 
+std::optional<std::filesystem::path> HTTPClient::getDefaultCAPath() {
+#ifndef WIN32
+  const std::vector<std::filesystem::path> possible_ca_paths = {
+      "/etc/ssl/certs/ca-certificates.crt",
+      "/etc/pki/tls/certs/ca-bundle.crt",
+      "/usr/share/ssl/certs/ca-bundle.crt",
+      "/usr/local/share/certs/ca-root-nss.crt",
+      "/etc/ssl/cert.pem"
+  };
+
+  for (const auto& possible_ca_path : possible_ca_paths) {
+    if (std::filesystem::exists(possible_ca_path)) {
+      return possible_ca_path;
+    }
+  }
+#endif
+  return std::nullopt;
+}
+
 REGISTER_RESOURCE(HTTPClient, InternalResource);
 
 }  // namespace org::apache::nifi::minifi::utils
diff --git a/extensions/http-curl/client/HTTPClient.h b/extensions/http-curl/client/HTTPClient.h
index 0ce64b882..ededeb5e2 100644
--- a/extensions/http-curl/client/HTTPClient.h
+++ b/extensions/http-curl/client/HTTPClient.h
@@ -238,6 +238,7 @@ class HTTPClient : public BaseHTTPClient, public core::Connectable {
 
   static bool isValidHttpHeaderField(std::string_view field_name);
   static std::string replaceInvalidCharactersInHttpHeaderFieldName(std::string field_name);
+  static std::optional<std::filesystem::path> getDefaultCAPath();
 
  private:
   static int onProgress(void *client, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
@@ -268,7 +269,7 @@ class HTTPClient : public BaseHTTPClient, public core::Connectable {
 #endif
   }
 
-  void configure_secure_connection(CURL *http_session);
+  void configure_secure_connection();
 
   bool isSecure(const std::string &url);
 
diff --git a/extensions/http-curl/tests/unit/HTTPClientTests.cpp b/extensions/http-curl/tests/unit/HTTPClientTests.cpp
index 87e1050da..dc1e0225c 100644
--- a/extensions/http-curl/tests/unit/HTTPClientTests.cpp
+++ b/extensions/http-curl/tests/unit/HTTPClientTests.cpp
@@ -113,3 +113,11 @@ TEST_CASE("HTTPClient replaceInvalidCharactersInHttpHeaderFieldName test") {
   CHECK(utils::HTTPClient::replaceInvalidCharactersInHttpHeaderFieldName(std::string("invalid") + static_cast<char>(128) + "character") == "invalid-character");
   CHECK(utils::HTTPClient::replaceInvalidCharactersInHttpHeaderFieldName("contains:invalid") == "contains-invalid");
 }
+
+#ifdef __linux__
+TEST_CASE("SSL without SSLContextService", "[HTTPClient]") {
+  utils::HTTPClient client;
+  client.initialize("GET", "https://apache.org", nullptr);
+  REQUIRE(client.submit());
+}
+#endif