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

xyz pushed a commit to branch branch-3.4
in repository https://gitbox.apache.org/repos/asf/pulsar-client-cpp.git

commit afe54daa51e1759b8a75503dce6e84b28f4ff2e5
Author: Yunze Xu <[email protected]>
AuthorDate: Wed Dec 6 10:41:04 2023 +0800

    Fix tlsTrustCertsFilePath config is not applied for OAuth2 (#364)
    
    ### Motivation
    
    https://github.com/apache/pulsar-client-cpp/pull/313 has reverted the
    fix of https://github.com/apache/pulsar-client-cpp/pull/190, which
    applies the `tlsTrustCertsFilePath` config for OAuth2 authentication.
    
    The macOS pre-built libraries are affected most because the bundled CA
    path is empty.
    
    ### Modification
    
    Apply the `tlsTrustCertsFilePath` for OAuth2.
    
    (cherry picked from commit 27cba3e7d154f97e01911cd5de2cc0d4eaf2ef50)
---
 lib/ClientConfiguration.cc |  1 +
 lib/ClientConnection.cc    | 12 ++++++++++--
 lib/auth/AuthOauth2.cc     |  9 +++++++--
 run-unit-tests.sh          |  9 ++++++++-
 tests/oauth2/Oauth2Test.cc | 21 +++++++++++++++++++++
 5 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/lib/ClientConfiguration.cc b/lib/ClientConfiguration.cc
index 977a880..63c0bf8 100644
--- a/lib/ClientConfiguration.cc
+++ b/lib/ClientConfiguration.cc
@@ -19,6 +19,7 @@
 #include <stdexcept>
 
 #include "ClientConfigurationImpl.h"
+#include "auth/AuthOauth2.h"
 
 namespace pulsar {
 
diff --git a/lib/ClientConnection.cc b/lib/ClientConnection.cc
index 4086bdd..97d8847 100644
--- a/lib/ClientConnection.cc
+++ b/lib/ClientConnection.cc
@@ -33,6 +33,7 @@
 #include "PulsarApi.pb.h"
 #include "ResultUtils.h"
 #include "Url.h"
+#include "auth/AuthOauth2.h"
 #include "auth/InitialAuthData.h"
 #include "checksum/ChecksumProvider.h"
 
@@ -193,6 +194,14 @@ ClientConnection::ClientConnection(const std::string& 
logicalAddress, const std:
         return;
     }
 
+    auto oauth2Auth = std::dynamic_pointer_cast<AuthOauth2>(authentication_);
+    if (oauth2Auth) {
+        // Configure the TLS trust certs file for Oauth2
+        auto authData = std::dynamic_pointer_cast<AuthenticationDataProvider>(
+            
std::make_shared<InitialAuthData>(clientConfiguration.getTlsTrustCertsFilePath()));
+        oauth2Auth->getAuthData(authData);
+    }
+
     if (clientConfiguration.isUseTls()) {
 #if BOOST_VERSION >= 105400
         boost::asio::ssl::context 
ctx(boost::asio::ssl::context::tlsv12_client);
@@ -223,8 +232,7 @@ ClientConnection::ClientConnection(const std::string& 
logicalAddress, const std:
         std::string tlsCertificates = 
clientConfiguration.getTlsCertificateFilePath();
         std::string tlsPrivateKey = 
clientConfiguration.getTlsPrivateKeyFilePath();
 
-        auto authData = std::dynamic_pointer_cast<AuthenticationDataProvider>(
-            
std::make_shared<InitialAuthData>(clientConfiguration.getTlsTrustCertsFilePath()));
+        AuthenticationDataPtr authData;
         if (authentication_->getAuthData(authData) == ResultOk && 
authData->hasDataForTls()) {
             tlsCertificates = authData->getTlsCertificates();
             tlsPrivateKey = authData->getTlsPrivateKey();
diff --git a/lib/auth/AuthOauth2.cc b/lib/auth/AuthOauth2.cc
index 799843b..c074557 100644
--- a/lib/auth/AuthOauth2.cc
+++ b/lib/auth/AuthOauth2.cc
@@ -342,8 +342,13 @@ Oauth2TokenResultPtr ClientCredentialFlow::authenticate() {
 
     CurlWrapper::Options options;
     options.postFields = std::move(postData);
-    auto result =
-        curl.get(tokenEndPoint_, "Content-Type: 
application/x-www-form-urlencoded", options, nullptr);
+    std::unique_ptr<CurlWrapper::TlsContext> tlsContext;
+    if (!tlsTrustCertsFilePath_.empty()) {
+        tlsContext.reset(new CurlWrapper::TlsContext);
+        tlsContext->trustCertsFilePath = tlsTrustCertsFilePath_;
+    }
+    auto result = curl.get(tokenEndPoint_, "Content-Type: 
application/x-www-form-urlencoded", options,
+                           tlsContext.get());
     if (!result.error.empty()) {
         LOG_ERROR("Failed to get the well-known configuration " << issuerUrl_ 
<< ": " << result.error);
         return resultPtr;
diff --git a/run-unit-tests.sh b/run-unit-tests.sh
index 693267f..898cfed 100755
--- a/run-unit-tests.sh
+++ b/run-unit-tests.sh
@@ -35,7 +35,14 @@ docker compose -f tests/oauth2/docker-compose.yml up -d
 # Wait until the namespace is created, currently there is no good way to check 
it
 # because it's hard to configure OAuth2 authentication via CLI.
 sleep 15
-$CMAKE_BUILD_DIRECTORY/tests/Oauth2Test
+$CMAKE_BUILD_DIRECTORY/tests/Oauth2Test --gtest_filter='-*testTlsTrustFilePath'
+if [[ -f /etc/ssl/certs/ca-certificates.crt ]]; then
+    sudo mv /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/my-cert.crt
+fi
+$CMAKE_BUILD_DIRECTORY/tests/Oauth2Test --gtest_filter='*testTlsTrustFilePath'
+if [[ -f /etc/ssl/certs/my-cert.crt ]]; then
+    sudo mv /etc/ssl/certs/my-cert.crt /etc/ssl/certs/ca-certificates.crt
+fi
 docker compose -f tests/oauth2/docker-compose.yml down
 
 # Run BrokerMetadata tests
diff --git a/tests/oauth2/Oauth2Test.cc b/tests/oauth2/Oauth2Test.cc
index 719ae69..158065e 100644
--- a/tests/oauth2/Oauth2Test.cc
+++ b/tests/oauth2/Oauth2Test.cc
@@ -22,6 +22,7 @@
 
 #include <boost/property_tree/json_parser.hpp>
 #include <boost/property_tree/ptree.hpp>
+#include <fstream>
 
 #include "lib/Base64Utils.h"
 
@@ -64,6 +65,26 @@ TEST(Oauth2Test, testWrongUrl) {
     ASSERT_EQ(ResultAuthenticationError, testCreateProducer("my-protocol:" + 
gKeyPath));
 }
 
+TEST(Oauth2Test, testTlsTrustFilePath) {
+    const auto caPath = "/etc/ssl/certs/my-cert.crt";
+    std::ifstream fin{caPath};
+    if (!fin) {  // Skip this test if the CA cert is not prepared
+        return;
+    }
+    fin.close();
+
+    ClientConfiguration conf;
+    conf.setTlsTrustCertsFilePath(caPath);
+    auto params = gCommonParams;
+    params["private_key"] = "file://" + gKeyPath;
+    conf.setAuth(AuthOauth2::create(params));
+
+    Client client{"pulsar://localhost:6650", conf};
+    Producer producer;
+    ASSERT_EQ(ResultOk, client.createProducer("oauth2-test", producer));
+    client.close();
+}
+
 int main(int argc, char* argv[]) {
     std::cout << "Load Oauth2 configs from " << gKeyPath << "..." << std::endl;
     boost::property_tree::ptree root;

Reply via email to