Skip to content

Commit f4474e6

Browse files
committed
[fix] Use ClientConfiguration::getTlsTrustCertsFilePath for the OAuth2 flow
Fixes apache#184 ### Modifications Add a `AuthenticationDataProvider` implementation `InitialAuthData`, which holds the CA cert path. Then, in `AuthOauth2::getAuthData`, retrieve the path and pass it to the `ClientCredentialFlow` for HTTP requests performed by libcurl. This solution is API and ABI compatible. ### Verifications It's hard to add the test in CI because we need an OAuth2 server configured with the CA configured. Follow the **How to reproduce** section in apache#184 (comment) to reproduce this issue. Apply this patch and build the `libpulsar.so` with `LINK_STATIC=ON`, then copy the `libpulsar.so` into the docker container (under `/app/lib`). Run `./a.out` directly, you will still see the `AuthenticationError`. However, if you added the path of `libpulsar.so` to the `LD_LIBRARY_PATH`: ```bash export LD_LIBRARY_PATH=/app/lib ./a.out ``` No error will happen. You can also replace the `/lib/libpulsar.so` with the `libpulsar.so` built from source. (cherry picked from commit d7eb539)
1 parent 56bf7bf commit f4474e6

File tree

4 files changed

+65
-1
lines changed

4 files changed

+65
-1
lines changed

lib/ClientConnection.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "ProducerImpl.h"
3131
#include "PulsarApi.pb.h"
3232
#include "Url.h"
33+
#include "auth/InitialAuthData.h"
3334
#include "checksum/ChecksumProvider.h"
3435

3536
DECLARE_LOG_OBJECT()
@@ -224,7 +225,8 @@ ClientConnection::ClientConnection(const std::string& logicalAddress, const std:
224225
std::string tlsCertificates = clientConfiguration.getTlsCertificateFilePath();
225226
std::string tlsPrivateKey = clientConfiguration.getTlsPrivateKeyFilePath();
226227

227-
AuthenticationDataPtr authData;
228+
auto authData = std::dynamic_pointer_cast<AuthenticationDataProvider>(
229+
std::make_shared<InitialAuthData>(clientConfiguration.getTlsTrustCertsFilePath()));
228230
if (authentication_->getAuthData(authData) == ResultOk && authData->hasDataForTls()) {
229231
tlsCertificates = authData->getTlsCertificates();
230232
tlsPrivateKey = authData->getTlsPrivateKey();

lib/auth/AuthOauth2.cc

+18
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <sstream>
2626
#include <stdexcept>
2727

28+
#include "InitialAuthData.h"
2829
#include "lib/LogUtils.h"
2930
DECLARE_LOG_OBJECT()
3031

@@ -191,6 +192,10 @@ void ClientCredentialFlow::initialize() {
191192
char errorBuffer[CURL_ERROR_SIZE];
192193
curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errorBuffer);
193194

195+
if (!tlsTrustCertsFilePath_.empty()) {
196+
curl_easy_setopt(handle, CURLOPT_CAINFO, tlsTrustCertsFilePath_.c_str());
197+
}
198+
194199
// Make get call to server
195200
res = curl_easy_perform(handle);
196201

@@ -317,6 +322,10 @@ Oauth2TokenResultPtr ClientCredentialFlow::authenticate() {
317322
char errorBuffer[CURL_ERROR_SIZE];
318323
curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errorBuffer);
319324

325+
if (!tlsTrustCertsFilePath_.empty()) {
326+
curl_easy_setopt(handle, CURLOPT_CAINFO, tlsTrustCertsFilePath_.c_str());
327+
}
328+
320329
// Make get call to server
321330
res = curl_easy_perform(handle);
322331

@@ -401,6 +410,15 @@ AuthenticationPtr AuthOauth2::create(ParamMap& params) { return AuthenticationPt
401410
const std::string AuthOauth2::getAuthMethodName() const { return "token"; }
402411

403412
Result AuthOauth2::getAuthData(AuthenticationDataPtr& authDataContent) {
413+
auto initialAuthData = std::dynamic_pointer_cast<InitialAuthData>(authDataContent);
414+
if (initialAuthData) {
415+
auto flowPtr = std::dynamic_pointer_cast<ClientCredentialFlow>(flowPtr_);
416+
if (!flowPtr_) {
417+
throw std::invalid_argument("AuthOauth2::flowPtr_ is not a ClientCredentialFlow");
418+
}
419+
flowPtr->setTlsTrustCertsFilePath(initialAuthData->tlsTrustCertsFilePath_);
420+
}
421+
404422
if (cachedTokenPtr_ == nullptr || cachedTokenPtr_->isExpired()) {
405423
try {
406424
cachedTokenPtr_ = CachedTokenPtr(new Oauth2CachedToken(flowPtr_->authenticate()));

lib/auth/AuthOauth2.h

+5
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,17 @@ class ClientCredentialFlow : public Oauth2Flow {
6060
ParamMap generateParamMap() const;
6161
std::string getTokenEndPoint() const;
6262

63+
void setTlsTrustCertsFilePath(const std::string& tlsTrustCertsFilePath) {
64+
tlsTrustCertsFilePath_ = tlsTrustCertsFilePath;
65+
}
66+
6367
private:
6468
std::string tokenEndPoint_;
6569
const std::string issuerUrl_;
6670
const KeyFile keyFile_;
6771
const std::string audience_;
6872
const std::string scope_;
73+
std::string tlsTrustCertsFilePath_;
6974
std::once_flag initializeOnce_;
7075
};
7176

lib/auth/InitialAuthData.h

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
#pragma once
20+
21+
#include <pulsar/Authentication.h>
22+
23+
namespace pulsar {
24+
25+
class ClientConfiguration;
26+
27+
struct InitialAuthData : public AuthenticationDataProvider {
28+
const std::string tlsTrustCertsFilePath_;
29+
30+
InitialAuthData(const std::string& tlsTrustCertsFilePath)
31+
: tlsTrustCertsFilePath_(tlsTrustCertsFilePath) {}
32+
33+
bool hasDataForHttp() override { return false; }
34+
std::string getHttpHeaders() override { return ""; }
35+
bool hasDataFromCommand() override { return false; }
36+
std::string getCommandData() override { return ""; }
37+
};
38+
39+
} // namespace pulsar

0 commit comments

Comments
 (0)