Skip to content

Commit fd5fd14

Browse files
scottfrederickphilwebb
authored andcommitted
Add SSL bundle support to MongoDB auto-configuration
Update MongoDB auto-configuration so that an SSL can be configured via an SSL bundle. Closes gh-35042
1 parent 1618aa2 commit fd5fd14

File tree

7 files changed

+162
-8
lines changed

7 files changed

+162
-8
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2626
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
2727
import org.springframework.boot.context.properties.EnableConfigurationProperties;
28+
import org.springframework.boot.ssl.SslBundles;
2829
import org.springframework.context.annotation.Bean;
2930
import org.springframework.context.annotation.Configuration;
3031

@@ -69,9 +70,9 @@ MongoClientSettings mongoClientSettings() {
6970

7071
@Bean
7172
StandardMongoClientSettingsBuilderCustomizer standardMongoSettingsCustomizer(MongoProperties properties,
72-
MongoConnectionDetails connectionDetails) {
73+
MongoConnectionDetails connectionDetails, ObjectProvider<SslBundles> sslBundles) {
7374
return new StandardMongoClientSettingsBuilderCustomizer(connectionDetails.getConnectionString(),
74-
properties.getUuidRepresentation());
75+
properties.getUuidRepresentation(), properties.getSsl(), sslBundles.getIfAvailable());
7576
}
7677

7778
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoProperties.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2022 the original author or authors.
2+
* Copyright 2012-2023 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.
@@ -110,6 +110,8 @@ public class MongoProperties {
110110
*/
111111
private UuidRepresentation uuidRepresentation = UuidRepresentation.JAVA_LEGACY;
112112

113+
private final Ssl ssl = new Ssl();
114+
113115
/**
114116
* Whether to enable auto-index creation.
115117
*/
@@ -226,6 +228,10 @@ public void setAdditionalHosts(List<String> additionalHosts) {
226228
this.additionalHosts = additionalHosts;
227229
}
228230

231+
public Ssl getSsl() {
232+
return this.ssl;
233+
}
234+
229235
public static class Gridfs {
230236

231237
/**
@@ -256,4 +262,35 @@ public void setBucket(String bucket) {
256262

257263
}
258264

265+
public static class Ssl {
266+
267+
/**
268+
* Whether to enable SSL support. Enabled automatically if "bundle" is provided
269+
* unless specified otherwise.
270+
*/
271+
private Boolean enabled;
272+
273+
/**
274+
* SSL bundle name.
275+
*/
276+
private String bundle;
277+
278+
public boolean isEnabled() {
279+
return (this.enabled != null) ? this.enabled : this.bundle != null;
280+
}
281+
282+
public void setEnabled(boolean enabled) {
283+
this.enabled = enabled;
284+
}
285+
286+
public String getBundle() {
287+
return this.bundle;
288+
}
289+
290+
public void setBundle(String bundle) {
291+
this.bundle = bundle;
292+
}
293+
294+
}
295+
259296
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfiguration.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3333
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
3434
import org.springframework.boot.context.properties.EnableConfigurationProperties;
35+
import org.springframework.boot.ssl.SslBundles;
3536
import org.springframework.context.annotation.Bean;
3637
import org.springframework.context.annotation.Configuration;
3738
import org.springframework.core.Ordered;
@@ -76,9 +77,9 @@ MongoClientSettings mongoClientSettings() {
7677

7778
@Bean
7879
StandardMongoClientSettingsBuilderCustomizer standardMongoSettingsCustomizer(MongoProperties properties,
79-
MongoConnectionDetails connectionDetails) {
80+
MongoConnectionDetails connectionDetails, ObjectProvider<SslBundles> sslBundles) {
8081
return new StandardMongoClientSettingsBuilderCustomizer(connectionDetails.getConnectionString(),
81-
properties.getUuidRepresentation());
82+
properties.getUuidRepresentation(), properties.getSsl(), sslBundles.getIfAvailable());
8283
}
8384

8485
}

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/StandardMongoClientSettingsBuilderCustomizer.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
1818

1919
import com.mongodb.ConnectionString;
2020
import com.mongodb.MongoClientSettings;
21+
import com.mongodb.connection.SslSettings;
2122
import org.bson.UuidRepresentation;
2223

24+
import org.springframework.boot.ssl.SslBundle;
25+
import org.springframework.boot.ssl.SslBundles;
2326
import org.springframework.core.Ordered;
2427

2528
/**
@@ -37,18 +40,35 @@ public class StandardMongoClientSettingsBuilderCustomizer implements MongoClient
3740

3841
private final UuidRepresentation uuidRepresentation;
3942

43+
private final MongoProperties.Ssl ssl;
44+
45+
private final SslBundles sslBundles;
46+
4047
private int order = 0;
4148

4249
public StandardMongoClientSettingsBuilderCustomizer(ConnectionString connectionString,
43-
UuidRepresentation uuidRepresentation) {
50+
UuidRepresentation uuidRepresentation, MongoProperties.Ssl ssl, SslBundles sslBundles) {
4451
this.connectionString = connectionString;
4552
this.uuidRepresentation = uuidRepresentation;
53+
this.ssl = ssl;
54+
this.sslBundles = sslBundles;
4655
}
4756

4857
@Override
4958
public void customize(MongoClientSettings.Builder settingsBuilder) {
5059
settingsBuilder.uuidRepresentation(this.uuidRepresentation);
5160
settingsBuilder.applyConnectionString(this.connectionString);
61+
if (this.ssl.isEnabled()) {
62+
settingsBuilder.applyToSslSettings(this::configureSsl);
63+
}
64+
}
65+
66+
private void configureSsl(SslSettings.Builder settings) {
67+
settings.enabled(true);
68+
if (this.ssl.getBundle() != null) {
69+
SslBundle sslBundle = this.sslBundles.getBundle(this.ssl.getBundle());
70+
settings.context(sslBundle.createSslContext());
71+
}
5272
}
5373

5474
@Override

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
import com.mongodb.client.MongoClient;
2424
import com.mongodb.client.MongoClients;
2525
import com.mongodb.client.internal.MongoClientImpl;
26+
import com.mongodb.connection.SslSettings;
2627
import org.junit.jupiter.api.Test;
2728

2829
import org.springframework.boot.autoconfigure.AutoConfigurations;
30+
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
2931
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
3032
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
3133
import org.springframework.context.annotation.Bean;
@@ -43,7 +45,7 @@
4345
class MongoAutoConfigurationTests {
4446

4547
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
46-
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class));
48+
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, SslAutoConfiguration.class));
4749

4850
@Test
4951
void clientExists() {
@@ -72,6 +74,39 @@ void settingsSslConfig() {
7274
.run((context) -> assertThat(getSettings(context).getSslSettings().isEnabled()).isTrue());
7375
}
7476

77+
@Test
78+
void configuresSslWhenEnabled() {
79+
this.contextRunner.withPropertyValues("spring.data.mongodb.ssl.enabled=true").run((context) -> {
80+
SslSettings sslSettings = getSettings(context).getSslSettings();
81+
assertThat(sslSettings.isEnabled()).isTrue();
82+
assertThat(sslSettings.getContext()).isNull();
83+
});
84+
}
85+
86+
@Test
87+
void configuresSslWithBundle() {
88+
this.contextRunner
89+
.withPropertyValues("spring.data.mongodb.ssl.bundle=test-bundle",
90+
"spring.ssl.bundle.jks.test-bundle.keystore.location=classpath:test.jks",
91+
"spring.ssl.bundle.jks.test-bundle.keystore.password=secret",
92+
"spring.ssl.bundle.jks.test-bundle.key.password=password")
93+
.run((context) -> {
94+
SslSettings sslSettings = getSettings(context).getSslSettings();
95+
assertThat(sslSettings.isEnabled()).isTrue();
96+
assertThat(sslSettings.getContext()).isNotNull();
97+
});
98+
}
99+
100+
@Test
101+
void configuresWithoutSslWhenDisabledWithBundle() {
102+
this.contextRunner
103+
.withPropertyValues("spring.data.mongodb.ssl.enabled=false", "spring.data.mongodb.ssl.bundle=test-bundle")
104+
.run((context) -> {
105+
SslSettings sslSettings = getSettings(context).getSslSettings();
106+
assertThat(sslSettings.isEnabled()).isFalse();
107+
});
108+
}
109+
75110
@Test
76111
void configuresSingleClient() {
77112
this.contextRunner.withUserConfiguration(FallbackMongoClientConfig.class)

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoReactiveAutoConfigurationTests.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.mongodb.MongoClientSettings;
2424
import com.mongodb.ReadPreference;
2525
import com.mongodb.connection.AsynchronousSocketChannelStreamFactoryFactory;
26+
import com.mongodb.connection.SslSettings;
2627
import com.mongodb.connection.StreamFactory;
2728
import com.mongodb.connection.StreamFactoryFactory;
2829
import com.mongodb.connection.netty.NettyStreamFactoryFactory;
@@ -32,6 +33,7 @@
3233
import org.junit.jupiter.api.Test;
3334

3435
import org.springframework.boot.autoconfigure.AutoConfigurations;
36+
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
3537
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
3638
import org.springframework.context.ApplicationContext;
3739
import org.springframework.context.annotation.Bean;
@@ -52,7 +54,7 @@
5254
class MongoReactiveAutoConfigurationTests {
5355

5456
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
55-
.withConfiguration(AutoConfigurations.of(MongoReactiveAutoConfiguration.class));
57+
.withConfiguration(AutoConfigurations.of(MongoReactiveAutoConfiguration.class, SslAutoConfiguration.class));
5658

5759
@Test
5860
void clientExists() {
@@ -86,6 +88,39 @@ void settingsSslConfig() {
8688
});
8789
}
8890

91+
@Test
92+
void configuresSslWhenEnabled() {
93+
this.contextRunner.withPropertyValues("spring.data.mongodb.ssl.enabled=true").run((context) -> {
94+
SslSettings sslSettings = getSettings(context).getSslSettings();
95+
assertThat(sslSettings.isEnabled()).isTrue();
96+
assertThat(sslSettings.getContext()).isNull();
97+
});
98+
}
99+
100+
@Test
101+
void configuresSslWithBundle() {
102+
this.contextRunner
103+
.withPropertyValues("spring.data.mongodb.ssl.bundle=test-bundle",
104+
"spring.ssl.bundle.jks.test-bundle.keystore.location=classpath:test.jks",
105+
"spring.ssl.bundle.jks.test-bundle.keystore.password=secret",
106+
"spring.ssl.bundle.jks.test-bundle.key.password=password")
107+
.run((context) -> {
108+
SslSettings sslSettings = getSettings(context).getSslSettings();
109+
assertThat(sslSettings.isEnabled()).isTrue();
110+
assertThat(sslSettings.getContext()).isNotNull();
111+
});
112+
}
113+
114+
@Test
115+
void configuresWithoutSslWhenDisabledWithBundle() {
116+
this.contextRunner
117+
.withPropertyValues("spring.data.mongodb.ssl.enabled=false", "spring.data.mongodb.ssl.bundle=test-bundle")
118+
.run((context) -> {
119+
SslSettings sslSettings = getSettings(context).getSslSettings();
120+
assertThat(sslSettings.isEnabled()).isFalse();
121+
});
122+
}
123+
89124
@Test
90125
void nettyStreamFactoryFactoryIsConfiguredAutomatically() {
91126
AtomicReference<EventLoopGroup> eventLoopGroupReference = new AtomicReference<>();

spring-boot-project/spring-boot-docs/src/docs/asciidoc/data/nosql.adoc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,31 @@ For example, you might declare the following settings in your `application.prope
114114
password: "secret"
115115
----
116116

117+
The auto-configured `MongoClient` can be configured to use SSL for communication with the server by setting the properties as shown in this example:
118+
119+
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
120+
----
121+
spring:
122+
data:
123+
mongodb:
124+
uri: "mongodb://user:[email protected]:27017,mongoserver2.example.com:23456/test"
125+
ssl:
126+
enabled: true
127+
----
128+
129+
Custom SSL trust material can be configured in an <<features#features.ssl,SSL bundle>> and applied to the `MongoClient` as shown in this example:
130+
131+
[source,yaml,indent=0,subs="verbatim",configprops,configblocks]
132+
----
133+
spring:
134+
data:
135+
mongodb:
136+
uri: "mongodb://user:[email protected]:27017,mongoserver2.example.com:23456/test"
137+
ssl:
138+
bundle: "example"
139+
----
140+
141+
117142
[TIP]
118143
====
119144
If `spring.data.mongodb.port` is not specified, the default of `27017` is used.

0 commit comments

Comments
 (0)