mTLS Setup
Configure mutual TLS authentication for Java client connections
Overview
Standard TLS only proves the server's identity — the server itself accepts any client that knows the address and client ID. Mutual TLS (mTLS) closes that gap: the client also presents a certificate, so the server verifies who is connecting before accepting the connection. That matters on zero-trust networks and in regulated environments where "reaches the port" isn't an acceptable authorization model — the certificate becomes the credential.
The builder's .tls(true), .caCertFile(), .tlsCertFile(), and .tlsKeyFile() (or the .caCertPem() / .tlsCertPem() / .tlsKeyPem() byte-array variants) wire in three artifacts at client construction: the CA certificate (to verify the server, same as one-way TLS) plus the client's own certificate and private key (for the server to verify in return). Verification happens during the handshake, before any messaging traffic flows.
Gotchas: the certificate and key must be a matched pair signed by a CA the server trusts — a mismatch fails the handshake outright; all three inputs must be valid, unexpired PEM, and expiry breaks connections with no warning; and the CA that signed the client cert isn't necessarily the CA that verifies the server — mixing them up causes "works with TLS, fails with mTLS" confusion.
Prerequisites
- KubeMQ server running with mTLS enabled
- Java SDK installed (Maven/Gradle dependency
io.kubemq.sdk:kubemq-sdk-Java:3.1.1) - TLS certificates (client certificate, client key, and CA certificate)
Code
package io.kubemq.example.tls;
import io.kubemq.sdk.client.KubeMQClient;
import io.kubemq.sdk.common.ServerInfo;
import io.kubemq.sdk.queues.QueuesClient;
/**
* Mutual TLS Setup Example
*
* Demonstrates establishing a mutual TLS (mTLS) connection to KubeMQ server
* where both client and server authenticate each other with certificates.
*/
public class MtlsSetupExample {
private static final String ADDRESS = "localhost:50001";
private static final String CLIENT_ID = "java-tls-mtls-setup-client";
private static final String CA_CERT_FILE = "/path/to/ca.pem";
private static final String CLIENT_CERT_FILE = "/path/to/client.pem";
private static final String CLIENT_KEY_FILE = "/path/to/client.key";
public void connectWithMutualTLS() {
System.out.println("=== Mutual TLS (mTLS) Connection ===\n");
// Create a client with mTLS (client cert + key + CA cert)
try (QueuesClient client = QueuesClient.builder()
.address(ADDRESS)
.clientId(CLIENT_ID)
.tls(true)
.caCertFile(CA_CERT_FILE)
.tlsCertFile(CLIENT_CERT_FILE)
.tlsKeyFile(CLIENT_KEY_FILE)
.logLevel(KubeMQClient.Level.INFO)
.build()) {
// Verify mTLS connection
ServerInfo serverInfo = client.ping();
System.out.println("Connected with mTLS. Server: " + serverInfo);
} catch (Exception e) {
System.err.println("mTLS connection failed: " + e.getMessage());
}
}
public void connectWithMutualTLSFromPemBytes() {
System.out.println("=== Mutual TLS from PEM bytes ===\n");
// Load certs from PEM bytes instead of files
byte[] caCertPem = "-----BEGIN CERTIFICATE-----\n... CA cert ...\n-----END CERTIFICATE-----".getBytes();
byte[] clientCertPem = "-----BEGIN CERTIFICATE-----\n... client cert ...\n-----END CERTIFICATE-----".getBytes();
byte[] clientKeyPem = "-----BEGIN PRIVATE KEY-----\n... client key ...\n-----END PRIVATE KEY-----".getBytes();
try (QueuesClient client = QueuesClient.builder()
.address(ADDRESS)
.clientId(CLIENT_ID + "-pem")
.tls(true)
.caCertPem(caCertPem)
.tlsCertPem(clientCertPem)
.tlsKeyPem(clientKeyPem)
.build()) {
ServerInfo serverInfo = client.ping();
System.out.println("Connected with mTLS (PEM bytes). Server: " + serverInfo);
} catch (Exception e) {
System.err.println("mTLS PEM connection failed: " + e.getMessage());
}
}
public static void main(String[] args) {
MtlsSetupExample example = new MtlsSetupExample();
example.connectWithMutualTLS();
example.connectWithMutualTLSFromPemBytes();
}
}How It Works
- The builder with
.tls(true),.caCertFile(),.tlsCertFile(), and.tlsKeyFile()enables mutual TLS authentication. - The server verifies the client's certificate, and the client verifies the server's certificate, establishing bidirectional trust.
- The SDK also supports loading certificates from PEM byte arrays via
.caCertPem(),.tlsCertPem(), and.tlsKeyPem()for environments where certificates are stored in memory or secrets managers. - The
try-with-resourcespattern ensures the client is properly closed after use.
Related
Was this page helpful?