Accessing a secured Elasticsearch 8.5 instance using Spring Data Elasticsearch 5.0

The problem

When starting an Elasticsearch instance in version 8 (the current version being 8.7.0) for the first time, the Elasticsearch server is by default automatically configured with a random generated password and a self signed certificate to secure the connection between clients and the Elasticsearch server.

The password and the fingerprint for the certificate are shown in the output of the server on the first start (output truncated for brevity):

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Elasticsearch security features have been automatically configured!
✅ Authentication is enabled and cluster connections are encrypted.

ℹ️  Password for the elastic user (reset with `bin/elasticsearch-reset-password -u elastic`):
  15krpsaTp0PFjaZlESEt

ℹ️  HTTP CA certificate SHA-256 fingerprint:
  61c0b4447564785c51b0a1394c92a35514de15de6892a188686c093effe900b2

...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

The values shown here are from the output of a locally started instance on my computer which I will delete later anyway, so I am not leaking any sensitive information here.

Now to access this server from an application using Spring Data Elasticsearch, it is necessary to configure the connection to Elasticsearch with this values.

Using Spring Data Elasticsearch 5.0.x

From version 5 on, Spring Data Elasticsearch is configured by providing a @Configuration bean that extends org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration for the imperative version and org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchConfiguration for the reactive version. This bean must implement the clientConfiguration() method to provide a org.springframework.data.elasticsearch.client.ClientConfiguration. This is normally done by using the provided builder class and passing in the necessary information to connect to Elasticsearch.

In order to configure the SSL connection we need to obtain a SSLContext; luckily from Elasticsearch version 8.5 on (which is the version that Spring Data Elasticsearch 5 uses) there is a helper class co.elastic.clients.transport.TransportUtils that can do this, so the minimal configuration looks like this:

import co.elastic.clients.transport.TransportUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration;

@Configuration
public class MyClientConfig extends ElasticsearchConfiguration {

  @Override
  public ClientConfiguration clientConfiguration() {
    return ClientConfiguration.builder()
      .connectedTo("localhost:9200")
      .usingSsl(TransportUtils.sslContextFromCaFingerprint("61c0b4447564785c51b0a1394c92a35514de15de6892a188686c093effe900b2"))
      .withBasicAuth("elastic", "15krpsaTp0PFjaZlESEt")
      .build();
  }
}

Using Spring Data Elasticsearch 5.1.x

With version 5.1 of Spring Data Elasticsearch – which will be released in about 2 weeks – this becomes even shorter, as the use of the fingerprint then is integrated as an overload of the usingSsl() method:

import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration;

@Configuration
public class MyClientConfig extends ElasticsearchConfiguration {

  @Override
  public ClientConfiguration clientConfiguration() {
    return ClientConfiguration.builder()
      .connectedTo("localhost:9200")
      .usingSsl("61c0b4447564785c51b0a1394c92a35514de15de6892a188686c093effe900b2")
      .withBasicAuth("elastic", "15krpsaTp0PFjaZlESEt")
      .build();
  }
}

This is all that is needed to access the Elasticsearch instance using the secured HTTPS connection.