Polish SslOptions usage

Add helper method and tighten usage so that exceptions are thrown when
options cannot be applied.

See gh-34814
pull/35180/head
Phillip Webb 2 years ago
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…
Cancel
Save