Add command line option to disable SSL/TLS 41/58841/2
authorkjaniak <kornel.janiak@nokia.com>
Tue, 17 Jul 2018 09:50:10 +0000 (11:50 +0200)
committerPiotr Jaszczyk <piotr.jaszczyk@nokia.com>
Fri, 3 Aug 2018 05:32:52 +0000 (07:32 +0200)
Closes ONAP-508

Change-Id: If6c3935ede7b00dea9b36747c6cd1422c1c8d330
Signed-off-by: kjaniak <kornel.janiak@nokia.com>
Issue-ID: DCAEGEN2-601

hv-collector-core/pom.xml
hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/NettyTcpServer.kt
hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactory.kt
hv-collector-core/src/test/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactoryTest.kt
hv-collector-domain/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/SecurityConfiguration.kt
hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/ArgBasedServerConfiguration.kt
hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/ArgBasedServerConfigurationTest.kt
hv-collector-utils/src/main/kotlin/org/onap/dcae/collectors/veshv/utils/commandline/CommandLineOption.kt
hv-collector-xnf-simulator/src/main/kotlin/org/onap/dcae/collectors/veshv/simulators/xnf/config/ArgConfigurationProvider.kt
hv-collector-xnf-simulator/src/test/kotlin/org/onap/dcae/collectors/veshv/main/config/ArgConfigurationProviderTest.kt

index 1865731..cf99867 100644 (file)
             <groupId>io.arrow-kt</groupId>
             <artifactId>arrow-effects</artifactId>
         </dependency>
+        <dependency>
+            <groupId>io.arrow-kt</groupId>
+            <artifactId>arrow-core</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.projectreactor</groupId>
             <artifactId>reactor-core</artifactId>
index e998576..61e1ebf 100644 (file)
@@ -19,7 +19,9 @@
  */
 package org.onap.dcae.collectors.veshv.impl.socket
 
+import arrow.core.Option
 import arrow.effects.IO
+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.boundary.ServerHandle
@@ -54,8 +56,9 @@ internal class NettyTcpServer(private val serverConfig: ServerConfiguration,
     }
 
     private fun configureServer(opts: ServerOptions.Builder<*>) {
+        val sslContext: Option<SslContext> = sslContextFactory.createSslContext(serverConfig.securityConfiguration)
+        if (sslContext.isDefined()) opts.sslContext(sslContext.orNull())
         opts.port(serverConfig.port)
-        opts.sslContext(sslContextFactory.createSslContext(serverConfig.securityConfiguration))
     }
 
     private fun handleConnection(nettyInbound: NettyInbound): Mono<Void> {
index b6fb1cf..0dce0d6 100644 (file)
@@ -19,6 +19,9 @@
  */
 package org.onap.dcae.collectors.veshv.impl.socket
 
+import arrow.core.None
+import arrow.core.Option
+import arrow.core.Some
 import io.netty.handler.ssl.ClientAuth
 import io.netty.handler.ssl.SslContext
 import io.netty.handler.ssl.SslContextBuilder
@@ -27,11 +30,15 @@ import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
 
 
 internal open class SslContextFactory {
-    fun createSslContext(secConfig: SecurityConfiguration): SslContext =
-            createSslContextWithConfiguredCerts(secConfig)
-                    .sslProvider(SslProvider.OPENSSL)
-                    .clientAuth(ClientAuth.REQUIRE)
-                    .build()
+    fun createSslContext(secConfig: SecurityConfiguration): Option<SslContext> =
+            if (secConfig.sslDisable) {
+                Option.empty()
+            } else {
+                Option.just(createSslContextWithConfiguredCerts(secConfig)
+                        .sslProvider(SslProvider.OPENSSL)
+                        .clientAuth(ClientAuth.REQUIRE)
+                        .build())
+            }
 
     protected open fun createSslContextWithConfiguredCerts(secConfig: SecurityConfiguration): SslContextBuilder =
             SslContextBuilder.forServer(secConfig.cert.toFile(), secConfig.privateKey.toFile())
index 26a25d3..deb4e18 100644 (file)
 package org.onap.dcae.collectors.veshv.impl.socket
 
 import io.netty.handler.ssl.ClientAuth
-import io.netty.handler.ssl.OpenSslServerContext
 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>
@@ -36,43 +38,66 @@ import java.nio.file.Paths
  */
 object SslContextFactoryTest : Spek({
     describe("SslContextFactory") {
-        val sampleConfig = SecurityConfiguration(
-                privateKey = Paths.get("/", "tmp", "pk.pem"),
-                cert = Paths.get("/", "tmp", "cert.crt"),
-                trustedCert = Paths.get("/", "tmp", "clientCa.crt"))
+        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() {
-            var actualConfig: SecurityConfiguration? = null
-            override fun createSslContextWithConfiguredCerts(secConfig: SecurityConfiguration): SslContextBuilder {
-                actualConfig = secConfig
-                return SslContextBuilder.forServer(resource("/ssl/ca.crt"), resource("/ssl/server.key"))
+            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)
             }
 
-            private fun resource(path: String) = SslContextFactoryTest.javaClass.getResourceAsStream(path)
-        }
+            on("creation of SSL context") {
+                val result = cut.createSslContext(sampleConfig)
 
-        val result = cut.createSslContext(sampleConfig)
+                it("should be server context") {
+                    assertTrue(result.exists {
+                        it.isServer
+                    })
+                }
 
-        it("should be server context") {
-            assertThat(result.isServer).isTrue()
-        }
+                it("should use OpenSSL provider") {
+                    assertTrue(result.isDefined())
+                }
 
-        it("should use OpenSSL provider") {
-            assertThat(result).isInstanceOf(OpenSslServerContext::class.java)
+                /*
+                 * 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)
+                }
+            }
         }
 
-        /*
-         * 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) 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 6f28b6e..e409eb7 100644 (file)
@@ -26,6 +26,7 @@ import java.nio.file.Path
  * @since May 2018
  */
 data class SecurityConfiguration(
+        val sslDisable: Boolean = false,
         val privateKey: Path,
         val cert: Path,
         val trustedCert: Path)
index 9e4c5f2..35ca09d 100644 (file)
@@ -42,6 +42,7 @@ internal class ArgBasedServerConfiguration : ArgBasedConfiguration<ServerConfigu
             LISTEN_PORT,
             CONSUL_CONFIG_URL,
             CONSUL_FIRST_REQUEST_DELAY,
+            SSL_DISABLE,
             PRIVATE_KEY_FILE,
             CERT_FILE,
             TRUST_CERT_FILE,
@@ -66,11 +67,13 @@ internal class ArgBasedServerConfiguration : ArgBasedConfiguration<ServerConfigu
     }
 
     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)
index b56b1b1..0498344 100644 (file)
@@ -59,7 +59,8 @@ object ArgBasedServerConfigurationTest : Spek({
             lateinit var result: ServerConfiguration
 
             beforeEachTest {
-                result = parse("--listen-port", listenPort,
+                result = parse("--ssl-disable",
+                        "--listen-port", listenPort,
                         "--config-url", configurationUrl,
                         "--first-request-delay", firstRequestDelay,
                         "--private-key-file", pk.toFile().absolutePath,
@@ -81,7 +82,7 @@ object ArgBasedServerConfigurationTest : Spek({
 
             it("should set proper security configuration") {
                 assertThat(result.securityConfiguration).isEqualTo(
-                        SecurityConfiguration(pk, cert, trustCert)
+                        SecurityConfiguration(sslDisable = true, privateKey = pk, cert = cert, trustedCert = trustCert)
                 )
             }
 
index 82711d9..27213c9 100644 (file)
@@ -75,6 +75,11 @@ enum class CommandLineOption(val option: Option) {
             .desc("Comma-separated Kafka topics")
             .build()
     ),
+    SSL_DISABLE(Option.builder("l")
+            .longOpt("ssl-disable")
+            .desc("Disable SSL encryption")
+            .build()
+    ),
     PRIVATE_KEY_FILE(Option.builder("k")
             .longOpt("private-key-file")
             .hasArg()
index 04654f8..96e6577 100644 (file)
@@ -23,12 +23,7 @@ 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.utils.commandline.ArgBasedConfiguration
-import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.CERT_FILE
-import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.MESSAGES_TO_SEND_AMOUNT
-import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.PRIVATE_KEY_FILE
-import org.onap.dcae.collectors.veshv.utils.commandline.CommandLineOption.TRUST_CERT_FILE
-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.CommandLineOption.*
 
 
 /**
@@ -40,6 +35,7 @@ internal class ArgConfigurationProvider : ArgBasedConfiguration<SimulatorConfigu
             VES_HV_PORT,
             VES_HV_HOST,
             MESSAGES_TO_SEND_AMOUNT,
+            SSL_DISABLE,
             PRIVATE_KEY_FILE,
             CERT_FILE,
             TRUST_CERT_FILE
@@ -57,10 +53,12 @@ internal class ArgConfigurationProvider : ArgBasedConfiguration<SimulatorConfigu
     }
 
     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))
index f2f92ff..fccd8b5 100644 (file)
@@ -31,6 +31,7 @@ import org.onap.dcae.collectors.veshv.simulators.xnf.config.ArgConfigurationProv
 import org.onap.dcae.collectors.veshv.simulators.xnf.config.ArgConfigurationProvider.*
 import org.onap.dcae.collectors.veshv.simulators.xnf.config.SimulatorConfiguration
 import java.nio.file.Paths
+import kotlin.test.assertTrue
 
 
 object ArgConfigurationProviderTest : Spek({
@@ -47,7 +48,7 @@ object ArgConfigurationProviderTest : Spek({
 
     fun parse(vararg cmdLine: String): SimulatorConfiguration =
             cut.parse(cmdLine).fold(
-                    {throw AssertionError("Parsing result should be present")},
+                    { throw AssertionError("Parsing result should be present") },
                     ::identity
             )
 
@@ -57,7 +58,8 @@ object ArgConfigurationProviderTest : Spek({
         given("all parameters are present in the long form") {
 
             beforeEachTest {
-                result = parse("--ves-port", "6969",
+                result = parse("--ssl-disable",
+                        "--ves-port", "6969",
                         "--ves-host", vesHost,
                         "--messages", messagesAmount.toString(),
                         "--private-key-file", pk.toFile().absolutePath,
@@ -76,7 +78,7 @@ object ArgConfigurationProviderTest : Spek({
 
             it("should set proper security configuration") {
                 assertThat(result.security).isEqualTo(
-                        SecurityConfiguration(pk, cert, trustCert)
+                        SecurityConfiguration(sslDisable = true, privateKey = pk, cert = cert, trustedCert = trustCert)
                 )
             }
         }
@@ -122,5 +124,35 @@ object ArgConfigurationProviderTest : Spek({
                 }
             }
         }
+
+        given("disabled ssl certs together with all other parameters") {
+            beforeEachTest {
+                result = parse("--ssl-disable",
+                        "--ves-port", "888",
+                        "--ves-host", vesHost,
+                        "--messages", messagesAmount.toString(),
+                        "--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)
+                    )
+                }
+            }
+        }
     }
 })