From c99dc6225983a31a9890bd8188649575e182f642 Mon Sep 17 00:00:00 2001
From: Scott Leberknight <174812+sleberknight@users.noreply.github.com>
Date: Fri, 24 Nov 2023 20:32:34 -0500
Subject: [PATCH] Add disableSniHostCheck property to TLS and SSL configuration
classes
* Add disableSniHostCheck to TlsContextConfiguration,
SSLContextConfiguration, and SimpleSSLContextFactory
* Update SSLContextConfiguration#toSimpleSSLContextFactory factory
method to provide disableSniHostCheck to SimpleSSLContextFactory
* Update SSLContextConfiguration#toTlsContextConfiguration factory
method to provide disableSniHostCheck to TlsContextConfiguration
* Update javadoc of the conversion functions in TlsContextConfiguration
to explain how disableSniHostCheck is handled (since it does
not exist in Dropwizard TlsConfiguration)
* Update TlsContextConfiguration#toSslContextConfiguration to
provide disableSniHostCheck to SSLContextConfiguration
* Add new all-args constructor to SimpleSSLContextFactory
* Clean up duplicative code in SimpleSSLContextFactory by extracting
several private helper methods
* Change SimpleSSLContextFactory#configuration method to be
public, and to return unmodifiable map.
* Change tests with lots of assertions to use assertAll
* Minor grammatical fixes in javadocs and comments
Closes #1080
Closes #1085
---
.../config/SSLContextConfiguration.java | 27 +-
.../config/TlsContextConfiguration.java | 28 ++-
.../security/SimpleSSLContextFactory.java | 140 ++++++++---
.../config/SSLContextConfigurationTest.java | 42 +++-
.../config/TlsContextConfigurationTest.java | 231 ++++++++++--------
.../security/SimpleSSLContextFactoryTest.java | 61 ++++-
.../full-tls-config.yml | 1 +
7 files changed, 370 insertions(+), 160 deletions(-)
diff --git a/src/main/java/org/kiwiproject/config/SSLContextConfiguration.java b/src/main/java/org/kiwiproject/config/SSLContextConfiguration.java
index 9afdc524..4ccc0439 100644
--- a/src/main/java/org/kiwiproject/config/SSLContextConfiguration.java
+++ b/src/main/java/org/kiwiproject/config/SSLContextConfiguration.java
@@ -25,6 +25,7 @@ public class SSLContextConfiguration implements KeyAndTrustStoreConfigProvider {
private String keyStoreType = KeyStoreType.JKS.value;
private String trustStoreType = KeyStoreType.JKS.value;
private boolean verifyHostname = true;
+ private boolean disableSniHostCheck;
/**
* A builder class for {@link SSLContextConfiguration}.
@@ -110,6 +111,20 @@ public Builder setVerifyHostname(boolean verifyHostname) {
return this;
}
+ /**
+ * Whether the SNI (Server Name Indication) host check is disabled. Default is {@code false}
+ *
+ * @see What is SNI? How TLS server name indication works
+ */
+ public Builder disableSniHostCheck(boolean disableSniHostCheck) {
+ return setDisableSniHostCheck(disableSniHostCheck);
+ }
+
+ public Builder setDisableSniHostCheck(boolean disableSniHostCheck) {
+ configuration.setDisableSniHostCheck(disableSniHostCheck);
+ return this;
+ }
+
public SSLContextConfiguration build() {
return configuration;
}
@@ -145,8 +160,15 @@ public SSLContext toSSLContext() {
* @return a new instance
*/
public SimpleSSLContextFactory toSimpleSSLContextFactory() {
- return new SimpleSSLContextFactory(
- keyStorePath, keyStorePassword, keyStoreType, trustStorePath, trustStorePassword, trustStoreType, protocol, verifyHostname);
+ return new SimpleSSLContextFactory(keyStorePath,
+ keyStorePassword,
+ keyStoreType,
+ trustStorePath,
+ trustStorePassword,
+ trustStoreType,
+ protocol,
+ verifyHostname,
+ disableSniHostCheck);
}
/**
@@ -164,6 +186,7 @@ public TlsContextConfiguration toTlsContextConfiguration() {
.trustStoreType(trustStoreType)
.protocol(protocol)
.verifyHostname(verifyHostname)
+ .disableSniHostCheck(disableSniHostCheck)
.build();
}
diff --git a/src/main/java/org/kiwiproject/config/TlsContextConfiguration.java b/src/main/java/org/kiwiproject/config/TlsContextConfiguration.java
index 5a87a9c8..3c37dbc3 100644
--- a/src/main/java/org/kiwiproject/config/TlsContextConfiguration.java
+++ b/src/main/java/org/kiwiproject/config/TlsContextConfiguration.java
@@ -34,7 +34,7 @@
@Builder
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE) // for Builder (b/c also need no-args constructor)
-@ToString(exclude = {"keyStorePassword", "trustStorePassword"})
+@ToString(exclude = { "keyStorePassword", "trustStorePassword" })
public class TlsContextConfiguration implements KeyAndTrustStoreConfigProvider {
/**
@@ -47,7 +47,7 @@ public class TlsContextConfiguration implements KeyAndTrustStoreConfigProvider {
private String protocol = SSLContextProtocol.TLS_1_2.value;
/**
- * The name of the JCE (Java Cryptography Extension) provider to use on client side for cryptographic
+ * The name of the JCE (Java Cryptography Extension) provider to use on the client side for cryptographic
* support (for example, SunJCE, Conscrypt, BC, etc.).
*
* For more details, see the "Java Cryptography Architecture (JCA) Reference Guide" section of the Java
@@ -75,7 +75,7 @@ public class TlsContextConfiguration implements KeyAndTrustStoreConfigProvider {
private String keyStoreType = KeyStoreType.JKS.value;
/**
- * The name of the provider for the key store, i.e. the value of {@code provider} to use when getting the
+ * The name of the provider for the key store, i.e., the value of {@code provider} to use when getting the
* {@link java.security.KeyStore} instance for the key store.
*
* For more details, see the "Java Cryptography Architecture (JCA) Reference Guide" section of the Java
@@ -107,7 +107,7 @@ public class TlsContextConfiguration implements KeyAndTrustStoreConfigProvider {
private String trustStoreType = KeyStoreType.JKS.value;
/**
- * The name of the provider for the trust store, i.e. the value of {@code provider} to use when getting the
+ * The name of the provider for the trust store, i.e., the value of {@code provider} to use when getting the
* {@link java.security.KeyStore} instance for the trust store.
*
* For more details, see the "Java Cryptography Architecture (JCA) Reference Guide" section of the Java
@@ -128,6 +128,13 @@ public class TlsContextConfiguration implements KeyAndTrustStoreConfigProvider {
@Builder.Default
private boolean verifyHostname = true;
+ /**
+ * Whether the SNI (Server Name Indication) host check is disabled. Default is {@code false}
+ *
+ * @see What is SNI? How TLS server name indication works
+ */
+ private boolean disableSniHostCheck;
+
/**
* List of supported protocols. It can be {@code null}. See the implementation note for why.
*
@@ -139,7 +146,7 @@ public class TlsContextConfiguration implements KeyAndTrustStoreConfigProvider {
* {@link org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory#createLayeredSocket(Socket, String, int, org.apache.hc.core5.http.protocol.HttpContext)}.
* You will need to look at the source code, as the JavaDoc doesn't mention this tidbit, nor do the constructors
* since they don't have any documentation regarding their arguments. If you don't like reading source code of the
- * open source tools you rely on, then please close this file, log out, and change careers.
+ * open-source tools you rely on, then please close this file, log out, and change careers.
*/
private List supportedProtocols;
@@ -162,8 +169,12 @@ public class TlsContextConfiguration implements KeyAndTrustStoreConfigProvider {
* Given a Dropwizard {@link TlsConfiguration}, create a new {@link TlsContextConfiguration}.
*
* Even though {@link TlsContextConfiguration} does not permit null trust store properties (per the validation
- * annotations), the {@link TlsConfiguration} does. If we encounter this sitation, we will be lenient; even though
+ * annotations), the {@link TlsConfiguration} does. If we encounter this situation, we will be lenient; even though
* this could possibly cause downstream problems, we will just assume the caller knows what it is doing.
+ *
+ * The Dropwizard {@link TlsConfiguration} class does not contain a {@code disableSniHostCheck} property, so
+ * it cannot transfer and is therefore ignored during conversions. Also note that it is set to {@code false}
+ * in the returned {@link TlsContextConfiguration} since that is the more secure option.
*
* @param tlsConfig the Dropwizard TlsConfiguration from which to pull information
* @return a new TlsContextConfiguration instance
@@ -185,6 +196,7 @@ public static TlsContextConfiguration fromDropwizardTlsConfiguration(TlsConfigur
.trustStoreProvider(tlsConfig.getTrustStoreProvider())
.trustSelfSignedCertificates(tlsConfig.isTrustSelfSignedCertificates())
.verifyHostname(tlsConfig.isVerifyHostname())
+ .disableSniHostCheck(false)
.supportedProtocols(tlsConfig.getSupportedProtocols())
.supportedCiphers(tlsConfig.getSupportedCiphers())
.certAlias(tlsConfig.getCertAlias())
@@ -198,6 +210,9 @@ private static String absolutePathOrNull(@Nullable File nullableFile) {
/**
* Convert this {@link TlsContextConfiguration} into a Dropwizard {@link TlsConfiguration} object. Assumes that
* this object is valid.
+ *
+ * The Dropwizard {@link TlsConfiguration} class does not contain a {@code disableSniHostCheck} property, so
+ * it cannot transfer and is therefore ignored during conversions.
*
* @return a new Dropwizard TlsConfiguration instance
* @implNote Requires dropwizard-client as a dependency
@@ -248,6 +263,7 @@ public SSLContextConfiguration toSslContextConfiguration() {
.trustStoreType(trustStoreType)
.protocol(protocol)
.verifyHostname(verifyHostname)
+ .disableSniHostCheck(disableSniHostCheck)
.build();
}
}
diff --git a/src/main/java/org/kiwiproject/security/SimpleSSLContextFactory.java b/src/main/java/org/kiwiproject/security/SimpleSSLContextFactory.java
index 0cf21de6..3906b9ef 100644
--- a/src/main/java/org/kiwiproject/security/SimpleSSLContextFactory.java
+++ b/src/main/java/org/kiwiproject/security/SimpleSSLContextFactory.java
@@ -3,12 +3,12 @@
import static java.util.Objects.isNull;
import static org.kiwiproject.base.KiwiStrings.f;
-import com.google.common.annotations.VisibleForTesting;
import lombok.Getter;
import lombok.Synchronized;
import org.kiwiproject.collect.KiwiMaps;
import javax.net.ssl.SSLContext;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -17,6 +17,8 @@
* A "simple" factory class that makes it simpler to create {@link SSLContext} instances.
*
* Construct using one of the public constructors or via the {@link #builder()}.
+ * Prefer using the builder, as the constructors may be deprecated
+ * (most likely for removal) in the future.
*
* This abstracts the much lower level {@link KiwiSecurity} class.
*
@@ -32,6 +34,7 @@ public class SimpleSSLContextFactory {
private static final String TRUST_STORE_TYPE_PROPERTY = "trustStoreType";
private static final String PROTOCOL_PROPERTY = "protocol";
private static final String VERIFY_HOSTNAME_PROPERTY = "verifyHostname";
+ private static final String DISABLE_SNI_HOST_CHECK_PROPERTY = "disableSniHostCheck";
private static final List REQUIRED_PROPERTIES = List.of(
TRUST_STORE_PATH_PROPERTY, TRUST_STORE_PASSWORD_PROPERTY, PROTOCOL_PROPERTY
@@ -55,6 +58,14 @@ public class SimpleSSLContextFactory {
@Getter
private final boolean verifyHostname;
+ /**
+ * This is not strictly needed when creating {@link SSLContext}s. It is here only in case this factory
+ * will be supplied to other code that makes HTTPS connections and needs to create {@link SSLContext}
+ * instances AND also needs to know whether it should perform SNI host checking.
+ */
+ @Getter
+ private boolean disableSniHostCheck;
+
/**
* Create a new {@link SimpleSSLContextFactory} with {@code verifyHostname} set to {@code true} and "JKS" as
* the key and trust store type.
@@ -89,7 +100,14 @@ public SimpleSSLContextFactory(String keyStorePath,
String trustStorePassword,
String protocol,
boolean verifyHostname) {
- this(keyStorePath, keyStorePassword, KeyStoreType.JKS.value, trustStorePath, trustStorePassword, KeyStoreType.JKS.value, protocol, verifyHostname);
+ this(keyStorePath,
+ keyStorePassword,
+ KeyStoreType.JKS.value,
+ trustStorePath,
+ trustStorePassword,
+ KeyStoreType.JKS.value,
+ protocol,
+ verifyHostname);
}
/**
@@ -123,6 +141,40 @@ public SimpleSSLContextFactory(String keyStorePath,
this.verifyHostname = verifyHostname;
}
+ /**
+ * Create a new {@link SimpleSSLContextFactory}.
+ *
+ * @param keyStorePath path to the key store
+ * @param keyStorePassword password of the key store
+ * @param keyStoreType the keystore type
+ * @param trustStorePath path to the trust store
+ * @param trustStorePassword password of the trust store
+ * @param trustStoreType the trust store type
+ * @param protocol the protocol to use
+ * @param verifyHostname whether to verify host names or not
+ * @param disableSniHostCheck whether to disable SNI host checking
+ */
+ @SuppressWarnings("java:S107")
+ public SimpleSSLContextFactory(String keyStorePath,
+ String keyStorePassword,
+ String keyStoreType,
+ String trustStorePath,
+ String trustStorePassword,
+ String trustStoreType,
+ String protocol,
+ boolean verifyHostname,
+ boolean disableSniHostCheck) {
+ this.keyStorePath = keyStorePath;
+ this.keyStorePassword = keyStorePassword;
+ this.keyStoreType = keyStoreType;
+ this.trustStorePath = trustStorePath;
+ this.trustStorePassword = trustStorePassword;
+ this.trustStoreType = trustStoreType;
+ this.protocol = protocol;
+ this.verifyHostname = verifyHostname;
+ this.disableSniHostCheck = disableSniHostCheck;
+ }
+
/**
* A builder class for {@link SimpleSSLContextFactory}.
*
@@ -145,7 +197,8 @@ protected Builder() {
TRUST_STORE_PASSWORD_PROPERTY, Optional.empty(),
TRUST_STORE_TYPE_PROPERTY, Optional.of(KeyStoreType.JKS.value),
PROTOCOL_PROPERTY, Optional.empty(),
- VERIFY_HOSTNAME_PROPERTY, Optional.of("true")
+ VERIFY_HOSTNAME_PROPERTY, Optional.of("true"),
+ DISABLE_SNI_HOST_CHECK_PROPERTY, Optional.of("false")
);
}
@@ -217,22 +270,36 @@ public Builder verifyHostname(boolean verifyHostname) {
}
public Builder setVerifyHostname(boolean verifyHostname) {
- entries.put(VERIFY_HOSTNAME_PROPERTY, Optional.of(String.valueOf(verifyHostname)));
+ entries.put(VERIFY_HOSTNAME_PROPERTY, optionalStringOf(verifyHostname));
+ return this;
+ }
+
+ public Builder disableSniHostCheck(boolean disableSniHostCheck) {
+ return setDisableSniHostCheck(disableSniHostCheck);
+ }
+
+ public Builder setDisableSniHostCheck(boolean disableSniHostCheck) {
+ entries.put(DISABLE_SNI_HOST_CHECK_PROPERTY, optionalStringOf(disableSniHostCheck));
return this;
}
+ private static Optional optionalStringOf(boolean value) {
+ return Optional.of(String.valueOf(value));
+ }
+
public SimpleSSLContextFactory build() {
validateBuilderState();
return new SimpleSSLContextFactory(
- entries.get(KEY_STORE_PATH_PROPERTY).orElse(null),
- entries.get(KEY_STORE_PASSWORD_PROPERTY).orElse(null),
- entries.get(KEY_STORE_TYPE_PROPERTY).orElseThrow(IllegalStateException::new),
- entries.get(TRUST_STORE_PATH_PROPERTY).orElseThrow(IllegalStateException::new),
- entries.get(TRUST_STORE_PASSWORD_PROPERTY).orElseThrow(IllegalStateException::new),
- entries.get(TRUST_STORE_TYPE_PROPERTY).orElseThrow(IllegalStateException::new),
- entries.get(PROTOCOL_PROPERTY).orElseThrow(IllegalStateException::new),
- Boolean.parseBoolean(entries.get(VERIFY_HOSTNAME_PROPERTY).orElseThrow(IllegalStateException::new))
+ stringOrNull(KEY_STORE_PATH_PROPERTY),
+ stringOrNull(KEY_STORE_PASSWORD_PROPERTY),
+ stringOrThrow(KEY_STORE_TYPE_PROPERTY),
+ stringOrThrow(TRUST_STORE_PATH_PROPERTY),
+ stringOrThrow(TRUST_STORE_PASSWORD_PROPERTY),
+ stringOrThrow(TRUST_STORE_TYPE_PROPERTY),
+ stringOrThrow(PROTOCOL_PROPERTY),
+ toBooleanOrThrow(VERIFY_HOSTNAME_PROPERTY),
+ toBooleanOrThrow(DISABLE_SNI_HOST_CHECK_PROPERTY)
);
}
@@ -244,6 +311,19 @@ public void validateBuilderState() {
.ifPresent(entry -> throwBuildException(entry.getKey()));
}
+ private String stringOrNull(String propertyName) {
+ return entries.get(propertyName).orElse(null);
+ }
+
+ private String stringOrThrow(String propertyName) {
+ return entries.get(propertyName).orElseThrow(IllegalStateException::new);
+ }
+
+ private boolean toBooleanOrThrow(String propertyName) {
+ var boolString = entries.get(propertyName).orElseThrow(IllegalStateException::new);
+ return Boolean.parseBoolean(boolString);
+ }
+
private static void throwBuildException(String property) {
throw new SSLContextException(
f("Required property '{}' not set; cannot build SimpleSSLContextFactory", property)
@@ -265,8 +345,8 @@ public static Builder builder() {
* {@link SimpleSSLContextFactory} instance was built with.
*
* @return a new {@link SSLContext} instance when first called; all subsequent calls return the same cached instance
- * @implNote This is intended to be called infrequently, e.g. once when a service/app starts. It is internally
- * synchronized to ensure thread-safety when creating the {@link SSLContext}.
+ * @implNote This is intended to be called infrequently, e.g., once when a service/app starts.
+ * It is internally synchronized to ensure thread-safety when creating the {@link SSLContext}.
*/
@Synchronized
public SSLContext getSslContext() {
@@ -279,23 +359,25 @@ public SSLContext getSslContext() {
/**
* Get the properties this factory was configured with, including passwords.
+ * Callers are responsible for securely handling the result, and not unnecessarily exposing it.
*
* @return a map containing the configuration of this factory
- * @apiNote Currently this is not publicly exposed, as it should not generally be needed except in tests.
- * @implNote Uses {@link KiwiMaps#newHashMap(Object...)} because some values may be {@code null}, e.g. the key
- * store path
+ * @apiNote This is publicly exposed, but should not generally be needed except in tests, and perhaps debugging.
+ * @implNote Uses {@link KiwiMaps#newHashMap(Object...)} because some values may be {@code null}, e.g., the key
+ * store path, and wraps that using {@link Collections#unmodifiableMap(Map)} to prevent modification of the
+ * returned map.
*/
- @VisibleForTesting
- Map configuration() {
- return KiwiMaps.newHashMap(
- KEY_STORE_PATH_PROPERTY, keyStorePath,
- KEY_STORE_PASSWORD_PROPERTY, keyStorePassword,
- KEY_STORE_TYPE_PROPERTY, keyStoreType,
- TRUST_STORE_PATH_PROPERTY, trustStorePath,
- TRUST_STORE_PASSWORD_PROPERTY, trustStorePassword,
- TRUST_STORE_TYPE_PROPERTY, trustStoreType,
- PROTOCOL_PROPERTY, protocol,
- VERIFY_HOSTNAME_PROPERTY, verifyHostname
- );
+ public Map configuration() {
+ return Collections.unmodifiableMap(KiwiMaps.newHashMap(
+ KEY_STORE_PATH_PROPERTY, keyStorePath,
+ KEY_STORE_PASSWORD_PROPERTY, keyStorePassword,
+ KEY_STORE_TYPE_PROPERTY, keyStoreType,
+ TRUST_STORE_PATH_PROPERTY, trustStorePath,
+ TRUST_STORE_PASSWORD_PROPERTY, trustStorePassword,
+ TRUST_STORE_TYPE_PROPERTY, trustStoreType,
+ PROTOCOL_PROPERTY, protocol,
+ VERIFY_HOSTNAME_PROPERTY, verifyHostname,
+ DISABLE_SNI_HOST_CHECK_PROPERTY, disableSniHostCheck
+ ));
}
}
diff --git a/src/test/java/org/kiwiproject/config/SSLContextConfigurationTest.java b/src/test/java/org/kiwiproject/config/SSLContextConfigurationTest.java
index 0440bb7d..bc160667 100644
--- a/src/test/java/org/kiwiproject/config/SSLContextConfigurationTest.java
+++ b/src/test/java/org/kiwiproject/config/SSLContextConfigurationTest.java
@@ -1,14 +1,18 @@
package org.kiwiproject.config;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
+import org.kiwiproject.beans.BeanConverter;
import org.kiwiproject.security.KeyStoreType;
import org.kiwiproject.security.SecureTestConstants;
+import java.util.Map;
+
@DisplayName("SSLContextConfiguration")
class SSLContextConfigurationTest {
@@ -66,15 +70,34 @@ void shouldConvertToTlsContextConfiguration() {
var tlsConfig = sslConfig.toTlsContextConfiguration();
- assertThat(tlsConfig.getKeyStorePath()).isEqualTo(sslConfig.getKeyStorePath());
- assertThat(tlsConfig.getKeyStorePassword()).isEqualTo(sslConfig.getKeyStorePassword());
- assertThat(tlsConfig.getKeyStoreType()).isEqualTo(sslConfig.getKeyStoreType());
- assertThat(tlsConfig.getTrustStorePath()).isEqualTo(sslConfig.getTrustStorePath());
- assertThat(tlsConfig.getTrustStorePassword()).isEqualTo(sslConfig.getTrustStorePassword());
- assertThat(tlsConfig.getTrustStoreType()).isEqualTo(sslConfig.getTrustStoreType());
- assertThat(tlsConfig.isVerifyHostname()).isEqualTo(sslConfig.isVerifyHostname());
- assertThat(tlsConfig.getProtocol()).isEqualTo(sslConfig.getProtocol());
- assertThat(tlsConfig.getSupportedProtocols()).isNull();
+ assertAll(
+ () -> assertThat(tlsConfig.getKeyStorePath()).isEqualTo(sslConfig.getKeyStorePath()),
+ () -> assertThat(tlsConfig.getKeyStorePassword()).isEqualTo(sslConfig.getKeyStorePassword()),
+ () -> assertThat(tlsConfig.getKeyStoreType()).isEqualTo(sslConfig.getKeyStoreType()),
+ () -> assertThat(tlsConfig.getTrustStorePath()).isEqualTo(sslConfig.getTrustStorePath()),
+ () -> assertThat(tlsConfig.getTrustStorePassword()).isEqualTo(sslConfig.getTrustStorePassword()),
+ () -> assertThat(tlsConfig.getTrustStoreType()).isEqualTo(sslConfig.getTrustStoreType()),
+ () -> assertThat(tlsConfig.isVerifyHostname()).isEqualTo(sslConfig.isVerifyHostname()),
+ () -> assertThat(tlsConfig.isDisableSniHostCheck()).isEqualTo(sslConfig.isDisableSniHostCheck()),
+ () -> assertThat(tlsConfig.getProtocol()).isEqualTo(sslConfig.getProtocol()),
+ () -> assertThat(tlsConfig.getSupportedProtocols()).isNull()
+ );
+ }
+
+ @Test
+ void shouldConvertToSimpleSSLContextFactory() {
+ var sslConfig = newSampleSslContextConfiguration();
+ var sslContextFactory = sslConfig.toSimpleSSLContextFactory();
+
+ // Since SimpleSSLContextFactory does not have getters for most properties, get its
+ // configuration as a Map, convert it to an SSLContextConfiguration, and verify that
+ // it is equal to the original sslConfig
+ var converter = new BeanConverter