Python connect to solace Pubsub+ cloud

onkar1712
onkar1712 Member Posts: 5
edited February 24 in PubSub+ Event Broker #1

I have service created on https://console.solace.cloud/services on GCP platform and I am trying to connect to this service from python 3.7 using solace-pubsubplus pypi package: https://pypi.org/project/solace-pubsubplus/
Here is my code snippet for connecting to the service:

_def publish(message):
    import solace.messaging.messaging_service as service
    from solace.messaging.publisher.outbound_message import OutboundMessageBuilder
    from solace.messaging.publisher.persistent_message_publisher import Topic

    broker_props = {"solace.messaging.transport.host": "https://mr-b7hnxi2xr1c.messaging.solace.cloud:9443",
                    "solace.messaging.service.vpn-name": "test-event-service",
                    "solace.messaging.authentication.scheme.basic.username": "solace-cloud-client",
                    "solace.messaging.authentication.scheme.basic.password": "qaa53j6ih9l8ru646n1l7rjm64"}

    messaging_service = service.MessagingServiceClientBuilder().from_properties(config=broker_props).build()
    messaging_service.connect()
    print("connected")

    # publisher = service.PersistentMessagePublisherBuilder().from_properties(configuration=broker_props).build()
    # message_properties = {'env': 'test', 'application': 'test', 'object': 'sales-order'}
    # out_message = OutboundMessageBuilder().build(payload=message, additional_message_properties=message_properties,
    #                                              converter=None)
    # publisher.publish(message=out_message, destination=Topic.of('test-service/message'))
    # print(f"Message published to solace...")_

After running the code I get error:

2021-04-27 17:22:54,917 [ERROR] solace.messaging.core: [_solace_session.py:580]  [[SERVICE: 0x23cefec66d0] - [APP ID: app_404dc464-c4d0-4bfd-81e9-4be48c078ac2]] SOLCLIENT_SUBCODE_FAILED_LOADING_TRUSTSTORE
2021-04-27 17:22:54,917 [ERROR] solace.messaging.core: [_solace_session.py:582]  [[SERVICE: 0x23cefec66d0] - [APP ID: app_404dc464-c4d0-4bfd-81e9-4be48c078ac2]] SESSION CREATION UNSUCCESSFUL. Failed to load trust store.

What truststore do I need to load to connect to this service in solace cloud?
Can someone please point me towards proper documentation for Python. I am referring to the documentation here: https://www.solace.dev/ and it looks like its incomplete.

Answers

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 377 admin
    edited April 2021 #2

    Hey @onkar1712 ! Just from a quick glance, I see that your solace.messaging.transport.host in your broker properties configuration is incorrect. https is not a valid protocol to connect to the broker Update: using http(s) is similar to using websocket to connect to the broker. To do so however you will need to connect to the websocket port if you are not using SMF, and since you are using SMF (Solace Message Format) to connect to the broker (via the Solace Python API) you will need to get the "Solace Messaging" configuration parameters. You can get this by navigating to your cloud service and under the connect tab, expand the "Solace Messaging" section

    You will see the SMF host, and that is what you should be using in your broker properties.

    I hope this helps! Feel free to share any project, tips and tricks or further questions

  • marc
    marc Member, Administrator, Moderator, Employee Posts: 695 admin

    Also in the last image in @Tamimi's response you'll see there is a link to download the TrustStore at the bottom of the Connection Details. That's the truststore that you'll want :)

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 377 admin
    edited April 2021 #4

    Marc has a good point! If you want to use a secure connection and download the TrustStore, you will need to add this to your broker prop as well

     "solace.messaging.tls.trust-store-path": "path_to_trusted_store"
    

    To have the following broker_props

    broker_props = {"solace.messaging.transport.host": "<protocol>://<host>:<port>",
                        "solace.messaging.service.vpn-name": "<vpn_name>",
                        "solace.messaging.authentication.scheme.basic.username": "<client>",
                        "solace.messaging.authentication.scheme.basic.password": "<passord>",
                         "solace.messaging.tls.trust-store-path": "path_to_trusted_store"}
    
  • onkar1712
    onkar1712 Member Posts: 5

    Hi @Tamimi , Thanks for the quick response. Okay, so I also tried to connect using SMF (not secured one) like this:

    def publish(message):
    import solace.messaging.messaging_service as service

    broker_props = {"solace.messaging.transport.host": "tcp://mr-b7hnxi2xr1c.messaging.solace.cloud:55555",
                    "solace.messaging.service.vpn-name": "test-event-service",
                    "solace.messaging.authentication.scheme.basic.username": "solace-cloud-client",
                    "solace.messaging.authentication.scheme.basic.password": "<password>"
                    }
    
    messaging_service = service.MessagingServiceClientBuilder().from_properties(
        config=broker_props).build()
    messaging_service.connect()
    print("connected")______
    

    It gives me timeout error:
    2021-04-28 11:02:56,225 [WARNING] solace.messaging.core: [_solace_session.py:768] [[SERVICE: 0x1c29cd85070] - [APP ID: app_184aa5fc-583b-4f49-a0fb-1cfff592097f]] {'caller_description': 'From service event callback', 'return_code': 'Ok', 'sub_code': 'SOLCLIENT_SUBCODE_COMMUNICATION_ERROR', 'error_info_sub_code': 14, 'error_info_contents': 'TCP connection failure for fd 1120, error = Connection timed out (10060)'}
    2021-04-28 11:02:56,226 [WARNING] solace.messaging.core: [_solace_session.py:679] [[SERVICE: 0x1c29cd85070] - [APP ID: app_184aa5fc-583b-4f49-a0fb-1cfff592097f]] {'caller_description': 'do_connect', 'return_code': 'Not ready', 'sub_code': 'SOLCLIENT_SUBCODE_COMMUNICATION_ERROR', 'error_info_sub_code': 14, 'error_info_contents': 'TCP connection failure for fd 1120, error = Connection timed out (10060)'}

    I also tried connecting using SSMF(using tcps) and specifying truststore .pem file path like this:

    def publish(message):
    import solace.messaging.messaging_service as service

    broker_props = {"solace.messaging.transport.host": "tcps://mr-b7hnxi2xr1c.messaging.solace.cloud:55443",
                    "solace.messaging.service.vpn-name": "test-event-service",
                    "solace.messaging.authentication.scheme.basic.username": "solace-cloud-client",
                    "solace.messaging.authentication.scheme.basic.password": "qaa53j6ih9l8ru646n1l7rjm64",
                    "solace.messaging.tls.trust-store-path": "C:\\Users\\onpat\\PycharmProjects\\solace-test\\data\\DigiCert_Global_Root_CA.pem"}
    
    messaging_service = service.MessagingServiceClientBuilder().from_properties(
        config=broker_props).build()
    messaging_service.connect()
    print("connected")
    

    solace.messaging.errors.pubsubplus_client_error.PubSubPlusClientError: (PubSubPlusClientError(...), 'SESSION CREATION UNSUCCESSFUL. Untrusted certificate. {\'caller_description\': \'do_connect\', \'return_code\': \'Not ready\', \'sub_code\': \'SOLCLIENT_SUBCODE_UNTRUSTED_CERTIFICATE\', \'error_info_sub_code\': 99, \'error_info_contents\': "Session \'(c0,s1)_test-event-service\': The peer certificate is not trusted, rc=\'unable to get local issuer certificate\'"}')

  • onkar1712
    onkar1712 Member Posts: 5

    Hi @Tamimi Thanks for your reply. So, I tried connecting over SMF(using tcp, unsecured) like this:

    def publish(message):
    import solace.messaging.messaging_service as service

    broker_props = {"solace.messaging.transport.host": "tcp://mr-b7hnxi2xr1c.messaging.solace.cloud:55555",
                    "solace.messaging.service.vpn-name": "test-event-service",
                    "solace.messaging.authentication.scheme.basic.username": "solace-cloud-client",
                    "solace.messaging.authentication.scheme.basic.password": "qaa53j6ih9l8ru646n1l7rjm64"
                    }
    
    messaging_service = service.MessagingServiceClientBuilder().from_properties(
        config=broker_props).build()
    messaging_service.connect()
    print("connected")
    

    And I get following error:
    solace.messaging.errors.pubsubplus_client_error.PubSubPlusClientError: (PubSubPlusClientError(...), {'caller_description': 'do_connect', 'return_code': 'Not ready', 'sub_code': 'SOLCLIENT_SUBCODE_COMMUNICATION_ERROR', 'error_info_sub_code': 14, 'error_info_contents': 'TCP connection failure for fd 1136, error = Connection timed out (10060)'})

    I also tried connecting to event broker over tcps(SSMF) like this by giving path to .pem file:

    def publish(message):
    import solace.messaging.messaging_service as service

    broker_props = {"solace.messaging.transport.host": "tcps://mr-b7hnxi2xr1c.messaging.solace.cloud:55443",
                    "solace.messaging.service.vpn-name": "test-event-service",
                    "solace.messaging.authentication.scheme.basic.username": "solace-cloud-client",
                    "solace.messaging.authentication.scheme.basic.password": "qaa53j6ih9l8ru646n1l7rjm64",
                    "solace.messaging.tls.trust-store-path": "C:\\Users\\onpat\\PycharmProjects\\solace-test\\data\\DigiCert_Global_Root_CA.pem"
                    }
    
    messaging_service = service.MessagingServiceClientBuilder().from_properties(
        config=broker_props).build()
    messaging_service.connect()
    print("connected")
    

    This gives me followinf error:
    solace.messaging.errors.pubsubplus_client_error.PubSubPlusClientError: (PubSubPlusClientError(...), 'SESSION CREATION UNSUCCESSFUL. Untrusted certificate. {\'caller_description\': \'do_connect\', \'return_code\': \'Not ready\', \'sub_code\': \'SOLCLIENT_SUBCODE_UNTRUSTED_CERTIFICATE\', \'error_info_sub_code\': 99, \'error_info_contents\': "Session \'(c0,s1)_test-event-service\': The peer certificate is not trusted, rc=\'unable to get local issuer certificate\'"}')
    2021-04-28 11:18:08,282 [WARNING] solace.messaging.core: [_solace_session.py:768] [[SERVICE: 0x230523f5070] - [APP ID: app_03d2829e-4176-4ac8-86c9-980bc3dfc191]] {'caller_description': 'From service event callback', 'return_code': 'Ok', 'sub_code': 'SOLCLIENT_SUBCODE_UNTRUSTED_CERTIFICATE', 'error_info_sub_code': 99, 'error_info_contents': "Session '(c0,s1)_test-event-service': The peer certificate is not trusted, rc='unable to get local issuer certificate'"}
    2021-04-28 11:18:08,284 [WARNING] solace.messaging.core: [_solace_session.py:671] [[SERVICE: 0x230523f5070] - [APP ID: app_03d2829e-4176-4ac8-86c9-980bc3dfc191]] SESSION CREATION UNSUCCESSFUL. Untrusted certificate. {'caller_description': 'do_connect', 'return_code': 'Not ready', 'sub_code': 'SOLCLIENT_SUBCODE_UNTRUSTED_CERTIFICATE', 'error_info_sub_code': 99, 'error_info_contents': "Session '(c0,s1)_test-event-service': The peer certificate is not trusted, rc='unable to get local issuer certificate'"}

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 377 admin

    Hey @onkar1712 it looks like your broker configuration is not setup correctly from what I see in the logs. You can confirm the following:

    • Is the machine you are using to run the application connected to the internet?
    • Are you able to connect to the broker with other means? you can try the Try-Me tab in this getting started page. Note you will need to use the Secured Web Messaging Host url instead of the SMF one
    • Is this the correct port number for your secured SMF connection
    • How did you install the pem file cert? SESSION CREATION UNSUCCESSFUL. Untrusted certificate is telling me that you have an issue with the certificate.

    Hope this helps, let me know if you were able to resolve this issue.

  • stushep
    stushep Member Posts: 20

    Hi all, im currently experiencing the exact same issue as mentioned above. Have downloaded and added the trust store path and get t he same 'the peer certificate is not trusted'.
    I can also NOT connect to my newly created solace cloud account using the try me on the homepage, but i can when i am logged into the account (basic try-me).

    Following the documentation none of this is covered and am at a loss... guessing the default cloud account does not allow external access maybe ?

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 377 admin

    Hey @stushep ! Following up on your comment, is your issue resolved? I can help out with it if you still have some challenges with the trust store connection 👍

  • stushep
    stushep Member Posts: 20

    Hi @Tamimi , apologies, hadn't seen your message pop up. Yes, I managed to connected as per my other thread (as you can tell, was pulling my hair out at this stage hunting for other peoples questions).
    Thank you for following up :smile:

  • Pavithra
    Pavithra Member Posts: 1
    edited April 25 #11

    @Tamimi We have successfully established solace connection to our organization's solace broker via JMS. but we use Spring Boot so it consumes lots for memory. single thread take up to 150MB RAM. So planned to migrate from Java to Python. I have managed to configure host name, VPN , app ID. We are using AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE scheme.

    When I try to establish connection using SSL cert and key file I face below exception.

     raise PubSubPlusCoreClientError(message=f'{UNTRUSTED_CERTIFICATE_MESSAGE} {core_exception_msg}',

    solace.messaging.errors.pubsubplus_client_error.PubSubPlusCoreClientError: SESSION CREATION UNSUCCESSFUL. Untrusted certificate. {'caller_description': 'do_connect', 'return_code': 'Not ready', 'sub_code': 'SOLCLIENT_SUBCODE_UNTRUSTED_CERTIFICATE', 'error_info_sub_code': 99, 'error_info_contents': "Session '(c0,s1)_vpn-imft': The peer certificate is not trusted, rc='unable to get local issuer certificate'"} 😖😭

    In Java we used to load key store and trust store file to establish connection. I am not sure how to load them in Python message service.

    Please advise how to configure below properties in python solace API. 😕

    solace.trustStore=/Temp/load/certificates/solace-test-auth.jks

    solace.trustStorePwd=solace-pass!

    solace.keyStore=/Temp/load/certificates/solace-test-auth.pfx

    solace.keyStorePwd=solace-pass!

    solace.keyStoreformat=PKCS12

    solace.AuthScheme=AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE

  • Tamimi
    Tamimi Member, Administrator, Employee Posts: 377 admin
    edited April 26 #12

    Hey @Pavithra to have a secure connection, you have to pass a transport security strategy to your messaging service prior to connecting. As you see in the TLS_connection.py sample, the messaging service is built with a transport security strategy

    messaging_service = MessagingService.builder().from_properties(broker_props)\
    	                    .with_transport_security_strategy(transport_security_strategy)\
    	                    .build()
    

    and the transport_security_strategy is defined as follows

    transport_security_strategy = TLS.create().with_certificate_validation(True, False, "/Temp/load/certificates/")
    

    which will pick up the .pem file in your /Temp/load/certificates/ directory. Since you have key stores and other files to pass to your connection, can you try to define a ClientCertificateAuthentication as per the docs here. Note you will have to pass this authentication strategy to your messaging service as follows

    messaging_service = MessagingService.builder().from_properties(broker_props)\
                        .with_authentication_strategy(authentication_strategy)\
                        .build()
    


    and define your authentication strategy as per the documentation as follows

    authentication_strategy = ClientCertificateAuthentication.of("/path/to/certificate","/path/to/key","key_password")\
                              .with_certificate_and_key_pem("/path/to/pem/file")\
                              .with_private_key_password("private_key_password")
    

    Notes

    Dont forget to import either TLS or authentication strategy

    from solace.messaging.config.transport_security_strategy import TLS
    

    or

    from solace.messaging.config.authentication_strategy import ClientCertificateAuthentication
    

    depending on which class you use. Please let me know if this works.

  • Pavithra
    Pavithra Member Posts: 1

    Hi @Tamimi , Thanks for your prompt response.

    I tried both the ways,

    1) Transport security stratergy :

    With the certificate we have, we generated a .pem file. it holds ENCRYPTED PRIVATE KEY and 3 CERTIFICATES

    I defined Transport security stratergy as below

    transport_security_strategy = TLS.create().with_certificate_validation(True, False, "C:\\Users\\XXXX\\Desktop\\IMFT\\certificates\\")

    and message service as below,

    messaging_service

    = MessagingService.builder().from_properties(broker_props)\

              .with_reconnection_retry_strategy(RetryStrategy.parametrized_retry(20,3))\

              .with_transport_security_strategy(transport_security_strategy)\

              .build(broker_props['application_id'])


    When i run i face below exception

    2022-04-26 10:29:50,865 [WARNING] solace.messaging.connections: [messaging_service.py:1073] Parent propert is not present so broker will ignore property: ['solace.messaging.authentication.scheme.basic.username']

    2022-04-26 10:29:50,896 [ERROR] solace.messaging.core: [_solace_session.py:665] [[SERVICE: 0x1eca3f6exxx] - [APP ID: 1234-TEST]] SOLCLIENT_SUBCODE_FAILED_LOADING_CERTIFICATE_AND_KEY

    2022-04-26 10:29:50,896 [ERROR] solace.messaging.core: [_solace_session.py:674] [[SERVICE: 0x1eca3f6exxx] - [APP ID: 1234-TEST]] SESSION CREATION UNSUCCESSFUL. Failed to load certificate.

    Traceback (most recent call last):

     File "TLS_connection.py", line 75, in <module>

      messaging_service = MessagingService.builder().from_properties(broker_props)\

     File "C:\Users\python-3.8.5-embed-amd64\lib\site-packages\solace\messaging\messaging_service.py", line 1047, in build

      return _BasicMessagingService(config=self._stored_config, application_id=application_id)

     File "C:\Users\python-3.8.5-embed-amd64\lib\site-packages\solace\messaging\messaging_service.py", line 548, in __init__

      self._api.create_session(self._config) # create the session as part of Messaging Service build process

     File "C:\Users\python-3.8.5-embed-amd64\lib\site-packages\solace\messaging\core\_solace_session.py", line 675, in create_session

      raise PubSubPlusCoreClientError(message=FAILED_TO_LOADING_CERTIFICATE_AND_KEY, sub_code=info_sub_code)

    solace.messaging.errors.pubsubplus_client_error.PubSubPlusCoreClientError: SESSION CREATION UNSUCCESSFUL. Failed to load certificate.


    😟 but all nessacry cetificates are kept in C:\\Users\\XXXX\\Desktop\\IMFT\\certificates\\ path.

    2) Authentication strategy :

    authentication_strategy = ClientCertificateAuthentication.of("C:\\Users\\XXXX\\Desktop\\IMFT\\certificates\\Organization-SSL-CA-G1-SHA2.cer","C:\\Users\\XXXX\\Desktop\\IMFT\\certificates\\Private.key","abcd")\

                 .with_certificate_and_key_pem("C:\\Users\\XXXX\\Desktop\\IMFT\\certificates\\Test\\server.pem")\

                 .with_private_key_password("abcd")

    and message service as

    messaging_service = MessagingService.builder().from_properties(broker_props)\

              .with_authentication_strategy(authentication_strategy)\

              .build(broker_props['application_id'])


    when I run I face below exception


    2022-04-26 10:54:19,629 [WARNING] solace.messaging.connections: [messaging_service.py:1073] Parent propert is not present so broker will ignore property: ['solace.messaging.authentication.scheme.basic.username']

    2022-04-26 10:54:19,730 [WARNING] solace.messaging.core: [_solace_session.py:845] [[SERVICE: 0x226ea17e310] - [APP ID: 1234-TEST]] SESSION CREATION UNSUCCESSFUL. Failed to load certificate. {'caller_description': 'do_connect', 'return_code': 'Fail', 'sub_code': 'SOLCLIENT_SUBCODE_FAILED_LOADING_CERTIFICATE_AND_KEY', 'error_info_sub_code': 102, 'error_info_contents': "Failed to add the private key from file 'C:\\Users\\XXXX\\Desktop\\IMFT\\certificates\\Test\\server.pem', session '(c0,s1)_vpn-imft'"}

    Traceback (most recent call last):

     File "TLS_connection.py", line 86, in <module>

      messaging_service.connect()

     File "C:\Users\python-3.8.5-embed-amd64\lib\site-packages\solace\messaging\messaging_service.py", line 615, in connect

      connect_status = self._api._session_connect()

     File "C:\Users\python-3.8.5-embed-amd64\lib\site-packages\solace\messaging\core\_solace_session.py", line 546, in _session_connect

      return self.__do_connect()

     File "C:\Users\python-3.8.5-embed-amd64\lib\site-packages\solace\messaging\core\_solace_session.py", line 833, in __do_connect

      self.__handle_exception_message(return_code=return_code, caller_desc='do_connect')

     File "C:\Users\python-3.8.5-embed-amd64\lib\site-packages\solace\messaging\core\_solace_session.py", line 846, in __handle_exception_message

      raise PubSubPlusCoreClientError(message=f'{FAILED_TO_LOADING_CERTIFICATE_AND_KEY} {core_exception_msg}',

    solace.messaging.errors.pubsubplus_client_error.PubSubPlusCoreClientError: SESSION CREATION UNSUCCESSFUL. Failed to load certificate. {'caller_description': 'do_connect', 'return_code': 'Fail', 'sub_code': 'SOLCLIENT_SUBCODE_FAILED_LOADING_CERTIFICATE_AND_KEY', 'error_info_sub_code': 102, 'error_info_contents': "Failed to add the private key from file 'C:\\Users\\XXXX\\Desktop\\IMFT\\certificates\\Test\\server.pem', session '(c0,s1)_vpn-imft'"}

    I defined all values for class ClientCertificateAuthentication as per the docs here.

    I AM STUCK !!! 😓