Elasticsearch 7.2 java client SSL configuration failing: bad_certificate

After updating my elasticsearch to 7.2 and updating kibana, and after enabling security and therefore SSL, my java (spring) application lost connection to it. Spring JPA still doesn't support ES 7 and security+SSL was a paid plugin, and now it is part of the basic free package.

Because of this, I have been trying to configure my own client to send the requests using the RestHighLevelClient provided by elasticsearch SDK. With SSL turned of for the development mode, I have been able to connect and create my indexes, but as soon as I turn it on, I cannot get it to work.

I followed a tutorial to setup a valid self signed certificate to use with it. The tutorial uses a certificate tool provided with elasticsearch.

The steps were as follows:

  1. Generate a CA: bin/elasticsearch-certutil ca ENTER ENTER
  2. Generate a certificate from this CA: bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12 ENTER ENTER ENTER

(both generated without passwords)

  1. Install the certificates in the ES configuration file (elasticsearch.yml):

    xpack.security.transport.ssl.enabled: true
    xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12
    xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12

  2. Defined user passwords: bin/elasticsearch-setup-passwords interactive

  3. Generated a client certificate (this part I still do not fully understand): bin/elasticsearch-certutil cert --ca config/certs/elastic-stack-ca.p12 -name "CN=xyz,OU=XXX Team,DC=mydomain,DC=com"
    client.p12 ENTER

After these steps, since ES was running fine, I started creating the java part that connects to the ES server.

For that I instantiated a Keystore: KeyStore truststore = KeyStore.getInstance("PKCS12");

Then I loaded my client certificate (client.p12) from the classpath:

try (InputStream resource = new ClassPathResource(keystorePath).getInputStream()) {
		    truststore.load(resource, new char[] {});//keystore pass is empty
	} catch (NoSuchAlgorithmException | CertificateException | IOException e) {
		log.error(e.getMessage(), e);

Then I built a SSL context as follows:
sslBuilder = SSLContexts.custom().loadTrustMaterial(truststore, new TrustSelfSignedStrategy());

And finally, from that context I have created my rest client builder (that I use to create my RestHighLevelClient:

RestClientBuilder builder = RestClient.builder(
			    new HttpHost(elasticAddress, elasticPort, "https"))
			    .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setSSLContext(sslContext));

return new RestHighLevelClient(builder);

The problem I'm getting is when I try to connect. In my java client I get this exception:
javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate

and in elastic I get this exception:
Caused by: javax.net.ssl.SSLHandshakeException: null cert chain

The elasticsearch documentation says that when these exceptions occur, the problem is: The SSLHandshakeException indicates that a self-signed certificate was returned by the client that is not trusted as it cannot be found in the truststore or keystore. This SSLException is seen on the client-side of the connection.

But it doesn't explain how to solve this problem. I have followed the official 7.2 documentation tutorial for certificate generation, and also for the java setup (the code they provide as example doesn't work and uses a JKS store which they don't explain how to generate).

This question is a clone of my original question in SO: https://stackoverflow.com/questions/57259477/elasticsearch-7-2-java-client-ssl-configuration-failing-bad-certificate
If you want som SO reputation, you can answer there :wink:

is bumping allowed in this forum?

I still have no idea on how to solve this. The topic is about to close so I'm adding another reply.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.