Add ability to configure client TLS enabled protocol versions and cipher suites via Spring properties.
- Adding the ability to explicitly configure the enabled SSL protocol versions and cipher suites used by the Vault HTTP client via the following Spring properties: * vault.ssl.enabled-protocols * vault.ssl.enabled-cipher-suites - Properties should be a comma-separated list of String constants that correspond to those used by the enabled SSL provider. Closes gh-635 Original pull request: gh-640.
This commit is contained in:
@@ -105,6 +105,14 @@ public class ClientHttpConnectorFactory {
|
||||
sslContextBuilder.keyManager(createKeyManagerFactory(sslConfiguration.getKeyStoreConfiguration(),
|
||||
sslConfiguration.getKeyConfiguration()));
|
||||
}
|
||||
|
||||
if (sslConfiguration.getEnabledProtocols() != null) {
|
||||
sslContextBuilder.protocols(sslConfiguration.getEnabledProtocols());
|
||||
}
|
||||
|
||||
if (sslConfiguration.getEnabledCipherSuites() != null) {
|
||||
sslContextBuilder.ciphers(sslConfiguration.getEnabledCipherSuites());
|
||||
}
|
||||
}
|
||||
catch (GeneralSecurityException | IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -189,6 +197,16 @@ public class ClientHttpConnectorFactory {
|
||||
sslContextFactory.setKeyManagerPassword(new String(keyConfiguration.getKeyPassword()));
|
||||
}
|
||||
|
||||
if (sslConfiguration.getEnabledProtocols() != null) {
|
||||
sslContextFactory
|
||||
.setIncludeProtocols(sslConfiguration.getEnabledProtocols().toArray(new String[0]));
|
||||
}
|
||||
|
||||
if (sslConfiguration.getEnabledCipherSuites() != null) {
|
||||
sslContextFactory
|
||||
.setIncludeCipherSuites(sslConfiguration.getEnabledCipherSuites().toArray(new String[0]));
|
||||
}
|
||||
|
||||
return new org.eclipse.jetty.client.HttpClient(sslContextFactory);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,9 +43,6 @@ import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.SslProvider;
|
||||
import okhttp3.OkHttpClient.Builder;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
@@ -55,7 +52,6 @@ import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.client.LaxRedirectStrategy;
|
||||
import org.apache.http.impl.conn.DefaultSchemePortResolver;
|
||||
import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
|
||||
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.client.Netty4ClientHttpRequestFactory;
|
||||
@@ -69,9 +65,13 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.support.ClientOptions;
|
||||
import org.springframework.vault.support.PemObject;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.vault.support.SslConfiguration.KeyConfiguration;
|
||||
import org.springframework.vault.support.SslConfiguration.KeyStoreConfiguration;
|
||||
|
||||
import static org.springframework.vault.support.SslConfiguration.KeyConfiguration;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.SslProvider;
|
||||
import okhttp3.ConnectionSpec;
|
||||
import okhttp3.OkHttpClient.Builder;
|
||||
|
||||
/**
|
||||
* Factory for {@link ClientHttpRequestFactory} that supports Apache HTTP Components,
|
||||
@@ -298,7 +298,21 @@ public class ClientHttpRequestFactoryFactory {
|
||||
if (hasSslConfiguration(sslConfiguration)) {
|
||||
|
||||
SSLContext sslContext = getSSLContext(sslConfiguration, getTrustManagers(sslConfiguration));
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
|
||||
|
||||
String[] enabledProtocols = null;
|
||||
|
||||
if (sslConfiguration.getEnabledProtocols() != null) {
|
||||
enabledProtocols = sslConfiguration.getEnabledProtocols().toArray(new String[0]);
|
||||
}
|
||||
|
||||
String[] enabledCipherSuites = null;
|
||||
|
||||
if (sslConfiguration.getEnabledCipherSuites() != null) {
|
||||
enabledCipherSuites = sslConfiguration.getEnabledCipherSuites().toArray(new String[0]);
|
||||
}
|
||||
|
||||
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
|
||||
enabledProtocols, enabledCipherSuites, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
|
||||
httpClientBuilder.setSSLSocketFactory(sslSocketFactory);
|
||||
httpClientBuilder.setSSLContext(sslContext);
|
||||
}
|
||||
@@ -332,6 +346,8 @@ public class ClientHttpRequestFactoryFactory {
|
||||
|
||||
Builder builder = new Builder();
|
||||
|
||||
ConnectionSpec sslConnectionSpec = ConnectionSpec.MODERN_TLS;
|
||||
|
||||
if (hasSslConfiguration(sslConfiguration)) {
|
||||
|
||||
TrustManager[] trustManagers = getTrustManagers(sslConfiguration);
|
||||
@@ -344,9 +360,24 @@ public class ClientHttpRequestFactoryFactory {
|
||||
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
|
||||
SSLContext sslContext = getSSLContext(sslConfiguration, trustManagers);
|
||||
|
||||
ConnectionSpec.Builder sslConnectionSpecBuilder = new ConnectionSpec.Builder(sslConnectionSpec);
|
||||
|
||||
if (sslConfiguration.getEnabledProtocols() != null) {
|
||||
sslConnectionSpecBuilder.tlsVersions(sslConfiguration.getEnabledProtocols().toArray(new String[0]));
|
||||
}
|
||||
|
||||
if (sslConfiguration.getEnabledCipherSuites() != null) {
|
||||
sslConnectionSpecBuilder
|
||||
.cipherSuites(sslConfiguration.getEnabledCipherSuites().toArray(new String[0]));
|
||||
}
|
||||
|
||||
sslConnectionSpec = sslConnectionSpecBuilder.build();
|
||||
|
||||
builder.sslSocketFactory(sslContext.getSocketFactory(), trustManager);
|
||||
}
|
||||
|
||||
builder.connectionSpecs(Arrays.asList(sslConnectionSpec, ConnectionSpec.CLEARTEXT));
|
||||
|
||||
builder.connectTimeout(options.getConnectionTimeout().toMillis(), TimeUnit.MILLISECONDS)
|
||||
.readTimeout(options.getReadTimeout().toMillis(), TimeUnit.MILLISECONDS);
|
||||
|
||||
@@ -382,6 +413,14 @@ public class ClientHttpRequestFactoryFactory {
|
||||
sslConfiguration.getKeyConfiguration()));
|
||||
}
|
||||
|
||||
if (sslConfiguration.getEnabledProtocols() != null) {
|
||||
sslContextBuilder.protocols(sslConfiguration.getEnabledProtocols());
|
||||
}
|
||||
|
||||
if (sslConfiguration.getEnabledCipherSuites() != null) {
|
||||
sslContextBuilder.ciphers(sslConfiguration.getEnabledCipherSuites());
|
||||
}
|
||||
|
||||
requestFactory.setSslContext(sslContextBuilder.sslProvider(SslProvider.JDK).build());
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
package org.springframework.vault.config;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -231,7 +232,12 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration im
|
||||
KeyStoreConfiguration trustStoreConfiguration = getKeyStoreConfiguration("vault.ssl.trust-store",
|
||||
"vault.ssl.trust-store-password", "vault.ssl.trust-store-type");
|
||||
|
||||
return new SslConfiguration(keyStoreConfiguration, trustStoreConfiguration);
|
||||
List<String> enabledProtocols = getList("vault.ssl.enabled-protocols");
|
||||
|
||||
List<String> enabledCipherSuites = getList("vault.ssl.enabled-cipher-suites");
|
||||
|
||||
return new SslConfiguration(keyStoreConfiguration, trustStoreConfiguration, enabledProtocols,
|
||||
enabledCipherSuites);
|
||||
}
|
||||
|
||||
private KeyStoreConfiguration getKeyStoreConfiguration(String resourceProperty, String passwordProperty,
|
||||
@@ -421,6 +427,16 @@ public class EnvironmentVaultConfiguration extends AbstractVaultConfiguration im
|
||||
return new KubernetesAuthentication(builder.build(), restOperations());
|
||||
}
|
||||
|
||||
private List<String> getList(String key) {
|
||||
String val = getEnvironment().getProperty(key);
|
||||
|
||||
if (val == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Arrays.asList(val.split(","));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getProperty(String key) {
|
||||
return getEnvironment().getProperty(key);
|
||||
|
||||
@@ -18,7 +18,10 @@ package org.springframework.vault.support;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.io.AbstractResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -60,6 +63,10 @@ public class SslConfiguration {
|
||||
|
||||
private final KeyConfiguration keyConfiguration;
|
||||
|
||||
private final List<String> enabledProtocols;
|
||||
|
||||
private final List<String> enabledCipherSuites;
|
||||
|
||||
/**
|
||||
* Create a new {@link SslConfiguration} with the default {@link KeyStore} type.
|
||||
* @param keyStore the key store resource, must not be {@literal null}.
|
||||
@@ -96,14 +103,23 @@ public class SslConfiguration {
|
||||
* Create a new {@link SslConfiguration}.
|
||||
* @param keyStoreConfiguration the key store configuration, must not be
|
||||
* {@literal null}.
|
||||
* @param keyConfiguration the configuration for a specific key in
|
||||
* {@code keyStoreConfiguration} to use.
|
||||
* @param trustStoreConfiguration the trust store configuration, must not be
|
||||
* {@literal null}.
|
||||
* @since 2.2
|
||||
* @param enabledProtocols the enabled SSL protocols, elements must match protocol
|
||||
* version strings used by the enabled Java SSL provider. May be {@literal null} to
|
||||
* indicate the SSL socket factory should use a default list of enabled protocol
|
||||
* versions.
|
||||
* @param enabledCipherSuites the enabled SSL cipher suites, elements must match
|
||||
* cipher suite strings used by the enabled Java SSL provider. May be {@literal null}
|
||||
* to indicate the SSL socket factory should use a default list of enabled cipher
|
||||
* suites.
|
||||
* @since 2.4
|
||||
* @see sun.security.ssl.ProtocolVersion
|
||||
* @see sun.security.ssl.CipherSuite
|
||||
*/
|
||||
public SslConfiguration(KeyStoreConfiguration keyStoreConfiguration, KeyConfiguration keyConfiguration,
|
||||
KeyStoreConfiguration trustStoreConfiguration) {
|
||||
KeyStoreConfiguration trustStoreConfiguration, List<String> enabledProtocols,
|
||||
List<String> enabledCipherSuites) {
|
||||
|
||||
Assert.notNull(keyStoreConfiguration, "KeyStore configuration must not be null");
|
||||
Assert.notNull(keyConfiguration, "KeyConfiguration must not be null");
|
||||
@@ -112,6 +128,50 @@ public class SslConfiguration {
|
||||
this.keyStoreConfiguration = keyStoreConfiguration;
|
||||
this.keyConfiguration = keyConfiguration;
|
||||
this.trustStoreConfiguration = trustStoreConfiguration;
|
||||
this.enabledProtocols = enabledProtocols != null
|
||||
? Collections.unmodifiableList(new ArrayList<>(enabledProtocols)) : null;
|
||||
this.enabledCipherSuites = enabledCipherSuites != null
|
||||
? Collections.unmodifiableList(new ArrayList<>(enabledCipherSuites)) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link SslConfiguration}.
|
||||
* @param keyStoreConfiguration the key store configuration, must not be
|
||||
* {@literal null}.
|
||||
* @param keyConfiguration the configuration for a specific key in
|
||||
* {@code keyStoreConfiguration} to use.
|
||||
* @param trustStoreConfiguration the trust store configuration, must not be
|
||||
* {@literal null}.
|
||||
* @since 2.2
|
||||
*/
|
||||
public SslConfiguration(KeyStoreConfiguration keyStoreConfiguration, KeyConfiguration keyConfiguration,
|
||||
KeyStoreConfiguration trustStoreConfiguration) {
|
||||
this(keyStoreConfiguration, keyConfiguration, trustStoreConfiguration, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link SslConfiguration}.
|
||||
* @param keyStoreConfiguration the key store configuration, must not be
|
||||
* {@literal null}.
|
||||
* @param trustStoreConfiguration the trust store configuration, must not be
|
||||
* {@literal null}.
|
||||
* @param enabledProtocols the enabled SSL protocols, elements must match protocol
|
||||
* version strings used by the enabled Java SSL provider. May be {@literal null} to
|
||||
* indicate the SSL socket factory should use a default list of enabled protocol
|
||||
* versions.
|
||||
* @param enabledCipherSuites the enabled SSL cipher suites, elements must match
|
||||
* cipher suite strings used by the enabled Java SSL provider. May be {@literal null}
|
||||
* to indicate the SSL socket factory should use a default list of enabled cipher
|
||||
* suites.
|
||||
* @since 2.4
|
||||
* @see sun.security.ssl.ProtocolVersion
|
||||
* @see sun.security.ssl.CipherSuite
|
||||
*/
|
||||
public SslConfiguration(KeyStoreConfiguration keyStoreConfiguration, KeyStoreConfiguration trustStoreConfiguration,
|
||||
List<String> enabledProtocols, List<String> enabledCipherSuites) {
|
||||
|
||||
this(keyStoreConfiguration, KeyConfiguration.unconfigured(), trustStoreConfiguration, enabledProtocols,
|
||||
enabledCipherSuites);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,6 +359,54 @@ public class SslConfiguration {
|
||||
return new SslConfiguration(KeyStoreConfiguration.unconfigured(), KeyStoreConfiguration.unconfigured());
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of SSL protocol versions that must be enabled. A value of {@literal null}
|
||||
* indicates that the SSL socket factory should use a default list of enabled protocol
|
||||
* versions.
|
||||
* @return the list of enabled SSL protocol versions.
|
||||
* @since 2.4
|
||||
*/
|
||||
public List<String> getEnabledProtocols() {
|
||||
return this.enabledProtocols;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link SslConfiguration} with the enabled protocol versions applied
|
||||
* retaining the other configuration from this instance.
|
||||
* @param enabledProtocols may be {@literal null}.
|
||||
* @return a new {@link SslConfiguration} with the enabled protocol versions applied.
|
||||
* @since 2.4
|
||||
* @see sun.security.ssl.ProtocolVersion
|
||||
*/
|
||||
public SslConfiguration withEnabledProtocols(List<String> enabledProtocols) {
|
||||
return new SslConfiguration(this.keyStoreConfiguration, this.keyConfiguration, this.trustStoreConfiguration,
|
||||
enabledProtocols, this.enabledCipherSuites);
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of SSL cipher suites that must be enabled. A value of {@literal null}
|
||||
* indicates that the SSL socket factory should use a default list of enabled cipher
|
||||
* suites.
|
||||
* @return the list of enabled SSL cipher suites.
|
||||
* @since 2.4
|
||||
*/
|
||||
public List<String> getEnabledCipherSuites() {
|
||||
return this.enabledCipherSuites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link SslConfiguration} with the enabled cipher suites applied
|
||||
* retaining the other configuration from this instance.
|
||||
* @param enabledCipherSuites may be {@literal null}.
|
||||
* @return a new {@link SslConfiguration} with the enabled cipher suites applied.
|
||||
* @since 2.4
|
||||
* @see sun.security.ssl.CipherSuite
|
||||
*/
|
||||
public SslConfiguration withEnabledCipherSuites(List<String> enabledCipherSuites) {
|
||||
return new SslConfiguration(this.keyStoreConfiguration, this.keyConfiguration, this.trustStoreConfiguration,
|
||||
this.enabledProtocols, enabledCipherSuites);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link java.security.KeyStore key store} resource or {@literal null} if
|
||||
* not configured.
|
||||
|
||||
@@ -27,6 +27,9 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
import static org.springframework.vault.client.ClientHttpConnectorFactory.JettyClient;
|
||||
import static org.springframework.vault.client.ClientHttpConnectorFactory.ReactorNetty;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ClientHttpConnectorFactory}.
|
||||
*
|
||||
@@ -49,6 +52,39 @@ class ClientHttpConnectorFactoryIntegrationTests {
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
}
|
||||
|
||||
@Test
|
||||
void reactorNettyClientWithExplicitEnabledCipherSuitesShouldWork() {
|
||||
|
||||
List<String> enabledCipherSuites = new ArrayList<String>();
|
||||
enabledCipherSuites.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
|
||||
enabledCipherSuites.add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||
|
||||
ClientHttpConnector factory = ReactorNetty.usingReactorNetty(new ClientOptions(),
|
||||
Settings.createSslConfiguration().withEnabledCipherSuites(enabledCipherSuites));
|
||||
|
||||
WebClient webClient = WebClient.builder().clientConnector(factory).build();
|
||||
|
||||
String response = request(webClient);
|
||||
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
}
|
||||
|
||||
@Test
|
||||
void reactorNettyClientWithExplicitEnabledProtocolsShouldWork() {
|
||||
|
||||
List<String> enabledProtocols = new ArrayList<String>();
|
||||
enabledProtocols.add("TLSv1.2");
|
||||
|
||||
ClientHttpConnector factory = ReactorNetty.usingReactorNetty(new ClientOptions(),
|
||||
Settings.createSslConfiguration().withEnabledProtocols(enabledProtocols));
|
||||
|
||||
WebClient webClient = WebClient.builder().clientConnector(factory).build();
|
||||
|
||||
String response = request(webClient);
|
||||
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
}
|
||||
|
||||
@Test
|
||||
void jettyClientShouldWork() {
|
||||
|
||||
@@ -61,6 +97,39 @@ class ClientHttpConnectorFactoryIntegrationTests {
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
}
|
||||
|
||||
@Test
|
||||
void jettyClientWithExplicitEnabledCipherSuitesShouldWork() {
|
||||
|
||||
List<String> enabledCipherSuites = new ArrayList<String>();
|
||||
enabledCipherSuites.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
|
||||
enabledCipherSuites.add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||
|
||||
ClientHttpConnector factory = JettyClient.usingJetty(new ClientOptions(),
|
||||
Settings.createSslConfiguration().withEnabledCipherSuites(enabledCipherSuites));
|
||||
|
||||
WebClient webClient = WebClient.builder().clientConnector(factory).build();
|
||||
|
||||
String response = request(webClient);
|
||||
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
}
|
||||
|
||||
@Test
|
||||
void jettyClientWithExplicitEnabledProtocolsShouldWork() {
|
||||
|
||||
List<String> enabledProtocols = new ArrayList<String>();
|
||||
enabledProtocols.add("TLSv1.2");
|
||||
|
||||
ClientHttpConnector factory = JettyClient.usingJetty(new ClientOptions(),
|
||||
Settings.createSslConfiguration().withEnabledProtocols(enabledProtocols));
|
||||
|
||||
WebClient webClient = WebClient.builder().clientConnector(factory).build();
|
||||
|
||||
String response = request(webClient);
|
||||
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
}
|
||||
|
||||
private String request(WebClient webClient) {
|
||||
|
||||
// Uninitialized and sealed can cause status 500
|
||||
|
||||
@@ -15,10 +15,13 @@
|
||||
*/
|
||||
package org.springframework.vault.client;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
@@ -27,17 +30,17 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.http.client.Netty4ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.vault.client.ClientHttpRequestFactoryFactory.HttpComponents;
|
||||
import org.springframework.vault.client.ClientHttpRequestFactoryFactory.Netty;
|
||||
import org.springframework.vault.client.ClientHttpRequestFactoryFactory.OkHttp3;
|
||||
import org.springframework.vault.support.ClientOptions;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.vault.util.Settings;
|
||||
import org.springframework.web.client.HttpStatusCodeException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ClientHttpRequestFactory}.
|
||||
*
|
||||
@@ -80,6 +83,43 @@ class ClientHttpRequestFactoryFactoryIntegrationTests {
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void httpComponentsClientWithExplicitEnabledCipherSuitesShouldWork() throws Exception {
|
||||
|
||||
List<String> enabledCipherSuites = new ArrayList<String>();
|
||||
enabledCipherSuites.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
|
||||
enabledCipherSuites.add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||
|
||||
ClientHttpRequestFactory factory = HttpComponents.usingHttpComponents(new ClientOptions(),
|
||||
Settings.createSslConfiguration().withEnabledCipherSuites(enabledCipherSuites));
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
|
||||
assertThat(factory).isInstanceOf(HttpComponentsClientHttpRequestFactory.class);
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void httpComponentsClientWithExplicitEnabledProtocolsShouldWork() throws Exception {
|
||||
|
||||
List<String> enabledProtocols = new ArrayList<String>();
|
||||
enabledProtocols.add("TLSv1.2");
|
||||
|
||||
ClientHttpRequestFactory factory = HttpComponents.usingHttpComponents(new ClientOptions(),
|
||||
Settings.createSslConfiguration().withEnabledProtocols(enabledProtocols));
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
|
||||
assertThat(factory).isInstanceOf(HttpComponentsClientHttpRequestFactory.class);
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void nettyClientWithoutSslConfigShouldWork() throws Exception {
|
||||
|
||||
@@ -103,6 +143,96 @@ class ClientHttpRequestFactoryFactoryIntegrationTests {
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void nettyClientWithExplicitEnabledCipherSuitesShouldWork() throws Exception {
|
||||
|
||||
List<String> enabledCipherSuites = new ArrayList<String>();
|
||||
enabledCipherSuites.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
|
||||
enabledCipherSuites.add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||
|
||||
ClientHttpRequestFactory factory = Netty.usingNetty(new ClientOptions(),
|
||||
Settings.createSslConfiguration().withEnabledCipherSuites(enabledCipherSuites));
|
||||
((InitializingBean) factory).afterPropertiesSet();
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
|
||||
assertThat(factory).isInstanceOf(Netty4ClientHttpRequestFactory.class);
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void nettyClientWithExplicitEnabledProtocolsShouldWork() throws Exception {
|
||||
|
||||
List<String> enabledProtocols = new ArrayList<String>();
|
||||
enabledProtocols.add("TLSv1.2");
|
||||
|
||||
ClientHttpRequestFactory factory = Netty.usingNetty(new ClientOptions(),
|
||||
Settings.createSslConfiguration().withEnabledProtocols(enabledProtocols));
|
||||
((InitializingBean) factory).afterPropertiesSet();
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
|
||||
assertThat(factory).isInstanceOf(Netty4ClientHttpRequestFactory.class);
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void okHttp3ClientShouldWork() throws Exception {
|
||||
|
||||
ClientHttpRequestFactory factory = OkHttp3.usingOkHttp3(new ClientOptions(), Settings.createSslConfiguration());
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
|
||||
assertThat(factory).isInstanceOf(OkHttp3ClientHttpRequestFactory.class);
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void okHttp3ClientWithExplicitCipherSuitesShouldWork() throws Exception {
|
||||
|
||||
List<String> enabledCipherSuites = new ArrayList<String>();
|
||||
enabledCipherSuites.add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
|
||||
enabledCipherSuites.add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||
|
||||
ClientHttpRequestFactory factory = OkHttp3.usingOkHttp3(new ClientOptions(),
|
||||
Settings.createSslConfiguration().withEnabledCipherSuites(enabledCipherSuites));
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
|
||||
assertThat(factory).isInstanceOf(OkHttp3ClientHttpRequestFactory.class);
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void okHttp3ClientWithExplicitProtocolsShouldWork() throws Exception {
|
||||
|
||||
List<String> enabledProtocols = new ArrayList<String>();
|
||||
enabledProtocols.add("TLSv1.2");
|
||||
|
||||
ClientHttpRequestFactory factory = OkHttp3.usingOkHttp3(new ClientOptions(),
|
||||
Settings.createSslConfiguration().withEnabledProtocols(enabledProtocols));
|
||||
RestTemplate template = new RestTemplate(factory);
|
||||
|
||||
String response = request(template);
|
||||
|
||||
assertThat(factory).isInstanceOf(OkHttp3ClientHttpRequestFactory.class);
|
||||
assertThat(response).isNotNull().contains("initialized");
|
||||
|
||||
((DisposableBean) factory).destroy();
|
||||
}
|
||||
|
||||
private String request(RestTemplate template) {
|
||||
|
||||
// Uninitialized and sealed can cause status 500
|
||||
|
||||
@@ -15,12 +15,13 @@
|
||||
*/
|
||||
package org.springframework.vault.config;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@@ -34,8 +35,6 @@ import org.springframework.vault.authentication.TokenAuthentication;
|
||||
import org.springframework.vault.support.SslConfiguration;
|
||||
import org.springframework.vault.support.VaultToken;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link EnvironmentVaultConfiguration}.
|
||||
*
|
||||
@@ -78,6 +77,9 @@ class EnvironmentVaultConfigurationUnitTests {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("vault.ssl.key-store", "classpath:certificate.json");
|
||||
map.put("vault.ssl.trust-store", "classpath:certificate.json");
|
||||
map.put("vault.ssl.enabled-protocols", "TLSv1.2,TLSv1.1");
|
||||
map.put("vault.ssl.enabled-cipher-suites",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||
|
||||
MapPropertySource propertySource = new MapPropertySource("shouldConfigureSsl", map);
|
||||
this.configurableEnvironment.getPropertySources().addFirst(propertySource);
|
||||
@@ -90,6 +92,10 @@ class EnvironmentVaultConfigurationUnitTests {
|
||||
assertThat(sslConfiguration.getTrustStore()).isInstanceOf(ClassPathResource.class);
|
||||
assertThat(sslConfiguration.getTrustStorePassword()).isEqualTo("trust store password");
|
||||
|
||||
assertThat(sslConfiguration.getEnabledProtocols()).containsExactly("TLSv1.2", "TLSv1.1");
|
||||
assertThat(sslConfiguration.getEnabledCipherSuites()).containsExactly("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||
|
||||
this.configurableEnvironment.getPropertySources().remove(propertySource.getName());
|
||||
}
|
||||
|
||||
|
||||
@@ -15,14 +15,15 @@
|
||||
*/
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.vault.support.SslConfiguration.KeyStoreConfiguration;
|
||||
import org.springframework.vault.util.Settings;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SslConfiguration}.
|
||||
*
|
||||
@@ -46,6 +47,8 @@ class SslConfigurationUnitTests {
|
||||
|
||||
assertThat(sslConfiguration.getKeyStoreConfiguration().isPresent()).isFalse();
|
||||
assertThat(sslConfiguration.getTrustStoreConfiguration().isPresent()).isFalse();
|
||||
assertThat(sslConfiguration.getEnabledCipherSuites()).isNull();
|
||||
assertThat(sslConfiguration.getEnabledProtocols()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -63,6 +66,35 @@ class SslConfigurationUnitTests {
|
||||
assertThat(tsConfig.getKeyStoreConfiguration().isPresent()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateConfigurationWithEnabledCipherSuites() {
|
||||
|
||||
KeyStoreConfiguration keystore = KeyStoreConfiguration.of(new ClassPathResource("certificate.json"));
|
||||
SslConfiguration tsConfig = SslConfiguration.unconfigured().withTrustStore(keystore)
|
||||
.withEnabledCipherSuites(Arrays.asList(new String[] { "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" }));
|
||||
|
||||
assertThat(tsConfig.getTrustStoreConfiguration()).isSameAs(keystore);
|
||||
assertThat(tsConfig.getKeyStoreConfiguration().isPresent()).isFalse();
|
||||
assertThat(tsConfig.getEnabledCipherSuites().size()).isEqualTo(2);
|
||||
assertThat(tsConfig.getEnabledCipherSuites().get(0)).isEqualTo("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384");
|
||||
assertThat(tsConfig.getEnabledCipherSuites().get(1)).isEqualTo("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateConfigurationWithEnabledProtocols() {
|
||||
|
||||
KeyStoreConfiguration keystore = KeyStoreConfiguration.of(new ClassPathResource("certificate.json"));
|
||||
SslConfiguration tsConfig = SslConfiguration.unconfigured().withTrustStore(keystore)
|
||||
.withEnabledProtocols(Arrays.asList(new String[] { "TLSv1.2", "TLSv1.1" }));
|
||||
|
||||
assertThat(tsConfig.getTrustStoreConfiguration()).isSameAs(keystore);
|
||||
assertThat(tsConfig.getKeyStoreConfiguration().isPresent()).isFalse();
|
||||
assertThat(tsConfig.getEnabledProtocols().size()).isEqualTo(2);
|
||||
assertThat(tsConfig.getEnabledProtocols().get(0)).isEqualTo("TLSv1.2");
|
||||
assertThat(tsConfig.getEnabledProtocols().get(1)).isEqualTo("TLSv1.1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreatePemConfiguration() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user