mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-24 13:02:10 +00:00
Allow SSL configuration with the Elasticsearch CA fingerprint.
Original Pull Request #2540 Closes #2539
This commit is contained in:
parent
17ecce4362
commit
406961c13b
@ -240,7 +240,7 @@ ClientConfiguration clientConfiguration = ClientConfiguration.builder()
|
|||||||
|
|
||||||
<.> Define default headers, if they need to be customized
|
<.> Define default headers, if they need to be customized
|
||||||
<.> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
|
<.> Use the builder to provide cluster addresses, set default `HttpHeaders` or enable SSL.
|
||||||
<.> Optionally enable SSL.
|
<.> Optionally enable SSL. There exist overloads of this function that can take a `SSLContext` or as an alternative the fingerprint of the certificate as it is output by Elasticsearch 8 on startup.
|
||||||
<.> Optionally set a proxy.
|
<.> Optionally set a proxy.
|
||||||
<.> Optionally set a path prefix, mostly used when different clusters a behind some reverse proxy.
|
<.> Optionally set a path prefix, mostly used when different clusters a behind some reverse proxy.
|
||||||
<.> Set the connection timeout.
|
<.> Set the connection timeout.
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
== New in Spring Data Elasticsearch 5.1
|
== New in Spring Data Elasticsearch 5.1
|
||||||
|
|
||||||
* Upgrade to Elasticsearch 8.7.0
|
* Upgrade to Elasticsearch 8.7.0
|
||||||
|
* Allow specification of the TLS certificate when connecting to an Elasticsearch 8 cluster
|
||||||
|
|
||||||
[[new-features.5-0-0]]
|
[[new-features.5-0-0]]
|
||||||
== New in Spring Data Elasticsearch 5.0
|
== New in Spring Data Elasticsearch 5.0
|
||||||
|
@ -20,7 +20,6 @@ import java.net.SocketAddress;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
@ -28,7 +27,6 @@ import javax.net.ssl.SSLContext;
|
|||||||
|
|
||||||
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration interface exposing common client configuration properties for Elasticsearch clients.
|
* Configuration interface exposing common client configuration properties for Elasticsearch clients.
|
||||||
@ -122,6 +120,12 @@ public interface ClientConfiguration {
|
|||||||
*/
|
*/
|
||||||
Optional<SSLContext> getSslContext();
|
Optional<SSLContext> getSslContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the optional SHA-256 fingerprint of the self-signed http_ca.crt certificate output by Elasticsearch at
|
||||||
|
* startup time.
|
||||||
|
*/
|
||||||
|
Optional<String> getCaFingerprint();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if not configured.
|
* Returns the {@link HostnameVerifier} to use. Can be {@link Optional#empty()} if not configured.
|
||||||
*
|
*
|
||||||
@ -250,6 +254,15 @@ public interface ClientConfiguration {
|
|||||||
* @return the {@link TerminalClientConfigurationBuilder}.
|
* @return the {@link TerminalClientConfigurationBuilder}.
|
||||||
*/
|
*/
|
||||||
TerminalClientConfigurationBuilder usingSsl(SSLContext sslContext, HostnameVerifier hostnameVerifier);
|
TerminalClientConfigurationBuilder usingSsl(SSLContext sslContext, HostnameVerifier hostnameVerifier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect via https using a SSLContext that is build from the given certificate fingerprint.
|
||||||
|
*
|
||||||
|
* @param caFingerprint the SHA-256 fingerprint of the self-signed http_ca.crt certificate output by Elasticsearch
|
||||||
|
* at startup time.
|
||||||
|
* @return the {@link TerminalClientConfigurationBuilder}.
|
||||||
|
*/
|
||||||
|
TerminalClientConfigurationBuilder usingSsl(String caFingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,7 +20,6 @@ import java.time.Duration;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
@ -33,7 +32,6 @@ import org.springframework.data.elasticsearch.client.ClientConfiguration.Termina
|
|||||||
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
import org.springframework.data.elasticsearch.support.HttpHeaders;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default builder implementation for {@link ClientConfiguration}.
|
* Default builder implementation for {@link ClientConfiguration}.
|
||||||
@ -51,14 +49,15 @@ class ClientConfigurationBuilder
|
|||||||
private final List<InetSocketAddress> hosts = new ArrayList<>();
|
private final List<InetSocketAddress> hosts = new ArrayList<>();
|
||||||
private HttpHeaders headers = new HttpHeaders();
|
private HttpHeaders headers = new HttpHeaders();
|
||||||
private boolean useSsl;
|
private boolean useSsl;
|
||||||
private @Nullable SSLContext sslContext;
|
@Nullable private SSLContext sslContext;
|
||||||
private @Nullable HostnameVerifier hostnameVerifier;
|
@Nullable private String caFingerprint;
|
||||||
|
@Nullable private HostnameVerifier hostnameVerifier;
|
||||||
private Duration connectTimeout = Duration.ofSeconds(10);
|
private Duration connectTimeout = Duration.ofSeconds(10);
|
||||||
private Duration soTimeout = Duration.ofSeconds(5);
|
private Duration soTimeout = Duration.ofSeconds(5);
|
||||||
private @Nullable String username;
|
@Nullable private String username;
|
||||||
private @Nullable String password;
|
@Nullable private String password;
|
||||||
private @Nullable String pathPrefix;
|
@Nullable private String pathPrefix;
|
||||||
private @Nullable String proxy;
|
@Nullable private String proxy;
|
||||||
private Supplier<HttpHeaders> headersSupplier = HttpHeaders::new;
|
private Supplier<HttpHeaders> headersSupplier = HttpHeaders::new;
|
||||||
@Deprecated private final HttpClientConfigCallback httpClientConfigurer = httpClientBuilder -> httpClientBuilder;
|
@Deprecated private final HttpClientConfigCallback httpClientConfigurer = httpClientBuilder -> httpClientBuilder;
|
||||||
private final List<ClientConfiguration.ClientConfigurationCallback<?>> clientConfigurers = new ArrayList<>();
|
private final List<ClientConfiguration.ClientConfigurationCallback<?>> clientConfigurers = new ArrayList<>();
|
||||||
@ -138,10 +137,20 @@ class ClientConfigurationBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerminalClientConfigurationBuilder usingSsl(String caFingerprint) {
|
||||||
|
|
||||||
|
Assert.notNull(caFingerprint, "caFingerprint must not be null");
|
||||||
|
|
||||||
|
this.useSsl = true;
|
||||||
|
this.caFingerprint = caFingerprint;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
* @see org.springframework.data.elasticsearch.client.ClientConfiguration.TerminalClientConfigurationBuilder#withDefaultHeaders(org.springframework.http.HttpHeaders)
|
* @see org.springframework.data.elasticsearch.client.ClientConfiguration.TerminalClientConfigurationBuilder#withDefaultHeaders(org.springframework.http.HttpHeaders)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public TerminalClientConfigurationBuilder withDefaultHeaders(HttpHeaders defaultHeaders) {
|
public TerminalClientConfigurationBuilder withDefaultHeaders(HttpHeaders defaultHeaders) {
|
||||||
|
|
||||||
@ -228,8 +237,12 @@ class ClientConfigurationBuilder
|
|||||||
headers.setBasicAuth(username, password);
|
headers.setBasicAuth(username, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DefaultClientConfiguration(hosts, headers, useSsl, sslContext, soTimeout, connectTimeout, pathPrefix,
|
if (sslContext != null && caFingerprint != null) {
|
||||||
hostnameVerifier, proxy, httpClientConfigurer, clientConfigurers, headersSupplier);
|
throw new IllegalArgumentException("Either SSLContext or caFingerprint must be set, but not both");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new DefaultClientConfiguration(hosts, headers, useSsl, sslContext, caFingerprint, soTimeout, connectTimeout,
|
||||||
|
pathPrefix, hostnameVerifier, proxy, httpClientConfigurer, clientConfigurers, headersSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static InetSocketAddress parse(String hostAndPort) {
|
private static InetSocketAddress parse(String hostAndPort) {
|
||||||
|
@ -42,19 +42,20 @@ class DefaultClientConfiguration implements ClientConfiguration {
|
|||||||
private final List<InetSocketAddress> hosts;
|
private final List<InetSocketAddress> hosts;
|
||||||
private final HttpHeaders headers;
|
private final HttpHeaders headers;
|
||||||
private final boolean useSsl;
|
private final boolean useSsl;
|
||||||
private final @Nullable SSLContext sslContext;
|
@Nullable private final SSLContext sslContext;
|
||||||
|
@Nullable private final String caFingerprint;
|
||||||
private final Duration soTimeout;
|
private final Duration soTimeout;
|
||||||
private final Duration connectTimeout;
|
private final Duration connectTimeout;
|
||||||
private final @Nullable String pathPrefix;
|
@Nullable private final String pathPrefix;
|
||||||
private final @Nullable HostnameVerifier hostnameVerifier;
|
@Nullable private final HostnameVerifier hostnameVerifier;
|
||||||
private final @Nullable String proxy;
|
@Nullable private final String proxy;
|
||||||
private final HttpClientConfigCallback httpClientConfigurer;
|
private final HttpClientConfigCallback httpClientConfigurer;
|
||||||
private final Supplier<HttpHeaders> headersSupplier;
|
private final Supplier<HttpHeaders> headersSupplier;
|
||||||
private final List<ClientConfigurationCallback<?>> clientConfigurers;
|
private final List<ClientConfigurationCallback<?>> clientConfigurers;
|
||||||
|
|
||||||
DefaultClientConfiguration(List<InetSocketAddress> hosts, HttpHeaders headers, boolean useSsl,
|
DefaultClientConfiguration(List<InetSocketAddress> hosts, HttpHeaders headers, boolean useSsl,
|
||||||
@Nullable SSLContext sslContext, Duration soTimeout, Duration connectTimeout, @Nullable String pathPrefix,
|
@Nullable SSLContext sslContext, @Nullable String caFingerprint, Duration soTimeout, Duration connectTimeout,
|
||||||
@Nullable HostnameVerifier hostnameVerifier, @Nullable String proxy,
|
@Nullable String pathPrefix, @Nullable HostnameVerifier hostnameVerifier, @Nullable String proxy,
|
||||||
HttpClientConfigCallback httpClientConfigurer, List<ClientConfigurationCallback<?>> clientConfigurers,
|
HttpClientConfigCallback httpClientConfigurer, List<ClientConfigurationCallback<?>> clientConfigurers,
|
||||||
Supplier<HttpHeaders> headersSupplier) {
|
Supplier<HttpHeaders> headersSupplier) {
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ class DefaultClientConfiguration implements ClientConfiguration {
|
|||||||
this.headers = headers;
|
this.headers = headers;
|
||||||
this.useSsl = useSsl;
|
this.useSsl = useSsl;
|
||||||
this.sslContext = sslContext;
|
this.sslContext = sslContext;
|
||||||
|
this.caFingerprint = caFingerprint;
|
||||||
this.soTimeout = soTimeout;
|
this.soTimeout = soTimeout;
|
||||||
this.connectTimeout = connectTimeout;
|
this.connectTimeout = connectTimeout;
|
||||||
this.pathPrefix = pathPrefix;
|
this.pathPrefix = pathPrefix;
|
||||||
@ -92,6 +94,11 @@ class DefaultClientConfiguration implements ClientConfiguration {
|
|||||||
return Optional.ofNullable(this.sslContext);
|
return Optional.ofNullable(this.sslContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<String> getCaFingerprint() {
|
||||||
|
return Optional.ofNullable(this.caFingerprint);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<HostnameVerifier> getHostNameVerifier() {
|
public Optional<HostnameVerifier> getHostNameVerifier() {
|
||||||
return Optional.ofNullable(this.hostnameVerifier);
|
return Optional.ofNullable(this.hostnameVerifier);
|
||||||
|
@ -19,6 +19,7 @@ import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
|||||||
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
|
||||||
import co.elastic.clients.transport.ElasticsearchTransport;
|
import co.elastic.clients.transport.ElasticsearchTransport;
|
||||||
import co.elastic.clients.transport.TransportOptions;
|
import co.elastic.clients.transport.TransportOptions;
|
||||||
|
import co.elastic.clients.transport.TransportUtils;
|
||||||
import co.elastic.clients.transport.Version;
|
import co.elastic.clients.transport.Version;
|
||||||
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
import co.elastic.clients.transport.rest_client.RestClientOptions;
|
||||||
import co.elastic.clients.transport.rest_client.RestClientTransport;
|
import co.elastic.clients.transport.rest_client.RestClientTransport;
|
||||||
@ -34,13 +35,7 @@ import java.util.function.Function;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.*;
|
||||||
import org.apache.http.HttpEntityEnclosingRequest;
|
|
||||||
import org.apache.http.HttpHost;
|
|
||||||
import org.apache.http.HttpRequest;
|
|
||||||
import org.apache.http.HttpRequestInterceptor;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.HttpResponseInterceptor;
|
|
||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.apache.http.entity.ByteArrayEntity;
|
import org.apache.http.entity.ByteArrayEntity;
|
||||||
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.ContentType;
|
||||||
@ -197,6 +192,10 @@ public final class ElasticsearchClients {
|
|||||||
}
|
}
|
||||||
|
|
||||||
builder.setHttpClientConfigCallback(clientBuilder -> {
|
builder.setHttpClientConfigCallback(clientBuilder -> {
|
||||||
|
if (clientConfiguration.getCaFingerprint().isPresent()) {
|
||||||
|
clientBuilder
|
||||||
|
.setSSLContext(TransportUtils.sslContextFromCaFingerprint(clientConfiguration.getCaFingerprint().get()));
|
||||||
|
}
|
||||||
clientConfiguration.getSslContext().ifPresent(clientBuilder::setSSLContext);
|
clientConfiguration.getSslContext().ifPresent(clientBuilder::setSSLContext);
|
||||||
clientConfiguration.getHostNameVerifier().ifPresent(clientBuilder::setSSLHostnameVerifier);
|
clientConfiguration.getHostNameVerifier().ifPresent(clientBuilder::setSSLHostnameVerifier);
|
||||||
clientBuilder.addInterceptorLast(new CustomHeaderInjector(clientConfiguration.getHeadersSupplier()));
|
clientBuilder.addInterceptorLast(new CustomHeaderInjector(clientConfiguration.getHeadersSupplier()));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user