Use JDK security provider 57/68057/8
authorPiotr Jaszczyk <piotr.jaszczyk@nokia.com>
Thu, 20 Sep 2018 10:04:03 +0000 (12:04 +0200)
committerPiotr Jaszczyk <piotr.jaszczyk@nokia.com>
Mon, 24 Sep 2018 12:25:32 +0000 (14:25 +0200)
Replace netty-tcnative bindings for OpenSSL with JDK provided
implementation by default.

Change-Id: I59a4797ce43d15a791eab00bfd25cb730a271207
Issue-ID: DCAEGEN2-816
Signed-off-by: Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
41 files changed:
docker-compose.yml
hv-collector-core/pom.xml
hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/factory/ServerFactory.kt
hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/NettyTcpServer.kt
hv-collector-core/src/test/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactoryTest.kt [deleted file]
hv-collector-core/src/test/resources/logback-test.xml
hv-collector-core/src/test/resources/ssl/ca.crt [deleted file]
hv-collector-core/src/test/resources/ssl/server.crt [deleted file]
hv-collector-core/src/test/resources/ssl/server.key [deleted file]
hv-collector-dcae-app-simulator/src/main/kotlin/org/onap/dcae/collectors/veshv/simulators/dcaeapp/impl/config/ArgDcaeAppSimConfiguration.kt
hv-collector-domain/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/SecurityConfiguration.kt
hv-collector-main/Dockerfile
hv-collector-main/pom.xml
hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/ArgVesHvConfiguration.kt
hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/ArgVesHvConfigurationTest.kt
hv-collector-ssl/pom.xml [new file with mode: 0644]
hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ClientSslContextFactory.kt [new file with mode: 0644]
hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactory.kt [new file with mode: 0644]
hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/SslContextFactory.kt [moved from hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactory.kt with 59% similarity]
hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/utils.kt [new file with mode: 0644]
hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/impl/SslFactories.kt [new file with mode: 0644]
hv-collector-ssl/src/test/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactoryTest.kt [new file with mode: 0644]
hv-collector-ssl/src/test/resources/logback-test.xml [new file with mode: 0644]
hv-collector-ssl/src/test/resources/ssl/ca.crt [new file with mode: 0644]
hv-collector-ssl/src/test/resources/ssl/server.crt [new file with mode: 0644]
hv-collector-ssl/src/test/resources/ssl/server.key [new file with mode: 0644]
hv-collector-ssl/src/test/resources/ssl/server.ks.pkcs12 [new file with mode: 0644]
hv-collector-ssl/src/test/resources/ssl/trust.pkcs12 [new file with mode: 0644]
hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/ArgBasedConfiguration.kt
hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOption.kt
hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/extensions.kt
hv-collector-xnf-simulator/Dockerfile
hv-collector-xnf-simulator/pom.xml
hv-collector-xnf-simulator/src/main/kotlin/org/onap/dcae/collectors/veshv/simulators/xnf/impl/adapters/VesHvClient.kt
hv-collector-xnf-simulator/src/main/kotlin/org/onap/dcae/collectors/veshv/simulators/xnf/impl/config/ArgXnfSimulatorConfiguration.kt
hv-collector-xnf-simulator/src/test/kotlin/org/onap/dcae/collectors/veshv/main/config/ArgXnfSimulatorConfiurationTest.kt [deleted file]
pom.xml
ssl/.gitignore
ssl/Makefile-openssl [moved from ssl/Makefile with 64% similarity]
ssl/README.md
ssl/gen-certs.sh [new file with mode: 0755]

index f37c823..fb8ff56 100644 (file)
@@ -39,7 +39,9 @@ services:
                  "-cp", "*:", "org.onap.dcae.collectors.veshv.main.MainKt"]
     command: ["--listen-port", "6061",
               "--health-check-api-port", "6060",
-              "--config-url", "http://consul:8500/v1/kv/veshv-config"]
+              "--config-url", "http://consul:8500/v1/kv/veshv-config",
+              "--key-store-password", "onaponap",
+              "--trust-store-password", "onaponap"]
     healthcheck:
       test: curl -f http://localhost:6060/health/ready || exit 1
       interval: 10s
@@ -59,7 +61,11 @@ services:
 #      dockerfile: Dockerfile
     ports:
       - "6062:6062/tcp"
-    command: ["--listen-port", "6062", "--ves-host", "ves-hv-collector", "--ves-port", "6061"]
+    command: ["--listen-port", "6062",
+              "--ves-host", "ves-hv-collector",
+              "--ves-port", "6061",
+              "--key-store-password", "onaponap",
+              "--trust-store-password", "onaponap"]
     depends_on:
       - ves-hv-collector
     volumes:
@@ -72,6 +78,8 @@ services:
 #      dockerfile: Dockerfile
     ports:
       - "6063:6063/tcp"
-    command: ["--listen-port", "6063", "--kafka-bootstrap-servers", "kafka:9092", "--kafka-topics", "ves_hvRanMeas"]
+    command: ["--listen-port", "6063",
+              "--kafka-bootstrap-servers", "kafka:9092",
+              "--kafka-topics", "ves_hvRanMeas"]
     depends_on:
       - kafka
index 9f4afe4..edc3e2f 100644 (file)
     </build>
 
     <dependencies>
+        <dependency>
+            <groupId>${project.parent.groupId}</groupId>
+            <artifactId>hv-collector-ssl</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
         <dependency>
             <groupId>${project.parent.groupId}</groupId>
             <artifactId>hv-collector-utils</artifactId>
             <groupId>io.projectreactor.kafka</groupId>
             <artifactId>reactor-kafka</artifactId>
         </dependency>
-        <dependency>
-            <groupId>io.netty</groupId>
-            <artifactId>netty-tcnative-boringssl-static</artifactId>
-            <scope>runtime</scope>
-            <classifier>${os.detected.classifier}</classifier>
-        </dependency>
         <dependency>
             <groupId>javax.json</groupId>
             <artifactId>javax.json-api</artifactId>
index 32fe6eb..dce933a 100644 (file)
@@ -21,9 +21,9 @@ package org.onap.dcae.collectors.veshv.factory
 
 import org.onap.dcae.collectors.veshv.boundary.CollectorProvider
 import org.onap.dcae.collectors.veshv.boundary.Server
-import org.onap.dcae.collectors.veshv.model.ServerConfiguration
 import org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer
-import org.onap.dcae.collectors.veshv.impl.socket.SslContextFactory
+import org.onap.dcae.collectors.veshv.model.ServerConfiguration
+import org.onap.dcae.collectors.veshv.ssl.boundary.ServerSslContextFactory
 
 /**
  * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
@@ -31,5 +31,5 @@ import org.onap.dcae.collectors.veshv.impl.socket.SslContextFactory
  */
 object ServerFactory {
     fun createNettyTcpServer(serverConfiguration: ServerConfiguration, collectorProvider: CollectorProvider): Server =
-            NettyTcpServer(serverConfiguration, SslContextFactory(), collectorProvider)
+            NettyTcpServer(serverConfiguration, ServerSslContextFactory(), collectorProvider)
 }
index b4ad4b7..ede5a66 100644 (file)
@@ -25,6 +25,7 @@ import io.netty.handler.ssl.SslContext
 import org.onap.dcae.collectors.veshv.boundary.CollectorProvider
 import org.onap.dcae.collectors.veshv.boundary.Server
 import org.onap.dcae.collectors.veshv.model.ServerConfiguration
+import org.onap.dcae.collectors.veshv.ssl.boundary.ServerSslContextFactory
 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
@@ -43,7 +44,7 @@ import java.util.function.BiFunction
  * @since May 2018
  */
 internal class NettyTcpServer(private val serverConfig: ServerConfiguration,
-                              private val sslContextFactory: SslContextFactory,
+                              private val sslContextFactory: ServerSslContextFactory,
                               private val collectorProvider: CollectorProvider) : Server {
 
     override fun start(): IO<ServerHandle> = IO {
diff --git a/hv-collector-core/src/test/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactoryTest.kt b/hv-collector-core/src/test/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactoryTest.kt
deleted file mode 100644 (file)
index deb4e18..0000000
+++ /dev/null
@@ -1,103 +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.impl.socket
-
-import io.netty.handler.ssl.ClientAuth
-import io.netty.handler.ssl.ReferenceCountedOpenSslContext
-import io.netty.handler.ssl.SslContextBuilder
-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.SecurityConfiguration
-import java.nio.file.Paths
-import kotlin.test.assertTrue
-
-/**
- * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
- * @since June 2018
- */
-object SslContextFactoryTest : Spek({
-    describe("SslContextFactory") {
-        given("config without disabled SSL") {
-            val sampleConfig = SecurityConfiguration(
-                    privateKey = Paths.get("/", "tmp", "pk.pem"),
-                    cert = Paths.get("/", "tmp", "cert.crt"),
-                    trustedCert = Paths.get("/", "tmp", "clientCa.crt"))
-
-            val cut = object : SslContextFactory() {
-                override fun createSslContextWithConfiguredCerts(secConfig: SecurityConfiguration): SslContextBuilder {
-                    return SslContextBuilder.forServer(resource("/ssl/ca.crt"), resource("/ssl/server.key"))
-                }
-
-                private fun resource(path: String) = SslContextFactoryTest.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
-                            }
-                    assertThat(clientAuth).isEqualTo(ClientAuth.REQUIRE)
-                }
-            }
-        }
-
-        given("config with SSL disabled") {
-            val securityConfiguration = SecurityConfiguration(
-                    sslDisable = true,
-                    privateKey = Paths.get("sample", "key"),
-                    cert = Paths.get("sample", "cert"),
-                    trustedCert = Paths.get("/", "sample", "trusted", "cert")
-            )
-            val cut = SslContextFactory()
-
-            on("creation of SSL context") {
-                val result = cut.createSslContext(securityConfiguration)
-
-                it("should not create any SSL context ") {
-                    assertThat(result.isDefined()).isFalse()
-                }
-            }
-        }
-
-    }
-})
index 84abc9d..9a4eacf 100644 (file)
@@ -32,4 +32,4 @@
       <appender-ref ref="CONSOLE"/>
       <appender-ref ref="ROLLING-FILE"/>
     </root>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/hv-collector-core/src/test/resources/ssl/ca.crt b/hv-collector-core/src/test/resources/ssl/ca.crt
deleted file mode 100644 (file)
index 29057f2..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDbDCCAlSgAwIBAgIJANad+zi5MeDSMA0GCSqGSIb3DQEBCwUAMEsxCzAJBgNV
-BAYTAlBMMQswCQYDVQQIDAJETDEQMA4GA1UEBwwHV3JvY2xhdzEOMAwGA1UECgwF
-Tm9raWExDTALBgNVBAsMBE1BTk8wHhcNMTgwNjAxMTMwOTE2WhcNMTkwNjAxMTMw
-OTE2WjBLMQswCQYDVQQGEwJQTDELMAkGA1UECAwCREwxEDAOBgNVBAcMB1dyb2Ns
-YXcxDjAMBgNVBAoMBU5va2lhMQ0wCwYDVQQLDARNQU5PMIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEArqcdlj5G4OTByGfZQ+vvdFX2ZPGKKUmUV6JYjbQH
-v9C131WD2GFpbE9fAXG+R0n9c+0mbqUj3rnHzB6g5zUJBCJZXk4mM9KTq5iUfFU1
-uSQGWVCkgqmWijCROR2Eqm+v/vaSCqj77EuDEqmLe8EkFOaOKGMMdlJYYfPAyExu
-k1qfmeXGzD0c/YR6ks72GW2q2xWDujvddOuxAC7CYa1iLTYSh39KLfDuoOvktqI0
-syCTyPExvmltJsb9N3AN78g+TObfAWGnkpD+QHlB1X52DU0S05+8OUkhV43aX1cd
-8cIQrCvJUL/FPKe3AKgyEbLjbhkQhGQhOyjM1ptKuMucSwIDAQABo1MwUTAdBgNV
-HQ4EFgQUBtX8BzxCxBS7ZTTL0pe8XcSp+McwHwYDVR0jBBgwFoAUBtX8BzxCxBS7
-ZTTL0pe8XcSp+McwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA
-niw6/qRG5ULJ6OTUd4kvw4i42EV3aV9ypd+EIzv3IuqNZBu4vqYoUSRoc1n6YwPZ
-YcDq0xrVi5uw8zRR8M4/GhhT4jGLxjPHD1Jby7IyuPzByBsMJUNfdjYHjebEC820
-WJ8nbHaGm3cJVB4zMlJd5gA5+R8vp4OQmQsULxoWhDn09X4IXb/izOSK5YClf/XB
-W2mQyYeAb+2H7q9fT5VVJved6h2BZsmq+SQSKlXnBMIvEjpgh7RLUuuANMgival6
-NlSezPQD9iuyj9g2Xz3z8ggRGahYPSKAb6+fg3TGg/Vokd4GYEMflfC2tw+eM07n
-oTa03o8tD9V4paP/vx7cUg==
------END CERTIFICATE-----
diff --git a/hv-collector-core/src/test/resources/ssl/server.crt b/hv-collector-core/src/test/resources/ssl/server.crt
deleted file mode 100644 (file)
index 0af22e2..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDEjCCAfoCCQDSzpBZljMk+jANBgkqhkiG9w0BAQsFADBLMQswCQYDVQQGEwJQ
-TDELMAkGA1UECAwCREwxEDAOBgNVBAcMB1dyb2NsYXcxDjAMBgNVBAoMBU5va2lh
-MQ0wCwYDVQQLDARNQU5PMB4XDTE4MDYwMTEzMDkxNloXDTE5MDUyNzEzMDkxNlow
-SzELMAkGA1UEBhMCUEwxCzAJBgNVBAgMAkRMMRAwDgYDVQQHDAdXcm9jbGF3MQ4w
-DAYDVQQKDAVOb2tpYTENMAsGA1UECwwETUFOTzCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBAOdOjGM8+5+ArMawknY+QPTO4Q//QuRi46OxkU28DshayG1o
-pyCoKD6zYB4Q7cgSY8xrwX7Ct6QINaGefSddKdDJl4zzjiVCUK7vaKxaOK2hOl7k
-Iq7HuvAG6TaO7CaeBFafGNxpocgC2WkoZCIqQ32gXHjU5mpTrzwtUyX91Xc43puP
-nHGBz6XDVlV52DvJQ1v9xed4bM70DgSg3FcD77mcPDbr98UvPa477RKeAz8eAc+J
-jxMg8uNGYX0sthGEcOiOf1Dz8UeMU1M2Qw6MGDqrW+RMaM9K8/mlbQ/SFqoPg4MD
-q3zbQie0IzfanQuygz9Zy7dDAVgzmjrX8/tf+nMCAwEAATANBgkqhkiG9w0BAQsF
-AAOCAQEALPII5UXwBSNGcVa14t3NUUb0jtXdtmKr6sRMqFdR81tREcJHGnMauxO9
-IuECQuDkIRkv2XR+Swn2vZdOkYtHSAHSRLxPUhwjYKFC7uTd6T1ljTiYJ/NtGCV3
-75n0qh2aneCXr9KVExK6KzYVFJKMKmbEJludaQrM/Z+kDXGwwUMcyb8LLO+avgek
-ke1796f0MJ56csHejT9V69/6zc07T/zn0gVcR42AnMr/MzhAkiqUOhy0Cxzek0Xv
-72/1PKaf2r9F+WtjQuPRd6LJrM7yTnkzLz7xK+yX17mycIN4KsVf8zhrsCgVJZGL
-kLkC4O9faHnrtj0qqV+BPhyF1Ii95w==
------END CERTIFICATE-----
diff --git a/hv-collector-core/src/test/resources/ssl/server.key b/hv-collector-core/src/test/resources/ssl/server.key
deleted file mode 100644 (file)
index 033c99a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDnToxjPPufgKzG
-sJJ2PkD0zuEP/0LkYuOjsZFNvA7IWshtaKcgqCg+s2AeEO3IEmPMa8F+wrekCDWh
-nn0nXSnQyZeM844lQlCu72isWjitoTpe5CKux7rwBuk2juwmngRWnxjcaaHIAtlp
-KGQiKkN9oFx41OZqU688LVMl/dV3ON6bj5xxgc+lw1ZVedg7yUNb/cXneGzO9A4E
-oNxXA++5nDw26/fFLz2uO+0SngM/HgHPiY8TIPLjRmF9LLYRhHDojn9Q8/FHjFNT
-NkMOjBg6q1vkTGjPSvP5pW0P0haqD4ODA6t820IntCM32p0LsoM/Wcu3QwFYM5o6
-1/P7X/pzAgMBAAECggEAYBIL1Rv7FqCHIm8sJdhtekCC0fYffmRkUBTsWPEG4shx
-/p886x9st74g6dv2JuccdEc9Mr0FMSgHvnzpVnQnbgSM4Yo3O9pzUHU3cH54lAUn
-DUqL7TQfvJniOzrZcqCnBKNH3CQzgbNNQZP5IweSyJbWUYl7uiXP3pqksl7fToiS
-JBSKzKphwtHRUHS3RCwN118N5RyZH+0LZi0EAOjxi1BVqmKQos0Zr8Gnl/7nHF+g
-oRG4vgDZUopNEGX5AELvMBq/hbSrfGT1z+wJkOtoRdinRMGFKO528vCqhEr629Sh
-FFUOv3xL7HUEEnDu97I0TxK1o6C5fG/QbeP9viiJIQKBgQD2upLpuyP6iTCdAl/S
-lLmQxwEUyD3vhF4oG+B0jKyNkzO7QzM695HH/bXV9GnRH+9HPgxLqtozVpztsuu2
-MXrac2tmJR9OiSchJwgDRvhSUyezEULFAzsIaSeGK16wrcT6xqwVeKumsKp1dW7I
-n0w5NxC/N2U87ffjmyOwldOAHwKBgQDv/58mMUutViwicw8ddRJP38QZs804vm7R
-YFb5sqt6L7hcSQCszVXdjHP2v/GeK+jl0vZrGS932kY3T2+FhA8ClbKByVdaFzXj
-PSEuY/Ow+ebGrlBPBH6sPN4Uvc00MEk1eZXRL8IaT32xJnq2vF4M7SvGNFeH39tc
-qOq9VqrrLQKBgQCRzdYN6/qqDrK8xm9sGVnD9eZsqpz3U2j1GOw+0/cQvyG+E0tO
-GIl8/zCa3JI/9DhKCJ/pg3DpD9EzIx3qkDkCqVyZg2yJ08Fc9RzmGuWaeOuoBZZI
-qM0U/ldOEYkmrboPXKLLGYGOwy4otZofUwwPb7wk1A6uwA5S4hZoP1I6jwKBgQCS
-yfH5ViVHO3F7EIyqI7SzjdVPMx3OGwuEnDwWNSWUciN8rlnvVxexjfpPbU7Gw2yL
-RODa2GikEajoo3k+XGsh1ZV8tDztKU0YU4c77H5cPDzeQDd2XPVtOz1Jylz8Epx0
-TI1JiMBbf0sNUs+zfLq5hUZE0DbJMC3nGpmYfK3FcQKBgQCFlXdwWzhu33HHa+wc
-X7JT0m8W81ex08ndNOCgdYqgOxmZ+VhK8WN91sj3N0X9nMsfSJ9WTRib+FVa8D4M
-e7hOddjrKxNcqAhjbnxeCHLExq9kYdjeXa0dS9ywP89nMlGm7qja7+9DSBPisRPe
-lcaTvr7E/zSTHK5WDBCzOsV3lQ==
------END PRIVATE KEY-----
index d5f5560..d082061 100644 (file)
@@ -31,6 +31,8 @@ import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.KAFKA_SERVERS
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.KAFKA_TOPICS
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.LISTEN_PORT
+import org.onap.dcae.collectors.veshv.utils.commandline.intValue
+import org.onap.dcae.collectors.veshv.utils.commandline.stringValue
 
 class ArgDcaeAppSimConfiguration : ArgBasedConfiguration<DcaeAppSimConfiguration>(DefaultParser()) {
     override val cmdLineOptionsList: List<CommandLineOption> = listOf(
index e409eb7..7f566a6 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.onap.dcae.collectors.veshv.domain
 
+import arrow.core.Option
+import java.io.InputStream
 import java.nio.file.Path
 
 /**
@@ -27,6 +29,22 @@ import java.nio.file.Path
  */
 data class SecurityConfiguration(
         val sslDisable: Boolean = false,
-        val privateKey: Path,
-        val cert: Path,
-        val trustedCert: Path)
+        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
index 8216ac4..746deb5 100644 (file)
@@ -6,8 +6,7 @@ LABEL license.url="http://www.apache.org/licenses/LICENSE-2.0"
 LABEL maintainer="Nokia Wroclaw ONAP Team"
 
 RUN apt-get update \
-        && apt-get install -y --no-install-recommends curl  \
-        && apt-get install -y --no-install-recommends netcat  \
+        && apt-get install -y --no-install-recommends curl netcat \
         && apt-get clean
 
 WORKDIR /opt/ves-hv-collector
index ed37515..571821a 100644 (file)
             <groupId>commons-cli</groupId>
             <artifactId>commons-cli</artifactId>
         </dependency>
+        <!-- See comment in main pom
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-native-epoll</artifactId>
+            <classifier>${os.detected.classifier}</classifier>
+        </dependency>
         <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-tcnative-boringssl-static</artifactId>
-            <scope>runtime</scope>
             <classifier>${os.detected.classifier}</classifier>
         </dependency>
+        -->
         <dependency>
             <groupId>io.micrometer</groupId>
             <artifactId>micrometer-registry-jmx</artifactId>
index 26230cd..d6ff9ef 100644 (file)
@@ -22,25 +22,31 @@ package org.onap.dcae.collectors.veshv.main
 import arrow.core.ForOption
 import arrow.core.Option
 import arrow.core.fix
+import arrow.core.monad
 import arrow.instances.extensions
 import arrow.typeclasses.binding
 import org.apache.commons.cli.CommandLine
 import org.apache.commons.cli.DefaultParser
-import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
 import org.onap.dcae.collectors.veshv.model.ConfigurationProviderParams
 import org.onap.dcae.collectors.veshv.model.ServerConfiguration
+import org.onap.dcae.collectors.veshv.ssl.boundary.createSecurityConfiguration
 import org.onap.dcae.collectors.veshv.utils.commandline.ArgBasedConfiguration
-import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.CERT_FILE
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.CONSUL_CONFIG_URL
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.CONSUL_FIRST_REQUEST_DELAY
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.CONSUL_REQUEST_INTERVAL
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.DUMMY_MODE
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.HEALTH_CHECK_API_PORT
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.IDLE_TIMEOUT_SEC
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.KEY_STORE_FILE
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.KEY_STORE_PASSWORD
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.LISTEN_PORT
-import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.PRIVATE_KEY_FILE
 import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.SSL_DISABLE
-import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.TRUST_CERT_FILE
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.TRUST_STORE_FILE
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.TRUST_STORE_PASSWORD
+import org.onap.dcae.collectors.veshv.utils.commandline.hasOption
+import org.onap.dcae.collectors.veshv.utils.commandline.intValue
+import org.onap.dcae.collectors.veshv.utils.commandline.longValue
+import org.onap.dcae.collectors.veshv.utils.commandline.stringValue
 import java.time.Duration
 
 internal class ArgVesHvConfiguration : ArgBasedConfiguration<ServerConfiguration>(DefaultParser()) {
@@ -51,34 +57,33 @@ internal class ArgVesHvConfiguration : ArgBasedConfiguration<ServerConfiguration
             CONSUL_FIRST_REQUEST_DELAY,
             CONSUL_REQUEST_INTERVAL,
             SSL_DISABLE,
-            PRIVATE_KEY_FILE,
-            CERT_FILE,
-            TRUST_CERT_FILE,
+            KEY_STORE_FILE,
+            KEY_STORE_PASSWORD,
+            TRUST_STORE_FILE,
+            TRUST_STORE_PASSWORD,
             IDLE_TIMEOUT_SEC,
             DUMMY_MODE
     )
 
     override fun getConfiguration(cmdLine: CommandLine): Option<ServerConfiguration> =
-            ForOption extensions {
-                binding {
-                    val healthCheckApiPort = cmdLine.intValue(
-                            HEALTH_CHECK_API_PORT,
-                            DefaultValues.HEALTH_CHECK_API_PORT
-                    )
-                    val listenPort = cmdLine.intValue(LISTEN_PORT).bind()
-                    val idleTimeoutSec = cmdLine.longValue(IDLE_TIMEOUT_SEC, DefaultValues.IDLE_TIMEOUT_SEC)
-                    val dummyMode = cmdLine.hasOption(DUMMY_MODE)
-                    val security = createSecurityConfiguration(cmdLine)
-                    val configurationProviderParams = createConfigurationProviderParams(cmdLine).bind()
-                    ServerConfiguration(
-                            healthCheckApiPort = healthCheckApiPort,
-                            listenPort = listenPort,
-                            configurationProviderParams = configurationProviderParams,
-                            securityConfiguration = security,
-                            idleTimeout = Duration.ofSeconds(idleTimeoutSec),
-                            dummyMode = dummyMode)
-                }.fix()
-            }
+            Option.monad().binding {
+                val healthCheckApiPort = cmdLine.intValue(
+                        HEALTH_CHECK_API_PORT,
+                        DefaultValues.HEALTH_CHECK_API_PORT
+                )
+                val listenPort = cmdLine.intValue(LISTEN_PORT).bind()
+                val idleTimeoutSec = cmdLine.longValue(IDLE_TIMEOUT_SEC, DefaultValues.IDLE_TIMEOUT_SEC)
+                val dummyMode = cmdLine.hasOption(DUMMY_MODE)
+                val security = createSecurityConfiguration(cmdLine).bind()
+                val configurationProviderParams = createConfigurationProviderParams(cmdLine).bind()
+                ServerConfiguration(
+                        healthCheckApiPort = healthCheckApiPort,
+                        listenPort = listenPort,
+                        configurationProviderParams = configurationProviderParams,
+                        securityConfiguration = security,
+                        idleTimeout = Duration.ofSeconds(idleTimeoutSec),
+                        dummyMode = dummyMode)
+            }.fix()
 
     private fun createConfigurationProviderParams(cmdLine: CommandLine): Option<ConfigurationProviderParams> =
             ForOption extensions {
@@ -100,27 +105,10 @@ internal class ArgVesHvConfiguration : ArgBasedConfiguration<ServerConfiguration
                 }.fix()
             }
 
-    private fun createSecurityConfiguration(cmdLine: CommandLine): SecurityConfiguration {
-        val sslDisable = cmdLine.hasOption(SSL_DISABLE)
-        val pkFile = cmdLine.stringValue(PRIVATE_KEY_FILE, DefaultValues.PRIVATE_KEY_FILE)
-        val certFile = cmdLine.stringValue(CERT_FILE, DefaultValues.CERT_FILE)
-        val trustCertFile = cmdLine.stringValue(TRUST_CERT_FILE, DefaultValues.TRUST_CERT_FILE)
-
-        return SecurityConfiguration(
-                sslDisable = sslDisable,
-                privateKey = stringPathToPath(pkFile),
-                cert = stringPathToPath(certFile),
-                trustedCert = stringPathToPath(trustCertFile)
-        )
-    }
-
     internal object DefaultValues {
         const val HEALTH_CHECK_API_PORT = 6060
         const val CONSUL_FIRST_REQUEST_DELAY = 10L
         const val CONSUL_REQUEST_INTERVAL = 5L
-        const val PRIVATE_KEY_FILE = "/etc/ves-hv/server.key"
-        const val CERT_FILE = "/etc/ves-hv/server.crt"
-        const val TRUST_CERT_FILE = "/etc/ves-hv/trust.crt"
         const val IDLE_TIMEOUT_SEC = 60L
     }
 }
index 2650719..0cf0bb2 100644 (file)
  */
 package org.onap.dcae.collectors.veshv.main
 
+import arrow.core.identity
 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.SecurityConfiguration
-import org.onap.dcae.collectors.veshv.main.ArgVesHvConfiguration.DefaultValues
+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 java.nio.file.Paths
 import java.time.Duration
+import kotlin.test.assertNotNull
 
 /**
  * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
@@ -45,9 +45,8 @@ object ArgVesHvConfigurationTest : Spek({
     val firstRequestDelay = "10"
     val requestInterval = "5"
     val listenPort = "6969"
-    val pk = Paths.get("/", "etc", "ves", "pk.pem")
-    val cert = Paths.get("/", "etc", "ssl", "certs", "ca-bundle.crt")
-    val trustCert = Paths.get("/", "etc", "ves", "trusted.crt")
+    val keyStorePassword = "kspass"
+    val trustStorePassword = "tspass"
 
     beforeEachTest {
         cut = ArgVesHvConfiguration()
@@ -58,15 +57,17 @@ object ArgVesHvConfigurationTest : Spek({
             lateinit var result: ServerConfiguration
 
             beforeEachTest {
-                result = cut.parseExpectingSuccess("--ssl-disable",
+                result = cut.parseExpectingSuccess(
                         "--health-check-api-port", healthCheckApiPort,
                         "--listen-port", listenPort,
                         "--config-url", configurationUrl,
                         "--first-request-delay", firstRequestDelay,
                         "--request-interval", requestInterval,
-                        "--private-key-file", pk.toFile().absolutePath,
-                        "--cert-file", cert.toFile().absolutePath,
-                        "--trust-cert-file", trustCert.toFile().absolutePath)
+                        "--key-store", "/tmp/keys.p12",
+                        "--trust-store", "/tmp/trust.p12",
+                        "--key-store-password", keyStorePassword,
+                        "--trust-store-password", trustStorePassword
+                )
             }
 
             it("should set proper health check api port") {
@@ -93,69 +94,13 @@ object ArgVesHvConfigurationTest : Spek({
             }
 
             it("should set proper security configuration") {
-                assertThat(result.securityConfiguration).isEqualTo(
-                        SecurityConfiguration(sslDisable = true, privateKey = pk, cert = cert, trustedCert = trustCert)
-                )
-            }
-        }
-
-        given("some parameters are present in the short form") {
-            lateinit var result: ServerConfiguration
-
-            beforeEachTest {
-                result = cut.parseExpectingSuccess(
-                        "-p", listenPort, "-c", configurationUrl, "-d", firstRequestDelay
-                )
-            }
+                assertThat(result.securityConfiguration.sslDisable).isFalse()
 
-            it("should set proper port") {
-                assertThat(result.listenPort).isEqualTo(listenPort.toInt())
-            }
-
-            it("should set proper first consul request delay") {
-                assertThat(result.configurationProviderParams.firstRequestDelay)
-                        .isEqualTo(Duration.ofSeconds(firstRequestDelay.toLong()))
-            }
-
-            it("should set proper config url") {
-                assertThat(result.configurationProviderParams.configurationUrl)
-                        .isEqualTo(configurationUrl)
-            }
-        }
-
-        given("all optional parameters are absent") {
-            lateinit var result: ServerConfiguration
-
-            beforeEachTest {
-                result = cut.parseExpectingSuccess(
-                        "--listen-port", listenPort, "--config-url", configurationUrl
-                )
-            }
-
-            it("should set default first consul request delay") {
-                assertThat(result.configurationProviderParams.firstRequestDelay)
-                        .isEqualTo(Duration.ofSeconds(DefaultValues.CONSUL_FIRST_REQUEST_DELAY))
-            }
-
-            it("should set default consul request interval") {
-                assertThat(result.configurationProviderParams.requestInterval)
-                        .isEqualTo(Duration.ofSeconds(DefaultValues.CONSUL_REQUEST_INTERVAL))
-            }
-
-            on("security config") {
-                val securityConfiguration = result.securityConfiguration
-
-                it("should set default trust cert file") {
-                    assertThat(securityConfiguration.trustedCert.toString()).isEqualTo(DefaultValues.TRUST_CERT_FILE)
-                }
-
-                it("should set default server cert file") {
-                    assertThat(securityConfiguration.cert.toString()).isEqualTo(DefaultValues.CERT_FILE)
-                }
-
-                it("should set default private key file") {
-                    assertThat(securityConfiguration.privateKey.toString()).isEqualTo(DefaultValues.PRIVATE_KEY_FILE)
-                }
+                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())
             }
         }
 
@@ -166,10 +111,7 @@ object ArgVesHvConfigurationTest : Spek({
                             "--config-url", configurationUrl,
                             "--ssl-disable",
                             "--first-request-delay", firstRequestDelay,
-                            "--request-interval", requestInterval,
-                            "--private-key-file", pk.toFile().absolutePath,
-                            "--cert-file", cert.toFile().absolutePath,
-                            "--trust-cert-file", trustCert.toFile().absolutePath)
+                            "--request-interval", requestInterval)
                     ).isInstanceOf(WrongArgumentError::class.java)
                 }
             }
@@ -179,10 +121,7 @@ object ArgVesHvConfigurationTest : Spek({
                             "--listen-port", listenPort,
                             "--ssl-disable",
                             "--first-request-delay", firstRequestDelay,
-                            "--request-interval", requestInterval,
-                            "--private-key-file", pk.toFile().absolutePath,
-                            "--cert-file", cert.toFile().absolutePath,
-                            "--trust-cert-file", trustCert.toFile().absolutePath)
+                            "--request-interval", requestInterval)
                     ).isInstanceOf(WrongArgumentError::class.java)
                 }
             }
diff --git a/hv-collector-ssl/pom.xml b/hv-collector-ssl/pom.xml
new file mode 100644 (file)
index 0000000..f5ea00c
--- /dev/null
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ ============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=========================================================
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+        </license>
+    </licenses>
+
+    <parent>
+        <groupId>org.onap.dcaegen2.collectors.hv-ves</groupId>
+        <artifactId>ves-hv-collector</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+
+    <artifactId>hv-collector-ssl</artifactId>
+    <description>VES HighVolume Collector :: SSL</description>
+
+    <properties>
+        <skipAnalysis>false</skipAnalysis>
+    </properties>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>kotlin-maven-plugin</artifactId>
+                <groupId>org.jetbrains.kotlin</groupId>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <groupId>org.apache.maven.plugins</groupId>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.parent.groupId}</groupId>
+            <artifactId>hv-collector-domain</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.parent.groupId}</groupId>
+            <artifactId>hv-collector-utils</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${project.parent.groupId}</groupId>
+            <artifactId>hv-collector-test-utils</artifactId>
+            <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>
+        </dependency>
+        <dependency>
+            <groupId>io.arrow-kt</groupId>
+            <artifactId>arrow-syntax</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains.kotlin</groupId>
+            <artifactId>kotlin-test</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains.spek</groupId>
+            <artifactId>spek-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.jetbrains.spek</groupId>
+            <artifactId>spek-junit-platform-engine</artifactId>
+        </dependency>
+    </dependencies>
+
+
+</project>
diff --git a/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ClientSslContextFactory.kt b/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ClientSslContextFactory.kt
new file mode 100644 (file)
index 0000000..0ad3d7b
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * ============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/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactory.kt b/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactory.kt
new file mode 100644 (file)
index 0000000..d26937f
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * ============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()
+            }
+}
  * limitations under the License.
  * ============LICENSE_END=========================================================
  */
-package org.onap.dcae.collectors.veshv.impl.socket
+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 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.domain.SecurityConfiguration
 
-
-internal open class SslContextFactory {
+/**
+ * @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 {
-                Option.just(createSslContextWithConfiguredCerts(secConfig)
-                        .sslProvider(SslProvider.OPENSSL)
-                        .clientAuth(ClientAuth.REQUIRE)
-                        .build())
+                createSslContextWithConfiguredCerts(secConfig)
+                        .map { builder ->
+                            builder.clientAuth(ClientAuth.REQUIRE)
+                                    .build()
+                        }
             }
 
-    protected open fun createSslContextWithConfiguredCerts(secConfig: SecurityConfiguration): SslContextBuilder =
-            SslContextBuilder.forServer(secConfig.cert.toFile(), secConfig.privateKey.toFile())
-                    .trustManager(secConfig.trustedCert.toFile())
+    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
 }
diff --git a/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/utils.kt b/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/utils.kt
new file mode 100644 (file)
index 0000000..2f2d02e
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * ============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.None
+import arrow.core.Option
+import arrow.core.Some
+import arrow.core.fix
+import arrow.core.monad
+import arrow.typeclasses.binding
+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
+
+/**
+ * @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)
+}
+
+private fun disabledSecurityConfiguration(sslDisable: Boolean): Some<SecurityConfiguration> {
+    return Some(SecurityConfiguration(
+            sslDisable = sslDisable,
+            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()
+
+        val keys = JdkKeys(
+                keyStore = streamFromFile(ksFile),
+                keyStorePassword = ksPass.toCharArray(),
+                trustStore = streamFromFile(tsFile),
+                trustStorePassword = tsPass.toCharArray()
+        )
+
+        SecurityConfiguration(
+                sslDisable = false,
+                keys = Some(keys)
+        )
+    }.fix()
+}
+
+private fun streamFromFile(file: String) = { File(file).inputStream() }
diff --git a/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/impl/SslFactories.kt b/hv-collector-ssl/src/main/kotlin/org/onap/dcae/collectors/veshv/ssl/impl/SslFactories.kt
new file mode 100644 (file)
index 0000000..4a73a2a
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * ============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/hv-collector-ssl/src/test/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactoryTest.kt b/hv-collector-ssl/src/test/kotlin/org/onap/dcae/collectors/veshv/ssl/boundary/ServerSslContextFactoryTest.kt
new file mode 100644 (file)
index 0000000..b4d7235
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * ============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.Left
+import arrow.core.Option
+import arrow.core.Right
+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/hv-collector-ssl/src/test/resources/logback-test.xml b/hv-collector-ssl/src/test/resources/logback-test.xml
new file mode 100644 (file)
index 0000000..9a4eacf
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+  <property name="LOG_FILE"
+    value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}ves-hv.log}"/>
+  <property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC} %-5level [%-40.40logger{10}] - %msg%n"/>
+
+  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>
+        %d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC} %highlight(%-5level) [%-40.40logger{10}] - %msg%n
+      </pattern>
+    </encoder>
+  </appender>
+
+    <appender name="ROLLING-FILE"
+      class="ch.qos.logback.core.rolling.RollingFileAppender">
+      <encoder>
+        <pattern>${FILE_LOG_PATTERN}</pattern>
+      </encoder>
+      <file>${LOG_FILE}</file>
+      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+        <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.log</fileNamePattern>
+        <maxFileSize>50MB</maxFileSize>
+        <maxHistory>30</maxHistory>
+        <totalSizeCap>10GB</totalSizeCap>
+      </rollingPolicy>
+    </appender>
+
+  <logger name="org.onap.dcae.collectors.veshv" level="TRACE"/>
+
+  <root level="INFO">
+      <appender-ref ref="CONSOLE"/>
+      <appender-ref ref="ROLLING-FILE"/>
+    </root>
+</configuration>
diff --git a/hv-collector-ssl/src/test/resources/ssl/ca.crt b/hv-collector-ssl/src/test/resources/ssl/ca.crt
new file mode 100644 (file)
index 0000000..f9a05b9
--- /dev/null
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDbDCCAlSgAwIBAgIJAMsh09jY3jSBMA0GCSqGSIb3DQEBCwUAMEsxCzAJBgNV
+BAYTAlBMMQswCQYDVQQIDAJETDEQMA4GA1UEBwwHV3JvY2xhdzEOMAwGA1UECgwF
+Tm9raWExDTALBgNVBAsMBE1BTk8wHhcNMTgwODEzMTE1OTE5WhcNMTkwODEzMTE1
+OTE5WjBLMQswCQYDVQQGEwJQTDELMAkGA1UECAwCREwxEDAOBgNVBAcMB1dyb2Ns
+YXcxDjAMBgNVBAoMBU5va2lhMQ0wCwYDVQQLDARNQU5PMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAyIs4sk5SlBRltDHZDDIGHdazzdduPRKdDBMUTE5i
+++iZe1MU9WnbPWgbnfj/1DN+VbbJEa32agDXBhS9mPiSrflDe8oqPPk12miiflsY
+TxGxY1bjH58kRNey164fPznzc9LqKqV1brUPktgBkHumM4zPVZYue5cp1T2FiWcE
+nFdqOKK2F0mdby+Pim9JHil34YcvavOlMXULkqayR7hxfUIAmMZtl59BKVx9BcKD
+9Sv9TQYRIYHhymrKnwIb8RolDaDdVUnr2ryREjZ8WfoBsOpraIYDUjKijF5FlgLs
+Fp8wcIflF6JyMbtchTm5acQZkcqK1AGYTD1wxT33E2pdDQIDAQABo1MwUTAdBgNV
+HQ4EFgQUOL9AR068MxqYCsKkEfgDzF2HrY8wHwYDVR0jBBgwFoAUOL9AR068MxqY
+CsKkEfgDzF2HrY8wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA
+OXNDDqrk8bTJfy78mkMZame/bLEUQ2h4EvWT6trd5XYNfPwQW/u6laLJAtLFbzth
+lpNBRK//sK+AYgwDURq0HcW5YczhgzZbfG9ab1J/7GUrFJh+DHL3bNL1YFX84JbI
+coUbxaJFkmIvlQDLWDYfpQ/gNwUbuUPZjGZC2bWobZw9sRC+e51TIoAmgZwvTElC
+v3vD2BwbIs7C4ylrIQU9Q1rY17MeWH9m8ZhEX1C4W4+N54V6jJ7czE9HQEnapeEu
+5rmEoDqP191x+tOxp/Xg8j+wcAK/dVy1Q3xQQZCW84rv0TBHbdaAPamBLUzHeW3W
+F7BpnVhn1NfYVOKx5W0NfA==
+-----END CERTIFICATE-----
diff --git a/hv-collector-ssl/src/test/resources/ssl/server.crt b/hv-collector-ssl/src/test/resources/ssl/server.crt
new file mode 100644 (file)
index 0000000..2b06108
--- /dev/null
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDEjCCAfoCCQCId29lGbm5LjANBgkqhkiG9w0BAQsFADBLMQswCQYDVQQGEwJQ
+TDELMAkGA1UECAwCREwxEDAOBgNVBAcMB1dyb2NsYXcxDjAMBgNVBAoMBU5va2lh
+MQ0wCwYDVQQLDARNQU5PMB4XDTE4MDgxMzEyMDAyNFoXDTE5MDgwODEyMDAyNFow
+SzELMAkGA1UEBhMCUEwxCzAJBgNVBAgMAkRMMRAwDgYDVQQHDAdXcm9jbGF3MQ4w
+DAYDVQQKDAVOb2tpYTENMAsGA1UECwwETUFOTzCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBALbblOyqeJayotBiY6aZnGWnMHCHNTileJF8hkFS5P5qM9BU
+XH7NW/p5wSNcQWBB81HrRVneHpm6zfZtUPtcqXC4vpTk/sy3WT8rlEU+uv1YYVP8
+r0jxXr1WZ8sGcxOjhiMMRpMqImoALRak3ombtktfMc2Yeab4J25941wpDSQoUjT8
+LlXhfyjbBijum0LY+cqsuV5qk2qrzo0ZLD6m51aaWEyeysQ/3JanYKvPZDKdvAYN
++98ud6d/rjdWIJXwxEGp1fpW0p+fHOUhjMB1a5gkPDIpU68ME6BZJ3xJZb1qqXLS
+pkUitMIWZSWx5xNhcifsnxWyhZfnhd8GnxU3Lf8CAwEAATANBgkqhkiG9w0BAQsF
+AAOCAQEAJCrPdc8R7kBOmeIPyVX8QBOsrVTBBDzhskpi51nMsAKvcGjtYdXknYPj
+bw3YVASE2efrq5QWHC0maIxDAHzI/kmWGH8F0s8S6QRH/7fstvxaNaSArzQB/thW
+qIWs7AufUSsLMwtcXQ6KdYNbnaMwTynuuK+ANilcLvV8GxRAzXgFdoWZ2OuJRyzu
+BWQZS49WanyqX1kDLMsrLtdJyl/yVEfsmDcUyhapuuGwtconkWK/CVrJlV1vh1Z+
+Svh9IfvAF7WPPpGsM/y9+hGNtK6sPVUKl4acBzIAv6aN1QS5H4zRvtbwv7xpUp4M
+P84PY3lv1X3NJCGrfVByh2lFWParKA==
+-----END CERTIFICATE-----
diff --git a/hv-collector-ssl/src/test/resources/ssl/server.key b/hv-collector-ssl/src/test/resources/ssl/server.key
new file mode 100644 (file)
index 0000000..40e2593
--- /dev/null
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC225TsqniWsqLQ
+YmOmmZxlpzBwhzU4pXiRfIZBUuT+ajPQVFx+zVv6ecEjXEFgQfNR60VZ3h6Zus32
+bVD7XKlwuL6U5P7Mt1k/K5RFPrr9WGFT/K9I8V69VmfLBnMTo4YjDEaTKiJqAC0W
+pN6Jm7ZLXzHNmHmm+CdufeNcKQ0kKFI0/C5V4X8o2wYo7ptC2PnKrLleapNqq86N
+GSw+pudWmlhMnsrEP9yWp2Crz2QynbwGDfvfLnenf643ViCV8MRBqdX6VtKfnxzl
+IYzAdWuYJDwyKVOvDBOgWSd8SWW9aqly0qZFIrTCFmUlsecTYXIn7J8VsoWX54Xf
+Bp8VNy3/AgMBAAECggEATzN4o7GKnast/hg/lU9/gEAUKQlHMgvp1woalHy1FsUl
+QBzqGzoTlr/Zudkhr/Gg1GCVH0Gn+2n//7aFlvohoeNDGPa+rijUDRpxFDUBhO4c
+6eXOfkedg2DDgBqBCYaQeOm+P8vGMCd3YBF1GiFJqgfHaIecWYeufJsmOSrGuFvK
+1OvHpvg4/FLLQqgVcVO812kD4UwSOKnZVnPuZ3pzQviUZvO8ZxI/LkzQB1EdH6u3
+rBtiGslYkiKl5cGpH39/Dx2nKhHfvSnkfsm7koB00Bl41yy61GPwdl4XUwg8LUhX
+TbsuoIPGTJX/2FUMn0UnAdDJm29hE4eyHyYOhew8gQKBgQDlAeUcnFr9uxe0i7cg
+6ctJlNIKJjlA1tH4qIMEytdn06STo9g2j8X5HVE0FX/3+gAYDtEVICTF66w8Y474
+aeazvf+TCfkxtEOiH2afvaNkIkfzKR0ceB48DECT0DCF7xha5rJVf/W4GpCz2WkZ
+ojDzw5ZVvzbx/FaF9A/IseJ63wKBgQDMaSjiephhdlCERGPdwWMg3AfthEX/VHM0
+YugbVjjYjDbn2pMkntW2hUuVXP8HD+9DnQZo0/c/hxe28Q5b+2fjZephdctnY8tL
+XWbaEerM2lxEjmrpA4jYTBZJ9nMsxkEYHGHb5I586aS2YaZ12e7DoKMFdl0EZzvi
+zGPIxSzQ4QKBgAxVv8t8uIH2M96rr997+FEsTOvzBx5w87pbCUOW0WdsRO8W4ix+
+LgGvDJKrncrzklG5apWit5hZi1ttWWQUADMqRrvay6tbtFDlNBfilQxttEZqroC8
+D5TYbBoKGrL8H+m1h2GHlOqns6ecTEbvL4fRvyU7OXBrURXCAZ+jxTktAoGACbQI
+O9AEAcRjCBRTBUjT0tB/E9hOllNE8LytNfb+1dC6HoFysK9Vh8eGEf4LISOxgO0o
+S7ucJgjcqFODEfy6LsI8wQmdcTf8g4RYiIuHMNhAvwRfsNX5HgNmn3Yye3Khzmoy
+fwS3etiAeCPkif2hZunuMykuOzJHVnnLVtF9UiECgYEA41d7FgUcnfPIyA5xLg7K
+lRgjFMsc68uzoCBQww2kio0HNJpdOPBJlg6oHHfYKriv2r9793jETRVwjSNPlKZb
+vqm9yhnbXuahYBZSgdo2W+NbhP6IbJ0vrF4t9g6byjancQptaCjNIr9St9g+Ugly
+8m0n3gIT/+Lr+it63cgk8SA=
+-----END PRIVATE KEY-----
diff --git a/hv-collector-ssl/src/test/resources/ssl/server.ks.pkcs12 b/hv-collector-ssl/src/test/resources/ssl/server.ks.pkcs12
new file mode 100644 (file)
index 0000000..a97eb65
Binary files /dev/null and b/hv-collector-ssl/src/test/resources/ssl/server.ks.pkcs12 differ
diff --git a/hv-collector-ssl/src/test/resources/ssl/trust.pkcs12 b/hv-collector-ssl/src/test/resources/ssl/trust.pkcs12
new file mode 100644 (file)
index 0000000..01b6137
Binary files /dev/null and b/hv-collector-ssl/src/test/resources/ssl/trust.pkcs12 differ
index 44d425e..da5ff91 100644 (file)
@@ -55,31 +55,5 @@ abstract class ArgBasedConfiguration<T>(private val parser: CommandLineParser) {
 
     protected abstract fun getConfiguration(cmdLine: CommandLine): Option<T>
 
-    protected fun CommandLine.longValue(cmdLineOpt: CommandLineOption, default: Long): Long =
-            longValue(cmdLineOpt).getOrElse { default }
-
-    protected fun CommandLine.stringValue(cmdLineOpt: CommandLineOption, default: String): String =
-            optionValue(cmdLineOpt).getOrElse { default }
-
-    protected fun CommandLine.intValue(cmdLineOpt: CommandLineOption, default: Int): Int =
-            intValue(cmdLineOpt).getOrElse { default }
-
-    protected fun CommandLine.intValue(cmdLineOpt: CommandLineOption): Option<Int> =
-            optionValue(cmdLineOpt).map(String::toInt)
-
-    private fun CommandLine.longValue(cmdLineOpt: CommandLineOption): Option<Long> =
-            optionValue(cmdLineOpt).map(String::toLong)
-
-    protected fun CommandLine.stringValue(cmdLineOpt: CommandLineOption): Option<String> =
-            optionValue(cmdLineOpt)
-
-    protected fun CommandLine.hasOption(cmdLineOpt: CommandLineOption): Boolean =
-            this.hasOption(cmdLineOpt.option.opt) ||
-                    System.getenv(cmdLineOpt.environmentVariableName()) != null
-
     protected fun stringPathToPath(path: String): Path = Paths.get(File(path).toURI())
-
-    private fun CommandLine.optionValue(cmdLineOpt: CommandLineOption) = Option.fromNullablesChain(
-            getOptionValue(cmdLineOpt.option.opt),
-            { System.getenv(cmdLineOpt.environmentVariableName()) })
 }
index 9379c40..288a578 100644 (file)
@@ -88,22 +88,28 @@ enum class CommandLineOption(val option: Option, val required: Boolean = false)
             .desc("Disable SSL encryption")
             .build()
     ),
-    PRIVATE_KEY_FILE(Option.builder("k")
-            .longOpt("private-key-file")
+    KEY_STORE_FILE(Option.builder("k")
+            .longOpt("key-store")
             .hasArg()
-            .desc("File with private key in PEM format")
+            .desc("Key store in PKCS12 format")
             .build()
     ),
-    CERT_FILE(Option.builder("e")
-            .longOpt("cert-file")
+    KEY_STORE_PASSWORD(Option.builder("kp")
+            .longOpt("key-store-password")
             .hasArg()
-            .desc("File with certificate bundle")
+            .desc("Key store password")
             .build()
     ),
-    TRUST_CERT_FILE(Option.builder("t")
-            .longOpt("trust-cert-file")
+    TRUST_STORE_FILE(Option.builder("t")
+            .longOpt("trust-store")
             .hasArg()
-            .desc("File with trusted certificate bundle for trusting connections")
+            .desc("File with trusted certificate bundle in PKCS12 format")
+            .build()
+    ),
+    TRUST_STORE_PASSWORD(Option.builder("tp")
+            .longOpt("trust-store-password")
+            .hasArg()
+            .desc("Trust store password")
             .build()
     ),
     IDLE_TIMEOUT_SEC(Option.builder("i")
index 718ebf8..ba4c080 100644 (file)
  */
 package org.onap.dcae.collectors.veshv.utils.commandline
 
+import arrow.core.Option
+import arrow.core.getOrElse
 import arrow.effects.IO
 import arrow.syntax.function.curried
+import org.apache.commons.cli.CommandLine
 import org.onap.dcae.collectors.veshv.utils.arrow.ExitFailure
+import org.onap.dcae.collectors.veshv.utils.arrow.fromNullablesChain
 
 /**
  * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
@@ -34,3 +38,29 @@ fun handleWrongArgumentError(programName: String, err: WrongArgumentError): IO<U
 }.flatMap { ExitFailure(2).io() }
 
 val handleWrongArgumentErrorCurried = ::handleWrongArgumentError.curried()
+
+fun CommandLine.longValue(cmdLineOpt: CommandLineOption, default: Long): Long =
+        longValue(cmdLineOpt).getOrElse { default }
+
+fun CommandLine.stringValue(cmdLineOpt: CommandLineOption, default: String): String =
+        optionValue(cmdLineOpt).getOrElse { default }
+
+fun CommandLine.intValue(cmdLineOpt: CommandLineOption, default: Int): Int =
+        intValue(cmdLineOpt).getOrElse { default }
+
+fun CommandLine.intValue(cmdLineOpt: CommandLineOption): Option<Int> =
+        optionValue(cmdLineOpt).map(String::toInt)
+
+fun CommandLine.longValue(cmdLineOpt: CommandLineOption): Option<Long> =
+        optionValue(cmdLineOpt).map(String::toLong)
+
+fun CommandLine.stringValue(cmdLineOpt: CommandLineOption): Option<String> =
+        optionValue(cmdLineOpt)
+
+fun CommandLine.hasOption(cmdLineOpt: CommandLineOption): Boolean =
+        this.hasOption(cmdLineOpt.option.opt) ||
+                System.getenv(cmdLineOpt.environmentVariableName()) != null
+
+private fun CommandLine.optionValue(cmdLineOpt: CommandLineOption) = Option.fromNullablesChain(
+        getOptionValue(cmdLineOpt.option.opt),
+        { System.getenv(cmdLineOpt.environmentVariableName()) })
\ No newline at end of file
index 5340645..ed9dd9b 100644 (file)
@@ -6,7 +6,7 @@ LABEL license.url="http://www.apache.org/licenses/LICENSE-2.0"
 LABEL maintainer="Nokia Wroclaw ONAP Team"
 
 RUN apt-get update \
-        && apt-get install -y --no-install-recommends curl  \
+        && apt-get install -y --no-install-recommends curl \
         && apt-get clean
 
 WORKDIR /opt/ves-hv-client-simulator
index cfe1dc1..b3de6b2 100644 (file)
             <artifactId>hv-collector-domain</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
+        <dependency>
+            <groupId>${project.parent.groupId}</groupId>
+            <artifactId>hv-collector-ssl</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
         <dependency>
             <groupId>${project.parent.groupId}</groupId>
             <artifactId>hv-collector-utils</artifactId>
             <groupId>org.jetbrains.kotlin</groupId>
             <artifactId>kotlin-stdlib-jdk8</artifactId>
         </dependency>
+        <!-- See comment in main pom
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-transport-native-epoll</artifactId>
+            <classifier>${os.detected.classifier}</classifier>
+        </dependency>
         <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-tcnative-boringssl-static</artifactId>
-            <scope>runtime</scope>
             <classifier>${os.detected.classifier}</classifier>
         </dependency>
+        -->
         <dependency>
             <groupId>com.nhaarman</groupId>
             <artifactId>mockito-kotlin</artifactId>
index af71e9c..7a280c1 100644 (file)
@@ -28,6 +28,7 @@ import org.onap.dcae.collectors.veshv.domain.WireFrameMessage
 import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
 import org.onap.dcae.collectors.veshv.domain.WireFrameEncoder
 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.utils.arrow.asIo
 import org.onap.dcae.collectors.veshv.utils.logging.Logger
 import org.reactivestreams.Publisher
@@ -37,7 +38,6 @@ import reactor.core.publisher.ReplayProcessor
 import reactor.ipc.netty.NettyOutbound
 import reactor.ipc.netty.tcp.TcpClient
 
-
 /**
  * @author Jakub Dudycz <jakub.dudycz@nokia.com>
  * @since June 2018
@@ -92,18 +92,7 @@ class VesHvClient(private val configuration: SimulatorConfiguration) {
     }
 
     private fun createSslContext(config: SecurityConfiguration): Option<SslContext> =
-            if (config.sslDisable) {
-                Option.empty()
-            } else {
-                Option.just(
-                        SslContextBuilder.forClient()
-                                .keyManager(config.cert.toFile(), config.privateKey.toFile())
-                                .trustManager(config.trustedCert.toFile())
-                                .sslProvider(SslProvider.OPENSSL)
-                                .clientAuth(ClientAuth.REQUIRE)
-                                .build()
-                )
-            }
+            ClientSslContextFactory().createSslContext(config)
 
     private fun NettyOutbound.logConnectionClosed(): NettyOutbound {
         context().onClose {
index 56d6212..3d8dc94 100644 (file)
  */
 package org.onap.dcae.collectors.veshv.simulators.xnf.impl.config
 
-import arrow.core.ForOption
 import arrow.core.Option
 import arrow.core.fix
-import arrow.instances.extensions
+import arrow.core.monad
 import arrow.typeclasses.binding
 import org.apache.commons.cli.CommandLine
 import org.apache.commons.cli.DefaultParser
-import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
+import org.onap.dcae.collectors.veshv.ssl.boundary.createSecurityConfiguration
 import org.onap.dcae.collectors.veshv.utils.commandline.ArgBasedConfiguration
-import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.*
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.KEY_STORE_FILE
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.KEY_STORE_PASSWORD
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.LISTEN_PORT
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.SSL_DISABLE
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.TRUST_STORE_FILE
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.TRUST_STORE_PASSWORD
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.VES_HV_HOST
+import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.VES_HV_PORT
+import org.onap.dcae.collectors.veshv.utils.commandline.intValue
+import org.onap.dcae.collectors.veshv.utils.commandline.stringValue
 
 
 /**
@@ -41,42 +49,22 @@ internal class ArgXnfSimulatorConfiguration : ArgBasedConfiguration<SimulatorCon
             VES_HV_HOST,
             LISTEN_PORT,
             SSL_DISABLE,
-            PRIVATE_KEY_FILE,
-            CERT_FILE,
-            TRUST_CERT_FILE
-    )
+            KEY_STORE_FILE,
+            KEY_STORE_PASSWORD,
+            TRUST_STORE_FILE,
+            TRUST_STORE_PASSWORD)
 
     override fun getConfiguration(cmdLine: CommandLine): Option<SimulatorConfiguration> =
-            ForOption extensions {
-                binding {
-                    val listenPort = cmdLine.intValue(LISTEN_PORT).bind()
-                    val vesHost = cmdLine.stringValue(VES_HV_HOST).bind()
-                    val vesPort = cmdLine.intValue(VES_HV_PORT).bind()
+            Option.monad().binding {
+                val listenPort = cmdLine.intValue(LISTEN_PORT).bind()
+                val vesHost = cmdLine.stringValue(VES_HV_HOST).bind()
+                val vesPort = cmdLine.intValue(VES_HV_PORT).bind()
 
-                    SimulatorConfiguration(
-                            listenPort,
-                            vesHost,
-                            vesPort,
-                            parseSecurityConfig(cmdLine))
-                }.fix()
-            }
+                SimulatorConfiguration(
+                        listenPort,
+                        vesHost,
+                        vesPort,
+                        createSecurityConfiguration(cmdLine).bind())
+            }.fix()
 
-    private fun parseSecurityConfig(cmdLine: CommandLine): SecurityConfiguration {
-        val sslDisable = cmdLine.hasOption(SSL_DISABLE)
-        val pkFile = cmdLine.stringValue(PRIVATE_KEY_FILE, DefaultValues.PRIVATE_KEY_FILE)
-        val certFile = cmdLine.stringValue(CERT_FILE, DefaultValues.CERT_FILE)
-        val trustCertFile = cmdLine.stringValue(TRUST_CERT_FILE, DefaultValues.TRUST_CERT_FILE)
-
-        return SecurityConfiguration(
-                sslDisable = sslDisable,
-                privateKey = stringPathToPath(pkFile),
-                cert = stringPathToPath(certFile),
-                trustedCert = stringPathToPath(trustCertFile))
-    }
-
-    internal object DefaultValues {
-        const val PRIVATE_KEY_FILE = "/etc/ves-hv/client.key"
-        const val CERT_FILE = "/etc/ves-hv/client.crt"
-        const val TRUST_CERT_FILE = "/etc/ves-hv/trust.crt"
-    }
 }
diff --git a/hv-collector-xnf-simulator/src/test/kotlin/org/onap/dcae/collectors/veshv/main/config/ArgXnfSimulatorConfiurationTest.kt b/hv-collector-xnf-simulator/src/test/kotlin/org/onap/dcae/collectors/veshv/main/config/ArgXnfSimulatorConfiurationTest.kt
deleted file mode 100644 (file)
index 69caf72..0000000
+++ /dev/null
@@ -1,181 +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.main.config
-
-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.SecurityConfiguration
-import org.onap.dcae.collectors.veshv.simulators.xnf.impl.config.ArgXnfSimulatorConfiguration
-import org.onap.dcae.collectors.veshv.simulators.xnf.impl.config.ArgXnfSimulatorConfiguration.DefaultValues
-import org.onap.dcae.collectors.veshv.simulators.xnf.impl.config.SimulatorConfiguration
-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 java.nio.file.Paths
-import kotlin.test.assertTrue
-
-
-object ArgXnfSimulatorConfiurationTest : Spek({
-    lateinit var cut: ArgXnfSimulatorConfiguration
-    val listenPort = "4321"
-    val vesHost = "localhost"
-    val vesPort = "1234"
-    val pk = Paths.get("/", "etc", "ves", "pk.pem")
-    val cert = Paths.get("/", "etc", "ssl", "certs", "ca-bundle.crt")
-    val trustCert = Paths.get("/", "etc", "ves", "trusted.crt")
-
-    beforeEachTest {
-        cut = ArgXnfSimulatorConfiguration()
-    }
-
-    describe("parsing arguments") {
-        lateinit var result: SimulatorConfiguration
-
-        given("all parameters are present in the long form") {
-
-            beforeEachTest {
-                result = cut.parseExpectingSuccess("--ssl-disable",
-                        "--listen-port", listenPort,
-                        "--ves-host", vesHost,
-                        "--ves-port", vesPort,
-                        "--private-key-file", pk.toFile().absolutePath,
-                        "--cert-file", cert.toFile().absolutePath,
-                        "--trust-cert-file", trustCert.toFile().absolutePath)
-            }
-
-            it("should set proper listen port") {
-                assertThat(result.listenPort).isEqualTo(listenPort.toInt())
-            }
-
-            it("should set proper ves host") {
-                assertThat(result.vesHost).isEqualTo(vesHost)
-            }
-
-            it("should set proper ves port") {
-                assertThat(result.vesPort).isEqualTo(vesPort.toInt())
-            }
-
-            it("should set proper security configuration") {
-                assertThat(result.security).isEqualTo(
-                        SecurityConfiguration(sslDisable = true, privateKey = pk, cert = cert, trustedCert = trustCert)
-                )
-            }
-        }
-
-        given("some parameters are present in the short form") {
-
-            beforeEachTest {
-                result = cut.parseExpectingSuccess("-p", listenPort, "-h", vesHost, "--ves-port", vesPort)
-            }
-
-            it("should set proper listen port") {
-                assertThat(result.listenPort).isEqualTo(listenPort.toInt())
-            }
-
-            it("should set proper ves host") {
-                assertThat(result.vesHost).isEqualTo(vesHost)
-            }
-
-            it("should set proper ves port") {
-                assertThat(result.vesPort).isEqualTo(vesPort.toInt())
-            }
-        }
-
-        given("all optional parameters are absent") {
-
-            beforeEachTest {
-                result = cut.parseExpectingSuccess("-p", listenPort, "-h", vesHost, "-v", vesPort)
-            }
-
-            on("security config") {
-                val securityConfiguration = result.security
-
-                it("should set default trust cert file") {
-                    assertThat(securityConfiguration.trustedCert.toString()).isEqualTo(DefaultValues.TRUST_CERT_FILE)
-                }
-
-                it("should set default server cert file") {
-                    assertThat(securityConfiguration.cert.toString()).isEqualTo(DefaultValues.CERT_FILE)
-                }
-
-                it("should set default private key file") {
-                    assertThat(securityConfiguration.privateKey.toString()).isEqualTo(DefaultValues.PRIVATE_KEY_FILE)
-                }
-            }
-        }
-
-        given("disabled ssl certs together with all other parameters") {
-            beforeEachTest {
-                result = cut.parseExpectingSuccess("--ssl-disable",
-                        "--listen-port", listenPort,
-                        "--ves-port", "888",
-                        "--ves-host", vesHost,
-                        "--private-key-file", pk.toFile().absolutePath,
-                        "--cert-file", cert.toFile().absolutePath,
-                        "--trust-cert-file", trustCert.toFile().absolutePath)
-            }
-
-            on("security config") {
-                val securityConfiguration = result.security
-
-                it("should set ssl disable to true") {
-                    assertTrue(securityConfiguration.sslDisable)
-                }
-
-                it("should set proper security configuration") {
-                    assertThat(securityConfiguration).isEqualTo(
-                            SecurityConfiguration(
-                                    sslDisable = true,
-                                    privateKey = pk,
-                                    cert = cert,
-                                    trustedCert = trustCert)
-                    )
-                }
-            }
-        }
-
-        describe("required parameter is absent") {
-            given("ves port is missing") {
-                it("should throw exception") {
-                    assertThat(cut.parseExpectingFailure("-p", listenPort, "-h", vesHost))
-                            .isInstanceOf(WrongArgumentError::class.java)
-                }
-            }
-
-            given("ves host is missing") {
-                it("should throw exception") {
-                    assertThat(cut.parseExpectingFailure("-p", listenPort, "-v", vesPort))
-                            .isInstanceOf(WrongArgumentError::class.java)
-                }
-            }
-
-            given("listen port is missing") {
-                it("should throw exception") {
-                    assertThat(cut.parseExpectingFailure("-h", vesHost, "-v", vesPort))
-                            .isInstanceOf(WrongArgumentError::class.java)
-                }
-            }
-        }
-    }
-})
diff --git a/pom.xml b/pom.xml
index a71f942..71f02fb 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -52,6 +52,7 @@
         <module>hv-collector-domain</module>
         <module>hv-collector-health-check</module>
         <module>hv-collector-main</module>
+        <module>hv-collector-ssl</module>
         <module>hv-collector-test-utils</module>
         <module>hv-collector-utils</module>
         <module>hv-collector-ves-message-generator</module>
@@ -64,7 +65,7 @@
         <maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
         <build-helper-maven-plugin.version>1.7</build-helper-maven-plugin.version>
         <jacoco.version>0.8.2</jacoco.version>
-        <jacoco.minimum.coverage>66</jacoco.minimum.coverage>
+        <jacoco.minimum.coverage>60</jacoco.minimum.coverage>
 
         <!-- Protocol buffers -->
         <protobuf.version>3.5.1</protobuf.version>
             <dependency>
                 <groupId>io.projectreactor</groupId>
                 <artifactId>reactor-bom</artifactId>
-                <version>Bismuth-SR10</version>
+                <!-- remember to update netty native bindings versions -->
+                <version>Bismuth-SR11</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.8.Final</version>
+                <version>2.0.15.Final</version>
+                <scope>runtime</scope>
+                <classifier>${os.detected.classifier}</classifier>
+            </dependency>
+            <!--
+            <dependency>
+                <groupId>io.netty</groupId>
+                <artifactId>netty-transport-native-epoll</artifactId>
+                <version>4.1.29.Final</version>
                 <classifier>${os.detected.classifier}</classifier>
             </dependency>
+            -->
             <dependency>
                 <groupId>com.google.protobuf</groupId>
                 <artifactId>protobuf-java</artifactId>
index 598dc75..23888eb 100644 (file)
@@ -2,3 +2,6 @@
 *.key
 *.srl
 *.csr
+*.pkcs12
+*.p12
+
similarity index 64%
rename from ssl/Makefile
rename to ssl/Makefile-openssl
index 2832650..09802ce 100644 (file)
@@ -1,12 +1,13 @@
 FILE=sample
-CA_PASSWD=onap
+PASSWD=onaponap
+CA_PASSWD=onaponap
 SUBJ=/C=PL/ST=DL/L=Wroclaw/O=Nokia/OU=MANO
 CA=trust
 
 sign: $(FILE).crt
 
 clean:
-       rm -f *.crt *.key *.srl *.csr
+       rm -f *.crt *.key *.srl *.csr *.pkcs12
 
 generate-ca-certificate: $(CA).crt
 
@@ -16,6 +17,11 @@ create-public-key: $(FILE).pub
 
 create-sign-request: $(FILE).csr
 
+create-key-store: $(FILE).ks.pkcs12
+
+create-trust-store: $(CA).crt
+       openssl pkcs12 -export -in $(CA).crt -CAfile $(CA).crt -out $(CA).pkcs12 -nokeys -noiter -nomaciter -passout pass:$(PASSWD)
+
 $(CA).crt:
        openssl req -new -x509 -keyout $(CA).key -out $(CA).crt -days 365 -passout pass:$(CA_PASSWD) -subj "$(SUBJ)"
 
@@ -31,3 +37,5 @@ $(FILE).csr: $(FILE).key
 $(FILE).crt: $(CA).crt $(FILE).csr
        openssl x509 -req -days 360 -in $(FILE).csr -CA $(CA).crt -CAkey $(CA).key -out $(FILE).crt -CAcreateserial -passin pass:$(CA_PASSWD)
 
+$(FILE).ks.pkcs12: $(FILE).key $(FILE).crt $(CA).crt
+       openssl pkcs12 -export -in $(FILE).crt -inkey $(FILE).key -CAfile $(CA).crt -out $(FILE).ks.pkcs12 -noiter -nomaciter -passout pass:$(PASSWD)
index efba610..c2819d2 100644 (file)
@@ -1,5 +1,23 @@
 # Generating SSL certificates
 
+## Java keytool way (recommended)
+
+To generate:
+
+```shell
+./gen-certs.sh
+```
+
+To clean (remove generated files):
+
+```shell
+./gen-certs.sh clean
+```
+
+## OpenSSL way (currently might not work)
+
+> Add `-f Makefile-openssl` to each command
+
 Typical usage:
 
 ```shell
@@ -7,6 +25,14 @@ make FILE=client
 make FILE=server
 ```
 
+or (to generate PKCS12 key and trust stores):
+
+```shell
+make create-key-store FILE=client
+make create-key-store FILE=server
+make create-trust-store
+```
+
 Will generate CA certificate and signed client and server certificates.
 
 More "low-level" usage:
diff --git a/ssl/gen-certs.sh b/ssl/gen-certs.sh
new file mode 100755 (executable)
index 0000000..b4f7822
--- /dev/null
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+
+set -eu -o pipefail -o xtrace
+
+STORE_PASS=onaponap
+CN_PREFIX=dcaegen2-hvves
+DNAME_PREFIX="C=PL,ST=DL,L=Wroclaw,O=Nokia,OU=MANO,CN=${CN_PREFIX}"
+TRUST=trust
+
+store_opts="-storetype PKCS12 -storepass ${STORE_PASS} -noprompt"
+
+function gen_key() {
+  local key_name="$1"
+  local ca="$2"
+  local keystore="-keystore ${key_name}.p12 ${store_opts}"
+  keytool -genkey -alias ${key_name} \
+      ${keystore} \
+      -keyalg RSA \
+      -validity 730 \
+      -keysize 2048 \
+      -dname "${DNAME_PREFIX}-${key_name}"
+  keytool -import -trustcacerts -alias ${ca} -file ${ca}.crt ${keystore}
+
+  keytool -certreq -alias ${key_name} -keyalg RSA ${keystore} | \
+      keytool -alias ${ca} -gencert -ext "san=dns:${CN_PREFIX}-${ca}" ${store_opts} -keystore ${ca}.p12 | \
+      keytool -alias ${key_name} -importcert ${keystore}
+}
+
+
+function gen_ca() {
+  local ca="$1"
+  keytool -genkeypair ${store_opts} -alias ${ca} -dname "${DNAME_PREFIX}-${ca}" -keystore ${ca}.p12
+  keytool -export -alias ${ca} -file ${ca}.crt ${store_opts} -keystore ${ca}.p12
+}
+
+function gen_truststore() {
+  local trusted_ca="$1"
+  keytool -import -trustcacerts -alias ca -file ${trusted_ca}.crt ${store_opts} -keystore ${TRUST}.p12
+}
+
+function clean() {
+  rm -f *.crt *.p12
+}
+
+if [[ $# -eq 0 ]]; then
+  gen_ca ca
+  gen_ca untrustedca
+  gen_truststore ca
+  gen_key client ca
+  gen_key server ca
+  gen_key untrustedclient untrustedca
+elif [[ $1 == "clean" ]]; then
+  clean
+else
+  echo "usage: $0 [clean]"
+  exit 1
+fi
+