com.solacesystems.jcsmp.JCSMPErrorResponseException: 401: Certificate Error [Subcode:1]

Options
Sahil
Sahil Member Posts: 6
Hi Team,

I'm trying to publish on Solace queue with Client Certificate Authentication using self signed certificate. But getting below error:
Remote addr: mr-connection-dcnuo3u5bkz.messaging.solace.cloud Remote port: 55443) - ) com.solacesystems.jcsmp.JCSMPErrorResponseException: 401: Certificate Error [Subcode:1]
at com.solacesystems.jcsmp.protocol.impl.TcpChannel.executePostOnce(TcpChannel.java:235)
at com.solacesystems.jcsmp.protocol.impl.ChannelOpStrategyClient.performOpen(ChannelOpStrategyClient.java:101)
at com.solacesystems.jcsmp.protocol.impl.TcpClientChannel.performOpenSingle(TcpClientChannel.java:428)
at com.solacesystems.jcsmp.protocol.impl.TcpClientChannel.access$800(TcpClientChannel.java:124)
at com.solacesystems.jcsmp.protocol.impl.TcpClientChannel$ClientChannelConnect.call(TcpClientChannel.java:2661)
at com.solacesystems.jcsmp.protocol.impl.TcpClientChannel.open(TcpClientChannel.java:404)
at com.solacesystems.jcsmp.impl.JCSMPBasicSession.sniffRouter(JCSMPBasicSession.java:423)
at com.solacesystems.jcsmp.impl.JCSMPBasicSession.connect(JCSMPBasicSession.java:1310)
==============================================
Below is the code snippet I'm using to publish over Solace Queue:

final JCSMPProperties properties = new JCSMPProperties();
properties.setProperty(JCSMPProperties.HOST, host); // host:port
properties.setProperty(JCSMPProperties.VPN_NAME, vpnName); // message-vpn

// Enable TLS
properties.setProperty(JCSMPProperties.AUTHENTICATION_SCHEME, JCSMPProperties.AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE);
properties.setProperty(JCSMPProperties.SSL_VALIDATE_CERTIFICATE, true);
properties.setProperty(JCSMPProperties.SSL_VALIDATE_CERTIFICATE_DATE, false);
properties.setProperty(JCSMPProperties.SSL_KEY_STORE, "path/keystore.jks");
properties.setProperty(JCSMPProperties.SSL_KEY_STORE_PASSWORD, "keystore_password");

===========================================
On Solace Cloud, I created service on AWS us-east-1 region with below configurations:
1. added self signed certificate on Client certificate authentication tab.
2. enabled Client certificate authentication on solace service.
2. basic authentication is enabled.
3. Created queue on PubSub+ Broker manager.
4. Tried executing the java code.

Please let me know if I'm missing anything.

Best Answer

  • yangsen
    yangsen Member, Employee Posts: 23 Solace Employee
    #2 Answer ✓
    Options

    Hi Sahil, I followed the steps as https://docs.solace.com/Cloud/ght_client_certs.htm to create the client1.key and clientCert1.pem. Then I used the following commands to import the certificate to a keystore:
    openssl pkcs12 -export -in clientCert1.pem -inkey client1.key -out client1Cert.p12 -name "client1Cert"
    keytool -importkeystore -srckeystore client1Cert.p12 -srcstoretype pkcs12 -destkeystore keystore.jks

    I used the same code as you shared above, and I was able to connect to the broker.

    So I suspect:
    1. there is an error when you generating the certificate. You can follow the steps in the above link to redo.
    2. Have you checked whether the DigiCertGlobalRootCA.crt.pem is imported into your Java's default Truststore? By default it should be there, but you can use this command to export the cert list in your truststore and double check.
    keytool -list -v -keystore file-to-java-cacerts > certList.txt
    "CN=DigiCert Global Root CA" should present in the list

Answers

  • yangsen
    yangsen Member, Employee Posts: 23 Solace Employee
    Options

    For step 1, please ensure you added the Certificate Authorities (CA) into the client certificate authority list, not the client certificate itself.
    For self-signed, this should be the (self-created)CA certificate used to sign the client certificate.

  • Sahil
    Sahil Member Posts: 6
    Options
    I'm using self signed certificate. Followerd below steps to upload the pem file to Solace

    1. Clicked on Manage
    2. Clicked Authentication widget
    3. Enabled "Client certificate Authentication"
    4. Enabled "Validate Certificates dates"
    5. Clcked on "Certificate Authorities"
    6. Clicked "Add certificate authorities"
    7. Clicked "Add client certificate authority" button
    8. entered a random Certificate authority name.
    9. uploaded the certificate pem file
    10. Clicked "save".
  • yangsen
    yangsen Member, Employee Posts: 23 Solace Employee
    Options

    in step 9, the certificate is for your client, it is not the Certificate Authorities.

    You can read this doc on how to generate self-signed Root CA(the contoso.crt file), then use it to create(sign) a certificate(for the client). You should upload the content of your Root CA in step 9. So that the broker can authenticate your client when the client present its certificate.

    https://learn.microsoft.com/en-us/azure/application-gateway/self-signed-certificates

  • Sahil
    Sahil Member Posts: 6
    Options

    Hi,

    I tried as per the link shared and created the certificates and keystore using below commands:

    openssl ecparam -out contoso.key -name prime256v1 -genkey
    openssl req -new -sha256 -key contoso.key -out contoso.csr
    openssl x509 -req -sha256 -days 365 -in contoso.csr -signkey contoso.key -out contoso.crt
    openssl ecparam -out fabrikam.key -name prime256v1 -genkey
    openssl req -new -sha256 -key fabrikam.key -out fabrikam.csr
    openssl x509 -req -in fabrikam.csr -CA contoso.crt -CAkey contoso.key -CAcreateserial -out fabrikam.crt -days 365 -sha256
    openssl x509 -in fabrikam.crt -text -noout

    keytool -import -trustcacerts -file contoso.crt -alias myAlias -keystore keystore.jks
    openssl pkcs12 -export -in contoso.crt -inkey contoso.key -out contoso.p12 -name myAlias
    keytool -importkeystore -srckeystore contoso.p12 -srcstoretype PKCS12 -destkeystore keystore.jks

    I uploaded contoso.csr on Solace UI in Client certificate authority and used the keystore.jks in my Java publisher code.

    final JCSMPProperties properties = new JCSMPProperties();
    properties.setProperty(JCSMPProperties.HOST, host); // host:port
    properties.setProperty(JCSMPProperties.VPN_NAME, vpnName); // message-vpn

    // Enable TLS
    properties.setProperty(JCSMPProperties.AUTHENTICATION_SCHEME, JCSMPProperties.AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE);
    properties.setProperty(JCSMPProperties.SSL_VALIDATE_CERTIFICATE, true);
    properties.setProperty(JCSMPProperties.SSL_VALIDATE_CERTIFICATE_DATE, false);
    properties.setProperty(JCSMPProperties.SSL_KEY_STORE, "path/keystore.jks");
    properties.setProperty(JCSMPProperties.SSL_KEY_STORE_PASSWORD, "keystore_password");

    I'm still getting same error:
    Remote addr: mr-connection-dcnuo3u5bkz.messaging.solace.cloud Remote port: 55443) - ) com.solacesystems.jcsmp.JCSMPErrorResponseException: 401: Certificate Error [Subcode:1]

    Can you please help.

  • Sahil
    Sahil Member Posts: 6
    Options

    Hi @yangsen,

    I tried as per the link shared and created the certificates and keystore using below commands:

    openssl ecparam -out contoso.key -name prime256v1 -genkey
    openssl req -new -sha256 -key contoso.key -out contoso.csr
    openssl x509 -req -sha256 -days 365 -in contoso.csr -signkey contoso.key -out contoso.crt
    openssl ecparam -out fabrikam.key -name prime256v1 -genkey
    openssl req -new -sha256 -key fabrikam.key -out fabrikam.csr
    openssl x509 -req -in fabrikam.csr -CA contoso.crt -CAkey contoso.key -CAcreateserial -out fabrikam.crt -days 365 -sha256
    openssl x509 -in fabrikam.crt -text -noout

    keytool -import -trustcacerts -file contoso.crt -alias myAlias -keystore keystore.jks
    openssl pkcs12 -export -in contoso.crt -inkey contoso.key -out contoso.p12 -name myAlias
    keytool -importkeystore -srckeystore contoso.p12 -srcstoretype PKCS12 -destkeystore keystore.jks

    I uploaded contoso.csr on Solace UI in Client certificate authority and used the keystore.jks in my Java publisher code.

    final JCSMPProperties properties = new JCSMPProperties();
    properties.setProperty(JCSMPProperties.HOST, host); // host:port
    properties.setProperty(JCSMPProperties.VPN_NAME, vpnName); // message-vpn

    // Enable TLS
    properties.setProperty(JCSMPProperties.AUTHENTICATION_SCHEME, JCSMPProperties.AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE);
    properties.setProperty(JCSMPProperties.SSL_VALIDATE_CERTIFICATE, true);
    properties.setProperty(JCSMPProperties.SSL_VALIDATE_CERTIFICATE_DATE, false);
    properties.setProperty(JCSMPProperties.SSL_KEY_STORE, "path/keystore.jks");
    properties.setProperty(JCSMPProperties.SSL_KEY_STORE_PASSWORD, "keystore_password");

    I'm still getting same error:
    Remote addr: mr-connection-dcnuo3u5bkz.messaging.solace.cloud Remote port: 55443) - ) com.solacesystems.jcsmp.JCSMPErrorResponseException: 401: Certificate Error [Subcode:1]

  • yangsen
    yangsen Member, Employee Posts: 23 Solace Employee
    Options

    Hi Sahil, sorry for the late response. I was quite overloaded recently.
    I haven't check your steps yet, but after adding the certificate authority to the broker, you also need to add a username for the client that matches the common name in our client certificate.
    You can follow this document page: https://docs.solace.com/Cloud/ght_client_certs.htm
    Pay attention to the section "Add the Client Username from a Client Certificate"

  • Sahil
    Sahil Member Posts: 6
    Options

    Hi @yangsen,

    I'm already adding the a common name of the certificate as username for the client in the Access Control section.

    Still getting above error. Can you please check whether I'm missing any configuration in the java code snippet:

    final JCSMPProperties properties = new JCSMPProperties();
    properties.setProperty(JCSMPProperties.HOST, host); // host:port
    properties.setProperty(JCSMPProperties.VPN_NAME, vpnName); // message-vpn

    // Enable TLS
    properties.setProperty(JCSMPProperties.AUTHENTICATION_SCHEME, JCSMPProperties.AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE);
    properties.setProperty(JCSMPProperties.SSL_VALIDATE_CERTIFICATE, true);
    properties.setProperty(JCSMPProperties.SSL_VALIDATE_CERTIFICATE_DATE, false);
    properties.setProperty(JCSMPProperties.SSL_KEY_STORE, "path/keystore.jks");
    properties.setProperty(JCSMPProperties.SSL_KEY_STORE_PASSWORD, "keystore_password");

    Also, can you let me know what com.solacesystems.jcsmp.JCSMPErrorResponseException: 401: Certificate Error [Subcode:1] actually means.

    Thanks

  • yangsen
    yangsen Member, Employee Posts: 23 Solace Employee
    #10 Answer ✓
    Options

    Hi Sahil, I followed the steps as https://docs.solace.com/Cloud/ght_client_certs.htm to create the client1.key and clientCert1.pem. Then I used the following commands to import the certificate to a keystore:
    openssl pkcs12 -export -in clientCert1.pem -inkey client1.key -out client1Cert.p12 -name "client1Cert"
    keytool -importkeystore -srckeystore client1Cert.p12 -srcstoretype pkcs12 -destkeystore keystore.jks

    I used the same code as you shared above, and I was able to connect to the broker.

    So I suspect:
    1. there is an error when you generating the certificate. You can follow the steps in the above link to redo.
    2. Have you checked whether the DigiCertGlobalRootCA.crt.pem is imported into your Java's default Truststore? By default it should be there, but you can use this command to export the cert list in your truststore and double check.
    keytool -list -v -keystore file-to-java-cacerts > certList.txt
    "CN=DigiCert Global Root CA" should present in the list

  • Sahil
    Sahil Member Posts: 6
    Options

    Hi @yangsen ,

    Thank you for your tremendous support. I'm able to connect with Solace broker using client certificate authentication.

    Regards