Skip to content

Commit 0600b4d

Browse files
niemanndspencergibb
authored andcommitted
add ability to use sslBundles
Fixes gh-2981
1 parent fd3c6f5 commit 0600b4d

File tree

6 files changed

+87
-16
lines changed

6 files changed

+87
-16
lines changed

spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/AbstractSslConfigurer.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,28 @@
3636
import org.apache.commons.logging.Log;
3737
import org.apache.commons.logging.LogFactory;
3838

39+
import org.springframework.boot.ssl.SslBundle;
40+
import org.springframework.boot.ssl.SslBundles;
3941
import org.springframework.util.ResourceUtils;
4042

4143
/**
4244
* Base class to configure SSL for component T. Returns an instance S with the resulting
4345
* configuration (can be the same as T).
4446
*
4547
* @author Abel Salgado Romero
48+
* @author Dominic Niemann
4649
*/
4750
public abstract class AbstractSslConfigurer<T, S> {
4851

4952
protected final Log logger = LogFactory.getLog(this.getClass());
5053

5154
private final HttpClientProperties.Ssl ssl;
5255

53-
protected AbstractSslConfigurer(HttpClientProperties.Ssl sslProperties) {
56+
private final SslBundles bundles;
57+
58+
protected AbstractSslConfigurer(HttpClientProperties.Ssl sslProperties, SslBundles bundles) {
5459
this.ssl = sslProperties;
60+
this.bundles = bundles;
5561
}
5662

5763
abstract public S configureSsl(T client) throws SSLException;
@@ -60,6 +66,16 @@ protected HttpClientProperties.Ssl getSslProperties() {
6066
return ssl;
6167
}
6268

69+
protected SslBundle getBundle() {
70+
if(ssl.getSslBundle() == null || ssl.getSslBundle().length() > 0) {
71+
return null;
72+
}
73+
if(bundles.getBundleNames().contains(ssl.getSslBundle())) {
74+
return bundles.getBundle(ssl.getSslBundle());
75+
}
76+
return null;
77+
}
78+
6379
protected X509Certificate[] getTrustedX509CertificatesForTrustManager() {
6480

6581
try {

spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GatewayAutoConfiguration.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
5757
import org.springframework.boot.context.properties.EnableConfigurationProperties;
5858
import org.springframework.boot.context.properties.PropertyMapper;
59+
import org.springframework.boot.ssl.SslBundles;
5960
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
6061
import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint;
6162
import org.springframework.cloud.gateway.actuate.GatewayLegacyControllerEndpoint;
@@ -187,6 +188,7 @@
187188
* @author Mete Alpaslan Katırcıoğlu
188189
* @author Alberto C. Ríos
189190
* @author Olga Maciaszek-Sharma
191+
* @author Dominic Niemann
190192
*/
191193
@Configuration(proxyBeanMethods = false)
192194
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@@ -353,13 +355,13 @@ public JsonToGrpcGatewayFilterFactory jsonToGRPCFilterFactory(GrpcSslConfigurer
353355
@ConditionalOnEnabledFilter(JsonToGrpcGatewayFilterFactory.class)
354356
@ConditionalOnMissingBean(GrpcSslConfigurer.class)
355357
@ConditionalOnClass(name = "io.grpc.Channel")
356-
public GrpcSslConfigurer grpcSslConfigurer(HttpClientProperties properties)
358+
public GrpcSslConfigurer grpcSslConfigurer(HttpClientProperties properties, SslBundles bundles)
357359
throws KeyStoreException, NoSuchAlgorithmException {
358360
TrustManagerFactory trustManagerFactory = TrustManagerFactory
359361
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
360362
trustManagerFactory.init(KeyStore.getInstance(KeyStore.getDefaultType()));
361363

362-
return new GrpcSslConfigurer(properties.getSsl());
364+
return new GrpcSslConfigurer(properties.getSsl(), bundles);
363365
}
364366

365367
@Bean
@@ -755,8 +757,9 @@ public void customize(NettyReactiveWebServerFactory factory) {
755757

756758
@Bean
757759
public HttpClientSslConfigurer httpClientSslConfigurer(ServerProperties serverProperties,
758-
HttpClientProperties httpClientProperties) {
759-
return new HttpClientSslConfigurer(httpClientProperties.getSsl(), serverProperties) {
760+
HttpClientProperties httpClientProperties,
761+
SslBundles bundles) {
762+
return new HttpClientSslConfigurer(httpClientProperties.getSsl(), serverProperties, bundles) {
760763
};
761764
}
762765

spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/GrpcSslConfigurer.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@
2525
import io.netty.handler.ssl.SslContextBuilder;
2626
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
2727

28+
import org.springframework.boot.ssl.SslBundle;
29+
import org.springframework.boot.ssl.SslBundles;
30+
2831
/**
2932
* @author Alberto C. Ríos
33+
* @author Dominic Niemann
3034
*/
3135
public class GrpcSslConfigurer extends AbstractSslConfigurer<NettyChannelBuilder, ManagedChannel> {
3236

33-
public GrpcSslConfigurer(HttpClientProperties.Ssl sslProperties) {
34-
super(sslProperties);
37+
public GrpcSslConfigurer(HttpClientProperties.Ssl sslProperties, SslBundles bundles) {
38+
super(sslProperties, bundles);
3539
}
3640

3741
@Override
@@ -45,15 +49,25 @@ private SslContext getSslContext() throws SSLException {
4549

4650
final HttpClientProperties.Ssl ssl = getSslProperties();
4751
boolean useInsecureTrustManager = ssl.isUseInsecureTrustManager();
52+
SslBundle bundle = getBundle();
4853
if (useInsecureTrustManager) {
4954
sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE.getTrustManagers()[0]);
5055
}
5156

5257
if (!useInsecureTrustManager && ssl.getTrustedX509Certificates().size() > 0) {
5358
sslContextBuilder.trustManager(getTrustedX509CertificatesForTrustManager());
5459
}
60+
else if (bundle != null) {
61+
sslContextBuilder.trustManager(bundle.getManagers().getTrustManagerFactory());
62+
}
5563

56-
return sslContextBuilder.keyManager(getKeyManagerFactory()).build();
64+
if (bundle != null) {
65+
sslContextBuilder.keyManager(bundle.getManagers().getKeyManagerFactory());
66+
}
67+
else {
68+
sslContextBuilder.keyManager(getKeyManagerFactory());
69+
}
70+
return sslContextBuilder.build();
5771
}
5872

5973
}

spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/HttpClientProperties.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,9 @@ public static class Ssl {
419419
/** Trusted certificates for verifying the remote endpoint's certificate. */
420420
private List<String> trustedX509Certificates = new ArrayList<>();
421421

422+
/** The name of the SSL bundle to use. */
423+
private String sslBundle;
424+
422425
// use netty default SSL timeouts
423426
/** SSL handshake timeout. Default to 10000 ms */
424427
private Duration handshakeTimeout = Duration.ofMillis(10000);
@@ -524,6 +527,14 @@ public void setCloseNotifyReadTimeout(Duration closeNotifyReadTimeout) {
524527
this.closeNotifyReadTimeout = closeNotifyReadTimeout;
525528
}
526529

530+
public String getSslBundle() {
531+
return sslBundle;
532+
}
533+
534+
public void setSslBundle(String sslBundle) {
535+
this.sslBundle = sslBundle;
536+
}
537+
527538
@Override
528539
public String toString() {
529540
return new ToStringCreator(this).append("useInsecureTrustManager", useInsecureTrustManager)

spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/config/HttpClientSslConfigurer.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,22 @@
2525
import reactor.netty.tcp.SslProvider;
2626

2727
import org.springframework.boot.autoconfigure.web.ServerProperties;
28+
import org.springframework.boot.ssl.SslBundle;
29+
import org.springframework.boot.ssl.SslBundles;
2830

2931
public class HttpClientSslConfigurer extends AbstractSslConfigurer<HttpClient, HttpClient> {
3032

3133
private final ServerProperties serverProperties;
3234

33-
public HttpClientSslConfigurer(HttpClientProperties.Ssl sslProperties, ServerProperties serverProperties) {
34-
super(sslProperties);
35+
public HttpClientSslConfigurer(HttpClientProperties.Ssl sslProperties, ServerProperties serverProperties, SslBundles bundles) {
36+
super(sslProperties, bundles);
3537
this.serverProperties = serverProperties;
3638
}
3739

3840
public HttpClient configureSsl(HttpClient client) {
3941
final HttpClientProperties.Ssl ssl = getSslProperties();
4042

41-
if ((ssl.getKeyStore() != null && ssl.getKeyStore().length() > 0)
43+
if (getBundle() != null || (ssl.getKeyStore() != null && ssl.getKeyStore().length() > 0)
4244
|| getTrustedX509CertificatesForTrustManager().length > 0 || ssl.isUseInsecureTrustManager()) {
4345
client = client.secure(sslContextSpec -> {
4446
// configure ssl
@@ -53,15 +55,24 @@ protected void configureSslContext(HttpClientProperties.Ssl ssl, SslProvider.Ssl
5355
? Http2SslContextSpec.forClient() : Http11SslContextSpec.forClient();
5456
clientSslContext.configure(sslContextBuilder -> {
5557
X509Certificate[] trustedX509Certificates = getTrustedX509CertificatesForTrustManager();
58+
SslBundle bundle = getBundle();
5659
if (trustedX509Certificates.length > 0) {
5760
setTrustManager(sslContextBuilder, trustedX509Certificates);
5861
}
5962
else if (ssl.isUseInsecureTrustManager()) {
6063
setTrustManager(sslContextBuilder, InsecureTrustManagerFactory.INSTANCE);
6164
}
65+
else if (bundle != null) {
66+
setTrustManager(sslContextBuilder, bundle.getManagers().getTrustManagerFactory());
67+
}
6268

6369
try {
64-
sslContextBuilder.keyManager(getKeyManagerFactory());
70+
if(bundle != null) {
71+
sslContextBuilder.keyManager(bundle.getManagers().getKeyManagerFactory());
72+
}
73+
else {
74+
sslContextBuilder.keyManager(getKeyManagerFactory());
75+
}
6576
}
6677
catch (Exception e) {
6778
logger.error(e);

spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/config/GatewayAutoConfigurationTests.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import reactor.netty.tcp.SslProvider;
3737
import reactor.netty.transport.ProxyProvider;
3838

39+
import org.springframework.beans.factory.ObjectProvider;
3940
import org.springframework.boot.SpringApplication;
4041
import org.springframework.boot.SpringBootConfiguration;
4142
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
@@ -45,9 +46,12 @@
4546
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
4647
import org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration;
4748
import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration;
49+
import org.springframework.boot.autoconfigure.ssl.SslBundleRegistrar;
4850
import org.springframework.boot.autoconfigure.web.ServerProperties;
4951
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
5052
import org.springframework.boot.context.properties.EnableConfigurationProperties;
53+
import org.springframework.boot.ssl.DefaultSslBundleRegistry;
54+
import org.springframework.boot.ssl.SslBundles;
5155
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
5256
import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint;
5357
import org.springframework.cloud.gateway.actuate.GatewayLegacyControllerEndpoint;
@@ -115,6 +119,7 @@ public void nettyHttpClientConfigured() {
115119
SimpleMetricsExportAutoConfiguration.class, GatewayAutoConfiguration.class,
116120
HttpClientCustomizedConfig.class, ServerPropertiesConfig.class))
117121
.withPropertyValues("spring.cloud.gateway.httpclient.ssl.use-insecure-trust-manager=true",
122+
"spring.cloud.gateway.httpclient.ssl.ssl-bundle=mybundle",
118123
"spring.cloud.gateway.httpclient.connect-timeout=10",
119124
"spring.cloud.gateway.httpclient.response-timeout=10s",
120125
"spring.cloud.gateway.httpclient.pool.eviction-interval=10s",
@@ -136,6 +141,7 @@ public void nettyHttpClientConfigured() {
136141
assertThat(properties.getPool().getEvictionInterval()).hasSeconds(10);
137142
assertThat(properties.getPool().isMetrics()).isEqualTo(true);
138143
assertThat(properties.getPool().getLeasingStrategy()).isEqualTo(LeasingStrategy.LIFO);
144+
assertThat(properties.getSsl().getSslBundle()).isEqualTo("mybundle");
139145

140146
assertThat(httpClient.configuration().isAcceptGzip()).isTrue();
141147
assertThat(httpClient.configuration().loggingHandler()).isNotNull();
@@ -345,10 +351,20 @@ CustomHttpClientFactory customHttpClientFactory(HttpClientProperties properties,
345351
@Bean
346352
@Primary
347353
CustomSslConfigurer customSslContextFactory(ServerProperties serverProperties,
348-
HttpClientProperties httpClientProperties) {
349-
return new CustomSslConfigurer(httpClientProperties.getSsl(), serverProperties);
354+
HttpClientProperties httpClientProperties,
355+
SslBundles bundles) {
356+
return new CustomSslConfigurer(httpClientProperties.getSsl(), serverProperties, bundles);
350357
}
351358

359+
@Bean
360+
@Primary
361+
SslBundles sslBundleRegistry(ObjectProvider<SslBundleRegistrar> sslBundleRegistrars) {
362+
DefaultSslBundleRegistry registry = new DefaultSslBundleRegistry();
363+
sslBundleRegistrars.orderedStream().forEach((registrar) -> {
364+
registrar.registerBundles(registry);
365+
});
366+
return registry;
367+
}
352368
}
353369

354370
protected static class CustomHttpClientFactory extends HttpClientFactory {
@@ -392,8 +408,8 @@ protected static class CustomSslConfigurer extends HttpClientSslConfigurer {
392408

393409
boolean insecureTrustManagerSet;
394410

395-
protected CustomSslConfigurer(HttpClientProperties.Ssl sslProperties, ServerProperties serverProperties) {
396-
super(sslProperties, serverProperties);
411+
protected CustomSslConfigurer(HttpClientProperties.Ssl sslProperties, ServerProperties serverProperties, SslBundles bundles) {
412+
super(sslProperties, serverProperties, bundles);
397413
}
398414

399415
@Override

0 commit comments

Comments
 (0)