From 71bd02495da6773172d0237d3585bf8233919699 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:03:33 +0000 Subject: [PATCH 01/21] Start building against Micrometer 1.15.9 snapshots See gh-49064 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 8ae6edb4972..6874ba96043 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1582,7 +1582,7 @@ bom { releaseNotes("https://github.com/apache/maven-war-plugin/releases/tag/maven-war-plugin-{version}") } } - library("Micrometer", "1.15.8") { + library("Micrometer", "1.15.9-SNAPSHOT") { considerSnapshots() group("io.micrometer") { modules = [ From 59c5bb9e687dcdb43ef5db049efd9402a2c9efd5 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:03:37 +0000 Subject: [PATCH 02/21] Start building against Micrometer Tracing 1.5.9 snapshots See gh-49065 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 6874ba96043..fa6ffe03baa 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1604,7 +1604,7 @@ bom { releaseNotes("https://github.com/micrometer-metrics/micrometer/releases/tag/v{version}") } } - library("Micrometer Tracing", "1.5.8") { + library("Micrometer Tracing", "1.5.9-SNAPSHOT") { considerSnapshots() group("io.micrometer") { bom("micrometer-tracing-bom") From 44ab4246c45a06ab8cbaa354935a1d8939a00055 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:03:41 +0000 Subject: [PATCH 03/21] Start building against Reactor Bom 2024.0.15 snapshots See gh-49066 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index fa6ffe03baa..833baf18a3e 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -2007,7 +2007,7 @@ bom { ] } } - library("Reactor Bom", "2024.0.14") { + library("Reactor Bom", "2024.0.15-SNAPSHOT") { considerSnapshots() calendarName = "Reactor" group("io.projectreactor") { From 22c72917732508f0719bb129a1342733376a455e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:03:46 +0000 Subject: [PATCH 04/21] Start building against Spring Authorization Server 1.5.6 snapshots See gh-49067 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 833baf18a3e..cb1a51d1ff8 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -2225,7 +2225,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-amqp/releases/tag/v{version}") } } - library("Spring Authorization Server", "1.5.5") { + library("Spring Authorization Server", "1.5.6-SNAPSHOT") { considerSnapshots() group("org.springframework.security") { modules = [ From 85b6e1e7feb0fd79e9754b1f4e2fac9487ad596a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:03:50 +0000 Subject: [PATCH 05/21] Start building against Spring Data Bom 2025.0.9 snapshots See gh-49068 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index cb1a51d1ff8..d6ce5ff8bcd 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -2257,7 +2257,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-batch/releases/tag/v{version}") } } - library("Spring Data Bom", "2025.0.8") { + library("Spring Data Bom", "2025.0.9-SNAPSHOT") { prohibit { versionRange "[2025.1.0-M1,)" because "it exceeds our baseline" From f7afe6a640f09a6beee594cf39c4505f73d6d371 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:03:54 +0000 Subject: [PATCH 06/21] Start building against Spring Framework 6.2.16 snapshots See gh-49069 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 43d6ee07425..891d8dbc92f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,7 @@ mavenVersion=3.9.10 mockitoVersion=5.17.0 nativeBuildToolsVersion=0.10.6 snakeYamlVersion=2.4 -springFrameworkVersion=6.2.15 +springFrameworkVersion=6.2.16-SNAPSHOT springFramework60xVersion=6.0.23 tomcatVersion=10.1.50 From b70673007a6c5bf7bcd913c7a3f4437da2f1653e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:03:58 +0000 Subject: [PATCH 07/21] Start building against Spring GraphQL 1.4.5 snapshots See gh-49070 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index d6ce5ff8bcd..d9b609e5797 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -2295,7 +2295,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-framework/releases/tag/v{version}") } } - library("Spring GraphQL", "1.4.4") { + library("Spring GraphQL", "1.4.5-SNAPSHOT") { considerSnapshots() group("org.springframework.graphql") { modules = [ From 4e7c22b82da9ba2f61ffdfe0f1b0b370ecfe7581 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:04:03 +0000 Subject: [PATCH 08/21] Start building against Spring Integration 6.5.7 snapshots See gh-49071 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index d9b609e5797..219a5e070b4 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -2334,7 +2334,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-hateoas/releases/tag/{version}") } } - library("Spring Integration", "6.5.6") { + library("Spring Integration", "6.5.7-SNAPSHOT") { considerSnapshots() group("org.springframework.integration") { bom("spring-integration-bom") From 645a1bb619a095e8c55704de43c4e251fc264165 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:04:07 +0000 Subject: [PATCH 09/21] Start building against Spring LDAP 3.3.6 snapshots See gh-49072 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 219a5e070b4..6e0ff8a062c 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -2367,7 +2367,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-kafka/releases/tag/v{version}") } } - library("Spring LDAP", "3.3.5") { + library("Spring LDAP", "3.3.6-SNAPSHOT") { considerSnapshots() group("org.springframework.ldap") { modules = [ From 2408d0bc09141da69ae179f3fe5b1baa3b61a220 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:04:11 +0000 Subject: [PATCH 10/21] Start building against Spring Pulsar 1.2.15 snapshots See gh-49073 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 6e0ff8a062c..9cfe1e801f0 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -2387,7 +2387,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-ldap/releases/tag/{version}") } } - library("Spring Pulsar", "1.2.14") { + library("Spring Pulsar", "1.2.15-SNAPSHOT") { considerSnapshots() group("org.springframework.pulsar") { bom("spring-pulsar-bom") From 5f8052613acb8df47897112acb4491a25d9a66d2 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:04:16 +0000 Subject: [PATCH 11/21] Start building against Spring Session 3.5.5 snapshots See gh-49074 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 9cfe1e801f0..cab7e198c81 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -2445,7 +2445,7 @@ bom { releaseNotes("https://github.com/spring-projects/spring-security/releases/tag/{version}") } } - library("Spring Session", "3.5.4") { + library("Spring Session", "3.5.5-SNAPSHOT") { considerSnapshots() prohibit { startsWith(["Apple-", "Bean-", "Corn-", "Dragonfruit-"]) From 31c08024c8510e4333dfe940a24e714df6cd1c58 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:07:30 +0000 Subject: [PATCH 12/21] Upgrade to AssertJ 3.27.7 Closes gh-49075 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 891d8dbc92f..1c545ab025f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.caching=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8 -assertjVersion=3.27.6 +assertjVersion=3.27.7 checkstyleToolVersion=10.12.4 commonsCodecVersion=1.18.0 graalVersion=22.3 From 29b7e5a2d474cb8e98af384e62e90fd92ccd9170 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:07:34 +0000 Subject: [PATCH 13/21] Upgrade to Groovy 4.0.30 Closes gh-49076 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index cab7e198c81..7851f0d509d 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -496,7 +496,7 @@ bom { releaseNotes("https://github.com/graphql-java/graphql-java/releases/tag/v{version}") } } - library("Groovy", "4.0.29") { + library("Groovy", "4.0.30") { prohibit { contains "-alpha-" because "we don't want alpha dependencies" From 9504cde1a73d8e599f8400494d0aa3e353e78cd0 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:07:38 +0000 Subject: [PATCH 14/21] Upgrade to Hibernate 6.6.42.Final Closes gh-49077 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 7851f0d509d..1cd6880d252 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -557,7 +557,7 @@ bom { releaseNotes("https://github.com/hazelcast/hazelcast/releases/tag/v{version}") } } - library("Hibernate", "6.6.41.Final") { + library("Hibernate", "6.6.42.Final") { prohibit { versionRange "[7.0.0.Alpha1,)" because "it exceeds our Jakarta EE 10 baseline" From 9262a63292ffdc1d7be7ef9dde20707da7fcefa7 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:07:43 +0000 Subject: [PATCH 15/21] Upgrade to Jaybird 6.0.4 Closes gh-49078 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 1cd6880d252..b9c2c52e5e4 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -991,7 +991,7 @@ bom { releaseNotes("https://github.com/jaxen-xpath/jaxen/releases/tag/v{version}") } } - library("Jaybird", "6.0.3") { + library("Jaybird", "6.0.4") { prohibit { endsWith ".java8" because "we use the .java11 version" From 9aedd8617d665a9af595ee626dd4fa77678b777e Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:07:47 +0000 Subject: [PATCH 16/21] Upgrade to JBoss Logging 3.6.2.Final Closes gh-49079 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index b9c2c52e5e4..1beaa8e34a8 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1006,7 +1006,7 @@ bom { .formatted(version.toString().replace(".java11", ""))) } } - library("JBoss Logging", "3.6.1.Final") { + library("JBoss Logging", "3.6.2.Final") { group("org.jboss.logging") { modules = [ "jboss-logging" From 9c42312fa1769cf85af40712f5ffda86cb9ff62a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:07:51 +0000 Subject: [PATCH 17/21] Upgrade to Jetty 12.0.32 Closes gh-49080 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 1beaa8e34a8..6c8d3eb5784 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1065,7 +1065,7 @@ bom { ] } } - library("Jetty", "12.0.31") { + library("Jetty", "12.0.32") { prohibit { contains ".alpha" because "we don't want alpha dependencies" From cdc5eb903100cae69ad0b386638d423f89c235c8 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:07:56 +0000 Subject: [PATCH 18/21] Upgrade to jOOQ 3.19.30 Closes gh-49081 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 6c8d3eb5784..bb09edf383f 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1089,7 +1089,7 @@ bom { ] } } - library("jOOQ", "3.19.29") { + library("jOOQ", "3.19.30") { prohibit { versionRange "[3.20.0,)" because "it requires Java 21" From e7db45354756e7743a1ba1ade4d7a10abc29b5ea Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:08:00 +0000 Subject: [PATCH 19/21] Upgrade to Logback 1.5.27 Closes gh-49082 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index bb09edf383f..ccb5855d43d 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1342,7 +1342,7 @@ bom { releaseNotes("https://github.com/apache/logging-log4j2/releases/tag/rel%2F{version}") } } - library("Logback", "1.5.25") { + library("Logback", "1.5.27") { group("ch.qos.logback") { modules = [ "logback-classic", From 43363ed428da19d066d8637d62f91c533e099524 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:08:05 +0000 Subject: [PATCH 20/21] Upgrade to MySQL 9.6.0 Closes gh-49083 --- spring-boot-project/spring-boot-dependencies/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index ccb5855d43d..fd7f73b3284 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -1665,7 +1665,7 @@ bom { .formatted(version.toString().replace(".jre11", ""))) } } - library("MySQL", "9.5.0") { + library("MySQL", "9.6.0") { upgradePolicy = "same-major-version" group("com.mysql") { modules = [ From d40ec740f5d8c2e09d34bcf6e825cd05d522b46a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 5 Feb 2026 12:08:09 +0000 Subject: [PATCH 21/21] Upgrade to Tomcat 10.1.52 Tomcat 9.0.115, 10.1.52, and 11.0.18 include a breaking change [1] to how ciphers are configured when using HTTPS. Previously, a single setting was used but this has now been split in two; the existing ciphers setting for TLSv1.2 ciphers and a new ciperSuites setting for TLSv1.3. As part of this split, the behavior of the ciphers setting has been changed such that any TLSv1.3 ciphers are ignored and a warning is logged. This change in Tomcat is problematic without also making some changes in Boot. If we had done nothing, a user that had configured only TLSv1.3 cipers would have them all ignored, leaving their SSL connection unexpectedly using all of the default ciphers which may be less secure. This commit adapts to the breaking change in Tomcat by taking the user's list of ciphers and splitting into into TLSv1.2 and TLSv1.3 ciphers before passing them into Tomcat's two settings (ciphers and cipherSuites respectively). This is done defensively for backwards compatibility. If the methods to identify and configure the TLSv1.3 ciphers are not present, we assume that we're running with an earlier version of Tomcat and fall back to passing them all into the ciphers setting as we did previously. Closes gh-49084 [1] https://github.com/apache/tomcat/commit/9abf6bddb2e84ecf1668780bb3150b799f832ccf --- gradle.properties | 2 +- .../tomcat/SslConnectorCustomizer.java | 64 +++++++++++++++++-- .../tomcat/SslConnectorCustomizerTests.java | 39 ++++++++++- 3 files changed, 99 insertions(+), 6 deletions(-) diff --git a/gradle.properties b/gradle.properties index 1c545ab025f..758c76317c0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,6 +21,6 @@ nativeBuildToolsVersion=0.10.6 snakeYamlVersion=2.4 springFrameworkVersion=6.2.16-SNAPSHOT springFramework60xVersion=6.0.23 -tomcatVersion=10.1.50 +tomcatVersion=10.1.52 kotlin.stdlib.default.dependency=false 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 8529d3ebbe3..0e2d04bd277 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 @@ -16,6 +16,8 @@ package org.springframework.boot.web.embedded.tomcat; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.apache.catalina.connector.Connector; @@ -25,6 +27,7 @@ import org.apache.coyote.http11.AbstractHttp11Protocol; import org.apache.tomcat.util.net.SSLHostConfig; import org.apache.tomcat.util.net.SSLHostConfigCertificate; import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type; +import org.apache.tomcat.util.net.openssl.ciphers.OpenSSLCipherConfigurationParser; import org.springframework.boot.ssl.SslBundle; import org.springframework.boot.ssl.SslBundleKey; @@ -111,14 +114,24 @@ class SslConnectorCustomizer { certificate.setCertificateKeyAlias(key.getAlias()); } sslHostConfig.addCertificate(certificate); - if (options.getCiphers() != null) { - String ciphers = StringUtils.arrayToCommaDelimitedString(options.getCiphers()); - sslHostConfig.setCiphers(ciphers); - } + configureCiphers(options, sslHostConfig); configureSslStores(sslHostConfig, certificate, stores); configureEnabledProtocols(sslHostConfig, options); } + private void configureCiphers(SslOptions options, SSLHostConfig sslHostConfig) { + CipherConfiguration cipherConfiguration = CipherConfiguration.from(options); + if (cipherConfiguration != null) { + sslHostConfig.setCiphers(cipherConfiguration.tls12Ciphers); + try { + sslHostConfig.setCipherSuites(cipherConfiguration.tls13Ciphers); + } + catch (Exception ex) { + // Tomcat version without setCipherSuites method. Continue. + } + } + } + private void configureEnabledProtocols(SSLHostConfig sslHostConfig, SslOptions options) { if (options.getEnabledProtocols() != null) { String enabledProtocols = StringUtils.arrayToDelimitedString(options.getEnabledProtocols(), "+"); @@ -145,4 +158,47 @@ class SslConnectorCustomizer { } } + private static class CipherConfiguration { + + private final String tls12Ciphers; + + private final String tls13Ciphers; + + CipherConfiguration(String tls12Ciphers, String tls13Ciphers) { + this.tls12Ciphers = tls12Ciphers; + this.tls13Ciphers = tls13Ciphers; + } + + static CipherConfiguration from(SslOptions options) { + List tls12Ciphers = new ArrayList<>(); + List tls13Ciphers = new ArrayList<>(); + String[] ciphers = options.getCiphers(); + if (ciphers == null || ciphers.length == 0) { + return null; + } + for (String cipher : ciphers) { + if (isTls13(cipher)) { + tls13Ciphers.add(cipher); + } + else { + tls12Ciphers.add(cipher); + } + } + return new CipherConfiguration(StringUtils.collectionToCommaDelimitedString(tls12Ciphers), + StringUtils.collectionToCommaDelimitedString(tls13Ciphers)); + } + + private static boolean isTls13(String cipher) { + try { + return OpenSSLCipherConfigurationParser.isTls13Cipher(cipher); + } + catch (Exception ex) { + // Tomcat version without isTls13Cipher method. Continue, treating all + // ciphers as TLSv1.2 + return false; + } + } + + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizerTests.java index 235bfde6d28..c9175bc0a59 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/SslConnectorCustomizerTests.java @@ -23,6 +23,7 @@ import org.apache.catalina.startup.Tomcat; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.tomcat.util.net.SSLHostConfig; +import org.apache.tomcat.util.net.openssl.ciphers.Cipher; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -73,7 +74,7 @@ class SslConnectorCustomizerTests { @Test @WithPackageResources("test.jks") - void sslCiphersConfiguration() throws Exception { + void tls12CiphersConfiguration() throws Exception { Ssl ssl = new Ssl(); ssl.setKeyStore("classpath:test.jks"); ssl.setKeyStorePassword("secret"); @@ -84,6 +85,42 @@ class SslConnectorCustomizerTests { this.tomcat.start(); SSLHostConfig[] sslHostConfigs = connector.getProtocolHandler().findSslHostConfigs(); assertThat(sslHostConfigs[0].getCiphers()).isEqualTo("ALPHA:BRAVO:CHARLIE"); + assertThat(sslHostConfigs[0].getCipherSuites()).isEmpty(); + } + + @Test + @WithPackageResources("test.jks") + void tls13CiphersConfiguration() throws Exception { + Ssl ssl = new Ssl(); + ssl.setKeyStore("classpath:test.jks"); + ssl.setKeyStorePassword("secret"); + ssl.setCiphers(new String[] { Cipher.TLS_AES_128_CCM_SHA256.getOpenSSLAlias(), + Cipher.TLS_AES_256_GCM_SHA384.getOpenSSLAlias() }); + Connector connector = this.tomcat.getConnector(); + SslConnectorCustomizer customizer = new SslConnectorCustomizer(this.logger, connector, ssl.getClientAuth()); + customizer.customize(WebServerSslBundle.get(ssl), Collections.emptyMap()); + this.tomcat.start(); + SSLHostConfig[] sslHostConfigs = connector.getProtocolHandler().findSslHostConfigs(); + assertThat(sslHostConfigs[0].getCiphers()).isEmpty(); + assertThat(sslHostConfigs[0].getCipherSuites()).isEqualTo("TLS_AES_128_CCM_SHA256:TLS_AES_256_GCM_SHA384"); + } + + @Test + @WithPackageResources("test.jks") + void mixedTls12AndTls13CiphersConfiguration() throws Exception { + Ssl ssl = new Ssl(); + ssl.setKeyStore("classpath:test.jks"); + ssl.setKeyStorePassword("secret"); + ssl.setCiphers(new String[] { Cipher.TLS_AES_128_CCM_SHA256.getOpenSSLAlias(), + Cipher.TLS_DH_DSS_WITH_AES_128_CBC_SHA256.getOpenSSLAlias(), + Cipher.TLS_AES_256_GCM_SHA384.getOpenSSLAlias() }); + Connector connector = this.tomcat.getConnector(); + SslConnectorCustomizer customizer = new SslConnectorCustomizer(this.logger, connector, ssl.getClientAuth()); + customizer.customize(WebServerSslBundle.get(ssl), Collections.emptyMap()); + this.tomcat.start(); + SSLHostConfig[] sslHostConfigs = connector.getProtocolHandler().findSslHostConfigs(); + assertThat(sslHostConfigs[0].getCiphers()).isEqualTo("DH-DSS-AES128-SHA256"); + assertThat(sslHostConfigs[0].getCipherSuites()).isEqualTo("TLS_AES_128_CCM_SHA256:TLS_AES_256_GCM_SHA384"); } @Test