aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej Wejs <maciej.wejs@nokia.com>2018-11-06 12:07:12 +0100
committerMaciej Wejs <maciej.wejs@nokia.com>2018-11-06 12:07:12 +0100
commit8330d0e6c2cf1d9d8215e13b928530c2277fa974 (patch)
treeb475506131e3aac411721da0c166609f054db02d
parente8a80102a45458b3f1d15e07dc0a63e1370c44a7 (diff)
SSL implementation for PRH to AAI calls
Change-Id: Ic9777760346258afb40610fa9c9bc261964752cf Issue-ID: DCAEGEN2-950 Signed-off-by: Maciej Wejs <maciej.wejs@nokia.com>
-rw-r--r--prh-aai-client/src/main/java/org/onap/dcaegen2/services/prh/service/AaiReactiveWebClient.java46
-rw-r--r--prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AppConfig.java18
-rw-r--r--prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfig.java7
-rw-r--r--prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTask.java3
-rw-r--r--prh-commons/pom.xml4
-rw-r--r--prh-commons/src/main/java/org/onap/dcaegen2/services/prh/ssl/SslFactory.java91
6 files changed, 143 insertions, 26 deletions
diff --git a/prh-aai-client/src/main/java/org/onap/dcaegen2/services/prh/service/AaiReactiveWebClient.java b/prh-aai-client/src/main/java/org/onap/dcaegen2/services/prh/service/AaiReactiveWebClient.java
index 5963d9c3..ad57ba47 100644
--- a/prh-aai-client/src/main/java/org/onap/dcaegen2/services/prh/service/AaiReactiveWebClient.java
+++ b/prh-aai-client/src/main/java/org/onap/dcaegen2/services/prh/service/AaiReactiveWebClient.java
@@ -25,11 +25,10 @@ import static org.onap.dcaegen2.services.prh.model.logging.MdcVariables.SERVICE_
import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
import io.netty.handler.ssl.SslContext;
-import io.netty.handler.ssl.SslContextBuilder;
-import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import java.util.Map;
import javax.net.ssl.SSLException;
import org.onap.dcaegen2.services.prh.config.AaiClientConfiguration;
+import org.onap.dcaegen2.services.prh.ssl.SslFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
@@ -45,21 +44,32 @@ public class AaiReactiveWebClient {
private static final Logger LOGGER = LoggerFactory.getLogger(AaiReactiveWebClient.class);
- private String aaiUserName;
- private String aaiUserPassword;
- private Map<String, String> aaiHeaders;
+ private final String aaiUserName;
+ private final String aaiUserPassword;
+ private final Map<String, String> aaiHeaders;
+ private final Boolean enableAaiCertAuth;
+ private final String trustStore;
+ private final String trustStorePassword;
+ private final String keyStore;
+ private final String keyStorePassword;
+ private final SslFactory sslFactory;
/**
* Creating AaiReactiveWebClient.
*
* @param configuration - configuration object
- * @return AaiReactiveWebClient
+ * @param sslFactory - factory for ssl setup
*/
- public AaiReactiveWebClient fromConfiguration(AaiClientConfiguration configuration) {
+ public AaiReactiveWebClient(SslFactory sslFactory, AaiClientConfiguration configuration) {
this.aaiUserName = configuration.aaiUserName();
this.aaiUserPassword = configuration.aaiUserPassword();
this.aaiHeaders = configuration.aaiHeaders();
- return this;
+ this.trustStore = configuration.trustStore();
+ this.trustStorePassword = configuration.trustStorePassword();
+ this.keyStore = configuration.keyStore();
+ this.keyStorePassword = configuration.keyStorePassword();
+ this.enableAaiCertAuth = configuration.enableAaiCertAuth();
+ this.sslFactory = sslFactory;
}
/**
@@ -69,12 +79,12 @@ public class AaiReactiveWebClient {
*/
public WebClient build() throws SSLException {
LOGGER.debug("Setting ssl context");
- SslContext sslContext = SslContextBuilder
- .forClient()
- .trustManager(InsecureTrustManagerFactory.INSTANCE)
- .build();
+
+ SslContext sslContext = createSslContext();
+
ClientHttpConnector reactorClientHttpConnector = new ReactorClientHttpConnector(
HttpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(sslContext)));
+
return WebClient.builder()
.clientConnector(reactorClientHttpConnector)
.defaultHeaders(httpHeaders -> httpHeaders.setAll(aaiHeaders))
@@ -84,6 +94,18 @@ public class AaiReactiveWebClient {
.build();
}
+ private SslContext createSslContext() throws SSLException {
+ if (enableAaiCertAuth) {
+ return sslFactory.createSecureContext(
+ keyStore,
+ keyStorePassword,
+ trustStore,
+ trustStorePassword
+ );
+ }
+ return sslFactory.createInsecureContext();
+ }
+
private ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
MDC.put(SERVICE_NAME, String.valueOf(clientRequest.url()));
diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AppConfig.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AppConfig.java
index 643462f1..191294fd 100644
--- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AppConfig.java
+++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/AppConfig.java
@@ -174,16 +174,16 @@ public class AppConfig extends PrhAppConfig {
.consumerId(Optional.ofNullable(consumerId).filter(isEmpty.negate())
.orElse(dmaapConsumerConfiguration.consumerId()))
.keyFile(
- Optional.ofNullable(keyFile).filter(p -> !p.isEmpty())
+ Optional.ofNullable(keyFile).filter(isEmpty.negate())
.orElse(dmaapConsumerConfiguration.keyFile()))
.trustStore(
- Optional.ofNullable(trustStore).filter(p -> !p.isEmpty())
+ Optional.ofNullable(trustStore).filter(isEmpty.negate())
.orElse(dmaapConsumerConfiguration.trustStore()))
.trustStorePassword(
Optional.ofNullable(trustStorePassword).filter(isEmpty.negate())
.orElse(dmaapConsumerConfiguration.trustStorePassword()))
.keyStore(
- Optional.ofNullable(keyStore).filter(p -> !p.isEmpty())
+ Optional.ofNullable(keyStore).filter(isEmpty.negate())
.orElse(dmaapConsumerConfiguration.keyStore()))
.keyStorePassword(
Optional.ofNullable(keyStorePassword).filter(isEmpty.negate())
@@ -216,16 +216,16 @@ public class AppConfig extends PrhAppConfig {
Optional.ofNullable(aaiPnfPath).filter(isEmpty.negate()).orElse(aaiClientConfiguration.aaiPnfPath()))
.aaiHeaders(aaiClientConfiguration.aaiHeaders())
.keyFile(
- Optional.ofNullable(keyFile).filter(p -> !p.isEmpty())
+ Optional.ofNullable(keyFile).filter(isEmpty.negate())
.orElse(aaiClientConfiguration.keyFile()))
.trustStore(
- Optional.ofNullable(trustStore).filter(p -> !p.isEmpty())
+ Optional.ofNullable(trustStore).filter(isEmpty.negate())
.orElse(aaiClientConfiguration.trustStore()))
.trustStorePassword(
Optional.ofNullable(trustStorePassword).filter(isEmpty.negate())
.orElse(aaiClientConfiguration.trustStorePassword()))
.keyStore(
- Optional.ofNullable(keyStore).filter(p -> !p.isEmpty())
+ Optional.ofNullable(keyStore).filter(isEmpty.negate())
.orElse(aaiClientConfiguration.keyStore()))
.keyStorePassword(
Optional.ofNullable(keyStorePassword).filter(isEmpty.negate())
@@ -261,16 +261,16 @@ public class AppConfig extends PrhAppConfig {
Optional.ofNullable(producerDmaapUserPassword).filter(isEmpty.negate())
.orElse(dmaapPublisherConfiguration.dmaapUserPassword()))
.keyFile(
- Optional.ofNullable(keyFile).filter(p -> !p.isEmpty())
+ Optional.ofNullable(keyFile).filter(isEmpty.negate())
.orElse(dmaapPublisherConfiguration.keyFile()))
.trustStore(
- Optional.ofNullable(trustStore).filter(p -> !p.isEmpty())
+ Optional.ofNullable(trustStore).filter(isEmpty.negate())
.orElse(dmaapPublisherConfiguration.trustStore()))
.trustStorePassword(
Optional.ofNullable(trustStorePassword).filter(isEmpty.negate())
.orElse(dmaapPublisherConfiguration.trustStorePassword()))
.keyStore(
- Optional.ofNullable(keyStore).filter(p -> !p.isEmpty())
+ Optional.ofNullable(keyStore).filter(isEmpty.negate())
.orElse(dmaapPublisherConfiguration.keyStore()))
.keyStorePassword(
Optional.ofNullable(keyStorePassword).filter(isEmpty.negate())
diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfig.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfig.java
index 54c63532..2b4b201a 100644
--- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfig.java
+++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/configuration/PrhAppConfig.java
@@ -95,11 +95,10 @@ public abstract class PrhAppConfig implements Config {
try (InputStream inputStream = resourceFile.getInputStream()) {
JsonElement rootElement = getJsonElement(parser, inputStream);
if (rootElement.isJsonObject()) {
- JsonObject jsonObject = concatenateJsonObjects(
- rootElement.getAsJsonObject().getAsJsonObject(CONFIG).getAsJsonObject(AAI).getAsJsonObject(AAI_CONFIG),
- rootElement.getAsJsonObject().getAsJsonObject(CONFIG).getAsJsonObject(SECURITY));
aaiClientConfiguration = deserializeType(gsonBuilder,
- jsonObject,
+ concatenateJsonObjects(
+ rootElement.getAsJsonObject().getAsJsonObject(CONFIG).getAsJsonObject(AAI).getAsJsonObject(AAI_CONFIG),
+ rootElement.getAsJsonObject().getAsJsonObject(CONFIG).getAsJsonObject(SECURITY)),
AaiClientConfiguration.class);
dmaapConsumerConfiguration = deserializeType(gsonBuilder,
concatenateJsonObjects(
diff --git a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTask.java b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTask.java
index efa4f66f..54a8ad89 100644
--- a/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTask.java
+++ b/prh-app-server/src/main/java/org/onap/dcaegen2/services/prh/tasks/AaiProducerTask.java
@@ -27,6 +27,7 @@ import org.onap.dcaegen2.services.prh.exceptions.PrhTaskException;
import org.onap.dcaegen2.services.prh.model.ConsumerDmaapModel;
import org.onap.dcaegen2.services.prh.service.AaiReactiveWebClient;
import org.onap.dcaegen2.services.prh.service.producer.AaiProducerReactiveHttpClient;
+import org.onap.dcaegen2.services.prh.ssl.SslFactory;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@@ -46,6 +47,6 @@ public abstract class AaiProducerTask {
throws PrhTaskException, SSLException;
WebClient buildWebClient() throws SSLException {
- return new AaiReactiveWebClient().fromConfiguration(resolveConfiguration()).build();
+ return new AaiReactiveWebClient(new SslFactory(), resolveConfiguration()).build();
}
}
diff --git a/prh-commons/pom.xml b/prh-commons/pom.xml
index 91fd9082..11a0babc 100644
--- a/prh-commons/pom.xml
+++ b/prh-commons/pom.xml
@@ -74,5 +74,9 @@
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
+ <dependency>
+ <groupId>io.projectreactor.netty</groupId>
+ <artifactId>reactor-netty</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git a/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/ssl/SslFactory.java b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/ssl/SslFactory.java
new file mode 100644
index 00000000..6ffff1b9
--- /dev/null
+++ b/prh-commons/src/main/java/org/onap/dcaegen2/services/prh/ssl/SslFactory.java
@@ -0,0 +1,91 @@
+/*
+ * ============LICENSE_START=======================================================
+ * PNF-REGISTRATION-HANDLER
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dcaegen2.services.prh.ssl;
+
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.KeyStore;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.TrustManagerFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SslFactory {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SslFactory.class);
+
+ public SslContext createSecureContext(String keyStoreFilename,
+ String keyStorePassword,
+ String trustStoreFilename,
+ String trustStorePassword) throws SSLException {
+ LOGGER.info("Creating secure ssl context for: {} {}", keyStoreFilename, trustStoreFilename);
+ try {
+ return SslContextBuilder
+ .forClient()
+ .keyManager(keyManagerFactory(keyStoreFilename, loadPasswordFromFile(keyStorePassword)))
+ .trustManager(trustManagerFactory(trustStoreFilename, loadPasswordFromFile(trustStorePassword)))
+ .build();
+ } catch (Exception ex) {
+ throw new SSLException(ex);
+ }
+ }
+
+ public SslContext createInsecureContext() throws SSLException {
+ LOGGER.info("Creating insecure ssl context");
+ return SslContextBuilder
+ .forClient()
+ .trustManager(InsecureTrustManagerFactory.INSTANCE)
+ .build();
+ }
+
+ private KeyManagerFactory keyManagerFactory(String fileName, String password) throws Exception {
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ kmf.init(loadKeyStoreFromFile(fileName, password),
+ password.toCharArray());
+ return kmf;
+ }
+
+ private TrustManagerFactory trustManagerFactory(String fileName, String password) throws Exception {
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ tmf.init(loadKeyStoreFromFile(fileName, password));
+ return tmf;
+ }
+
+ private KeyStore loadKeyStoreFromFile(String fileName, String keyStorePassword) throws Exception {
+ KeyStore ks = KeyStore.getInstance("jks");
+ ks.load(getResource(fileName), keyStorePassword.toCharArray());
+ return ks;
+ }
+
+ private InputStream getResource(String fileName) throws Exception {
+ return new FileInputStream(fileName);
+ }
+
+ private String loadPasswordFromFile(String path) throws Exception {
+ return new String(Files.readAllBytes(Paths.get(path)));
+ }
+}