<p>Hava a Java client application that can connect to a Kubernetes cluster over SSL using <code>io.kubernetes.client.ApiClient</code> okay on its own. The same Java client application can also connect to an MQ cluster over SSL on its own. The same application however cannot connect to both Kubernetes cluster over SSL and MQ cluster over SSL all at once.</p>

<p>I believe this may be due to the fact that only one SSL key/trust store can be configured on a JVM at any one time? But do not know what the best way forward is in order to resolve this.</p>

<p>What would be the simplest way to allow a Java client to connect to both a Kubernetes cluster and an MQ cluster each over SSL?</p>

<p>The two configurations shown in this post result in the following error being thrown when both are run together:</p>

<pre><code>WARN  io.kubernetes.client.util.credentials.ClientCertificateAuthentication - Could not create key manager for Client Certificate authentication.
java.security.UnrecoverableKeyException: Cannot recover key
</code></pre>

<p>The Kubernetes part of the client application connects to the Kubernetes cluster by configuring as follows:</p>

<pre><code>String kubeConfigPath = "~/.kube/config";
apiClient = ClientBuilder.kubeconfig(
                    KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath))).build();
apiClient.getHttpClient().setReadTimeout(0, TimeUnit.SECONDS);
            Configuration.setDefaultApiClient(apiClient);
</code></pre>

<p>The Mq part of the client application connects to the MQ cluster by configuring as follows:</p>

<pre><code>System.setProperty("javax.net.ssl.trustStore", "C:\\tmp\\ssl\\dev\\mgr_mq.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
System.setProperty("javax.net.ssl.keyStore", "C:\\tmp\\ssl\\dev\\mgr_mq.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
System.setProperty("com.ibm.mq.cfg.useIBMCipherMappings", "false");

java.net.URL ccdt = new URL("file:./config/qmgrs/mgr/AMQCLCHL.TAB");
MQQueueManager mqQueueManager = new MQQueueManager("*mgr", ccdt);
</code></pre>

<p>The <a href="https://github.com/kubernetes-client/java" rel="nofollow noreferrer">Kubernetes java client API code</a> seems to force adding the certificate referenced in <code>.kube/config</code> to a new truststore that it creates new each time before adding the certificate to it.</p>

<p>This seems to take place in <code>ClientCertifiacteAuthentication.java</code> class' <code>provide(ApiClient client)</code> method:</p>

<pre><code>final KeyManager[] keyManagers = SSLUtils.keyManagers(certificate, key, algo, "", null, null);
</code></pre>

<p>Where the two <code>null</code> values which are <code>keyStoreFile</code> and <code>keyStorePassphrase</code> then force a new truststore to be created within.</p>

<p>So for now and to prove that a solution is possible I have overriden this class to be:</p>

<pre><code>final KeyManager[] keyManagers = SSLUtils.keyManagers(certificate, key, algo, "password", "C:\\tmp\\ssl\\dev\\mgr_mq.jks", "password");
</code></pre>

<p>With this overriden code, both Kubernetes cluster and MQ cluster can be successfully connected to over SSL within the same JVM.</p>
