Skip to content

Commit d8b470a

Browse files
committed
Add method to create an SslBundle which uses the system default managers
See gh-41137
1 parent 631d07c commit d8b470a

File tree

4 files changed

+69
-6
lines changed

4 files changed

+69
-6
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/SslBundle.java

+45-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,9 +16,16 @@
1616

1717
package org.springframework.boot.ssl;
1818

19+
import java.security.KeyStore;
20+
import java.security.KeyStoreException;
21+
import java.security.NoSuchAlgorithmException;
22+
import java.security.UnrecoverableKeyException;
23+
1924
import javax.net.ssl.KeyManager;
25+
import javax.net.ssl.KeyManagerFactory;
2026
import javax.net.ssl.SSLContext;
2127
import javax.net.ssl.TrustManager;
28+
import javax.net.ssl.TrustManagerFactory;
2229

2330
import org.springframework.core.style.ToStringCreator;
2431
import org.springframework.util.StringUtils;
@@ -27,6 +34,7 @@
2734
* A bundle of trust material that can be used to establish an SSL connection.
2835
*
2936
* @author Scott Frederick
37+
* @author Moritz Halbritter
3038
* @since 3.1.0
3139
*/
3240
public interface SslBundle {
@@ -174,4 +182,40 @@ public String toString() {
174182
};
175183
}
176184

185+
/**
186+
* Factory method to create a new {@link SslBundle} which uses the system defaults.
187+
* @return a new {@link SslBundle} instance
188+
* @since 3.5.0
189+
*/
190+
static SslBundle systemDefault() {
191+
try {
192+
KeyManagerFactory keyManagerFactory = KeyManagerFactory
193+
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
194+
keyManagerFactory.init(null, null);
195+
TrustManagerFactory trustManagerFactory = TrustManagerFactory
196+
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
197+
trustManagerFactory.init((KeyStore) null);
198+
SSLContext sslContext = SSLContext.getDefault();
199+
return of(null, null, null, null, new SslManagerBundle() {
200+
@Override
201+
public KeyManagerFactory getKeyManagerFactory() {
202+
return keyManagerFactory;
203+
}
204+
205+
@Override
206+
public TrustManagerFactory getTrustManagerFactory() {
207+
return trustManagerFactory;
208+
}
209+
210+
@Override
211+
public SSLContext createSslContext(String protocol) {
212+
return sslContext;
213+
}
214+
});
215+
}
216+
catch (NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException ex) {
217+
throw new IllegalStateException("Could not initialize system default SslBundle: " + ex.getMessage(), ex);
218+
}
219+
}
220+
177221
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/SslOptions.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ public interface SslOptions {
3838
/**
3939
* {@link SslOptions} that returns {@code null} results.
4040
*/
41-
SslOptions NONE = of((Set<String>) null, (Set<String>) null);
41+
SslOptions NONE = of(null, (Set<String>) null);
4242

4343
/**
4444
* Return if any SSL options have been specified.

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ssl/pem/PemContent.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.springframework.core.io.ResourceLoader;
3434
import org.springframework.util.Assert;
3535
import org.springframework.util.StreamUtils;
36+
import org.springframework.util.StringUtils;
3637

3738
/**
3839
* PEM encoded content that can provide {@link X509Certificate certificates} and
@@ -109,11 +110,11 @@ public String toString() {
109110
* reference to the resource to load).
110111
* @param content the content to load
111112
* @param resourceLoader the resource loader used to load content
112-
* @return a new {@link PemContent} instance
113+
* @return a new {@link PemContent} instance or {@code null}
113114
* @throws IOException on IO error
114115
*/
115116
static PemContent load(String content, ResourceLoader resourceLoader) throws IOException {
116-
if (content == null) {
117+
if (!StringUtils.hasLength(content)) {
117118
return null;
118119
}
119120
if (isPresentInText(content)) {

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/ssl/SslBundleTests.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,10 @@
1616

1717
package org.springframework.boot.ssl;
1818

19+
import javax.net.ssl.SSLContext;
20+
import javax.net.ssl.TrustManager;
21+
import javax.net.ssl.X509TrustManager;
22+
1923
import org.junit.jupiter.api.Test;
2024

2125
import static org.assertj.core.api.Assertions.assertThat;
@@ -26,6 +30,7 @@
2630
* Tests for {@link SslBundle}.
2731
*
2832
* @author Phillip Webb
33+
* @author Moritz Halbritter
2934
*/
3035
class SslBundleTests {
3136

@@ -52,4 +57,17 @@ void ofCreatesSslBundle() {
5257
assertThat(bundle.getManagers()).isSameAs(managers);
5358
}
5459

60+
@Test
61+
void shouldCreateSystemDefaultBundle() {
62+
SslBundle sslBundle = SslBundle.systemDefault();
63+
SSLContext sslContext = sslBundle.createSslContext();
64+
assertThat(sslContext).isNotNull();
65+
TrustManager[] trustManagers = sslBundle.getManagers().getTrustManagers();
66+
assertThat(trustManagers).isNotEmpty();
67+
TrustManager trustManager = trustManagers[0];
68+
assertThat(trustManager).isInstanceOf(X509TrustManager.class);
69+
X509TrustManager x509TrustManager = (X509TrustManager) trustManager;
70+
assertThat(x509TrustManager.getAcceptedIssuers()).isNotEmpty();
71+
}
72+
5573
}

0 commit comments

Comments
 (0)