From 96ecee296b68db51ca7f69371e9d162486e836e1 Mon Sep 17 00:00:00 2001 From: elinuxhenrik Date: Mon, 20 Jul 2020 18:38:11 +0200 Subject: [PATCH] Fix Rest client of policy agent Change-Id: I8a4eebb9e4e7d2e91a7612cadb3d2f78341390dd Issue-ID: NONRTRIC-262 Signed-off-by: elinuxhenrik --- .../policyagent/clients/AsyncRestClient.java | 56 +++++++++++++++++----- .../configuration/ApplicationConfig.java | 16 +++++++ .../policyagent/configuration/WebClientConfig.java | 10 ++++ .../org/oransc/policyagent/ApplicationTest.java | 4 ++ 4 files changed, 73 insertions(+), 13 deletions(-) diff --git a/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java b/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java index b292c519..4bc29ee0 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java @@ -29,6 +29,7 @@ import io.netty.handler.timeout.WriteTimeoutHandler; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.lang.invoke.MethodHandles; import java.security.KeyStore; import java.security.KeyStoreException; @@ -41,7 +42,8 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; -import org.oransc.policyagent.configuration.ImmutableWebClientConfig; +import javax.net.ssl.KeyManagerFactory; + import org.oransc.policyagent.configuration.WebClientConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,10 +72,11 @@ public class AsyncRestClient { private static final AtomicInteger sequenceNumber = new AtomicInteger(); private final WebClientConfig clientConfig; static KeyStore clientTrustStore = null; + private boolean sslEnabled = true; public AsyncRestClient(String baseUrl) { - this(baseUrl, - ImmutableWebClientConfig.builder().isTrustStoreUsed(false).trustStore("").trustStorePassword("").build()); + this(baseUrl, null); + this.sslEnabled = false; } public AsyncRestClient(String baseUrl, WebClientConfig config) { @@ -236,7 +239,8 @@ public class AsyncRestClient { return clientTrustStore; } - private SslContext createSslContextRejectingUntrustedPeers(String trustStorePath, String trustStorePass) + private SslContext createSslContextRejectingUntrustedPeers(String trustStorePath, String trustStorePass, + KeyManagerFactory keyManager) throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException { final KeyStore trustStore = getTrustStore(trustStorePath, trustStorePass); @@ -247,40 +251,50 @@ public class AsyncRestClient { final X509Certificate[] certificates = certificateList.toArray(new X509Certificate[certificateList.size()]); return SslContextBuilder.forClient() // + .keyManager(keyManager) // .trustManager(certificates) // .build(); } - private SslContext createSslContext() + private SslContext createSslContext(KeyManagerFactory keyManager) throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException { if (this.clientConfig.isTrustStoreUsed()) { return createSslContextRejectingUntrustedPeers(this.clientConfig.trustStore(), - this.clientConfig.trustStorePassword()); + this.clientConfig.trustStorePassword(), keyManager); } else { // Trust anyone return SslContextBuilder.forClient() // + .keyManager(keyManager) // .trustManager(InsecureTrustManagerFactory.INSTANCE) // .build(); } } - private WebClient createWebClient(String baseUrl, SslContext sslContext) { - ConnectionProvider connectionProvider = ConnectionProvider.newConnection(); - TcpClient tcpClient = TcpClient.create(connectionProvider) // + private TcpClient createTcpClientSecure(SslContext sslContext) { + return TcpClient.create(ConnectionProvider.newConnection()) // .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) // .secure(c -> c.sslContext(sslContext)) // + .doOnConnected(connection -> { + connection.addHandlerLast(new ReadTimeoutHandler(30)); + connection.addHandlerLast(new WriteTimeoutHandler(30)); + }); + } + private TcpClient createTcpClientInsecure() { + return TcpClient.create(ConnectionProvider.newConnection()) // + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) // .doOnConnected(connection -> { connection.addHandlerLast(new ReadTimeoutHandler(30)); connection.addHandlerLast(new WriteTimeoutHandler(30)); }); + } + + private WebClient createWebClient(String baseUrl, TcpClient tcpClient) { HttpClient httpClient = HttpClient.from(tcpClient); ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient); - ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() // .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)) // .build(); - return WebClient.builder() // .clientConnector(connector) // .baseUrl(baseUrl) // @@ -291,8 +305,24 @@ public class AsyncRestClient { private Mono getWebClient() { if (this.webClient == null) { try { - SslContext sslContext = createSslContext(); - this.webClient = createWebClient(this.baseUrl, sslContext); + if (this.sslEnabled) { + final KeyManagerFactory keyManager = + KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + final KeyStore keyStore = KeyStore.getInstance(this.clientConfig.keyStoreType()); + final String keyStoreFile = this.clientConfig.keyStore(); + final String keyStorePassword = this.clientConfig.keyStorePassword(); + final String keyPassword = this.clientConfig.keyPassword(); + try (final InputStream inputStream = new FileInputStream(keyStoreFile)) { + keyStore.load(inputStream, keyStorePassword.toCharArray()); + } + keyManager.init(keyStore, keyPassword.toCharArray()); + SslContext sslContext = createSslContext(keyManager); + TcpClient tcpClient = createTcpClientSecure(sslContext); + this.webClient = createWebClient(this.baseUrl, tcpClient); + } else { + TcpClient tcpClient = createTcpClientInsecure(); + this.webClient = createWebClient(this.baseUrl, tcpClient); + } } catch (Exception e) { logger.error("Could not create WebClient {}", e.getMessage()); return Mono.error(e); diff --git a/policy-agent/src/main/java/org/oransc/policyagent/configuration/ApplicationConfig.java b/policy-agent/src/main/java/org/oransc/policyagent/configuration/ApplicationConfig.java index a2533733..5e020983 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/configuration/ApplicationConfig.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/configuration/ApplicationConfig.java @@ -43,6 +43,18 @@ public class ApplicationConfig { @Value("${app.filepath}") private String localConfigurationFilePath; + @Value("${server.ssl.key-store-type}") + private String sslKeyStoreType = ""; + + @Value("${server.ssl.key-store-password}") + private String sslKeyStorePassword = ""; + + @Value("${server.ssl.key-store}") + private String sslKeyStore = ""; + + @Value("${server.ssl.key-password}") + private String sslKeyPassword = ""; + @Value("${app.webclient.trust-store-used}") private boolean sslTrustStoreUsed = false; @@ -68,6 +80,10 @@ public class ApplicationConfig { public WebClientConfig getWebClientConfig() { return ImmutableWebClientConfig.builder() // + .keyStoreType(this.sslKeyStoreType) // + .keyStorePassword(this.sslKeyStorePassword) // + .keyStore(this.sslKeyStore) // + .keyPassword(this.sslKeyPassword) // .isTrustStoreUsed(this.sslTrustStoreUsed) // .trustStore(this.sslTrustStore) // .trustStorePassword(this.sslTrustStorePassword) // diff --git a/policy-agent/src/main/java/org/oransc/policyagent/configuration/WebClientConfig.java b/policy-agent/src/main/java/org/oransc/policyagent/configuration/WebClientConfig.java index 5f494983..7f0b233e 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/configuration/WebClientConfig.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/configuration/WebClientConfig.java @@ -25,6 +25,16 @@ import org.immutables.value.Value; @Value.Immutable @Value.Style(redactedMask = "####") public interface WebClientConfig { + public String keyStoreType(); + + @Value.Redacted + public String keyStorePassword(); + + public String keyStore(); + + @Value.Redacted + public String keyPassword(); + public boolean isTrustStoreUsed(); @Value.Redacted diff --git a/policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java b/policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java index a1972f62..6295c3b0 100644 --- a/policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java +++ b/policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java @@ -738,6 +738,10 @@ class ApplicationTest { private AsyncRestClient restClient(boolean useTrustValidation) { WebClientConfig config = this.applicationConfig.getWebClientConfig(); config = ImmutableWebClientConfig.builder() // + .keyStoreType(config.keyStoreType()) // + .keyStorePassword(config.keyStorePassword()) // + .keyStore(config.keyStore()) // + .keyPassword(config.keyPassword()) // .isTrustStoreUsed(useTrustValidation) // .trustStore(config.trustStore()) // .trustStorePassword(config.trustStorePassword()) // -- 2.16.6