Use SSL for encrypting the connection
Netty's OpenSSL bindings are used
Closes ONAP-179
Change-Id: I8249fbaaed1dd869b733db04a27cebf53962c80c
Issue-ID: DCAEGEN2-601
Signed-off-by: Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
diff --git a/hv-collector-main/Dockerfile b/hv-collector-main/Dockerfile
index 84ffb43..749edb8 100644
--- a/hv-collector-main/Dockerfile
+++ b/hv-collector-main/Dockerfile
@@ -5,11 +5,12 @@
LABEL license.url="http://www.apache.org/licenses/LICENSE-2.0"
LABEL maintainer="Nokia Wroclaw ONAP Team"
-EXPOSE 8081
+EXPOSE 6061
WORKDIR /opt/ves-hv-collector
+VOLUME /etc/ves-hv/
ENTRYPOINT ["java", "-cp", "*:", "org.onap.dcae.collectors.veshv.main.MainKt"]
-CMD ["--listen-port", "8081", "--config-url", ""]
+CMD ["--listen-port", "6061"]
COPY target/libs/external/* ./
COPY target/libs/internal/* ./
COPY target/hv-collector-main-*.jar ./
\ No newline at end of file
diff --git a/hv-collector-main/pom.xml b/hv-collector-main/pom.xml
index 80d7233..58fc5d7 100644
--- a/hv-collector-main/pom.xml
+++ b/hv-collector-main/pom.xml
@@ -19,8 +19,8 @@
~ ============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">
+ 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>
@@ -55,43 +55,60 @@
<artifactId>maven-surefire-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
</plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-internal-deps</id>
- <phase>package</phase>
- <goals>
- <goal>copy-dependencies</goal>
- </goals>
- <configuration>
- <outputDirectory>${project.build.directory}/libs/internal</outputDirectory>
- <includeGroupIds>${project.parent.groupId}</includeGroupIds>
- <includeScope>runtime</includeScope>
- </configuration>
- </execution>
- <execution>
- <id>copy-external-deps</id>
- <phase>package</phase>
- <goals>
- <goal>copy-dependencies</goal>
- </goals>
- <configuration>
- <outputDirectory>${project.build.directory}/libs/external</outputDirectory>
- <excludeGroupIds>${project.parent.groupId}</excludeGroupIds>
- <includeScope>runtime</includeScope>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>io.fabric8</groupId>
- <artifactId>docker-maven-plugin</artifactId>
- </plugin>
</plugins>
</build>
+ <profiles>
+ <profile>
+ <id>docker</id>
+ <activation>
+ <property>
+ <name>!skipDocker</name>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-internal-deps</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/libs/internal</outputDirectory>
+ <includeGroupIds>${project.parent.groupId}</includeGroupIds>
+ <includeScope>runtime</includeScope>
+ </configuration>
+ </execution>
+ <execution>
+ <id>copy-external-deps</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/libs/external</outputDirectory>
+ <excludeGroupIds>${project.parent.groupId}</excludeGroupIds>
+ <includeScope>runtime</includeScope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <!--
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ </plugin>
+ -->
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
<dependencies>
<dependency>
<groupId>${project.parent.groupId}</groupId>
@@ -111,6 +128,12 @@
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-tcnative-boringssl-static</artifactId>
+ <scope>runtime</scope>
+ <classifier>${os.detected.classifier}</classifier>
+ </dependency>
<dependency>
<groupId>org.assertj</groupId>
@@ -128,6 +151,14 @@
<groupId>org.jetbrains.spek</groupId>
<artifactId>spek-junit-platform-engine</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.nhaarman</groupId>
+ <artifactId>mockito-kotlin</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ </dependency>
</dependencies>
diff --git a/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/ArgBasedServerConfiguration.kt b/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/ArgBasedServerConfiguration.kt
index 4e614cd..5689a3e 100644
--- a/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/ArgBasedServerConfiguration.kt
+++ b/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/ArgBasedServerConfiguration.kt
@@ -20,54 +20,55 @@
package org.onap.dcae.collectors.veshv.main
import org.apache.commons.cli.*
+import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
import org.onap.dcae.collectors.veshv.domain.ServerConfiguration
+import java.io.File
+import java.nio.file.Paths
internal object DefaultValues {
- const val PORT = 8600
+ const val PORT = 6061
const val CONFIG_URL = ""
+ 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"
}
-internal object ArgBasedServerConfiguration {
- private val OPT_PORT = Option.builder("p")
- .longOpt("listen-port")
- .hasArg()
- .desc("Listen port")
- .build()
-
- private val OPT_CONFIG_URL = Option.builder("c")
- .longOpt("config-url")
- .optionalArg(true)
- .hasArg()
- .desc("Url of ves configuration on consul")
- .build()
-
- private val options by lazy {
- val options = Options()
- options.addOption(OPT_PORT)
- options.addOption(OPT_CONFIG_URL)
- options
- }
+internal class ArgBasedServerConfiguration {
fun parse(args: Array<out String>): ServerConfiguration {
val parser = DefaultParser()
try {
- parser.parse(options, args).run {
- return ServerConfiguration(
- stringValue(OPT_CONFIG_URL, DefaultValues.CONFIG_URL),
- intValue(OPT_PORT, DefaultValues.PORT))
- }
+ val cmdLine = parser.parse(options, args)
+ val port = cmdLine.intValue(OPT_PORT, DefaultValues.PORT)
+ val configUrl = cmdLine.stringValue(OPT_CONFIG_URL, DefaultValues.CONFIG_URL)
+ val secConf = createSecurityConfiguration(cmdLine)
+ return ServerConfiguration(port, configUrl, secConf)
} catch (ex: Exception) {
throw WrongArgumentException(ex)
}
}
+ private fun createSecurityConfiguration(cmdLine: CommandLine): SecurityConfiguration {
+
+ val pkFile = cmdLine.stringValue(OPT_PK_FILE, DefaultValues.PRIVATE_KEY_FILE)
+ val certFile = cmdLine.stringValue(OPT_CERT_FILE, DefaultValues.CERT_FILE)
+ val trustCertFile = cmdLine.stringValue(OPT_TRUST_CERT_FILE, DefaultValues.TRUST_CERT_FILE)
+
+ return SecurityConfiguration(
+ privateKey = stringPathToPath(pkFile),
+ cert = stringPathToPath(certFile),
+ trustedCert = stringPathToPath(trustCertFile)
+ )
+ }
+
private fun CommandLine.intValue(option: Option, default: Int) =
getOptionValue(option.opt)?.toInt() ?: default
private fun CommandLine.stringValue(option: Option, default: String) =
getOptionValue(option.opt) ?: default
+ private fun stringPathToPath(path: String) = Paths.get(File(path).toURI())
class WrongArgumentException(parent: Exception) : Exception(parent.message, parent) {
fun printMessage() {
@@ -79,4 +80,46 @@
formatter.printHelp(programName, options)
}
}
+
+ companion object {
+ private val OPT_PORT = Option.builder("p")
+ .longOpt("listen-port")
+ .hasArg()
+ .desc("Listen port")
+ .build()
+
+ private val OPT_CONFIG_URL = Option.builder("c")
+ .longOpt("config-url")
+ .hasArg()
+ .desc("URL of ves configuration on consul")
+ .build()
+
+ private val OPT_PK_FILE = Option.builder("k")
+ .longOpt("private-key-file")
+ .hasArg()
+ .desc("File with private key in PEM format")
+ .build()
+
+ private val OPT_CERT_FILE = Option.builder("e")
+ .longOpt("cert-file")
+ .hasArg()
+ .desc("File with server certificate bundle")
+ .build()
+
+ private val OPT_TRUST_CERT_FILE = Option.builder("t")
+ .longOpt("trust-cert-file")
+ .hasArg()
+ .desc("File with trusted certificate bundle for authenticating clients")
+ .build()
+
+ private val options by lazy {
+ val options = Options()
+ options.addOption(OPT_PORT)
+ options.addOption(OPT_CONFIG_URL)
+ options.addOption(OPT_PK_FILE)
+ options.addOption(OPT_CERT_FILE)
+ options.addOption(OPT_TRUST_CERT_FILE)
+ options
+ }
+ }
}
diff --git a/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/main.kt b/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/main.kt
index d81a063..3685250 100644
--- a/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/main.kt
+++ b/hv-collector-main/src/main/kotlin/org/onap/dcae/collectors/veshv/main/main.kt
@@ -35,7 +35,7 @@
fun main(args: Array<String>) {
try {
- val serverConfiguration = ArgBasedServerConfiguration.parse(args)
+ val serverConfiguration = ArgBasedServerConfiguration().parse(args)
val collectorProvider = CollectorFactory(
resolveConfigurationProvider(serverConfiguration),
diff --git a/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/ArgBasedServerConfigurationTest.kt b/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/ArgBasedServerConfigurationTest.kt
index 0d2188c..6eec577 100644
--- a/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/ArgBasedServerConfigurationTest.kt
+++ b/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/ArgBasedServerConfigurationTest.kt
@@ -23,31 +23,60 @@
import org.jetbrains.spek.api.Spek
import org.jetbrains.spek.api.dsl.given
import org.jetbrains.spek.api.dsl.it
+import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
+import org.onap.dcae.collectors.veshv.domain.ServerConfiguration
+import java.nio.file.Paths
/**
* @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
* @since May 2018
*/
object ArgBasedServerConfigurationTest : Spek({
- val cut = ArgBasedServerConfiguration
+ lateinit var cut: ArgBasedServerConfiguration
val configurationUrl = "http://test-address/test"
+ 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 = ArgBasedServerConfiguration()
+ }
fun parse(vararg cmdLine: String) = cut.parse(cmdLine)
given("all parameters are present in the long form") {
- val result = parse("--listen-port", "6969", "--config-url", configurationUrl)
+ lateinit var result: ServerConfiguration
+
+ beforeEachTest {
+ result = parse("--listen-port", "6969",
+ "--config-url", configurationUrl,
+ "--private-key-file", pk.toFile().absolutePath,
+ "--cert-file", cert.toFile().absolutePath,
+ "--trust-cert-file", trustCert.toFile().absolutePath)
+ }
it("should set proper port") {
assertThat(result.port).isEqualTo(6969)
}
+
it("should set proper config url") {
assertThat(result.configurationUrl).isEqualTo(configurationUrl)
}
+
+ it("should set proper security configuration") {
+ assertThat(result.securityConfiguration).isEqualTo(
+ SecurityConfiguration(pk, cert, trustCert)
+ )
+ }
}
- given("all parameters are present in the short form") {
- val result = parse("-p", "666", "-c", configurationUrl)
+ given("some parameters are present in the short form") {
+ lateinit var result: ServerConfiguration
+
+ beforeEachTest {
+ result = parse("-p", "666", "-c", configurationUrl)
+ }
it("should set proper port") {
assertThat(result.port).isEqualTo(666)
@@ -59,7 +88,11 @@
}
given("all optional parameters are absent") {
- val result = parse()
+ lateinit var result: ServerConfiguration
+
+ beforeEachTest {
+ result = parse()
+ }
it("should set default port") {
assertThat(result.port).isEqualTo(DefaultValues.PORT)
@@ -69,4 +102,4 @@
assertThat(result.configurationUrl).isEqualTo(DefaultValues.CONFIG_URL)
}
}
-})
\ No newline at end of file
+})
diff --git a/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/NioBuffersTest.kt b/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/NioBuffersTest.kt
index b46d5a2..42bf363 100644
--- a/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/NioBuffersTest.kt
+++ b/hv-collector-main/src/test/kotlin/org/onap/dcae/collectors/veshv/main/NioBuffersTest.kt
@@ -22,13 +22,14 @@
import org.jetbrains.spek.api.Spek
import org.jetbrains.spek.api.dsl.describe
import org.jetbrains.spek.api.dsl.it
+import org.jetbrains.spek.api.dsl.xdescribe
import java.nio.ByteBuffer
-fun Int.toKibibytes(): Int = this * 1024
-fun Int.toMebibytes(): Int = this * 1024 * 1024
-
-
object NioBuffersTest : Spek({
+
+ fun Int.toKibibytes(): Int = this * 1024
+ fun Int.toMebibytes(): Int = this * 1024 * 1024
+
val BUFFER_SIZES = listOf(128.toKibibytes(), 512.toKibibytes(), 1.toMebibytes(), 2.toMebibytes())
val NUMBER_OF_ITERATIONS = 100
@@ -53,7 +54,7 @@
for (singleBufferSize in BUFFER_SIZES) {
- describe("$singleBufferSize bytes buffers") {
+ xdescribe("$singleBufferSize bytes buffers") {
describe("direct buffers") {
val bb1 = ByteBuffer.allocateDirect(singleBufferSize)