diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java index 85d09dd4e0..4105ca9ac9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java @@ -160,8 +160,8 @@ public class CassandraAutoConfiguration { private void configureSsl(CqlSessionBuilder builder, SslBundle sslBundle) { SslOptions options = sslBundle.getOptions(); 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)); + builder + .withSslEngineFactory(new ProgrammaticSslEngineFactory(sslBundle.createSslContext(), options.getCiphers())); } @Bean(destroyMethod = "") diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/JedisConnectionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/JedisConnectionConfiguration.java index 7164319028..80bcde7116 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/JedisConnectionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/JedisConnectionConfiguration.java @@ -119,8 +119,8 @@ class JedisConnectionConfiguration extends RedisConnectionConfiguration { SslOptions sslOptions = sslBundle.getOptions(); SSLParameters sslParameters = new SSLParameters(); PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); - map.from(SslOptions.toArray(sslOptions.getCiphers())).to(sslParameters::setCipherSuites); - map.from(SslOptions.toArray(sslOptions.getEnabledProtocols())).to(sslParameters::setProtocols); + map.from(sslOptions.getCiphers()).to(sslParameters::setCipherSuites); + map.from(sslOptions.getEnabledProtocols()).to(sslParameters::setProtocols); sslBuilder.sslParameters(sslParameters); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java index 9f1b6d74d5..0f88d90296 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.java @@ -151,13 +151,12 @@ class LettuceConnectionConfiguration extends RedisConnectionConfiguration { io.lettuce.core.SslOptions.Builder sslOptionsBuilder = io.lettuce.core.SslOptions.builder(); sslOptionsBuilder.keyManager(sslBundle.getManagers().getKeyManagerFactory()); sslOptionsBuilder.trustManager(sslBundle.getManagers().getTrustManagerFactory()); - String[] ciphers = SslOptions.toArray(sslBundle.getOptions().getCiphers()); - if (ciphers != null) { - sslOptionsBuilder.cipherSuites(ciphers); + SslOptions sslOptions = sslBundle.getOptions(); + if (sslOptions.getCiphers() != null) { + sslOptionsBuilder.cipherSuites(sslOptions.getCiphers()); } - String[] protocols = SslOptions.toArray(sslBundle.getOptions().getEnabledProtocols()); - if (protocols != null) { - sslOptionsBuilder.protocols(protocols); + if (sslOptions.getEnabledProtocols() != null) { + sslOptionsBuilder.protocols(sslOptions.getEnabledProtocols()); } builder.sslOptions(sslOptionsBuilder.build()); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchRestClientConfigurations.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchRestClientConfigurations.java index 0b2aaf1e85..58c26aae9c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchRestClientConfigurations.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/elasticsearch/ElasticsearchRestClientConfigurations.java @@ -116,10 +116,8 @@ class ElasticsearchRestClientConfigurations { private void configureSsl(HttpAsyncClientBuilder httpClientBuilder, SslBundle sslBundle) { SSLContext sslcontext = sslBundle.createSslContext(); SslOptions sslOptions = sslBundle.getOptions(); - String[] enabledProtocols = SslOptions.toArray(sslOptions.getEnabledProtocols()); - String[] ciphers = SslOptions.toArray(sslOptions.getCiphers()); - httpClientBuilder.setSSLStrategy( - new SSLIOSessionStrategy(sslcontext, enabledProtocols, ciphers, (HostnameVerifier) null)); + httpClientBuilder.setSSLStrategy(new SSLIOSessionStrategy(sslcontext, sslOptions.getEnabledProtocols(), + sslOptions.getCiphers(), (HostnameVerifier) null)); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundle.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundle.java index 337db88f13..abb9ab6cc6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundle.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/PropertiesSslBundle.java @@ -59,9 +59,8 @@ public final class PropertiesSslBundle implements SslBundle { return (key != null) ? SslBundleKey.of(key.getPassword(), key.getAlias()) : SslBundleKey.NONE; } - private static SslOptions asSslOptions(SslBundleProperties.Options properties) { - return (properties != null) ? SslOptions.of(properties.getCiphers(), properties.getEnabledProtocols()) - : SslOptions.NONE; + private static SslOptions asSslOptions(SslBundleProperties.Options options) { + return (options != null) ? SslOptions.of(options.getCiphers(), options.getEnabledProtocols()) : SslOptions.NONE; } @Override diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/HttpComponentsClientHttpConnectorFactory.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/HttpComponentsClientHttpConnectorFactory.java index 3a895239c2..a09a2fe132 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/HttpComponentsClientHttpConnectorFactory.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/HttpComponentsClientHttpConnectorFactory.java @@ -17,17 +17,13 @@ package org.springframework.boot.autoconfigure.web.reactive.function.client; import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLException; import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; import org.apache.hc.client5.http.impl.async.HttpAsyncClients; import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; import org.apache.hc.client5.http.nio.AsyncClientConnectionManager; import org.apache.hc.core5.http.nio.ssl.BasicClientTlsStrategy; -import org.apache.hc.core5.net.NamedEndpoint; import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier; -import org.apache.hc.core5.reactor.ssl.TlsDetails; import org.springframework.boot.ssl.SslBundle; import org.springframework.boot.ssl.SslOptions; @@ -47,19 +43,14 @@ class HttpComponentsClientHttpConnectorFactory if (sslBundle != null) { SslOptions options = sslBundle.getOptions(); SSLContext sslContext = sslBundle.createSslContext(); - SSLSessionVerifier sessionVerifier = new SSLSessionVerifier() { - - @Override - public TlsDetails verify(NamedEndpoint endpoint, SSLEngine sslEngine) throws SSLException { - if (options.getCiphers() != null) { - sslEngine.setEnabledCipherSuites(SslOptions.toArray(options.getCiphers())); - } - if (options.getEnabledProtocols() != null) { - sslEngine.setEnabledProtocols(SslOptions.toArray(options.getEnabledProtocols())); - } - return null; + SSLSessionVerifier sessionVerifier = (endpoint, sslEngine) -> { + if (options.getCiphers() != null) { + sslEngine.setEnabledCipherSuites(options.getCiphers()); } - + if (options.getEnabledProtocols() != null) { + sslEngine.setEnabledProtocols(options.getEnabledProtocols()); + } + return null; }; BasicClientTlsStrategy tlsStrategy = new BasicClientTlsStrategy(sslContext, sessionVerifier); AsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create() diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/JdkClientHttpConnectorFactory.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/JdkClientHttpConnectorFactory.java index 2688e647e7..99d713fa80 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/JdkClientHttpConnectorFactory.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/reactive/function/client/JdkClientHttpConnectorFactory.java @@ -40,8 +40,8 @@ class JdkClientHttpConnectorFactory implements ClientHttpConnectorFactory getCiphers(); + String[] getCiphers(); /** * Return the protocols that should be enabled or an empty set. The protocols names in @@ -60,7 +60,7 @@ public interface SslOptions { * {@link SSLEngine#getSupportedProtocols()}. * @return the protocols to enable or {@code null} */ - Set getEnabledProtocols(); + String[] getEnabledProtocols(); /** * Factory method to create a new {@link SslOptions} instance. @@ -69,7 +69,19 @@ public interface SslOptions { * @return a new {@link SslOptions} instance */ static SslOptions of(String[] ciphers, String[] enabledProtocols) { - return of(asSet(ciphers), asSet(enabledProtocols)); + return new SslOptions() { + + @Override + public String[] getCiphers() { + return ciphers; + } + + @Override + public String[] getEnabledProtocols() { + return enabledProtocols; + } + + }; } /** @@ -79,34 +91,21 @@ public interface SslOptions { * @return a new {@link SslOptions} instance */ static SslOptions of(Set ciphers, Set enabledProtocols) { - return new SslOptions() { - - @Override - public Set getCiphers() { - return ciphers; - } - - @Override - public Set getEnabledProtocols() { - return enabledProtocols; - } - - }; - + return of(toArray(ciphers), toArray(enabledProtocols)); } /** - * 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} + * Helper method that provides a null-safe way to convert a {@code String[]} to a + * {@link Collection} for client libraries to use. + * @param array the array to convert + * @return a collection or {@code null} */ - static String[] toArray(Collection collection) { - return (collection != null) ? collection.toArray(String[]::new) : null; - } - - private static Set asSet(String[] array) { + static Set asSet(String[] array) { return (array != null) ? Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(array))) : null; } + private static String[] toArray(Collection collection) { + return (collection != null) ? collection.toArray(String[]::new) : null; + } + } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java index ecaecd25b2..4f6de573f6 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/client/ClientHttpRequestFactories.java @@ -171,10 +171,8 @@ public final class ClientHttpRequestFactories { } if (sslBundle != null) { SslOptions options = sslBundle.getOptions(); - String[] enabledProtocols = SslOptions.toArray(options.getEnabledProtocols()); - String[] ciphers = SslOptions.toArray(options.getCiphers()); SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslBundle.createSslContext(), - enabledProtocols, ciphers, new DefaultHostnameVerifier()); + options.getEnabledProtocols(), options.getCiphers(), new DefaultHostnameVerifier()); connectionManagerBuilder.setSSLSocketFactory(socketFactory); } PoolingHttpClientConnectionManager connectionManager = connectionManagerBuilder.build(); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/SslServerCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/SslServerCustomizer.java index 22a5ead2b6..cffefa6f09 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/SslServerCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/SslServerCustomizer.java @@ -179,11 +179,11 @@ class SslServerCustomizer implements JettyServerCustomizer { } factory.setCertAlias(key.getAlias()); if (options.getCiphers() != null) { - factory.setIncludeCipherSuites(SslOptions.toArray(options.getCiphers())); + factory.setIncludeCipherSuites(options.getCiphers()); factory.setExcludeCipherSuites(); } if (options.getEnabledProtocols() != null) { - factory.setIncludeProtocols(SslOptions.toArray(options.getEnabledProtocols())); + factory.setIncludeProtocols(options.getEnabledProtocols()); factory.setExcludeProtocols(); } try { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java index b790bf79c1..5480c4d0c8 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/netty/SslServerCustomizer.java @@ -66,7 +66,7 @@ public class SslServerCustomizer implements NettyServerCustomizer { builder.trustManager(this.sslBundle.getManagers().getTrustManagerFactory()); SslOptions options = this.sslBundle.getOptions(); builder.protocols(options.getEnabledProtocols()); - builder.ciphers(options.getCiphers()); + builder.ciphers(SslOptions.asSet(options.getCiphers())); builder.clientAuth(org.springframework.boot.web.server.Ssl.ClientAuth.map(this.clientAuth, ClientAuth.NONE, ClientAuth.OPTIONAL, ClientAuth.REQUIRE)); }); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizer.java index 9eb8b65b9c..813edb3fbe 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizer.java @@ -86,7 +86,7 @@ class SslConnectorCustomizer implements TomcatConnectorCustomizer { } sslHostConfig.addCertificate(certificate); if (options.getCiphers() != null) { - String ciphers = StringUtils.collectionToCommaDelimitedString(options.getCiphers()); + String ciphers = StringUtils.arrayToCommaDelimitedString(options.getCiphers()); sslHostConfig.setCiphers(ciphers); } configureEnabledProtocols(protocol); @@ -96,7 +96,7 @@ class SslConnectorCustomizer implements TomcatConnectorCustomizer { private void configureEnabledProtocols(AbstractHttp11JsseProtocol protocol) { SslOptions options = this.sslBundle.getOptions(); if (options.getEnabledProtocols() != null) { - String enabledProtocols = StringUtils.collectionToCommaDelimitedString(options.getEnabledProtocols()); + String enabledProtocols = StringUtils.arrayToCommaDelimitedString(options.getEnabledProtocols()); for (SSLHostConfig sslHostConfig : protocol.findSslHostConfigs()) { sslHostConfig.setProtocols(enabledProtocols); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/SslOptionsTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/SslOptionsTests.java index aeca69fc57..513fa2b7fd 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/SslOptionsTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/SslOptionsTests.java @@ -59,8 +59,8 @@ class SslOptionsTests { Set ciphers = Set.of("a", "b", "c"); Set enabledProtocols = Set.of("d", "e", "f"); SslOptions options = SslOptions.of(ciphers, enabledProtocols); - assertThat(options.getCiphers()).isEqualTo(ciphers); - assertThat(options.getEnabledProtocols()).isEqualTo(enabledProtocols); + assertThat(options.getCiphers()).contains("a", "b", "c"); + assertThat(options.getEnabledProtocols()).contains("d", "e", "f"); } @Test