This is an automated email from the ASF dual-hosted git repository.
baodi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-client-node.git
The following commit(s) were added to refs/heads/master by this push:
new 772ab49 Support separate TLS handshake certificate/private key in
Client (#440)
772ab49 is described below
commit 772ab491e97e34919519b829890dab852ed3c34f
Author: Baodi Shi <[email protected]>
AuthorDate: Thu Nov 27 21:32:35 2025 +0800
Support separate TLS handshake certificate/private key in Client (#440)
### Motivation
Support separate TLS handshake certificate/private key parameters
independent from auth, enabling proper mTLS handshake configuration.
### Modifications
- Add and to .
- Wire to C client via and .
- Update end-to-end test to provide client cert/key for TLS endpoints.
### Verifying this change
- Ran only for cases; TLS endpoints pass with client cert/key.
### Documentation
- [x] doc-not-needed (Type hints updated in ).
---
index.d.ts | 2 ++
src/Client.cc | 14 ++++++++++++++
tests/conf/standalone.conf | 4 +++-
tests/end_to_end.test.js | 4 ++++
4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/index.d.ts b/index.d.ts
index e9bf8e8..9dc3e8f 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -27,6 +27,8 @@ export interface ClientConfig {
concurrentLookupRequest?: number;
useTls?: boolean;
tlsTrustCertsFilePath?: string;
+ tlsCertificateFilePath?: string;
+ tlsPrivateKeyFilePath?: string;
tlsValidateHostname?: boolean;
tlsAllowInsecureConnection?: boolean;
statsIntervalInSeconds?: number;
diff --git a/src/Client.cc b/src/Client.cc
index 80052f0..29d542c 100644
--- a/src/Client.cc
+++ b/src/Client.cc
@@ -39,6 +39,8 @@ static const std::string CFG_USE_TLS = "useTls";
static const std::string CFG_TLS_TRUST_CERT = "tlsTrustCertsFilePath";
static const std::string CFG_TLS_VALIDATE_HOSTNAME = "tlsValidateHostname";
static const std::string CFG_TLS_ALLOW_INSECURE = "tlsAllowInsecureConnection";
+static const std::string CFG_TLS_CERT_FILE = "tlsCertificateFilePath";
+static const std::string CFG_TLS_PRIVATE_KEY_FILE = "tlsPrivateKeyFilePath";
static const std::string CFG_STATS_INTERVAL = "statsIntervalInSeconds";
static const std::string CFG_LOG = "log";
static const std::string CFG_LOG_LEVEL = "logLevel";
@@ -196,6 +198,18 @@ Client::Client(const Napi::CallbackInfo &info) :
Napi::ObjectWrap<Client>(info)
tlsTrustCertsFilePath.Utf8Value().c_str());
}
+ if (clientConfig.Has(CFG_TLS_CERT_FILE) &&
clientConfig.Get(CFG_TLS_CERT_FILE).IsString()) {
+ Napi::String tlsCertFilePath =
clientConfig.Get(CFG_TLS_CERT_FILE).ToString();
+
pulsar_client_configuration_set_tls_certificate_file_path(cClientConfig.get(),
+
tlsCertFilePath.Utf8Value().c_str());
+ }
+
+ if (clientConfig.Has(CFG_TLS_PRIVATE_KEY_FILE) &&
clientConfig.Get(CFG_TLS_PRIVATE_KEY_FILE).IsString()) {
+ Napi::String tlsPrivateKeyFilePath =
clientConfig.Get(CFG_TLS_PRIVATE_KEY_FILE).ToString();
+
pulsar_client_configuration_set_tls_private_key_file_path(cClientConfig.get(),
+
tlsPrivateKeyFilePath.Utf8Value().c_str());
+ }
+
if (clientConfig.Has(CFG_TLS_VALIDATE_HOSTNAME) &&
clientConfig.Get(CFG_TLS_VALIDATE_HOSTNAME).IsBoolean()) {
Napi::Boolean tlsValidateHostname =
clientConfig.Get(CFG_TLS_VALIDATE_HOSTNAME).ToBoolean();
diff --git a/tests/conf/standalone.conf b/tests/conf/standalone.conf
index b3618fa..e0789a3 100755
--- a/tests/conf/standalone.conf
+++ b/tests/conf/standalone.conf
@@ -115,6 +115,9 @@ tlsKeyFilePath=/pulsar/test-conf/server.key
# fails, then the certs are untrusted and the connections are dropped.
tlsTrustCertsFilePath=/pulsar/test-conf/server.crt
+# Require clients to present a trusted certificate (enable mTLS)
+tlsRequireTrustedClientCertOnConnect=true
+
### --- Authentication --- ###
# Enable authentication
@@ -305,4 +308,3 @@ brokerServicePurgeInactiveFrequencyInSeconds=60
# The maximum netty frame size in bytes. Any message received larger than this
will be rejected. The default value is 5MB.
nettyMaxFrameSizeBytes=5253120
-
diff --git a/tests/end_to_end.test.js b/tests/end_to_end.test.js
index ce3693f..2c08418 100644
--- a/tests/end_to_end.test.js
+++ b/tests/end_to_end.test.js
@@ -34,6 +34,10 @@ const Pulsar = require('../index');
operationTimeoutSeconds: 30,
connectionTimeoutMs: 20000,
listenerName,
+ ...(serviceUrl.startsWith('pulsar+ssl://') ||
serviceUrl.startsWith('https://') ? {
+ tlsCertificateFilePath: `${__dirname}/certificate/server.crt`,
+ tlsPrivateKeyFilePath: `${__dirname}/certificate/server.key`,
+ } : {}),
});
const topic = 'persistent://public/default/produce-consume';