Use SDK/SSL in HV-VES 59/78559/5
authorPiotr Jaszczyk <piotr.jaszczyk@nokia.com>
Fri, 15 Feb 2019 11:59:26 +0000 (12:59 +0100)
committerPiotr Jaszczyk <piotr.jaszczyk@nokia.com>
Tue, 19 Feb 2019 11:51:46 +0000 (12:51 +0100)
Issue-ID: DCAEGEN2-1226
Change-Id: I7cfc09001f7315c1b6f4fcf150ad631630c810ef
Signed-off-by: Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
20 files changed:
pom.xml
sources/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/factory/ServerFactory.kt
sources/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/adapters/HttpAdapter.kt
sources/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/NettyTcpServer.kt
sources/hv-collector-domain/pom.xml
sources/hv-collector-domain/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/SecurityConfiguration.kt
sources/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/ArgVesHvConfiguration.kt
sources/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/ArgVesHvConfigurationTest.kt
sources/hv-collector-ssl/pom.xml
sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ClientSslContextFactory.kt [deleted file]
sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactory.kt [deleted file]
sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/SslContextFactory.kt
sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/utils.kt
sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/impl/SslFactories.kt [deleted file]
sources/hv-collector-ssl/src/test/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactoryTest.kt [deleted file]
sources/hv-collector-ssl/src/test/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/SslContextFactoryTest.kt [new file with mode: 0644]
sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/arrow/core.kt
sources/hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOption.kt
sources/hv-collector-xnf-simulator/src/main/kotlin/org/onap/dcae/collectors/veshv/simulators/xnf/impl/adapters/VesHvClient.kt
sources/hv-collector-xnf-simulator/src/main/kotlin/org/onap/dcae/collectors/veshv/simulators/xnf/impl/config/ArgXnfSimulatorConfiguration.kt

diff --git a/pom.xml b/pom.xml
index 780147c..dfccb2b 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -50,7 +50,7 @@
     </modules>
 
     <properties>
-        <kotlin.version>1.3.11</kotlin.version>
+        <kotlin.version>1.3.21</kotlin.version>
         <arrow.version>0.8.0</arrow.version>
         <maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
         <build-helper-maven-plugin.version>1.7</build-helper-maven-plugin.version>
                 <groupId>io.projectreactor</groupId>
                 <artifactId>reactor-bom</artifactId>
                 <!-- remember to update netty native bindings versions -->
-                <version>Californium-SR2</version>
+                <version>Californium-SR4</version>
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
-
-            <!--
-            Disable native extensions (ssl and epoll) on production for now.
-            Might be reintroduced if performance tests prove there is some performance issue.
-            -->
-            <dependency>
-                <groupId>io.netty</groupId>
-                <artifactId>netty-tcnative-boringssl-static</artifactId>
-                <version>2.0.15.Final</version>
-                <scope>runtime</scope>
-                <classifier>${os.detected.classifier}</classifier>
-            </dependency>
             <!--
             <dependency>
                 <groupId>io.netty</groupId>
                 <artifactId>hvvesclient-protobuf</artifactId>
                 <version>${sdk.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.onap.dcaegen2.services.sdk.security</groupId>
+                <artifactId>ssl</artifactId>
+                <version>${sdk.version}</version>
+            </dependency>
 
             <!-- Test dependencies -->
 
index 2e6bb4d..31c0636 100644 (file)
@@ -24,7 +24,7 @@ import org.onap.dcae.collectors.veshv.boundary.Metrics
 import org.onap.dcae.collectors.veshv.boundary.Server
 import org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer
 import org.onap.dcae.collectors.veshv.model.ServerConfiguration
-import org.onap.dcae.collectors.veshv.ssl.boundary.ServerSslContextFactory
+import org.onap.dcae.collectors.veshv.ssl.boundary.SslContextFactory
 
 /**
  * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
@@ -34,5 +34,5 @@ object ServerFactory {
     fun createNettyTcpServer(serverConfiguration: ServerConfiguration,
                              collectorProvider: CollectorProvider,
                              metrics: Metrics): Server =
-            NettyTcpServer(serverConfiguration, ServerSslContextFactory(), collectorProvider, metrics)
+            NettyTcpServer(serverConfiguration, SslContextFactory(), collectorProvider, metrics)
 }
index 51f7410..8d15409 100644 (file)
@@ -22,7 +22,6 @@ package org.onap.dcae.collectors.veshv.impl.adapters
 import io.netty.handler.codec.http.HttpStatusClass
 import org.onap.dcae.collectors.veshv.utils.logging.Logger
 import org.onap.dcae.collectors.veshv.utils.logging.OnapMdc
-import org.slf4j.LoggerFactory
 import reactor.core.publisher.Mono
 import reactor.netty.http.client.HttpClient
 import java.util.*
index 0d07d16..16edb55 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.onap.dcae.collectors.veshv.impl.socket
 
-import arrow.core.Try
 import arrow.core.getOrElse
 import arrow.effects.IO
 import org.onap.dcae.collectors.veshv.boundary.Collector
@@ -31,7 +30,7 @@ import org.onap.dcae.collectors.veshv.impl.adapters.ClientContextLogging.info
 import org.onap.dcae.collectors.veshv.model.ClientContext
 import org.onap.dcae.collectors.veshv.model.ServerConfiguration
 import org.onap.dcae.collectors.veshv.model.ServiceContext
-import org.onap.dcae.collectors.veshv.ssl.boundary.ServerSslContextFactory
+import org.onap.dcae.collectors.veshv.ssl.boundary.SslContextFactory
 import org.onap.dcae.collectors.veshv.utils.NettyServerHandle
 import org.onap.dcae.collectors.veshv.utils.ServerHandle
 import org.onap.dcae.collectors.veshv.utils.logging.Logger
@@ -50,7 +49,7 @@ import java.time.Duration
  * @since May 2018
  */
 internal class NettyTcpServer(private val serverConfig: ServerConfiguration,
-                              private val sslContextFactory: ServerSslContextFactory,
+                              private val sslContextFactory: SslContextFactory,
                               private val collectorProvider: CollectorProvider,
                               private val metrics: Metrics) : Server {
 
@@ -68,7 +67,7 @@ internal class NettyTcpServer(private val serverConfig: ServerConfiguration,
 
     private fun TcpServer.configureSsl() =
             sslContextFactory
-                    .createSslContext(serverConfig.securityConfiguration)
+                    .createServerContext(serverConfig.securityConfiguration)
                     .map { sslContext ->
                         logger.info { "Collector configured with SSL enabled" }
                         this.secure { b -> b.sslContext(sslContext) }
index 4e01be3..bac42a2 100644 (file)
             <groupId>io.projectreactor.netty</groupId>
             <artifactId>reactor-netty</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.onap.dcaegen2.services.sdk.security</groupId>
+            <artifactId>ssl</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.arrow-kt</groupId>
             <artifactId>arrow-core</artifactId>
         </dependency>
-
         <dependency>
             <groupId>org.assertj</groupId>
             <artifactId>assertj-core</artifactId>
index 7f566a6..4bb0d84 100644 (file)
@@ -20,7 +20,7 @@
 package org.onap.dcae.collectors.veshv.domain
 
 import arrow.core.Option
-import java.io.InputStream
+import org.onap.dcaegen2.services.sdk.security.ssl.SecurityKeys
 import java.nio.file.Path
 
 /**
@@ -28,23 +28,4 @@ import java.nio.file.Path
  * @since May 2018
  */
 data class SecurityConfiguration(
-        val sslDisable: Boolean = false,
-        val keys: Option<SslKeys>)
-
-sealed class SslKeys
-
-data class OpenSslKeys(val privateKey: Path,
-                       val cert: Path,
-                       val trustedCert: Path) : SslKeys()
-
-data class JdkKeys(val keyStore: StreamProvider,
-                   val keyStorePassword: CharArray,
-                   val trustStore: StreamProvider,
-                   val trustStorePassword: CharArray) : SslKeys() {
-    fun forgetPasswords() {
-        keyStorePassword.fill('x')
-        trustStorePassword.fill('x')
-    }
-}
-
-typealias StreamProvider = () -> InputStream
+        val keys: Option<SecurityKeys>)
index c97486c..56bb1d8 100644 (file)
@@ -30,7 +30,9 @@ import org.onap.dcae.collectors.veshv.domain.WireFrameMessage
 import org.onap.dcae.collectors.veshv.model.ConfigurationProviderParams
 import org.onap.dcae.collectors.veshv.model.KafkaConfiguration
 import org.onap.dcae.collectors.veshv.model.ServerConfiguration
+import org.onap.dcae.collectors.veshv.model.ServiceContext
 import org.onap.dcae.collectors.veshv.ssl.boundary.createSecurityConfiguration
+import org.onap.dcae.collectors.veshv.utils.arrow.doOnFailure
 import org.onap.dcae.collectors.veshv.utils.commandline.*
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.CONSUL_CONFIG_URL
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.KAFKA_SERVERS
@@ -55,80 +57,87 @@ import java.time.Duration
 
 internal class ArgVesHvConfiguration : ArgBasedConfiguration<ServerConfiguration>(DefaultParser()) {
     override val cmdLineOptionsList = listOf(
-        KAFKA_SERVERS,
-        HEALTH_CHECK_API_PORT,
-        LISTEN_PORT,
-        CONSUL_CONFIG_URL,
-        CONSUL_FIRST_REQUEST_DELAY,
-        CONSUL_REQUEST_INTERVAL,
-        SSL_DISABLE,
-        KEY_STORE_FILE,
-        KEY_STORE_PASSWORD,
-        TRUST_STORE_FILE,
-        TRUST_STORE_PASSWORD,
-        IDLE_TIMEOUT_SEC,
-        MAXIMUM_PAYLOAD_SIZE_BYTES,
-        DUMMY_MODE,
-        LOG_LEVEL
+            KAFKA_SERVERS,
+            HEALTH_CHECK_API_PORT,
+            LISTEN_PORT,
+            CONSUL_CONFIG_URL,
+            CONSUL_FIRST_REQUEST_DELAY,
+            CONSUL_REQUEST_INTERVAL,
+            SSL_DISABLE,
+            KEY_STORE_FILE,
+            KEY_STORE_PASSWORD,
+            TRUST_STORE_FILE,
+            TRUST_STORE_PASSWORD,
+            IDLE_TIMEOUT_SEC,
+            MAXIMUM_PAYLOAD_SIZE_BYTES,
+            DUMMY_MODE,
+            LOG_LEVEL
     )
 
     override fun getConfiguration(cmdLine: CommandLine): Option<ServerConfiguration> =
-        Option.monad().binding {
-            val healthCheckApiPort = cmdLine.intValue(
-                HEALTH_CHECK_API_PORT,
-                DefaultValues.HEALTH_CHECK_API_PORT
-            )
-            val kafkaServers = cmdLine.stringValue(KAFKA_SERVERS).bind()
-            val listenPort = cmdLine.intValue(LISTEN_PORT).bind()
-            val idleTimeoutSec = cmdLine.longValue(IDLE_TIMEOUT_SEC, DefaultValues.IDLE_TIMEOUT_SEC)
-            val maxPayloadSizeBytes = cmdLine.intValue(
-                MAXIMUM_PAYLOAD_SIZE_BYTES,
-                DefaultValues.MAX_PAYLOAD_SIZE_BYTES
-            )
-            val dummyMode = cmdLine.hasOption(DUMMY_MODE)
-            val security = createSecurityConfiguration(cmdLine).bind()
-            val logLevel = cmdLine.stringValue(LOG_LEVEL, DefaultValues.LOG_LEVEL)
-            val configurationProviderParams = createConfigurationProviderParams(cmdLine).bind()
-            ServerConfiguration(
-                serverListenAddress = InetSocketAddress(listenPort),
-                kafkaConfiguration = KafkaConfiguration(kafkaServers, maxPayloadSizeBytes),
-                healthCheckApiListenAddress = InetSocketAddress(healthCheckApiPort),
-                configurationProviderParams = configurationProviderParams,
-                securityConfiguration = security,
-                idleTimeout = Duration.ofSeconds(idleTimeoutSec),
-                maximumPayloadSizeBytes = maxPayloadSizeBytes,
-                dummyMode = dummyMode,
-                logLevel = determineLogLevel(logLevel)
-            )
-        }.fix()
+            Option.monad().binding {
+                val healthCheckApiPort = cmdLine.intValue(
+                        HEALTH_CHECK_API_PORT,
+                        DefaultValues.HEALTH_CHECK_API_PORT
+                )
+                val kafkaServers = cmdLine.stringValue(KAFKA_SERVERS).bind()
+                val listenPort = cmdLine.intValue(LISTEN_PORT).bind()
+                val idleTimeoutSec = cmdLine.longValue(IDLE_TIMEOUT_SEC, DefaultValues.IDLE_TIMEOUT_SEC)
+                val maxPayloadSizeBytes = cmdLine.intValue(
+                        MAXIMUM_PAYLOAD_SIZE_BYTES,
+                        DefaultValues.MAX_PAYLOAD_SIZE_BYTES
+                )
+                val dummyMode = cmdLine.hasOption(DUMMY_MODE)
+                val security = createSecurityConfiguration(cmdLine)
+                        .doOnFailure { ex ->
+                            logger.withError(ServiceContext::mdc) {
+                                log("Could not read security keys", ex)
+                            }
+                        }
+                        .toOption()
+                        .bind()
+                val logLevel = cmdLine.stringValue(LOG_LEVEL, DefaultValues.LOG_LEVEL)
+                val configurationProviderParams = createConfigurationProviderParams(cmdLine).bind()
+                ServerConfiguration(
+                        serverListenAddress = InetSocketAddress(listenPort),
+                        kafkaConfiguration = KafkaConfiguration(kafkaServers, maxPayloadSizeBytes),
+                        healthCheckApiListenAddress = InetSocketAddress(healthCheckApiPort),
+                        configurationProviderParams = configurationProviderParams,
+                        securityConfiguration = security,
+                        idleTimeout = Duration.ofSeconds(idleTimeoutSec),
+                        maximumPayloadSizeBytes = maxPayloadSizeBytes,
+                        dummyMode = dummyMode,
+                        logLevel = determineLogLevel(logLevel)
+                )
+            }.fix()
 
 
     private fun createConfigurationProviderParams(cmdLine: CommandLine): Option<ConfigurationProviderParams> =
-        Option.monad().binding {
-            val configUrl = cmdLine.stringValue(CONSUL_CONFIG_URL).bind()
-            val firstRequestDelay = cmdLine.longValue(
-                CONSUL_FIRST_REQUEST_DELAY,
-                DefaultValues.CONSUL_FIRST_REQUEST_DELAY
-            )
-            val requestInterval = cmdLine.longValue(
-                CONSUL_REQUEST_INTERVAL,
-                DefaultValues.CONSUL_REQUEST_INTERVAL
-            )
-            ConfigurationProviderParams(
-                configUrl,
-                Duration.ofSeconds(firstRequestDelay),
-                Duration.ofSeconds(requestInterval)
-            )
-        }.fix()
+            Option.monad().binding {
+                val configUrl = cmdLine.stringValue(CONSUL_CONFIG_URL).bind()
+                val firstRequestDelay = cmdLine.longValue(
+                        CONSUL_FIRST_REQUEST_DELAY,
+                        DefaultValues.CONSUL_FIRST_REQUEST_DELAY
+                )
+                val requestInterval = cmdLine.longValue(
+                        CONSUL_REQUEST_INTERVAL,
+                        DefaultValues.CONSUL_REQUEST_INTERVAL
+                )
+                ConfigurationProviderParams(
+                        configUrl,
+                        Duration.ofSeconds(firstRequestDelay),
+                        Duration.ofSeconds(requestInterval)
+                )
+            }.fix()
 
     private fun determineLogLevel(logLevel: String) = LogLevel.optionFromString(logLevel)
-        .getOrElse {
-            logger.warn {
-                "Failed to parse $logLevel as $LOG_LEVEL command line. " +
-                        "Using default log level (${DefaultValues.LOG_LEVEL})"
+            .getOrElse {
+                logger.warn {
+                    "Failed to parse $logLevel as $LOG_LEVEL command line. " +
+                            "Using default log level (${DefaultValues.LOG_LEVEL})"
+                }
+                LogLevel.valueOf(DefaultValues.LOG_LEVEL)
             }
-            LogLevel.valueOf(DefaultValues.LOG_LEVEL)
-        }
 
 
     internal object DefaultValues {
index 03bf44f..90571ce 100644 (file)
@@ -25,12 +25,12 @@ import org.jetbrains.spek.api.dsl.describe
 import org.jetbrains.spek.api.dsl.given
 import org.jetbrains.spek.api.dsl.it
 import org.jetbrains.spek.api.dsl.on
-import org.onap.dcae.collectors.veshv.domain.JdkKeys
 import org.onap.dcae.collectors.veshv.model.ServerConfiguration
 import org.onap.dcae.collectors.veshv.tests.utils.parseExpectingFailure
 import org.onap.dcae.collectors.veshv.tests.utils.parseExpectingSuccess
 import org.onap.dcae.collectors.veshv.utils.commandline.WrongArgumentError
 import org.onap.dcae.collectors.veshv.utils.logging.LogLevel
+import org.onap.dcaegen2.services.sdk.security.ssl.SecurityKeys
 import java.time.Duration
 import kotlin.test.assertNotNull
 
@@ -60,17 +60,17 @@ object ArgVesHvConfigurationTest : Spek({
 
             beforeEachTest {
                 result = cut.parseExpectingSuccess(
-                    "--kafka-bootstrap-servers", kafkaBootstrapServers,
-                    "--health-check-api-port", healthCheckApiPort,
-                    "--listen-port", listenPort,
-                    "--config-url", configurationUrl,
-                    "--first-request-delay", firstRequestDelay,
-                    "--request-interval", requestInterval,
-                    "--key-store", "/tmp/keys.p12",
-                    "--trust-store", "/tmp/trust.p12",
-                    "--key-store-password", keyStorePassword,
-                    "--trust-store-password", trustStorePassword,
-                    "--log-level", logLevel
+                        "--kafka-bootstrap-servers", kafkaBootstrapServers,
+                        "--health-check-api-port", healthCheckApiPort,
+                        "--listen-port", listenPort,
+                        "--config-url", configurationUrl,
+                        "--first-request-delay", firstRequestDelay,
+                        "--request-interval", requestInterval,
+                        "--key-store", "/tmp/keys.p12",
+                        "--trust-store", "/tmp/trust.p12",
+                        "--key-store-password", keyStorePassword,
+                        "--trust-store-password", trustStorePassword,
+                        "--log-level", logLevel
                 )
             }
 
@@ -97,27 +97,32 @@ object ArgVesHvConfigurationTest : Spek({
 
             it("should set proper first consul request delay") {
                 assertThat(result.configurationProviderParams.firstRequestDelay)
-                    .isEqualTo(Duration.ofSeconds(firstRequestDelay.toLong()))
+                        .isEqualTo(Duration.ofSeconds(firstRequestDelay.toLong()))
             }
 
             it("should set proper consul request interval") {
                 assertThat(result.configurationProviderParams.requestInterval)
-                    .isEqualTo(Duration.ofSeconds(requestInterval.toLong()))
+                        .isEqualTo(Duration.ofSeconds(requestInterval.toLong()))
             }
 
             it("should set proper config url") {
                 assertThat(result.configurationProviderParams.configurationUrl)
-                    .isEqualTo(configurationUrl)
+                        .isEqualTo(configurationUrl)
             }
 
             it("should set proper security configuration") {
-                assertThat(result.securityConfiguration.sslDisable).isFalse()
+                assertThat(result.securityConfiguration.keys.isEmpty()).isFalse()
+
+                val keys = result.securityConfiguration.keys.orNull() as SecurityKeys
+                assertNotNull(keys.keyStore())
+                assertNotNull(keys.trustStore())
+                keys.keyStorePassword().useChecked {
+                    assertThat(it).isEqualTo(keyStorePassword.toCharArray())
 
-                val keys = result.securityConfiguration.keys.orNull() as JdkKeys
-                assertNotNull(keys.keyStore)
-                assertNotNull(keys.trustStore)
-                assertThat(keys.keyStorePassword).isEqualTo(keyStorePassword.toCharArray())
-                assertThat(keys.trustStorePassword).isEqualTo(trustStorePassword.toCharArray())
+                }
+                keys.trustStorePassword().useChecked {
+                    assertThat(it).isEqualTo(trustStorePassword.toCharArray())
+                }
             }
 
             it("should set proper log level") {
@@ -129,24 +134,24 @@ object ArgVesHvConfigurationTest : Spek({
             on("missing listen port") {
                 it("should throw exception") {
                     assertThat(
-                        cut.parseExpectingFailure(
-                            "--config-url", configurationUrl,
-                            "--ssl-disable",
-                            "--first-request-delay", firstRequestDelay,
-                            "--request-interval", requestInterval
-                        )
+                            cut.parseExpectingFailure(
+                                    "--config-url", configurationUrl,
+                                    "--ssl-disable",
+                                    "--first-request-delay", firstRequestDelay,
+                                    "--request-interval", requestInterval
+                            )
                     ).isInstanceOf(WrongArgumentError::class.java)
                 }
             }
             on("missing configuration url") {
                 it("should throw exception") {
                     assertThat(
-                        cut.parseExpectingFailure(
-                            "--listen-port", listenPort,
-                            "--ssl-disable",
-                            "--first-request-delay", firstRequestDelay,
-                            "--request-interval", requestInterval
-                        )
+                            cut.parseExpectingFailure(
+                                    "--listen-port", listenPort,
+                                    "--ssl-disable",
+                                    "--first-request-delay", firstRequestDelay,
+                                    "--request-interval", requestInterval
+                            )
                     ).isInstanceOf(WrongArgumentError::class.java)
                 }
             }
@@ -156,16 +161,16 @@ object ArgVesHvConfigurationTest : Spek({
             on("missing log level") {
                 it("should set default INFO value") {
                     val config = cut.parseExpectingSuccess(
-                        "--kafka-bootstrap-servers", kafkaBootstrapServers,
-                        "--health-check-api-port", healthCheckApiPort,
-                        "--listen-port", listenPort,
-                        "--config-url", configurationUrl,
-                        "--first-request-delay", firstRequestDelay,
-                        "--request-interval", requestInterval,
-                        "--key-store", "/tmp/keys.p12",
-                        "--trust-store", "/tmp/trust.p12",
-                        "--key-store-password", keyStorePassword,
-                        "--trust-store-password", trustStorePassword
+                            "--kafka-bootstrap-servers", kafkaBootstrapServers,
+                            "--health-check-api-port", healthCheckApiPort,
+                            "--listen-port", listenPort,
+                            "--config-url", configurationUrl,
+                            "--first-request-delay", firstRequestDelay,
+                            "--request-interval", requestInterval,
+                            "--key-store", "/tmp/keys.p12",
+                            "--trust-store", "/tmp/trust.p12",
+                            "--key-store-password", keyStorePassword,
+                            "--trust-store-password", trustStorePassword
                     )
 
                     assertThat(config.logLevel).isEqualTo(LogLevel.INFO)
@@ -175,17 +180,17 @@ object ArgVesHvConfigurationTest : Spek({
             on("incorrect log level") {
                 it("should set default INFO value") {
                     val config = cut.parseExpectingSuccess(
-                        "--kafka-bootstrap-servers", kafkaBootstrapServers,
-                        "--health-check-api-port", healthCheckApiPort,
-                        "--listen-port", listenPort,
-                        "--config-url", configurationUrl,
-                        "--first-request-delay", firstRequestDelay,
-                        "--request-interval", requestInterval,
-                        "--key-store", "/tmp/keys.p12",
-                        "--trust-store", "/tmp/trust.p12",
-                        "--key-store-password", keyStorePassword,
-                        "--trust-store-password", trustStorePassword,
-                        "--log-level", "1"
+                            "--kafka-bootstrap-servers", kafkaBootstrapServers,
+                            "--health-check-api-port", healthCheckApiPort,
+                            "--listen-port", listenPort,
+                            "--config-url", configurationUrl,
+                            "--first-request-delay", firstRequestDelay,
+                            "--request-interval", requestInterval,
+                            "--key-store", "/tmp/keys.p12",
+                            "--trust-store", "/tmp/trust.p12",
+                            "--key-store-password", keyStorePassword,
+                            "--trust-store-password", trustStorePassword,
+                            "--log-level", "1"
                     )
 
                     assertThat(config.logLevel).isEqualTo(LogLevel.INFO)
index 98c07f4..dad7ab5 100644 (file)
             <version>${project.parent.version}</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-tcnative-boringssl-static</artifactId>
-            <classifier>${os.detected.classifier}</classifier>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>io.arrow-kt</groupId>
             <artifactId>arrow-core</artifactId>
diff --git a/sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ClientSslContextFactory.kt b/sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ClientSslContextFactory.kt
deleted file mode 100644 (file)
index 0ad3d7b..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * dcaegen2-collectors-veshv
- * ================================================================================
- * Copyright (C) 2018 NOKIA
- * ================================================================================
- * 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.dcae.collectors.veshv.ssl.boundary
-
-import io.netty.handler.ssl.SslContextBuilder
-import io.netty.handler.ssl.SslProvider
-import org.onap.dcae.collectors.veshv.domain.JdkKeys
-import org.onap.dcae.collectors.veshv.domain.OpenSslKeys
-import org.onap.dcae.collectors.veshv.ssl.impl.SslFactories.keyManagerFactory
-import org.onap.dcae.collectors.veshv.ssl.impl.SslFactories.trustManagerFactory
-
-/**
- * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
- * @since September 2018
- */
-open class ClientSslContextFactory : SslContextFactory() {
-
-    override fun openSslContext(openSslKeys: OpenSslKeys) = SslContextBuilder.forClient()
-            .keyManager(openSslKeys.cert.toFile(), openSslKeys.privateKey.toFile())
-            .trustManager(openSslKeys.trustedCert.toFile())
-            .sslProvider(SslProvider.OPENSSL)!!
-
-    override fun jdkContext(jdkKeys: JdkKeys) =
-            try {
-                val kmf = keyManagerFactory(jdkKeys)
-                val tmf = trustManagerFactory(jdkKeys)
-                SslContextBuilder.forClient()
-                        .keyManager(kmf)
-                        .trustManager(tmf)
-                        .sslProvider(SslProvider.JDK)!!
-            } finally {
-                jdkKeys.forgetPasswords()
-            }
-
-}
diff --git a/sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactory.kt b/sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactory.kt
deleted file mode 100644 (file)
index d26937f..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * dcaegen2-collectors-veshv
- * ================================================================================
- * Copyright (C) 2018 NOKIA
- * ================================================================================
- * 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.dcae.collectors.veshv.ssl.boundary
-
-import io.netty.handler.ssl.SslContextBuilder
-import io.netty.handler.ssl.SslProvider
-import org.onap.dcae.collectors.veshv.domain.JdkKeys
-import org.onap.dcae.collectors.veshv.domain.OpenSslKeys
-import org.onap.dcae.collectors.veshv.ssl.impl.SslFactories.keyManagerFactory
-import org.onap.dcae.collectors.veshv.ssl.impl.SslFactories.trustManagerFactory
-
-/**
- * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
- * @since September 2018
- */
-open class ServerSslContextFactory : SslContextFactory() {
-
-    override fun openSslContext(openSslKeys: OpenSslKeys) = SslContextBuilder
-            .forServer(openSslKeys.cert.toFile(), openSslKeys.privateKey.toFile())
-            .trustManager(openSslKeys.trustedCert.toFile())
-            .sslProvider(SslProvider.OPENSSL)!!
-
-    override fun jdkContext(jdkKeys: JdkKeys) =
-            try {
-                val kmf = keyManagerFactory(jdkKeys)
-                val tmf = trustManagerFactory(jdkKeys)
-                SslContextBuilder.forServer(kmf)
-                        .trustManager(tmf)
-                        .sslProvider(SslProvider.JDK)!!
-            } finally {
-                jdkKeys.forgetPasswords()
-            }
-}
index cad81ee..8a5959d 100644 (file)
 package org.onap.dcae.collectors.veshv.ssl.boundary
 
 import arrow.core.Option
-import io.netty.handler.ssl.ClientAuth
 import io.netty.handler.ssl.SslContext
-import io.netty.handler.ssl.SslContextBuilder
-import org.onap.dcae.collectors.veshv.domain.JdkKeys
-import org.onap.dcae.collectors.veshv.domain.OpenSslKeys
 import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
+import org.onap.dcaegen2.services.sdk.security.ssl.SslFactory
 
 /**
  * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
  * @since September 2018
  */
-abstract class SslContextFactory {
-    fun createSslContext(secConfig: SecurityConfiguration): Option<SslContext> =
-            if (secConfig.sslDisable) {
-                Option.empty()
-            } else {
-                createSslContextWithConfiguredCerts(secConfig)
-                        .map { builder ->
-                            builder.clientAuth(ClientAuth.REQUIRE)
-                                    .build()
-                        }
-            }
+class SslContextFactory(private val sslFactory: SslFactory = SslFactory()) {
+    fun createServerContext(secConfig: SecurityConfiguration): Option<SslContext> =
+            secConfig.keys.map { sslFactory.createSecureServerContext(it) }
+    fun createClientContext(secConfig: SecurityConfiguration): Option<SslContext> =
+            secConfig.keys.map { sslFactory.createSecureClientContext(it) }
 
-    protected open fun createSslContextWithConfiguredCerts(
-            secConfig: SecurityConfiguration
-    ): Option<SslContextBuilder> =
-            secConfig.keys.map { keys ->
-                when (keys) {
-                    is JdkKeys -> jdkContext(keys)
-                    is OpenSslKeys -> openSslContext(keys)
-                }
-            }
-
-    protected abstract fun openSslContext(openSslKeys: OpenSslKeys): SslContextBuilder
-    protected abstract fun jdkContext(jdkKeys: JdkKeys): SslContextBuilder
 }
index d3640c8..fb14263 100644 (file)
 package org.onap.dcae.collectors.veshv.ssl.boundary
 
 import arrow.core.None
-import arrow.core.Option
 import arrow.core.Some
-import arrow.core.fix
-import arrow.instances.option.monad.monad
-import arrow.typeclasses.binding
+import arrow.core.Try
+import arrow.core.getOrElse
 import org.apache.commons.cli.CommandLine
-import org.onap.dcae.collectors.veshv.domain.JdkKeys
 import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption
 import org.onap.dcae.collectors.veshv.utils.commandline.hasOption
 import org.onap.dcae.collectors.veshv.utils.commandline.stringValue
-import java.io.File
+import org.onap.dcaegen2.services.sdk.security.ssl.ImmutableSecurityKeys
+import org.onap.dcaegen2.services.sdk.security.ssl.ImmutableSecurityKeysStore
+import org.onap.dcaegen2.services.sdk.security.ssl.Passwords
+import java.nio.file.Paths
 
 /**
  * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
  * @since September 2018
  */
 
-
 const val KEY_STORE_FILE = "/etc/ves-hv/server.p12"
 const val TRUST_STORE_FILE = "/etc/ves-hv/trust.p12"
 
-fun createSecurityConfiguration(cmdLine: CommandLine): Option<SecurityConfiguration> {
-    val sslDisable = cmdLine.hasOption(CommandLineOption.SSL_DISABLE)
-
-    return if (sslDisable) disabledSecurityConfiguration(sslDisable) else enabledSecurityConfiguration(cmdLine)
-}
+fun createSecurityConfiguration(cmdLine: CommandLine): Try<SecurityConfiguration> =
+        if (cmdLine.hasOption(CommandLineOption.SSL_DISABLE))
+            Try { disabledSecurityConfiguration() }
+        else
+            enabledSecurityConfiguration(cmdLine)
 
-private fun disabledSecurityConfiguration(sslDisable: Boolean): Some<SecurityConfiguration> {
-    return Some(SecurityConfiguration(
-            sslDisable = sslDisable,
-            keys = None
-    ))
-}
+private fun disabledSecurityConfiguration() = SecurityConfiguration(keys = None)
 
-private fun enabledSecurityConfiguration(cmdLine: CommandLine): Option<SecurityConfiguration> {
-    return Option.monad().binding {
-        val ksFile = cmdLine.stringValue(CommandLineOption.KEY_STORE_FILE, KEY_STORE_FILE)
-        val ksPass = cmdLine.stringValue(CommandLineOption.KEY_STORE_PASSWORD).bind()
-        val tsFile = cmdLine.stringValue(CommandLineOption.TRUST_STORE_FILE, TRUST_STORE_FILE)
-        val tsPass = cmdLine.stringValue(CommandLineOption.TRUST_STORE_PASSWORD).bind()
+private fun enabledSecurityConfiguration(cmdLine: CommandLine) = Try {
+    val ksFile = cmdLine.stringValue(CommandLineOption.KEY_STORE_FILE, KEY_STORE_FILE)
+    val ksPass = cmdLine.stringValue(CommandLineOption.KEY_STORE_PASSWORD).getOrElse { "" }
+    val tsFile = cmdLine.stringValue(CommandLineOption.TRUST_STORE_FILE, TRUST_STORE_FILE)
+    val tsPass = cmdLine.stringValue(CommandLineOption.TRUST_STORE_PASSWORD).getOrElse { "" }
 
-        val keys = JdkKeys(
-                keyStore = streamFromFile(ksFile),
-                keyStorePassword = ksPass.toCharArray(),
-                trustStore = streamFromFile(tsFile),
-                trustStorePassword = tsPass.toCharArray()
-        )
+    val keys = ImmutableSecurityKeys.builder()
+            .keyStore(ImmutableSecurityKeysStore.of(pathFromFile(ksFile)))
+            .keyStorePassword(Passwords.fromString(ksPass))
+            .trustStore(ImmutableSecurityKeysStore.of(pathFromFile(tsFile)))
+            .trustStorePassword(Passwords.fromString(tsPass))
+            .build()
 
-        SecurityConfiguration(
-                sslDisable = false,
-                keys = Some(keys)
-        )
-    }.fix()
+    SecurityConfiguration(keys = Some(keys))
 }
 
-private fun streamFromFile(file: String) = { File(file).inputStream() }
+private fun pathFromFile(file: String) = Paths.get(file)
diff --git a/sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/impl/SslFactories.kt b/sources/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/impl/SslFactories.kt
deleted file mode 100644 (file)
index 4a73a2a..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * dcaegen2-collectors-veshv
- * ================================================================================
- * Copyright (C) 2018 NOKIA
- * ================================================================================
- * 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.dcae.collectors.veshv.ssl.impl
-
-import org.onap.dcae.collectors.veshv.domain.JdkKeys
-import org.onap.dcae.collectors.veshv.domain.StreamProvider
-import java.security.KeyStore
-import javax.net.ssl.KeyManagerFactory
-import javax.net.ssl.TrustManagerFactory
-
-/**
- * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
- * @since September 2018
- */
-internal object SslFactories {
-
-    fun trustManagerFactory(jdkKeys: JdkKeys): TrustManagerFactory? {
-        val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
-        val ts = loadKeyStoreFromFile(jdkKeys.trustStore, jdkKeys.trustStorePassword)
-        tmf.init(ts)
-        return tmf
-    }
-
-    fun keyManagerFactory(jdkKeys: JdkKeys): KeyManagerFactory? {
-        val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
-        val ks = loadKeyStoreFromFile(jdkKeys.keyStore, jdkKeys.keyStorePassword)
-        kmf.init(ks, jdkKeys.keyStorePassword)
-        return kmf
-    }
-
-    private fun loadKeyStoreFromFile(streamProvider: StreamProvider, password: CharArray): KeyStore {
-        val ks = KeyStore.getInstance("pkcs12")
-        streamProvider().use {
-            ks.load(it, password)
-        }
-        return ks
-    }
-}
diff --git a/sources/hv-collector-ssl/src/test/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactoryTest.kt b/sources/hv-collector-ssl/src/test/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactoryTest.kt
deleted file mode 100644 (file)
index 7e0bc60..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * dcaegen2-collectors-veshv
- * ================================================================================
- * Copyright (C) 2018 NOKIA
- * ================================================================================
- * 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.dcae.collectors.veshv.ssl.boundary
-
-import arrow.core.Some
-import arrow.core.toOption
-import io.netty.handler.ssl.ClientAuth
-import io.netty.handler.ssl.JdkSslContext
-import io.netty.handler.ssl.ReferenceCountedOpenSslContext
-import io.netty.handler.ssl.SslContextBuilder
-import org.assertj.core.api.Assertions
-import org.assertj.core.api.Assertions.assertThat
-import org.jetbrains.spek.api.Spek
-import org.jetbrains.spek.api.dsl.describe
-import org.jetbrains.spek.api.dsl.given
-import org.jetbrains.spek.api.dsl.it
-import org.jetbrains.spek.api.dsl.on
-import org.onap.dcae.collectors.veshv.domain.JdkKeys
-import org.onap.dcae.collectors.veshv.domain.OpenSslKeys
-import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
-import java.nio.file.Paths
-import kotlin.test.assertTrue
-
-/**
- * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
- * @since June 2018
- */
-object ServerSslContextFactoryTest : Spek({
-    val PASSWORD = "onap"
-
-    describe("SslContextFactory (OpenSSL)") {
-        val keys = OpenSslKeys(
-                privateKey = Paths.get("/", "tmp", "pk.pem"),
-                cert = Paths.get("/", "tmp", "cert.crt"),
-                trustedCert = Paths.get("/", "tmp", "clientCa.crt"))
-
-        given("config with security enabled") {
-            val sampleConfig = SecurityConfiguration(keys = Some(keys))
-
-            val cut = object : ServerSslContextFactory() {
-                override fun createSslContextWithConfiguredCerts(secConfig: SecurityConfiguration) =
-                    SslContextBuilder.forServer(resource("/ssl/ca.crt"), resource("/ssl/server.key")).toOption()
-
-                private fun resource(path: String) = ServerSslContextFactoryTest.javaClass.getResourceAsStream(path)
-            }
-
-            on("creation of SSL context") {
-                val result = cut.createSslContext(sampleConfig)
-
-                it("should be server context") {
-                    assertTrue(result.exists {
-                        it.isServer
-                    })
-                }
-
-                it("should use OpenSSL provider") {
-                    assertTrue(result.isDefined())
-                }
-
-                /*
-                 * It is too important to leave it untested on unit level.
-                 * Because of the Netty API design we need to do it this way.
-                 */
-                it("should turn on client authentication") {
-                    val clientAuth: ClientAuth = ReferenceCountedOpenSslContext::class.java
-                            .getDeclaredField("clientAuth")
-                            .run {
-                                isAccessible = true
-                                get(result.orNull()) as ClientAuth
-                            }
-                    Assertions.assertThat(clientAuth).isEqualTo(ClientAuth.REQUIRE)
-                }
-            }
-        }
-
-        given("config with SSL disabled") {
-            val securityConfiguration = SecurityConfiguration(
-                    sslDisable = true,
-                    keys = Some(keys)
-            )
-            val cut = ServerSslContextFactory()
-
-            on("creation of SSL context") {
-                val result = cut.createSslContext(securityConfiguration)
-
-                it("should not create any SSL context ") {
-                    assertThat(result.isDefined()).isFalse()
-                }
-            }
-        }
-    }
-
-    describe("SslContextFactory (JDK)") {
-        val keys = JdkKeys(
-                keyStore = resourceStreamProvider("/ssl/server.ks.pkcs12"),
-                keyStorePassword = PASSWORD.toCharArray(),
-                trustStore = resourceStreamProvider("/ssl/trust.pkcs12"),
-                trustStorePassword = PASSWORD.toCharArray()
-        )
-
-        given("config without disabled SSL") {
-            val sampleConfig = SecurityConfiguration(keys = Some(keys))
-            val cut = ServerSslContextFactory()
-
-            on("creation of SSL context") {
-                val result = cut.createSslContext(sampleConfig)
-
-                it("should work") {
-                    assertTrue(result.isDefined())
-                }
-
-                it("should be server context") {
-                    assertTrue(result.exists {
-                        it.isServer
-                    })
-                }
-
-                /*
-                 * It is too important to leave it untested on unit level.
-                 * Because of the Netty API design we need to do it this way.
-                 */
-                it("should turn on client authentication") {
-                    val clientAuth: ClientAuth = JdkSslContext::class.java
-                            .getDeclaredField("clientAuth")
-                            .run {
-                                isAccessible = true
-                                get(result.orNull()) as ClientAuth
-                            }
-                    Assertions.assertThat(clientAuth).isEqualTo(ClientAuth.REQUIRE)
-                }
-
-                it("should clear passwords so heap dumps won't contain them") {
-                    val xedPassword = PASSWORD.toCharArray()
-                    xedPassword.fill('x')
-                    Assertions.assertThat(keys.keyStorePassword).isEqualTo(xedPassword)
-                    Assertions.assertThat(keys.trustStorePassword).isEqualTo(xedPassword)
-                }
-            }
-        }
-    }
-})
-
-fun resourceStreamProvider(resource: String) = { ServerSslContextFactoryTest::class.java.getResourceAsStream(resource) }
diff --git a/sources/hv-collector-ssl/src/test/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/SslContextFactoryTest.kt b/sources/hv-collector-ssl/src/test/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/SslContextFactoryTest.kt
new file mode 100644 (file)
index 0000000..f9c6726
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2019 NOKIA
+ * ================================================================================
+ * 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.dcae.collectors.veshv.ssl.boundary
+
+import arrow.core.None
+import arrow.core.Some
+import com.nhaarman.mockitokotlin2.mock
+import com.nhaarman.mockitokotlin2.verify
+import org.assertj.core.api.Assertions.assertThat
+import org.jetbrains.spek.api.Spek
+import org.jetbrains.spek.api.dsl.given
+import org.jetbrains.spek.api.dsl.it
+import org.jetbrains.spek.api.dsl.on
+import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
+import org.onap.dcaegen2.services.sdk.security.ssl.ImmutableSecurityKeys
+import org.onap.dcaegen2.services.sdk.security.ssl.ImmutableSecurityKeysStore
+import org.onap.dcaegen2.services.sdk.security.ssl.Passwords
+import org.onap.dcaegen2.services.sdk.security.ssl.SslFactory
+import java.nio.file.Paths
+
+/**
+ * @author <a href="mailto:piotr.jaszczyk@nokia.com">Piotr Jaszczyk</a>
+ * @since February 2019
+ */
+internal object SslContextFactoryTest : Spek({
+    val sslFactory: SslFactory = mock()
+    val cut = SslContextFactory(sslFactory)
+
+    given("empty security configuration") {
+        val secConfig = SecurityConfiguration(None)
+
+        on("creating server context") {
+            val result = cut.createServerContext(secConfig)
+
+            it("should return None") {
+                assertThat(result.isDefined()).isFalse()
+            }
+        }
+
+        on("creating client context") {
+            val result = cut.createClientContext(secConfig)
+
+            it("should return None") {
+                assertThat(result.isDefined()).isFalse()
+            }
+        }
+    }
+
+    given("security configuration with keys") {
+        val keys = ImmutableSecurityKeys.builder()
+                .trustStore(ImmutableSecurityKeysStore.of(Paths.get("ts.jks")))
+                .trustStorePassword(Passwords.fromString("xxx"))
+                .keyStore(ImmutableSecurityKeysStore.of(Paths.get("ks.pkcs12")))
+                .keyStorePassword(Passwords.fromString("yyy"))
+                .build()
+        val secConfig = SecurityConfiguration(Some(keys))
+
+        on("creating server context") {
+            val result = cut.createServerContext(secConfig)
+
+            it("should return Some") {
+                assertThat(result.isDefined()).isTrue()
+            }
+
+            it("should have called SslFactory") {
+                verify(sslFactory).createSecureServerContext(keys)
+            }
+        }
+
+        on("creating client context") {
+            val result = cut.createClientContext(secConfig)
+
+            it("should return Some") {
+                assertThat(result.isDefined()).isTrue()
+            }
+
+            it("should have called SslFactory") {
+                verify(sslFactory).createSecureClientContext(keys)
+            }
+        }
+    }
+
+})
\ No newline at end of file
index cb1c622..bedc2fc 100644 (file)
@@ -52,4 +52,8 @@ fun <A, B> Either<A, B>.doOnLeft(action: () -> Unit): Either<A, B> = apply { if
 
 fun <A> Option<A>.doOnEmpty(action: () -> Unit): Option<A> = apply { if (isEmpty()) action() }
 
-fun <A> Try<A>.doOnFailure(action: () -> Unit): Try<A> = apply { if (isFailure()) action() }
+fun <A> Try<A>.doOnFailure(action: (Throwable) -> Unit): Try<A> = apply {
+    if (this is Try.Failure) {
+        action(exception)
+    }
+}
index e869901..aaa8ff8 100644 (file)
@@ -106,11 +106,11 @@ enum class CommandLineOption(val option: Option, val required: Boolean = false)
             .build()
     ),
     KEY_STORE_PASSWORD(
-        Option.builder("kp")
-            .longOpt("key-store-password")
-            .hasArg()
-            .desc("Key store password")
-            .build()
+            Option.builder("kp")
+                    .longOpt("key-store-password")
+                    .hasArg()
+                    .desc("Key store password")
+                    .build()
     ),
     TRUST_STORE_FILE(
         Option.builder("t")
index db5e5e8..eba8ed8 100644 (file)
@@ -26,7 +26,7 @@ import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
 import org.onap.dcae.collectors.veshv.domain.WireFrameEncoder
 import org.onap.dcae.collectors.veshv.domain.WireFrameMessage
 import org.onap.dcae.collectors.veshv.simulators.xnf.impl.config.SimulatorConfiguration
-import org.onap.dcae.collectors.veshv.ssl.boundary.ClientSslContextFactory
+import org.onap.dcae.collectors.veshv.ssl.boundary.SslContextFactory
 import org.onap.dcae.collectors.veshv.utils.arrow.asIo
 import org.onap.dcae.collectors.veshv.utils.logging.Logger
 import org.reactivestreams.Publisher
@@ -91,7 +91,7 @@ class VesHvClient(private val configuration: SimulatorConfiguration) {
     }
 
     private fun createSslContext(config: SecurityConfiguration): Option<SslContext> =
-            ClientSslContextFactory().createSslContext(config)
+            SslContextFactory().createClientContext(config)
 
     private fun NettyOutbound.logConnectionClosed() =
             withConnection { conn ->
index 7885514..b5751a3 100644 (file)
@@ -27,6 +27,7 @@ import org.apache.commons.cli.CommandLine
 import org.apache.commons.cli.DefaultParser
 import org.onap.dcae.collectors.veshv.domain.WireFrameMessage
 import org.onap.dcae.collectors.veshv.ssl.boundary.createSecurityConfiguration
+import org.onap.dcae.collectors.veshv.utils.arrow.doOnFailure
 import org.onap.dcae.collectors.veshv.utils.commandline.ArgBasedConfiguration
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.VES_HV_PORT
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.VES_HV_HOST
@@ -40,6 +41,7 @@ import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.TRUST_
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.TRUST_STORE_PASSWORD
 import org.onap.dcae.collectors.veshv.utils.commandline.intValue
 import org.onap.dcae.collectors.veshv.utils.commandline.stringValue
+import org.onap.dcae.collectors.veshv.utils.logging.Logger
 import java.net.InetSocketAddress
 
 /**
@@ -69,15 +71,28 @@ internal class ArgXnfSimulatorConfiguration : ArgBasedConfiguration<SimulatorCon
                 val maxPayloadSizeBytes = cmdLine.intValue(MAXIMUM_PAYLOAD_SIZE_BYTES,
                         WireFrameMessage.DEFAULT_MAX_PAYLOAD_SIZE_BYTES)
 
+                val security = createSecurityConfiguration(cmdLine)
+                    .doOnFailure { ex ->
+                        logger.withError {
+                            log("Could not read security keys", ex)
+                        }
+                    }
+                    .toOption()
+                    .bind()
+
                 SimulatorConfiguration(
                         InetSocketAddress(listenPort),
                         InetSocketAddress(healthCheckApiListenAddress),
                         InetSocketAddress(vesHost, vesPort),
                         maxPayloadSizeBytes,
-                        createSecurityConfiguration(cmdLine).bind())
+                        security)
             }.fix()
 
     internal object DefaultValues {
         const val HEALTH_CHECK_API_PORT = 6063
     }
+
+    companion object {
+        private val logger = Logger(ArgXnfSimulatorConfiguration::class)
+    }
 }