Add method to create an SslBundle which uses the system default managers

See gh-41137
This commit is contained in:
Moritz Halbritter 2025-02-11 10:07:32 +01:00
parent 631d07cfe1
commit d8b470a511
4 changed files with 69 additions and 6 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,9 +16,16 @@
package org.springframework.boot.ssl;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.StringUtils;
@ -27,6 +34,7 @@ import org.springframework.util.StringUtils;
* A bundle of trust material that can be used to establish an SSL connection.
*
* @author Scott Frederick
* @author Moritz Halbritter
* @since 3.1.0
*/
public interface SslBundle {
@ -174,4 +182,40 @@ public interface SslBundle {
};
}
/**
* Factory method to create a new {@link SslBundle} which uses the system defaults.
* @return a new {@link SslBundle} instance
* @since 3.5.0
*/
static SslBundle systemDefault() {
try {
KeyManagerFactory keyManagerFactory = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(null, null);
TrustManagerFactory trustManagerFactory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
SSLContext sslContext = SSLContext.getDefault();
return of(null, null, null, null, new SslManagerBundle() {
@Override
public KeyManagerFactory getKeyManagerFactory() {
return keyManagerFactory;
}
@Override
public TrustManagerFactory getTrustManagerFactory() {
return trustManagerFactory;
}
@Override
public SSLContext createSslContext(String protocol) {
return sslContext;
}
});
}
catch (NoSuchAlgorithmException | KeyStoreException | UnrecoverableKeyException ex) {
throw new IllegalStateException("Could not initialize system default SslBundle: " + ex.getMessage(), ex);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -38,7 +38,7 @@ public interface SslOptions {
/**
* {@link SslOptions} that returns {@code null} results.
*/
SslOptions NONE = of((Set<String>) null, (Set<String>) null);
SslOptions NONE = of(null, (Set<String>) null);
/**
* Return if any SSL options have been specified.

View File

@ -33,6 +33,7 @@ import java.util.stream.Collectors;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
/**
* PEM encoded content that can provide {@link X509Certificate certificates} and
@ -109,11 +110,11 @@ public final class PemContent {
* reference to the resource to load).
* @param content the content to load
* @param resourceLoader the resource loader used to load content
* @return a new {@link PemContent} instance
* @return a new {@link PemContent} instance or {@code null}
* @throws IOException on IO error
*/
static PemContent load(String content, ResourceLoader resourceLoader) throws IOException {
if (content == null) {
if (!StringUtils.hasLength(content)) {
return null;
}
if (isPresentInText(content)) {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +16,10 @@
package org.springframework.boot.ssl;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@ -26,6 +30,7 @@ import static org.mockito.Mockito.mock;
* Tests for {@link SslBundle}.
*
* @author Phillip Webb
* @author Moritz Halbritter
*/
class SslBundleTests {
@ -52,4 +57,17 @@ class SslBundleTests {
assertThat(bundle.getManagers()).isSameAs(managers);
}
@Test
void shouldCreateSystemDefaultBundle() {
SslBundle sslBundle = SslBundle.systemDefault();
SSLContext sslContext = sslBundle.createSslContext();
assertThat(sslContext).isNotNull();
TrustManager[] trustManagers = sslBundle.getManagers().getTrustManagers();
assertThat(trustManagers).isNotEmpty();
TrustManager trustManager = trustManagers[0];
assertThat(trustManager).isInstanceOf(X509TrustManager.class);
X509TrustManager x509TrustManager = (X509TrustManager) trustManager;
assertThat(x509TrustManager.getAcceptedIssuers()).isNotEmpty();
}
}