Polish SslOptions usage
Add helper method and tighten usage so that exceptions are thrown when options cannot be applied. See gh-34814
This commit is contained in:
parent
423c60acfa
commit
b5c9e7c06a
|
|
@ -58,6 +58,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
|
|
@ -158,7 +159,8 @@ public class CassandraAutoConfiguration {
|
|||
|
||||
private void configureSsl(CqlSessionBuilder builder, SslBundle sslBundle) {
|
||||
SslOptions options = sslBundle.getOptions();
|
||||
String[] ciphers = (options.getCiphers() != null) ? options.getCiphers().toArray(String[]::new) : null;
|
||||
Assert.state(options.getEnabledProtocols() == null, "SSL protocol options cannot be specified with Cassandra");
|
||||
String[] ciphers = SslOptions.toArray(options.getCiphers());
|
||||
builder.withSslEngineFactory(new ProgrammaticSslEngineFactory(sslBundle.createSslContext(), ciphers));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
|||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
|
||||
import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration.CouchbaseCondition;
|
||||
import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties.Ssl;
|
||||
import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties.Timeouts;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
|
@ -50,7 +51,9 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for Couchbase.
|
||||
|
|
@ -125,10 +128,14 @@ public class CouchbaseAutoConfiguration {
|
|||
}
|
||||
|
||||
private void configureSsl(Builder builder, SslBundles sslBundles) {
|
||||
Ssl sslProperties = this.properties.getEnv().getSsl();
|
||||
SslBundle sslBundle = (StringUtils.hasText(sslProperties.getBundle()))
|
||||
? sslBundles.getBundle(sslProperties.getBundle()) : null;
|
||||
Assert.state(sslBundle == null || !sslBundle.getOptions().isSpecified(),
|
||||
"SSL Options cannot be specified with Couchbase");
|
||||
builder.securityConfig((config) -> {
|
||||
config.enableTls(true);
|
||||
TrustManagerFactory trustManagerFactory = getTrustManagerFactory(this.properties.getEnv().getSsl(),
|
||||
sslBundles);
|
||||
TrustManagerFactory trustManagerFactory = getTrustManagerFactory(sslProperties, sslBundle);
|
||||
if (trustManagerFactory != null) {
|
||||
config.trustManagerFactory(trustManagerFactory);
|
||||
}
|
||||
|
|
@ -136,15 +143,11 @@ public class CouchbaseAutoConfiguration {
|
|||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private TrustManagerFactory getTrustManagerFactory(CouchbaseProperties.Ssl ssl, SslBundles sslBundles) {
|
||||
if (ssl.getKeyStore() != null) {
|
||||
return loadTrustManagerFactory(ssl);
|
||||
private TrustManagerFactory getTrustManagerFactory(CouchbaseProperties.Ssl sslProperties, SslBundle sslBundle) {
|
||||
if (sslProperties.getKeyStore() != null) {
|
||||
return loadTrustManagerFactory(sslProperties);
|
||||
}
|
||||
if (ssl.getBundle() != null) {
|
||||
SslBundle bundle = sslBundles.getBundle(ssl.getBundle());
|
||||
return bundle.getManagers().getTrustManagerFactory();
|
||||
}
|
||||
return null;
|
||||
return (sslBundle != null) ? sslBundle.getManagers().getTrustManagerFactory() : null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package org.springframework.boot.autoconfigure.elasticsearch;
|
|||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
|
|
@ -117,16 +116,12 @@ class ElasticsearchRestClientConfigurations {
|
|||
private void configureSsl(HttpAsyncClientBuilder httpClientBuilder, SslBundle sslBundle) {
|
||||
SSLContext sslcontext = sslBundle.createSslContext();
|
||||
SslOptions sslOptions = sslBundle.getOptions();
|
||||
String[] enabledProtocols = toArray(sslOptions.getEnabledProtocols());
|
||||
String[] ciphers = toArray(sslOptions.getCiphers());
|
||||
String[] enabledProtocols = SslOptions.toArray(sslOptions.getEnabledProtocols());
|
||||
String[] ciphers = SslOptions.toArray(sslOptions.getCiphers());
|
||||
httpClientBuilder.setSSLStrategy(
|
||||
new SSLIOSessionStrategy(sslcontext, enabledProtocols, ciphers, (HostnameVerifier) null));
|
||||
}
|
||||
|
||||
private static String[] toArray(Set<String> set) {
|
||||
return (set != null) ? set.toArray(String[]::new) : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import org.bson.UuidRepresentation;
|
|||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.ssl.SslBundles;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link MongoClientSettingsBuilderCustomizer} that applies standard settings to a
|
||||
|
|
@ -67,6 +68,7 @@ public class StandardMongoClientSettingsBuilderCustomizer implements MongoClient
|
|||
settings.enabled(true);
|
||||
if (this.ssl.getBundle() != null) {
|
||||
SslBundle sslBundle = this.sslBundles.getBundle(this.ssl.getBundle());
|
||||
Assert.state(!sslBundle.getOptions().isSpecified(), "SSL options cannot be specified with MongoDB");
|
||||
settings.context(sslBundle.createSslContext());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,10 +52,10 @@ class HttpComponentsClientHttpConnectorFactory
|
|||
@Override
|
||||
public TlsDetails verify(NamedEndpoint endpoint, SSLEngine sslEngine) throws SSLException {
|
||||
if (options.getCiphers() != null) {
|
||||
sslEngine.setEnabledCipherSuites(options.getCiphers().toArray(String[]::new));
|
||||
sslEngine.setEnabledCipherSuites(SslOptions.toArray(options.getCiphers()));
|
||||
}
|
||||
if (options.getEnabledProtocols() != null) {
|
||||
sslEngine.setEnabledProtocols(options.getEnabledProtocols().toArray(String[]::new));
|
||||
sslEngine.setEnabledProtocols(SslOptions.toArray(options.getEnabledProtocols()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,14 +18,13 @@ package org.springframework.boot.autoconfigure.web.reactive.function.client;
|
|||
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpClient.Builder;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.net.ssl.SSLParameters;
|
||||
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.ssl.SslOptions;
|
||||
import org.springframework.http.client.reactive.JdkClientHttpConnector;
|
||||
import org.springframework.http.client.reactive.JettyClientHttpConnector;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* {@link ClientHttpConnectorFactory} for {@link JettyClientHttpConnector}.
|
||||
|
|
@ -38,17 +37,14 @@ class JdkClientHttpConnectorFactory implements ClientHttpConnectorFactory<JdkCli
|
|||
public JdkClientHttpConnector createClientHttpConnector(SslBundle sslBundle) {
|
||||
Builder builder = HttpClient.newBuilder();
|
||||
if (sslBundle != null) {
|
||||
SslOptions options = sslBundle.getOptions();
|
||||
builder.sslContext(sslBundle.createSslContext());
|
||||
SSLParameters parameters = new SSLParameters();
|
||||
parameters.setCipherSuites(asArray(sslBundle.getOptions().getCiphers()));
|
||||
parameters.setProtocols(asArray(sslBundle.getOptions().getEnabledProtocols()));
|
||||
parameters.setCipherSuites(SslOptions.toArray(options.getCiphers()));
|
||||
parameters.setProtocols(SslOptions.toArray(options.getEnabledProtocols()));
|
||||
builder.sslParameters(parameters);
|
||||
}
|
||||
return new JdkClientHttpConnector(builder.build());
|
||||
}
|
||||
|
||||
private String[] asArray(Set<String> set) {
|
||||
return (CollectionUtils.isEmpty(set)) ? null : set.toArray(String[]::new);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@ class JettyClientHttpConnectorFactory implements ClientHttpConnectorFactory<Jett
|
|||
if (sslBundle != null) {
|
||||
SslOptions options = sslBundle.getOptions();
|
||||
if (options.getCiphers() != null) {
|
||||
sslContextFactory.setIncludeCipherSuites(options.getCiphers().toArray(String[]::new));
|
||||
sslContextFactory.setIncludeCipherSuites(SslOptions.toArray(options.getCiphers()));
|
||||
sslContextFactory.setExcludeCipherSuites();
|
||||
}
|
||||
if (options.getEnabledProtocols() != null) {
|
||||
sslContextFactory.setIncludeProtocols(options.getEnabledProtocols().toArray(String[]::new));
|
||||
sslContextFactory.setIncludeProtocols(SslOptions.toArray(options.getEnabledProtocols()));
|
||||
sslContextFactory.setExcludeProtocols();
|
||||
}
|
||||
sslContextFactory.setSslContext(sslBundle.createSslContext());
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.boot.ssl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
|
@ -37,6 +38,14 @@ public interface SslOptions {
|
|||
*/
|
||||
SslOptions NONE = of((Set<String>) null, (Set<String>) null);
|
||||
|
||||
/**
|
||||
* Return if any SSL options have been specified.
|
||||
* @return {@true} if SSL options have been specified
|
||||
*/
|
||||
default boolean isSpecified() {
|
||||
return (getCiphers() != null) && (getEnabledProtocols() != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ciphers that can be used or an empty set. The cipher names in this set
|
||||
* should be compatible with those supported by
|
||||
|
|
@ -86,6 +95,16 @@ public interface SslOptions {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that provides a null-safe way to convert a {@link Collection} to a
|
||||
* {@code String[]} for client libraries to use.
|
||||
* @param collection the collection to convert
|
||||
* @return a string array or {@code null}
|
||||
*/
|
||||
static String[] toArray(Collection<String> collection) {
|
||||
return (collection != null) ? collection.toArray(String[]::new) : null;
|
||||
}
|
||||
|
||||
private static Set<String> asSet(String[] array) {
|
||||
return (array != null) ? Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(array))) : null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import java.lang.reflect.Field;
|
|||
import java.lang.reflect.Method;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.time.Duration;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
|
@ -172,8 +171,8 @@ public final class ClientHttpRequestFactories {
|
|||
}
|
||||
if (sslBundle != null) {
|
||||
SslOptions options = sslBundle.getOptions();
|
||||
String[] enabledProtocols = toArray(options.getEnabledProtocols());
|
||||
String[] ciphers = toArray(options.getCiphers());
|
||||
String[] enabledProtocols = SslOptions.toArray(options.getEnabledProtocols());
|
||||
String[] ciphers = SslOptions.toArray(options.getCiphers());
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslBundle.createSslContext(),
|
||||
enabledProtocols, ciphers, new DefaultHostnameVerifier());
|
||||
connectionManagerBuilder.setSSLSocketFactory(socketFactory);
|
||||
|
|
@ -182,10 +181,6 @@ public final class ClientHttpRequestFactories {
|
|||
return HttpClientBuilder.create().setConnectionManager(connectionManager).build();
|
||||
}
|
||||
|
||||
private static String[] toArray(Set<String> set) {
|
||||
return (set != null) ? set.toArray(String[]::new) : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -205,6 +200,7 @@ public final class ClientHttpRequestFactories {
|
|||
|
||||
private static OkHttp3ClientHttpRequestFactory createRequestFactory(SslBundle sslBundle) {
|
||||
if (sslBundle != null) {
|
||||
Assert.state(!sslBundle.getOptions().isSpecified(), "SSL Options cannot be specified with OkHttp");
|
||||
SSLSocketFactory socketFactory = sslBundle.createSslContext().getSocketFactory();
|
||||
TrustManager[] trustManagers = sslBundle.getManagers().getTrustManagers();
|
||||
Assert.state(trustManagers.length == 1,
|
||||
|
|
@ -228,6 +224,8 @@ public final class ClientHttpRequestFactories {
|
|||
SslBundle sslBundle = settings.sslBundle();
|
||||
SimpleClientHttpRequestFactory requestFactory = (sslBundle != null)
|
||||
? new SimpleClientHttpsRequestFactory(sslBundle) : new SimpleClientHttpRequestFactory();
|
||||
Assert.state(sslBundle == null || !sslBundle.getOptions().isSpecified(),
|
||||
"SSL Options cannot be specified with Java connections");
|
||||
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
|
||||
map.from(settings::readTimeout).asInt(Duration::toMillis).to(requestFactory::setReadTimeout);
|
||||
map.from(settings::connectTimeout).asInt(Duration::toMillis).to(requestFactory::setConnectTimeout);
|
||||
|
|
|
|||
|
|
@ -179,11 +179,12 @@ class SslServerCustomizer implements JettyServerCustomizer {
|
|||
}
|
||||
factory.setCertAlias(key.getAlias());
|
||||
if (options.getCiphers() != null) {
|
||||
factory.setIncludeCipherSuites(options.getCiphers().toArray(String[]::new));
|
||||
factory.setIncludeCipherSuites(SslOptions.toArray(options.getCiphers()));
|
||||
factory.setExcludeCipherSuites();
|
||||
}
|
||||
if (options.getEnabledProtocols() != null) {
|
||||
factory.setIncludeProtocols(options.getEnabledProtocols().toArray(String[]::new));
|
||||
factory.setIncludeProtocols(SslOptions.toArray(options.getEnabledProtocols()));
|
||||
factory.setExcludeProtocols();
|
||||
}
|
||||
try {
|
||||
if (key.getPassword() != null) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue