Skip to content

Commit 7224f3f

Browse files
committed
support for custom TLS protocols such as TLSv1.2,TLSv1.3
1 parent 1e548a0 commit 7224f3f

File tree

6 files changed

+105
-6
lines changed

6 files changed

+105
-6
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## [Unreleased]
88

99
### Added
10+
- support for custom TLS protocols such as TLSv1.2,TLSv1.3
1011

1112
### Changed
1213
- removed implicit reliance on internal java-certificate-classes (thanks to @Arkinator)

mockserver-core/src/main/java/org/mockserver/configuration/Configuration.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public static Configuration configuration() {
123123
private Boolean proactivelyInitialiseTLS;
124124
private boolean rebuildTLSContext;
125125
private boolean rebuildServerTLSContext;
126+
private String tlsProtocols;
126127

127128
// inbound - dynamic CA
128129
private Boolean dynamicallyCreateCertificateAuthorityCertificate;
@@ -1481,6 +1482,23 @@ public Configuration rebuildServerTLSContext(boolean rebuildServerTLSContext) {
14811482
return this;
14821483
}
14831484

1485+
public String tlsProtocols() {
1486+
if (tlsProtocols == null) {
1487+
return ConfigurationProperties.tlsProtocols();
1488+
}
1489+
return tlsProtocols;
1490+
}
1491+
1492+
/**
1493+
* Comma seperated list of TLS protocols, by default TLSv1,TLSv1.1,TLSv1.2
1494+
*
1495+
* @param tlsProtocols comma seperated list of TLS protocols
1496+
*/
1497+
public Configuration tlsProtocols(String tlsProtocols) {
1498+
this.tlsProtocols = tlsProtocols;
1499+
return this;
1500+
}
1501+
14841502
public Boolean dynamicallyCreateCertificateAuthorityCertificate() {
14851503
if (dynamicallyCreateCertificateAuthorityCertificate == null) {
14861504
return ConfigurationProperties.dynamicallyCreateCertificateAuthorityCertificate();

mockserver-core/src/main/java/org/mockserver/configuration/ConfigurationProperties.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ public class ConfigurationProperties {
137137

138138
// TLS
139139
private static final String MOCKSERVER_PROACTIVELY_INITIALISE_TLS = "mockserver.proactivelyInitialiseTLS";
140+
private static final String MOCKSERVER_TLS_PROTOCOLS = "mockserver.tlsProtocols";
140141

141142
// inbound - dynamic CA
142143
private static final String MOCKSERVER_DYNAMICALLY_CREATE_CERTIFICATE_AUTHORITY_CERTIFICATE = "mockserver.dynamicallyCreateCertificateAuthorityCertificate";
@@ -1373,6 +1374,19 @@ public static boolean proactivelyInitialiseTLS() {
13731374
return Boolean.parseBoolean(readPropertyHierarchically(PROPERTIES, MOCKSERVER_PROACTIVELY_INITIALISE_TLS, "MOCKSERVER_PROACTIVELY_INITIALISE_TLS", "false"));
13741375
}
13751376

1377+
public static String tlsProtocols() {
1378+
return readPropertyHierarchically(PROPERTIES, MOCKSERVER_TLS_PROTOCOLS, "MOCKSERVER_TLS_PROTOCOLS", "TLSv1,TLSv1.1,TLSv1.2");
1379+
}
1380+
1381+
/**
1382+
* Comma seperated list of TLS protocols, by default TLSv1,TLSv1.1,TLSv1.2
1383+
*
1384+
* @param tlsProtocols comma seperated list of TLS protocols
1385+
*/
1386+
public static void tlsProtocols(String tlsProtocols) {
1387+
setProperty(MOCKSERVER_TLS_PROTOCOLS, tlsProtocols);
1388+
}
1389+
13761390
public static boolean dynamicallyCreateCertificateAuthorityCertificate() {
13771391
return Boolean.parseBoolean(readPropertyHierarchically(PROPERTIES, MOCKSERVER_DYNAMICALLY_CREATE_CERTIFICATE_AUTHORITY_CERTIFICATE, "MOCKSERVER_DYNAMICALLY_CREATE_CERTIFICATE_AUTHORITY_CERTIFICATE", "false"));
13781392
}

mockserver-core/src/main/java/org/mockserver/socket/tls/NettySslContextFactory.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.mockserver.socket.tls;
22

3-
import com.google.common.base.Joiner;
43
import io.netty.handler.codec.http2.Http2SecurityUtil;
54
import io.netty.handler.ssl.*;
65
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
@@ -34,7 +33,6 @@
3433
*/
3534
public class NettySslContextFactory {
3635

37-
private static final String[] TLS_PROTOCOLS = "TLSv1,TLSv1.1,TLSv1.2".split(",");
3836
public static Function<SslContextBuilder, SslContext> clientSslContextBuilderFunction =
3937
sslContextBuilder -> {
4038
try {
@@ -65,7 +63,7 @@ public NettySslContextFactory(MockServerLogger mockServerLogger) {
6563
this.mockServerLogger = mockServerLogger;
6664
this.forServer = true;
6765
keyAndCertificateFactory = createKeyAndCertificateFactory(configuration, mockServerLogger);
68-
System.setProperty("https.protocols", Joiner.on(",").join(TLS_PROTOCOLS));
66+
System.setProperty("https.protocols", configuration.tlsProtocols());
6967
nettySslContextFactoryCustomizer.accept(this);
7068
if (configuration.proactivelyInitialiseTLS()) {
7169
createServerSslContext();
@@ -77,7 +75,7 @@ public NettySslContextFactory(Configuration configuration, MockServerLogger mock
7775
this.mockServerLogger = mockServerLogger;
7876
this.forServer = forServer;
7977
keyAndCertificateFactory = createKeyAndCertificateFactory(configuration, mockServerLogger, forServer);
80-
System.setProperty("https.protocols", Joiner.on(",").join(TLS_PROTOCOLS));
78+
System.setProperty("https.protocols", configuration.tlsProtocols());
8179
nettySslContextFactoryCustomizer.accept(this);
8280
if (configuration.proactivelyInitialiseTLS()) {
8381
createServerSslContext();
@@ -101,7 +99,7 @@ public synchronized SslContext createClientSslContext(boolean forwardProxyClient
10199
SslContextBuilder sslContextBuilder =
102100
SslContextBuilder
103101
.forClient()
104-
.protocols(TLS_PROTOCOLS)
102+
.protocols(configuration.tlsProtocols().split(","))
105103
.keyManager(
106104
forwardProxyPrivateKey(),
107105
forwardProxyCertificateChain()
@@ -205,7 +203,7 @@ public synchronized SslContext createServerSslContext() {
205203
keyAndCertificateFactory.privateKey(),
206204
keyAndCertificateFactory.certificateChain()
207205
)
208-
.protocols(TLS_PROTOCOLS)
206+
.protocols(configuration.tlsProtocols().split(","))
209207
.clientAuth(configuration.tlsMutualAuthenticationRequired() ? ClientAuth.REQUIRE : ClientAuth.OPTIONAL);
210208
configureALPN(sslContextBuilder);
211209
if (isNotBlank(configuration.tlsMutualAuthenticationCertificateChain()) || configuration.tlsMutualAuthenticationRequired()) {

mockserver-core/src/test/java/org/mockserver/configuration/ConfigurationTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1735,6 +1735,32 @@ public void shouldSetAndGetRebuildServerTLSContext() {
17351735
assertThat(configuration.rebuildServerTLSContext(), equalTo(true));
17361736
}
17371737

1738+
@Test
1739+
public void shouldSetAndGetTlsProtocols() {
1740+
String original = ConfigurationProperties.tlsProtocols();
1741+
try {
1742+
// then - default value
1743+
assertThat(configuration.tlsProtocols(), equalTo("TLSv1,TLSv1.1,TLSv1.2"));
1744+
1745+
// when - system property setter
1746+
String firstPath = tempFilePath();
1747+
ConfigurationProperties.tlsProtocols(firstPath);
1748+
1749+
// then - system property getter
1750+
assertThat(ConfigurationProperties.tlsProtocols(), equalTo(firstPath));
1751+
assertThat(System.getProperty("mockserver.tlsProtocols"), equalTo(firstPath));
1752+
assertThat(configuration.tlsProtocols(), equalTo(firstPath));
1753+
1754+
// when - setter
1755+
configuration.tlsProtocols("TLSv1.2,TLSv1.3");
1756+
1757+
// then - getter
1758+
assertThat(configuration.tlsProtocols(), equalTo("TLSv1.2,TLSv1.3"));
1759+
} finally {
1760+
ConfigurationProperties.tlsProtocols(original);
1761+
}
1762+
}
1763+
17381764
@Test
17391765
public void shouldSetAndGetDynamicallyCreateCertificateAuthorityCertificate() {
17401766
boolean original = ConfigurationProperties.dynamicallyCreateCertificateAuthorityCertificate();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.mockserver.netty.integration.tls.inbound;
2+
3+
import org.junit.AfterClass;
4+
import org.junit.BeforeClass;
5+
import org.mockserver.integration.ClientAndServer;
6+
import org.mockserver.testing.integration.mock.AbstractBasicMockingSameJVMIntegrationTest;
7+
8+
import static org.mockserver.configuration.ConfigurationProperties.tlsProtocols;
9+
import static org.mockserver.stop.Stop.stopQuietly;
10+
11+
/**
12+
* @author jamesdbloom
13+
*/
14+
public class CustomTLSProtocolsMockingIntegrationTest extends AbstractBasicMockingSameJVMIntegrationTest {
15+
16+
private static String originalTlsProtocols;
17+
18+
@BeforeClass
19+
public static void startServer() {
20+
// save original value
21+
originalTlsProtocols = tlsProtocols();
22+
23+
// set new certificate authority values
24+
tlsProtocols("TLSv1.2,TLSv1.3");
25+
26+
mockServerClient = ClientAndServer.startClientAndServer().withSecure(true);
27+
}
28+
29+
@AfterClass
30+
public static void stopServer() {
31+
stopQuietly(mockServerClient);
32+
33+
// set back to original value
34+
tlsProtocols(originalTlsProtocols);
35+
}
36+
37+
@Override
38+
public int getServerPort() {
39+
return mockServerClient.getPort();
40+
}
41+
42+
}

0 commit comments

Comments
 (0)