diff --git a/pulsar-client-cpp/python/pulsar/__init__.py b/pulsar-client-cpp/python/pulsar/__init__.py index 8c36c08a3d0f6..9f87931538e77 100644 --- a/pulsar-client-cpp/python/pulsar/__init__.py +++ b/pulsar-client-cpp/python/pulsar/__init__.py @@ -172,7 +172,8 @@ def message_id(self): class Authentication: """ - Authentication provider object. + Authentication provider object. Used to load authentication from an external + shared library. """ def __init__(self, dynamicLibPath, authParamsString): """ @@ -189,6 +190,38 @@ def __init__(self, dynamicLibPath, authParamsString): _check_type(str, authParamsString, 'authParamsString') self.auth = _pulsar.Authentication(dynamicLibPath, authParamsString) +class AuthenticationTLS(Authentication): + """ + TLS Authentication implementation + """ + def __init__(self, certificate_path, private_key_path): + """ + Create the TLS authentication provider instance. + + **Args** + + * `certificatePath`: Path to the public certificate + * `privateKeyPath`: Path to private TLS key + """ + _check_type(str, certificate_path, 'certificate_path') + _check_type(str, private_key_path, 'private_key_path') + self.auth = _pulsar.AuthenticationTLS(certificate_path, private_key_path) + +class AuthenticationAthenz(Authentication): + """ + Athenz Authentication implementation + """ + def __init__(self, auth_params_string): + """ + Create the Athenz authentication provider instance. + + **Args** + + * `auth_params_string`: JSON encoded configuration for Athenz client + """ + _check_type(str, auth_params_string, 'auth_params_string') + self.auth = _pulsar.AuthenticationAthenz(auth_params_string) + class Client: """ @@ -220,7 +253,8 @@ def __init__(self, service_url, **Options** * `authentication`: - Set the authentication provider to be used with the broker. + Set the authentication provider to be used with the broker. For example: + `AuthenticationTls` or `AuthenticationAthenz` * `operation_timeout_seconds`: Set timeout on client operations (subscribe, create producer, close, unsubscribe). @@ -238,7 +272,9 @@ def __init__(self, service_url, * `log_conf_file_path`: Initialize log4cxx from a configuration file. * `use_tls`: - Configure whether to use TLS encryption on the connection. + Configure whether to use TLS encryption on the connection. This setting + is deprecated. TLS will be automatically enabled if the `serviceUrl` is + set to `pulsar+ssl://` or `https://` * `tls_trust_certs_file_path`: Set the path to the trusted TLS certificate file. * `tls_allow_insecure_connection`: @@ -265,7 +301,8 @@ def __init__(self, service_url, conf.concurrent_lookup_requests(concurrent_lookup_requests) if log_conf_file_path: conf.log_conf_file_path(log_conf_file_path) - conf.use_tls(use_tls) + if use_tls or service_url.startswith('pulsar+ssl://') or service_url.startswith('https://'): + conf.use_tls(True) if tls_trust_certs_file_path: conf.tls_trust_certs_file_path(tls_trust_certs_file_path) conf.tls_allow_insecure_connection(tls_allow_insecure_connection) diff --git a/pulsar-client-cpp/python/pulsar_test.py b/pulsar-client-cpp/python/pulsar_test.py index 31163f845a924..8f80f4494f10b 100755 --- a/pulsar-client-cpp/python/pulsar_test.py +++ b/pulsar-client-cpp/python/pulsar_test.py @@ -22,7 +22,8 @@ from unittest import TestCase, main import time from pulsar import Client, MessageId, \ - CompressionType, ConsumerType, PartitionsRoutingMode + CompressionType, ConsumerType, PartitionsRoutingMode, \ + AuthenticationTLS from _pulsar import ProducerConfiguration, ConsumerConfiguration @@ -52,6 +53,8 @@ class PulsarTest(TestCase): serviceUrl = 'pulsar://localhost:8885' adminUrl = 'http://localhost:8765' + serviceUrlTls = 'pulsar+ssl://localhost:9886' + def test_producer_config(self): conf = ProducerConfiguration() conf.send_timeout_millis(12) @@ -121,6 +124,31 @@ def test_producer_consumer(self): client.close() + def test_tls_auth(self): + certs_dir = "../../pulsar-broker/src/test/resources/authentication/tls/" + client = Client(self.serviceUrlTls, + tls_trust_certs_file_path=certs_dir + 'cacert.pem', + tls_allow_insecure_connection=False, + authentication=AuthenticationTLS(certs_dir + 'client-cert.pem', certs_dir + 'client-key.pem')) + + consumer = client.subscribe('persistent://property/cluster/namespace/my-python-topic-producer-consumer', + 'my-sub', + consumer_type=ConsumerType.Shared) + producer = client.create_producer('persistent://property/cluster/namespace/my-python-topic-producer-consumer') + producer.send('hello') + + msg = consumer.receive(1000) + self.assertTrue(msg) + self.assertEqual(msg.data(), b'hello') + + try: + msg = consumer.receive(100) + self.assertTrue(False) # Should not reach this point + except: + pass # Exception is expected + + client.close() + def test_message_listener(self): client = Client(self.serviceUrl) diff --git a/pulsar-client-cpp/python/src/authentication.cc b/pulsar-client-cpp/python/src/authentication.cc index 813022821c53a..9cfb2e717bafb 100644 --- a/pulsar-client-cpp/python/src/authentication.cc +++ b/pulsar-client-cpp/python/src/authentication.cc @@ -18,14 +18,38 @@ */ #include "utils.h" +AuthenticationWrapper::AuthenticationWrapper() {} + AuthenticationWrapper::AuthenticationWrapper(const std::string& dynamicLibPath, const std::string& authParamsString) { this->auth = AuthFactory::create(dynamicLibPath, authParamsString); } +struct AuthenticationTlsWrapper : public AuthenticationWrapper { + AuthenticationTlsWrapper(const std::string& certificatePath, const std::string& privateKeyPath) : + AuthenticationWrapper() { + this->auth = AuthTls::create(certificatePath, privateKeyPath); + } +}; + +struct AuthenticationAthenzWrapper : public AuthenticationWrapper { + AuthenticationAthenzWrapper(const std::string& authParamsString) : + AuthenticationWrapper() { + this->auth = AuthAthenz::create(authParamsString); + } +}; + void export_authentication() { using namespace boost::python; class_("Authentication", init()) ; + + class_ >("AuthenticationTLS", + init()) + ; + + class_ >("AuthenticationAthenz", + init()) + ; } diff --git a/pulsar-client-cpp/python/src/utils.h b/pulsar-client-cpp/python/src/utils.h index 66ad852390302..4911b566cc551 100644 --- a/pulsar-client-cpp/python/src/utils.h +++ b/pulsar-client-cpp/python/src/utils.h @@ -39,5 +39,6 @@ inline void CHECK_RESULT(Result res) { struct AuthenticationWrapper { AuthenticationPtr auth; + AuthenticationWrapper(); AuthenticationWrapper(const std::string& dynamicLibPath, const std::string& authParamsString); };