I'm trying to connect to a SSL enabled MQ channel in order to place a message using JMS(within Spring boot app) . below are the connection factory properties set before sending the message. I'm getting the following error when jms trying to put the message.
Caused by: com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2397' ('MQRC_JSSE_ERROR')....
.....
at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:203)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
at java.base/sun.security.validator.Validator.validate(Validator.java:264)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.checkServerCerts(CertificateMessage.java:638)
... 81 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
** certificates are already installed at QM level. it seems jms client is not picking the root certificate from the specified location. the CA root certificate(myCAcertfile.cer) (self signed) was generated using runmqckm tool in IBM mq.
MQ channel information
CHANNEL(KAU.CONN) CHLTYPE(SVRCONN)
ALTDATE(2014-02-28) ALTTIME(17.28.55)
CERTLABL( ) COMPHDR(NONE)
COMPMSG(NONE)
DESCR(Server-connection to windows host)
DISCINT(0) HBINT(300)
KAINT(AUTO) MAXINST(999999999)
MAXINSTC(999999999) MAXMSGL(4194304)
MCAUSER( ) MONCHL(QMGR)
RCVDATA( ) RCVEXIT( )
SCYDATA( ) SCYEXIT( )
SENDDATA( ) SENDEXIT( )
SHARECNV(10) SSLCAUTH(REQUIRED)
SSLCIPH(TLS_RSA_WITH_AES_128_CBC_SHA256)
SSLPEER( ) TRPTYPE(TCP)
JMS connection factory properties
// Create a connection factory
JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
JmsConnectionFactory cf = ff.createConnectionFactory();
// Set the properties
cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, HOST);
cf.setIntProperty(WMQConstants.WMQ_PORT, PORT);
cf.setStringProperty(WMQConstants.WMQ_CHANNEL, CHANNEL);
cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, QMGR);
cf.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "Manual message publihser");
cf.setBooleanProperty(WMQConstants.USER_AUTHENTICATION_MQCSP, true);
cf.setStringProperty(WMQConstants.USERID, "");
cf.setStringProperty(WMQConstants.PASSWORD, "");
System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false" );
cf.setStringProperty("Djavax.net.ssl.trustStore", "D:\\mq-message-handler-1.0\\ssl\\myCAcertfile.cer");
cf.setStringProperty(WMQConstants.WMQ_SSL_CIPHER_SUITE, "TLS_RSA_WITH_AES_128_CBC_SHA256");
Commands used to create CA's certificate
runmqckm -keydb -create -db myCA.kdb -type cms -pw mycakeypassword -stash
runmqckm -cert -create -db myCA.kdb -type cms -label "myCAcertificate" -dn "CN=demmoCA,O=DemmoOrg,OU=DemmoDepartment,L=DemmoLocation,C=UK" -expire 1000 -size 1024
runmqckm -cert -extract -db myCA.kdb -type cms -label "myCAcertificate" -target myCAcertfile.cer -format ascii -stashed
then created the keystore for the client using above certificate using key tool
keytool -keystore kautstclient.jks -genkey -alias winclientcert -storepass clientpassword
keytool -import -keystore kautstclient.jks -file myCAcertfile.cer -alias theCARoot
30/02/2022 update > I have now added the certificates to the client side using below commands.
generating client side's CA to self sign the client's certificate
================================================================
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
creating certificate request from the jks in order to signed by the above CA.
===========================================================================
keytool -certreq -v -alias winclientcert -file kauclient.csr -keypass clientpassword -storepass clientpassword -keystore kautstclient.jks
signing the certificate requst(csr file) using the generated CA key
==================================================
openssl x509 -req -in kauclient.csr -CA cert.pem -CAkey key.pem -CAcreateserial -out kauclientown.crt
Import the the signed and then provided certificate certificate into your keystore using the following command:
========================================================================================
keytool -import -v -alias kauclientowncert -file kauclientown.crt -keystore kautstclient.jks -keypass clientpassword -storepass clientpassword
adding the client's key signed root CA in to queue manager's key.db
=================================================================
runmqckm -cert -add -db myqmgr.kdb -file cert.pem -label kauclientsignercertificate
Djavax.net.ssl.trustStore
is not a connection factory property. You need to pass it as a Java system property. The value of the property needs to be either a JKS or PKCS12 file.
You can do this in two ways:
-D
command line option:
-Djavax.net.ssl.trustStore=D:\mq-message-handler-1.0\ssl\myCAcertfile.jks
System.setProperty
:
System.setProperty(javax.net.ssl.trustStore, "D:\mq-message-handler-1.0\ssl\myCAcertfile.jks");