Hi @Morag Hughson,
If I need to enable mTLS and have set SSLCAUTH(REQUIRED) for the MQ channel, then I am also getting this in the MQ server logs - During handshake, the remote partner sent no certificate.
I read your inputs on this. So, I understand that we need to have it configured on client-side for the client public cert to be presented during Two-Way handshake, and also it needs to be stored on MQ server side as well for verification of client cert. I have done all these, still getting the aforementioned error. I am attching my Jms/SSL Config code for your ref. Your assistance will be massively appreciated:
@Bean
public SSLSocketFactory sslSocketFactory() throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
String storeType = System.getProperty("javax.net.ssl.keyStoreType", KeyStore.getDefaultType());
// Key Manager Factory
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
char[] tsPwdBytes = CLIENT_TRUSTSTORE_PASSWORD.toCharArray();
char[] ksPwdBytes = CLIENT_KEYSTORE_PASSWORD.toCharArray();
String truststorePath = BASE_DIR_CERT+"client_truststore.jks";
String keystorePath = BASE_DIR_CERT+"ks\\client_keystore.jks";
// configure TS
initTMF(truststorePath, tsPwdBytes, tmf);
// configure KS
initKMF(keystorePath, ksPwdBytes, kmf);
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
log.error("Exception occurred while SSLContext init: ", e);
throw new RuntimeException(e);
}
}
private static void initTMF(String truststorePath, char[] tsPwdBytes, TrustManagerFactory tmf) throws KeyStoreException {
KeyStore trustStore = KeyStore.getInstance(DEFAULT_STORE_TYPE);
try (FileInputStream fis = new FileInputStream(truststorePath)) {
trustStore.load(fis, tsPwdBytes);
} catch (FileNotFoundException e) {
log.error("Exception occurred while file path search: ", e);
throw new RuntimeException(e);
} catch (IOException e) {
log.error("Exception occurred while file read: ", e);
throw new RuntimeException(e);
} catch (CertificateException e) {
log.error("Exception occurred with Certificate: ", e);
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
log.error("Exception occurred with KeyAlgo: ", e);
throw new RuntimeException(e);
}
tmf.init(trustStore);
}
private static void initKMF(String keystorePath, char[] ksPwdBytes, KeyManagerFactory kmf) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException {
KeyStore keyStore = KeyStore.getInstance(DEFAULT_STORE_TYPE);
try (FileInputStream fis = new FileInputStream(keystorePath)) {
keyStore.load(fis, ksPwdBytes);
} catch (FileNotFoundException e) {
log.error("Exception occurred while file path search: ", e);
throw new RuntimeException(e);
} catch (IOException e) {
log.error("Exception occurred while file read: ", e);
throw new RuntimeException(e);
} catch (CertificateException e) {
log.error("Exception occurred with Certificate: ", e);
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
log.error("Exception occurred with KeyAlgo: ", e);
throw new RuntimeException(e);
}
kmf.init(keyStore, ksPwdBytes);
}
@Bean
public MQQueueConnectionFactory mqConnectionFactory(SSLSocketFactory sslSocketFactory) throws Exception {
/**
* Configure SSL properties
*/
System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false");
MQQueueConnectionFactory factory = new MQQueueConnectionFactory();
factory.setHostName("localhost");
factory.setPort(1414);
factory.setQueueManager("QM1");
//factory.setChannel("DEV.APP.SVRCONN");
factory.setChannel("DEV.ADMIN.SVRCONN");
//factory.setTransportType(1); // 1 for Client
factory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
// Set the SSLContext in the connection factory
factory.setSSLSocketFactory(sslSocketFactory);
// ssl configs
factory.setSSLCipherSuite("TLS_RSA_WITH_AES_128_CBC_SHA256");
// Setting username and password
factory.setStringProperty(WMQConstants.USERID, "admin"); // Replace with your actual username
factory.setStringProperty(WMQConstants.PASSWORD, "passw0rd"); // Replace with your actual password
return factory;
}
private static MQQueueConnectionFactory getMqQueueConnectionFactory(SSLSocketFactory sslSocketFactory) throws JMSException {
MQQueueConnectionFactory factory = new MQQueueConnectionFactory();
factory.setHostName("localhost");
factory.setPort(1414);
factory.setQueueManager("QM1");
//factory.setChannel("DEV.APP.SVRCONN");
factory.setChannel("DEV.ADMIN.SVRCONN");
//factory.setTransportType(1); // 1 for Client
factory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
// Set the SSLContext in the connection factory
factory.setSSLSocketFactory(sslSocketFactory);
// ssl configs
factory.setSSLCipherSuite("TLS_RSA_WITH_AES_128_CBC_SHA256");
// Setting username and password
factory.setStringProperty(WMQConstants.USERID, "admin"); // Replace with your actual username
factory.setStringProperty(WMQConstants.PASSWORD, "passw0rd"); // Replace with your actual password
return factory;
}
------------------------------
Piyush Ojha
------------------------------
Original Message:
Sent: Wed July 28, 2021 11:59 PM
From: Morag Hughson
Subject: MQ TLS verification tool
If the client is intended to be anonymous, then the SVRCONN that it is connecting to must be defined to use SSLCAUTH(OPTIONAL).
If the SVRCONN that the client is connecting to is mandated to use SSLCAUTH(REQUIRED) then your client cannot be anonymous and you will need a certificate identifying the client, the CA of which will need to be in the queue manager KDB.
Cheers,
Morag
------------------------------
Morag Hughson
MQ Technical Education Specialist
MQGem Software Limited
Website: https://www.mqgem.com
Original Message:
Sent: Wed July 28, 2021 12:33 PM
From: Vignesh
Subject: MQ TLS verification tool
Thank you! Yes, I don't have a personal certificate in my client(C1) kdb.
My client is anonymous and don't have a CA ,whereas my server qmgr (A) has CA.
In this case does a self signed cert of client in the kdb alone is suffice in client side along with root?
------------------------------
Vignesh
Original Message:
Sent: Tue July 27, 2021 06:12 PM
From: Morag Hughson
Subject: MQ TLS verification tool
Your Client (C1) kdb doesn't appear to have a certificate identifying the client in it? If your SVRCONN is defined to use SSLCAUTH(REQUIRED) then the queue manager will bounce the connect with that error message.
------------------------------
Morag Hughson
MQ Technical Education Specialist
MQGem Software Limited
Website: https://www.mqgem.com
Original Message:
Sent: Tue July 27, 2021 05:26 PM
From: Vignesh
Subject: MQ TLS verification tool
Hi Peter,
Thank you for the note!
Server qmgr(A) kdb has CA certs (Root , Intermediate , ServerCertificate)
Client (C1) kdb has only (Root cert from CA- it is he same that qmgr(A) kdb has)
However when i run my code , i'm getting MQRC_SSL_Initialization_Error and on the qmgr(A) error log i see "AMQ9637E: During handshake, the remote partner sent no certificate."
------------------------------
Vignesh
Original Message:
Sent: Mon July 26, 2021 04:10 PM
From: Peter Vander Woude
Subject: MQ TLS verification tool
Vignesh,
The client needs to have the CA certs, that signed the remote server's ssl certificate, so it can accept the certificate. Similarly, the remote server must have the CA certs that signed the client ssl certificate. If either of those are not signed by a certificate authority (i.e. a self-signed certificate), then the public portion of the self signed cert needs to be supplied to the other side and added as a certificate authority to the appropriate keyring.
------------------------------
Peter
Original Message:
Sent: Mon July 26, 2021 02:57 PM
From: Vignesh
Subject: MQ TLS verification tool
Hello,
I'm looking for a simple tool that would validate MQ connection via TLS enabled channels.
Every time we renew a cert in Qmgr (A) , we need to validate if a client is able to successfully establish a connection.
When I renew a cert in server qmgr (A) ,
I create a CSR ,copy the arm file and upload in CA website.
CA signs the CSR and send me a zip file containing (Intermediate , Root and ServerCertificate) . we receive them in qmgr (A) kdb.
In order to validate I picked MQ explorer as one of the client - C1 - but having few questions to get an understanding on this
Created a kdb(jks) in my local PC (C1) where my MQ explorer runs.
What are the certs that my local kdb needs to establish a connection with remote qmgr(A) (TLS enabled channel - SSLCAUTH(Required)) ?
please share your ideas or any documentation that would help me get clarity on this topic.
Thanks,
Vignesh
------------------------------
Vignesh
------------------------------