You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ro...@apache.org on 2019/11/14 09:13:27 UTC
[james-project] 07/07: JAMES-2905 One more option about
HostNameVerifier
This is an automated email from the ASF dual-hosted git repository.
rouazana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 2e87e12dbce48737c21ad29138e445ceb1b8a35b
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Wed Nov 13 18:20:06 2019 +0700
JAMES-2905 One more option about HostNameVerifier
---
.../apache/james/backends/es/ClientProvider.java | 29 ++++-
.../backends/es/ElasticSearchConfiguration.java | 144 ++++++++++++++++-----
...iderImplConnectionAuthESIgnoreSSLCheckTest.java | 7 +-
...ImplConnectionAuthESOverrideTrustStoreTest.java | 10 +-
.../es/ElasticSearchConfigurationTest.java | 118 +++++++++++++----
.../destination/conf/elasticsearch.properties | 6 +
.../destination/conf/elasticsearch.properties | 6 +
.../destination/conf/elasticsearch.properties | 6 +
.../destination/conf/elasticsearch.properties | 6 +
src/site/xdoc/server/config-elasticsearch.xml | 15 +++
10 files changed, 282 insertions(+), 65 deletions(-)
diff --git a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/ClientProvider.java b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/ClientProvider.java
index 50a51e7..1ff14cd 100644
--- a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/ClientProvider.java
+++ b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/ClientProvider.java
@@ -38,13 +38,15 @@ import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
+import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.james.backends.es.ElasticSearchConfiguration.HostScheme;
-import org.apache.james.backends.es.ElasticSearchConfiguration.SSLTrustConfiguration.SSLTrustStore;
-import org.apache.james.backends.es.ElasticSearchConfiguration.SSLTrustConfiguration.SSLValidationStrategy;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration.HostNameVerifier;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration.SSLTrustStore;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration.SSLValidationStrategy;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.slf4j.Logger;
@@ -60,7 +62,7 @@ public class ClientProvider implements Provider<RestHighLevelClient> {
private static class HttpAsyncClientConfigurer {
private static final TrustStrategy TRUST_ALL = (x509Certificates, authType) -> true;
- private static final HostnameVerifier ACCEPT_ANY_HOST = (hostname, sslSession) -> true;
+ private static final HostnameVerifier ACCEPT_ANY_HOSTNAME = (hostname, sslSession) -> true;
private final ElasticSearchConfiguration configuration;
@@ -94,7 +96,7 @@ public class ClientProvider implements Provider<RestHighLevelClient> {
try {
builder
.setSSLContext(sslContext())
- .setSSLHostnameVerifier(ACCEPT_ANY_HOST);
+ .setSSLHostnameVerifier(hostnameVerifier());
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | CertificateException | IOException e) {
throw new RuntimeException("Cannot set SSL options to the builder", e);
}
@@ -105,7 +107,7 @@ public class ClientProvider implements Provider<RestHighLevelClient> {
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
- SSLValidationStrategy strategy = configuration.getSslTrustConfiguration()
+ SSLValidationStrategy strategy = configuration.getSslConfiguration()
.getStrategy();
switch (strategy) {
@@ -123,10 +125,25 @@ public class ClientProvider implements Provider<RestHighLevelClient> {
}
}
+ private HostnameVerifier hostnameVerifier() {
+ HostNameVerifier hostnameVerifier = configuration.getSslConfiguration()
+ .getHostNameVerifier();
+
+ switch (hostnameVerifier) {
+ case DEFAULT:
+ return new DefaultHostnameVerifier();
+ case ACCEPT_ANY_HOSTNAME:
+ return ACCEPT_ANY_HOSTNAME;
+ default:
+ throw new NotImplementedException(
+ String.format("unrecognized HostNameVerifier '%s'", hostnameVerifier.name()));
+ }
+ }
+
private SSLContextBuilder applyTrustStore(SSLContextBuilder sslContextBuilder) throws CertificateException, NoSuchAlgorithmException,
KeyStoreException, IOException {
- SSLTrustStore trustStore = configuration.getSslTrustConfiguration()
+ SSLTrustStore trustStore = configuration.getSslConfiguration()
.getTrustStore()
.orElseThrow(() -> new IllegalStateException("SSLTrustStore cannot to be empty"));
diff --git a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/ElasticSearchConfiguration.java b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/ElasticSearchConfiguration.java
index 47681a5..16727ea 100644
--- a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/ElasticSearchConfiguration.java
+++ b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/ElasticSearchConfiguration.java
@@ -19,7 +19,7 @@
package org.apache.james.backends.es;
-import static org.apache.james.backends.es.ElasticSearchConfiguration.SSLTrustConfiguration.SSLValidationStrategy.OVERRIDE;
+import static org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration.SSLValidationStrategy.OVERRIDE;
import java.io.File;
import java.nio.file.Files;
@@ -35,8 +35,9 @@ import java.util.stream.Stream;
import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.ex.ConfigurationException;
-import org.apache.james.backends.es.ElasticSearchConfiguration.SSLTrustConfiguration.SSLTrustStore;
-import org.apache.james.backends.es.ElasticSearchConfiguration.SSLTrustConfiguration.SSLValidationStrategy;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration.HostNameVerifier;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration.SSLTrustStore;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration.SSLValidationStrategy;
import org.apache.james.util.Host;
import com.github.steveash.guavate.Guavate;
@@ -110,7 +111,7 @@ public class ElasticSearchConfiguration {
}
}
- public static class SSLTrustConfiguration {
+ public static class SSLConfiguration {
public enum SSLValidationStrategy {
DEFAULT,
@@ -128,6 +129,21 @@ public class ElasticSearchConfiguration {
}
}
+ public enum HostNameVerifier {
+ DEFAULT,
+ ACCEPT_ANY_HOSTNAME;
+
+ static HostNameVerifier from(String rawValue) {
+ Preconditions.checkNotNull(rawValue);
+
+ return Stream.of(values())
+ .filter(verifier -> verifier.name().equalsIgnoreCase(rawValue))
+ .findAny()
+ .orElseThrow(() -> new IllegalArgumentException(String.format("invalid HostNameVerifier '%s'", rawValue)));
+
+ }
+ }
+
public static class SSLTrustStore {
public static SSLTrustStore of(String filePath, String password) {
@@ -174,28 +190,79 @@ public class ElasticSearchConfiguration {
}
}
- static SSLTrustConfiguration defaultBehavior() {
- return new SSLTrustConfiguration(SSLValidationStrategy.DEFAULT, Optional.empty());
+ static class Builder {
+
+ interface RequireSSLStrategyTrustStore {
+ RequireHostNameVerifier sslStrategy(SSLValidationStrategy strategy, Optional<SSLTrustStore> trustStore);
+
+ default RequireHostNameVerifier strategyIgnore() {
+ return sslStrategy(SSLValidationStrategy.IGNORE, Optional.empty());
+ }
+
+ default RequireHostNameVerifier strategyOverride(SSLTrustStore trustStore) {
+ return sslStrategy(SSLValidationStrategy.OVERRIDE, Optional.of(trustStore));
+ }
+
+ default RequireHostNameVerifier strategyDefault() {
+ return sslStrategy(SSLValidationStrategy.DEFAULT, Optional.empty());
+ }
+ }
+
+ interface RequireHostNameVerifier {
+ ReadyToBuild hostNameVerifier(HostNameVerifier hostNameVerifier);
+
+ default ReadyToBuild acceptAnyHostNameVerifier() {
+ return hostNameVerifier(HostNameVerifier.ACCEPT_ANY_HOSTNAME);
+ }
+
+ default ReadyToBuild defaultHostNameVerifier() {
+ return hostNameVerifier(HostNameVerifier.DEFAULT);
+ }
+ }
+
+ static class ReadyToBuild {
+ private final SSLValidationStrategy sslValidationStrategy;
+ private final HostNameVerifier hostNameVerifier;
+ private Optional<SSLTrustStore> sslTrustStore;
+
+ private ReadyToBuild(SSLValidationStrategy sslValidationStrategy, HostNameVerifier hostNameVerifier, Optional<SSLTrustStore> sslTrustStore) {
+ this.sslValidationStrategy = sslValidationStrategy;
+ this.hostNameVerifier = hostNameVerifier;
+ this.sslTrustStore = sslTrustStore;
+ }
+
+ public ReadyToBuild sslTrustStore(SSLTrustStore sslTrustStore) {
+ this.sslTrustStore = Optional.of(sslTrustStore);
+ return this;
+ }
+
+ public SSLConfiguration build() {
+ return new SSLConfiguration(sslValidationStrategy, hostNameVerifier, sslTrustStore);
+ }
+ }
}
- static SSLTrustConfiguration ignore() {
- return new SSLTrustConfiguration(SSLValidationStrategy.IGNORE, Optional.empty());
+ static SSLConfiguration defaultBehavior() {
+ return new SSLConfiguration(SSLValidationStrategy.DEFAULT, HostNameVerifier.DEFAULT, Optional.empty());
}
- static SSLTrustConfiguration override(SSLTrustStore sslTrustStore) {
- return new SSLTrustConfiguration(OVERRIDE, Optional.of(sslTrustStore));
+ static Builder.RequireSSLStrategyTrustStore builder() {
+ return (strategy, trustStore) -> hostNameVerifier -> new Builder.ReadyToBuild(strategy, hostNameVerifier, trustStore);
}
private final SSLValidationStrategy strategy;
+ private final HostNameVerifier hostNameVerifier;
private final Optional<SSLTrustStore> trustStore;
- private SSLTrustConfiguration(SSLValidationStrategy strategy, Optional<SSLTrustStore> trustStore) {
+ private SSLConfiguration(SSLValidationStrategy strategy, HostNameVerifier hostNameVerifier, Optional<SSLTrustStore> trustStore) {
Preconditions.checkNotNull(strategy);
Preconditions.checkNotNull(trustStore);
+ Preconditions.checkNotNull(hostNameVerifier);
Preconditions.checkArgument(strategy != OVERRIDE || trustStore.isPresent(), OVERRIDE.name() + " strategy requires trustStore to be present");
this.strategy = strategy;
this.trustStore = trustStore;
+ this.hostNameVerifier = hostNameVerifier;
}
public SSLValidationStrategy getStrategy() {
@@ -206,20 +273,25 @@ public class ElasticSearchConfiguration {
return trustStore;
}
+ public HostNameVerifier getHostNameVerifier() {
+ return hostNameVerifier;
+ }
+
@Override
public final boolean equals(Object o) {
- if (o instanceof SSLTrustConfiguration) {
- SSLTrustConfiguration that = (SSLTrustConfiguration) o;
+ if (o instanceof SSLConfiguration) {
+ SSLConfiguration that = (SSLConfiguration) o;
return Objects.equals(this.strategy, that.strategy)
- && Objects.equals(this.trustStore, that.trustStore);
+ && Objects.equals(this.trustStore, that.trustStore)
+ && Objects.equals(this.hostNameVerifier, that.hostNameVerifier);
}
return false;
}
@Override
public final int hashCode() {
- return Objects.hash(strategy, trustStore);
+ return Objects.hash(strategy, trustStore, hostNameVerifier);
}
}
@@ -234,7 +306,7 @@ public class ElasticSearchConfiguration {
private Optional<Duration> requestTimeout;
private Optional<HostScheme> hostScheme;
private Optional<Credential> credential;
- private Optional<SSLTrustConfiguration> sslTrustConfiguration;
+ private Optional<SSLConfiguration> sslTrustConfiguration;
public Builder() {
hosts = ImmutableList.builder();
@@ -302,12 +374,12 @@ public class ElasticSearchConfiguration {
return this;
}
- public Builder sslTrustConfiguration(SSLTrustConfiguration sslTrustConfiguration) {
- this.sslTrustConfiguration = Optional.of(sslTrustConfiguration);
+ public Builder sslTrustConfiguration(SSLConfiguration sslConfiguration) {
+ this.sslTrustConfiguration = Optional.of(sslConfiguration);
return this;
}
- public Builder sslTrustConfiguration(Optional<SSLTrustConfiguration> sslTrustStore) {
+ public Builder sslTrustConfiguration(Optional<SSLConfiguration> sslTrustStore) {
this.sslTrustConfiguration = sslTrustStore;
return this;
}
@@ -338,6 +410,7 @@ public class ElasticSearchConfiguration {
public static final String ELASTICSEARCH_PORT = "elasticsearch.port";
public static final String ELASTICSEARCH_HOST_SCHEME = "elasticsearch.hostScheme";
public static final String ELASTICSEARCH_HTTPS_SSL_VALIDATION_STRATEGY = "elasticsearch.hostScheme.https.sslValidationStrategy";
+ public static final String ELASTICSEARCH_HTTPS_HOSTNAME_VERIFIER = "elasticsearch.hostScheme.https.hostNameVerifier";
public static final String ELASTICSEARCH_HTTPS_TRUST_STORE_PATH = "elasticsearch.hostScheme.https.trustStorePath";
public static final String ELASTICSEARCH_HTTPS_TRUST_STORE_PASSWORD = "elasticsearch.hostScheme.https.trustStorePassword";
public static final String ELASTICSEARCH_USER = "elasticsearch.user";
@@ -358,7 +431,7 @@ public class ElasticSearchConfiguration {
public static final String LOCALHOST = "127.0.0.1";
public static final Optional<Integer> DEFAULT_PORT_AS_OPTIONAL = Optional.of(DEFAULT_PORT);
public static final HostScheme DEFAULT_SCHEME = HostScheme.HTTP;
- public static final SSLTrustConfiguration DEFAULT_SSL_TRUST_CONFIGURATION = SSLTrustConfiguration.defaultBehavior();
+ public static final SSLConfiguration DEFAULT_SSL_TRUST_CONFIGURATION = SSLConfiguration.defaultBehavior();
public static final ElasticSearchConfiguration DEFAULT_CONFIGURATION = builder()
.addHost(Host.from(LOCALHOST, DEFAULT_PORT))
@@ -378,10 +451,21 @@ public class ElasticSearchConfiguration {
.build();
}
- private static Optional<SSLTrustConfiguration> sslTrustConfiguration(Configuration configuration) {
- return Optional.ofNullable(configuration.getString(ELASTICSEARCH_HTTPS_SSL_VALIDATION_STRATEGY))
+ private static SSLConfiguration sslTrustConfiguration(Configuration configuration) {
+ SSLValidationStrategy sslStrategy = Optional
+ .ofNullable(configuration.getString(ELASTICSEARCH_HTTPS_SSL_VALIDATION_STRATEGY))
.map(SSLValidationStrategy::from)
- .map(strategy -> new SSLTrustConfiguration(strategy, getSSLTrustStore(configuration)));
+ .orElse(SSLValidationStrategy.DEFAULT);
+
+ HostNameVerifier hostNameVerifier = Optional
+ .ofNullable(configuration.getString(ELASTICSEARCH_HTTPS_HOSTNAME_VERIFIER))
+ .map(HostNameVerifier::from)
+ .orElse(HostNameVerifier.DEFAULT);
+
+ return SSLConfiguration.builder()
+ .sslStrategy(sslStrategy, getSSLTrustStore(configuration))
+ .hostNameVerifier(hostNameVerifier)
+ .build();
}
private static Optional<SSLTrustStore> getSSLTrustStore(Configuration configuration) {
@@ -455,10 +539,10 @@ public class ElasticSearchConfiguration {
private final Duration requestTimeout;
private final HostScheme hostScheme;
private final Optional<Credential> credential;
- private final SSLTrustConfiguration sslTrustConfiguration;
+ private final SSLConfiguration sslConfiguration;
private ElasticSearchConfiguration(ImmutableList<Host> hosts, int nbShards, int nbReplica, int waitForActiveShards, int minDelay, int maxRetries, Duration requestTimeout,
- HostScheme hostScheme, Optional<Credential> credential, SSLTrustConfiguration sslTrustConfiguration) {
+ HostScheme hostScheme, Optional<Credential> credential, SSLConfiguration sslConfiguration) {
this.hosts = hosts;
this.nbShards = nbShards;
this.nbReplica = nbReplica;
@@ -468,7 +552,7 @@ public class ElasticSearchConfiguration {
this.requestTimeout = requestTimeout;
this.hostScheme = hostScheme;
this.credential = credential;
- this.sslTrustConfiguration = sslTrustConfiguration;
+ this.sslConfiguration = sslConfiguration;
}
public ImmutableList<Host> getHosts() {
@@ -507,8 +591,8 @@ public class ElasticSearchConfiguration {
return credential;
}
- public SSLTrustConfiguration getSslTrustConfiguration() {
- return sslTrustConfiguration;
+ public SSLConfiguration getSslConfiguration() {
+ return sslConfiguration;
}
@Override
@@ -525,7 +609,7 @@ public class ElasticSearchConfiguration {
&& Objects.equals(this.requestTimeout, that.requestTimeout)
&& Objects.equals(this.hostScheme, that.hostScheme)
&& Objects.equals(this.credential, that.credential)
- && Objects.equals(this.sslTrustConfiguration, that.sslTrustConfiguration);
+ && Objects.equals(this.sslConfiguration, that.sslConfiguration);
}
return false;
}
@@ -533,6 +617,6 @@ public class ElasticSearchConfiguration {
@Override
public final int hashCode() {
return Objects.hash(hosts, nbShards, nbReplica, waitForActiveShards, minDelay, maxRetries, requestTimeout,
- hostScheme, credential, sslTrustConfiguration);
+ hostScheme, credential, sslConfiguration);
}
}
diff --git a/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionAuthESIgnoreSSLCheckTest.java b/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionAuthESIgnoreSSLCheckTest.java
index 1de1996..a97c6a3 100644
--- a/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionAuthESIgnoreSSLCheckTest.java
+++ b/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionAuthESIgnoreSSLCheckTest.java
@@ -24,7 +24,7 @@ import static org.apache.james.backends.es.ElasticSearchClusterExtension.Elastic
import java.util.Optional;
import org.apache.james.backends.es.ElasticSearchConfiguration.HostScheme;
-import org.apache.james.backends.es.ElasticSearchConfiguration.SSLTrustConfiguration;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration;
import org.junit.jupiter.api.extension.RegisterExtension;
class ClientProviderImplConnectionAuthESIgnoreSSLCheckTest implements ClientProviderImplConnectionContract {
@@ -39,6 +39,9 @@ class ClientProviderImplConnectionAuthESIgnoreSSLCheckTest implements ClientProv
return ElasticSearchConfiguration.builder()
.credential(Optional.of(DockerElasticSearch.WithAuth.DEFAULT_CREDENTIAL))
.hostScheme(Optional.of(HostScheme.HTTPS))
- .sslTrustConfiguration(SSLTrustConfiguration.ignore());
+ .sslTrustConfiguration(SSLConfiguration.builder()
+ .strategyIgnore()
+ .acceptAnyHostNameVerifier()
+ .build());
}
}
diff --git a/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionAuthESOverrideTrustStoreTest.java b/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionAuthESOverrideTrustStoreTest.java
index 5b92cf7..7493681 100644
--- a/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionAuthESOverrideTrustStoreTest.java
+++ b/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ClientProviderImplConnectionAuthESOverrideTrustStoreTest.java
@@ -21,8 +21,8 @@ package org.apache.james.backends.es;
import java.util.Optional;
-import org.apache.james.backends.es.ElasticSearchConfiguration.SSLTrustConfiguration;
-import org.apache.james.backends.es.ElasticSearchConfiguration.SSLTrustConfiguration.SSLTrustStore;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration.SSLTrustStore;
import org.junit.jupiter.api.extension.RegisterExtension;
public class ClientProviderImplConnectionAuthESOverrideTrustStoreTest implements ClientProviderImplConnectionContract {
@@ -40,7 +40,9 @@ public class ClientProviderImplConnectionAuthESOverrideTrustStoreTest implements
return ElasticSearchConfiguration.builder()
.credential(Optional.of(DockerElasticSearch.WithAuth.DEFAULT_CREDENTIAL))
.hostScheme(Optional.of(ElasticSearchConfiguration.HostScheme.HTTPS))
- .sslTrustConfiguration(SSLTrustConfiguration.override(
- SSLTrustStore.of(TRUST_STORE_FILE_PATH, TRUST_STORE_PASSWORD)));
+ .sslTrustConfiguration(SSLConfiguration.builder()
+ .strategyOverride(SSLTrustStore.of(TRUST_STORE_FILE_PATH, TRUST_STORE_PASSWORD))
+ .acceptAnyHostNameVerifier()
+ .build());
}
}
\ No newline at end of file
diff --git a/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ElasticSearchConfigurationTest.java b/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ElasticSearchConfigurationTest.java
index cf50942..35bf3f4 100644
--- a/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ElasticSearchConfigurationTest.java
+++ b/backends-common/elasticsearch/src/test/java/org/apache/james/backends/es/ElasticSearchConfigurationTest.java
@@ -29,8 +29,8 @@ import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.james.backends.es.ElasticSearchConfiguration.Credential;
import org.apache.james.backends.es.ElasticSearchConfiguration.HostScheme;
-import org.apache.james.backends.es.ElasticSearchConfiguration.SSLTrustConfiguration;
-import org.apache.james.backends.es.ElasticSearchConfiguration.SSLTrustConfiguration.SSLTrustStore;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration;
+import org.apache.james.backends.es.ElasticSearchConfiguration.SSLConfiguration.SSLTrustStore;
import org.apache.james.util.Host;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
@@ -62,7 +62,7 @@ class ElasticSearchConfigurationTest {
}
@Nested
- class SSLTrustConfigurationTest {
+ class SSLConfigurationTest {
@Test
void sslTrustStoreShouldMatchBeanContact() {
@@ -72,45 +72,112 @@ class ElasticSearchConfigurationTest {
@Test
void shouldMatchBeanContact() {
- EqualsVerifier.forClass(SSLTrustConfiguration.class)
+ EqualsVerifier.forClass(SSLConfiguration.class)
.verify();
}
+ @Test
+ void getSSLConfigurationShouldReturnDefaultValueWhenEmpty() throws Exception {
+ PropertiesConfiguration configuration = new PropertiesConfiguration();
+ configuration.addProperty("elasticsearch.hosts", "127.0.0.1");
+
+ assertThat(ElasticSearchConfiguration.fromProperties(configuration)
+ .getSslConfiguration())
+ .isEqualTo(SSLConfiguration.defaultBehavior());
+ }
+
+ @Test
+ void getSSLConfigurationShouldReturnConfiguredValue() throws Exception {
+ PropertiesConfiguration configuration = new PropertiesConfiguration();
+ configuration.addProperty("elasticsearch.hosts", "127.0.0.1");
+
+ String trustStorePath = "src/test/resources/auth-es/server.jks";
+ String trustStorePassword = "secret";
+
+ configuration.addProperty("elasticsearch.hostScheme.https.sslValidationStrategy", "override");
+ configuration.addProperty("elasticsearch.hostScheme.https.trustStorePath", trustStorePath);
+ configuration.addProperty("elasticsearch.hostScheme.https.trustStorePassword", trustStorePassword);
+ configuration.addProperty("elasticsearch.hostScheme.https.hostNameVerifier", "default");
+
+ assertThat(ElasticSearchConfiguration.fromProperties(configuration)
+ .getSslConfiguration())
+ .isEqualTo(SSLConfiguration.builder()
+ .strategyOverride(SSLTrustStore.of(trustStorePath, trustStorePassword))
+ .defaultHostNameVerifier()
+ .build());
+ }
+
@Nested
class WithSSLValidationStrategy {
@Test
- void getSSLConfigurationShouldReturnDefaultValueWhenEmpty() throws Exception {
+ void getSSLConfigurationShouldAcceptCaseInsensitiveStrategy() throws Exception {
PropertiesConfiguration configuration = new PropertiesConfiguration();
configuration.addProperty("elasticsearch.hosts", "127.0.0.1");
+ configuration.addProperty("elasticsearch.hostScheme.https.sslValidationStrategy", "DEfault");
+
assertThat(ElasticSearchConfiguration.fromProperties(configuration)
- .getSslTrustConfiguration())
- .isEqualTo(SSLTrustConfiguration.defaultBehavior());
+ .getSslConfiguration())
+ .isEqualTo(SSLConfiguration.defaultBehavior());
}
@Test
- void getSSLConfigurationShouldAcceptCaseInsensitiveStrategy() throws Exception {
+ void fromPropertiesShouldThrowWhenInvalidStrategy() throws Exception {
PropertiesConfiguration configuration = new PropertiesConfiguration();
configuration.addProperty("elasticsearch.hosts", "127.0.0.1");
- configuration.addProperty("elasticsearch.hostScheme.https.sslValidationStrategy", "DEfault");
+ configuration.addProperty("elasticsearch.hostScheme.https.sslValidationStrategy", "invalid");
+
+ assertThatThrownBy(() -> ElasticSearchConfiguration.fromProperties(configuration))
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("invalid strategy 'invalid'");
+ }
+ }
+
+ @Nested
+ class WithHostNameVerifier {
+
+ @Test
+ void getSSLConfigurationShouldReturnConfiguredValue() throws Exception {
+ PropertiesConfiguration configuration = new PropertiesConfiguration();
+ configuration.addProperty("elasticsearch.hosts", "127.0.0.1");
+
+ configuration.addProperty("elasticsearch.hostScheme.https.hostNameVerifier", "DEFAULT");
assertThat(ElasticSearchConfiguration.fromProperties(configuration)
- .getSslTrustConfiguration())
- .isEqualTo(SSLTrustConfiguration.defaultBehavior());
+ .getSslConfiguration())
+ .isEqualTo(SSLConfiguration.builder()
+ .strategyDefault()
+ .defaultHostNameVerifier()
+ .build());
}
@Test
- void fromPropertiesShouldThrowWhenInvalidStrategy() throws Exception {
+ void getSSLConfigurationShouldAcceptCaseInsensitiveVerifier() throws Exception {
PropertiesConfiguration configuration = new PropertiesConfiguration();
configuration.addProperty("elasticsearch.hosts", "127.0.0.1");
- configuration.addProperty("elasticsearch.hostScheme.https.sslValidationStrategy", "invalid");
+ configuration.addProperty("elasticsearch.hostScheme.https.hostNameVerifier", "Accept_Any_Hostname");
+
+ assertThat(ElasticSearchConfiguration.fromProperties(configuration)
+ .getSslConfiguration())
+ .isEqualTo(SSLConfiguration.builder()
+ .strategyDefault()
+ .acceptAnyHostNameVerifier()
+ .build());
+ }
+
+ @Test
+ void fromPropertiesShouldThrowWhenInvalidVerifier() throws Exception {
+ PropertiesConfiguration configuration = new PropertiesConfiguration();
+ configuration.addProperty("elasticsearch.hosts", "127.0.0.1");
+
+ configuration.addProperty("elasticsearch.hostScheme.https.hostNameVerifier", "invalid");
assertThatThrownBy(() -> ElasticSearchConfiguration.fromProperties(configuration))
.isInstanceOf(IllegalArgumentException.class)
- .hasMessage("invalid strategy 'invalid'");
+ .hasMessage("invalid HostNameVerifier 'invalid'");
}
}
@@ -125,8 +192,8 @@ class ElasticSearchConfigurationTest {
configuration.addProperty("elasticsearch.hostScheme.https.sslValidationStrategy", "default");
assertThat(ElasticSearchConfiguration.fromProperties(configuration)
- .getSslTrustConfiguration())
- .isEqualTo(SSLTrustConfiguration.defaultBehavior());
+ .getSslConfiguration())
+ .isEqualTo(SSLConfiguration.defaultBehavior());
}
}
@@ -141,8 +208,11 @@ class ElasticSearchConfigurationTest {
configuration.addProperty("elasticsearch.hostScheme.https.sslValidationStrategy", "ignore");
assertThat(ElasticSearchConfiguration.fromProperties(configuration)
- .getSslTrustConfiguration())
- .isEqualTo(SSLTrustConfiguration.ignore());
+ .getSslConfiguration())
+ .isEqualTo(SSLConfiguration.builder()
+ .strategyIgnore()
+ .defaultHostNameVerifier()
+ .build());
}
}
@@ -206,18 +276,20 @@ class ElasticSearchConfigurationTest {
PropertiesConfiguration configuration = new PropertiesConfiguration();
configuration.addProperty("elasticsearch.hosts", "127.0.0.1");
- String strategy = "override";
String trustStorePath = "src/test/resources/auth-es/server.jks";
String trustStorePassword = "secret";
- configuration.addProperty("elasticsearch.hostScheme.https.sslValidationStrategy", strategy);
+ configuration.addProperty("elasticsearch.hostScheme.https.sslValidationStrategy", "override");
configuration.addProperty("elasticsearch.hostScheme.https.trustStorePath", trustStorePath);
configuration.addProperty("elasticsearch.hostScheme.https.trustStorePassword", trustStorePassword);
+ configuration.addProperty("elasticsearch.hostScheme.https.hostNameVerifier", "default");
assertThat(ElasticSearchConfiguration.fromProperties(configuration)
- .getSslTrustConfiguration())
- .isEqualTo(SSLTrustConfiguration.override(
- SSLTrustStore.of(trustStorePath, trustStorePassword)));
+ .getSslConfiguration())
+ .isEqualTo(SSLConfiguration.builder()
+ .strategyOverride(SSLTrustStore.of(trustStorePath, trustStorePassword))
+ .defaultHostNameVerifier()
+ .build());
}
}
}
diff --git a/dockerfiles/run/guice/cassandra-ldap/destination/conf/elasticsearch.properties b/dockerfiles/run/guice/cassandra-ldap/destination/conf/elasticsearch.properties
index b2eefc5..74e5a3d 100644
--- a/dockerfiles/run/guice/cassandra-ldap/destination/conf/elasticsearch.properties
+++ b/dockerfiles/run/guice/cassandra-ldap/destination/conf/elasticsearch.properties
@@ -45,6 +45,12 @@ elasticsearch.port=9200
# You need to specify both trustStorePath and trustStorePassword
# elasticsearch.hostScheme.https.trustStorePassword=myJKSPassword
+# Optional. default is `default`
+# Configure Elasticsearch rest client to use host name verifier during SSL handshake
+# default: using the default hostname verifier provided by apache http client.
+# accept_any_hostname: accept any hostname (not recommended).
+# elasticsearch.hostScheme.https.hostNameVerifier=default
+
# Optional.
# Basic auth username to access elasticsearch.
# Ignore elasticsearch.user and elasticsearch.password to not be using authentication (default behaviour).
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/elasticsearch.properties b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/elasticsearch.properties
index eecf449..0ea86db 100644
--- a/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/elasticsearch.properties
+++ b/dockerfiles/run/guice/cassandra-rabbitmq-ldap/destination/conf/elasticsearch.properties
@@ -44,6 +44,12 @@ elasticsearch.port=9200
# You need to specify both trustStorePath and trustStorePassword
# elasticsearch.hostScheme.https.trustStorePassword=myJKSPassword
+# Optional. default is `default`
+# Configure Elasticsearch rest client to use host name verifier during SSL handshake
+# default: using the default hostname verifier provided by apache http client.
+# accept_any_hostname: accept any hostname (not recommended).
+# elasticsearch.hostScheme.https.hostNameVerifier=default
+
# Optional.
# Basic auth username to access elasticsearch.
# Ignore elasticsearch.user and elasticsearch.password to not be using authentication (default behaviour).
diff --git a/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/elasticsearch.properties b/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/elasticsearch.properties
index eecf449..16ea216 100644
--- a/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/elasticsearch.properties
+++ b/dockerfiles/run/guice/cassandra-rabbitmq/destination/conf/elasticsearch.properties
@@ -44,6 +44,12 @@ elasticsearch.port=9200
# You need to specify both trustStorePath and trustStorePassword
# elasticsearch.hostScheme.https.trustStorePassword=myJKSPassword
+# Optional. default is `default`
+# Configure Elasticsearch rest client to use host name verifier during SSL handshake
+# default: using the default hostname verifier provided by apache http client.
+# accept_any_hostname: accept any host (not recommended).
+# elasticsearch.hostScheme.https.hostNameVerifier=default
+
# Optional.
# Basic auth username to access elasticsearch.
# Ignore elasticsearch.user and elasticsearch.password to not be using authentication (default behaviour).
diff --git a/dockerfiles/run/guice/cassandra/destination/conf/elasticsearch.properties b/dockerfiles/run/guice/cassandra/destination/conf/elasticsearch.properties
index b2eefc5..74e5a3d 100644
--- a/dockerfiles/run/guice/cassandra/destination/conf/elasticsearch.properties
+++ b/dockerfiles/run/guice/cassandra/destination/conf/elasticsearch.properties
@@ -45,6 +45,12 @@ elasticsearch.port=9200
# You need to specify both trustStorePath and trustStorePassword
# elasticsearch.hostScheme.https.trustStorePassword=myJKSPassword
+# Optional. default is `default`
+# Configure Elasticsearch rest client to use host name verifier during SSL handshake
+# default: using the default hostname verifier provided by apache http client.
+# accept_any_hostname: accept any hostname (not recommended).
+# elasticsearch.hostScheme.https.hostNameVerifier=default
+
# Optional.
# Basic auth username to access elasticsearch.
# Ignore elasticsearch.user and elasticsearch.password to not be using authentication (default behaviour).
diff --git a/src/site/xdoc/server/config-elasticsearch.xml b/src/site/xdoc/server/config-elasticsearch.xml
index f763272..789f044 100644
--- a/src/site/xdoc/server/config-elasticsearch.xml
+++ b/src/site/xdoc/server/config-elasticsearch.xml
@@ -252,6 +252,21 @@
Once you chose <strong>override</strong>, you need to specify both trustStorePath and trustStorePassword.
</dd>
</dl>
+
+ <p>
+ During SSL handshaking, the client can determine whether accept or reject connecting to a remote server by its hostname.
+ You can configure to use which HostNameVerifier in the client.
+ </p>
+ <dl>
+ <dt><strong>elasticsearch.hostScheme.https.hostNameVerifier</strong></dt>
+ <dd>
+ Optional. Default is <strong>default</strong>.
+ </dd>
+ <dd>
+ default: using the default hostname verifier provided by apache http client.
+ accept_any_hostname: accept any host (not recommended).
+ </dd>
+ </dl>
</section>
</body>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org