summaryrefslogtreecommitdiffstats
path: root/hv-collector-core
diff options
context:
space:
mode:
authorPiotr Jaszczyk <piotr.jaszczyk@nokia.com>2018-05-29 13:35:11 +0200
committerPiotr Jaszczyk <piotr.jaszczyk@nokia.com>2018-08-01 09:48:32 +0200
commita4becf29f32de7467793867c3be1d5ab5876477e (patch)
tree1e32d3e71188b36e712c8a8ac35c774da70537e1 /hv-collector-core
parenta150bc08ad326699717e09903e42d462e5e9c935 (diff)
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>
Diffstat (limited to 'hv-collector-core')
-rw-r--r--hv-collector-core/pom.xml6
-rw-r--r--hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/boundary/adapters.kt1
-rw-r--r--hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/SecurityConfiguration.kt31
-rw-r--r--hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/ServerConfiguration.kt5
-rw-r--r--hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/factory/ServerFactory.kt6
-rw-r--r--hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/NettyTcpServer.kt (renamed from hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/NettyTcpServer.kt)17
-rw-r--r--hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactory.kt40
-rw-r--r--hv-collector-core/src/test/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactoryTest.kt79
-rw-r--r--hv-collector-core/src/test/resources/ssl/ca.crt21
-rw-r--r--hv-collector-core/src/test/resources/ssl/server.crt19
-rw-r--r--hv-collector-core/src/test/resources/ssl/server.key28
11 files changed, 245 insertions, 8 deletions
diff --git a/hv-collector-core/pom.xml b/hv-collector-core/pom.xml
index ed501a44..6509e899 100644
--- a/hv-collector-core/pom.xml
+++ b/hv-collector-core/pom.xml
@@ -94,6 +94,12 @@
<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>
</dependency>
diff --git a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/boundary/adapters.kt b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/boundary/adapters.kt
index d4de1b5b..2cda86e9 100644
--- a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/boundary/adapters.kt
+++ b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/boundary/adapters.kt
@@ -22,7 +22,6 @@ package org.onap.dcae.collectors.veshv.boundary
import org.onap.dcae.collectors.veshv.domain.CollectorConfiguration
import org.onap.dcae.collectors.veshv.domain.RoutedMessage
import org.onap.dcae.collectors.veshv.domain.VesMessage
-import org.onap.ves.VesEventV5.VesEvent.CommonEventHeader
import reactor.core.publisher.Flux
interface Sink {
diff --git a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/SecurityConfiguration.kt b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/SecurityConfiguration.kt
new file mode 100644
index 00000000..ea430c2c
--- /dev/null
+++ b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/SecurityConfiguration.kt
@@ -0,0 +1,31 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.domain
+
+import java.nio.file.Path
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since May 2018
+ */
+data class SecurityConfiguration(
+ val privateKey: Path,
+ val cert: Path,
+ val trustedCert: Path)
diff --git a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/ServerConfiguration.kt b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/ServerConfiguration.kt
index cf484d7c..b58dffbf 100644
--- a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/ServerConfiguration.kt
+++ b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/domain/ServerConfiguration.kt
@@ -23,4 +23,7 @@ package org.onap.dcae.collectors.veshv.domain
* @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
* @since May 2018
*/
-data class ServerConfiguration( val configurationUrl: String, val port: Int)
+data class ServerConfiguration(
+ val port: Int,
+ val configurationUrl: String,
+ val securityConfiguration: SecurityConfiguration)
diff --git a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/factory/ServerFactory.kt b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/factory/ServerFactory.kt
index 5e60fa56..ca81d69d 100644
--- a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/factory/ServerFactory.kt
+++ b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/factory/ServerFactory.kt
@@ -22,12 +22,14 @@ 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.domain.ServerConfiguration
-import org.onap.dcae.collectors.veshv.impl.NettyTcpServer
+import org.onap.dcae.collectors.veshv.impl.socket.NettyTcpServer
+import org.onap.dcae.collectors.veshv.impl.socket.SslContextFactory
/**
* @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
* @since May 2018
*/
object ServerFactory {
- val createNettyTcpServer: (ServerConfiguration, CollectorProvider) -> Server = ::NettyTcpServer
+ fun createNettyTcpServer(serverConfiguration: ServerConfiguration, collectorProvider: CollectorProvider): Server =
+ NettyTcpServer(serverConfiguration, SslContextFactory(), collectorProvider)
}
diff --git a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/NettyTcpServer.kt b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/NettyTcpServer.kt
index ca77df2a..34aa2e8f 100644
--- a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/NettyTcpServer.kt
+++ b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/NettyTcpServer.kt
@@ -17,7 +17,7 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
-package org.onap.dcae.collectors.veshv.impl
+package org.onap.dcae.collectors.veshv.impl.socket
import org.onap.dcae.collectors.veshv.boundary.CollectorProvider
import org.onap.dcae.collectors.veshv.boundary.Server
@@ -27,6 +27,7 @@ import org.reactivestreams.Publisher
import reactor.core.publisher.Mono
import reactor.ipc.netty.NettyInbound
import reactor.ipc.netty.NettyOutbound
+import reactor.ipc.netty.options.ServerOptions
import reactor.ipc.netty.tcp.TcpServer
import java.util.function.BiFunction
@@ -34,13 +35,16 @@ import java.util.function.BiFunction
* @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
* @since May 2018
*/
-internal class NettyTcpServer(val serverConfig: ServerConfiguration,
- val collectorProvider: CollectorProvider) : Server {
+internal class NettyTcpServer(private val serverConfig: ServerConfiguration,
+ private val sslContextFactory: SslContextFactory,
+ private val collectorProvider: CollectorProvider) : Server {
override fun start(): Mono<Void> {
logger.info { "Listening on port ${serverConfig.port}" }
return Mono.defer {
- val nettyContext = TcpServer.create(serverConfig.port)
+ val nettyContext = TcpServer.builder()
+ .options(this::configureServer)
+ .build()
.start(BiFunction<NettyInbound, NettyOutbound, Publisher<Void>> { t, u ->
handleConnection(t, u)
})
@@ -48,6 +52,11 @@ internal class NettyTcpServer(val serverConfig: ServerConfiguration,
}
}
+ private fun configureServer(opts: ServerOptions.Builder<*>) {
+ opts.port(serverConfig.port)
+ opts.sslContext(sslContextFactory.createSslContext(serverConfig.securityConfiguration))
+ }
+
private fun handleConnection(nettyInbound: NettyInbound, nettyOutbound: NettyOutbound): Mono<Void> {
logger.debug("Got connection")
val pipe = collectorProvider().handleConnection(nettyInbound.receive())
diff --git a/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactory.kt b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactory.kt
new file mode 100644
index 00000000..e94965cd
--- /dev/null
+++ b/hv-collector-core/src/main/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactory.kt
@@ -0,0 +1,40 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dcae.collectors.veshv.impl.socket
+
+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.SecurityConfiguration
+
+
+internal open class SslContextFactory {
+ fun createSslContext(secConfig: SecurityConfiguration): SslContext =
+ createSslContextWithConfiguredCerts(secConfig)
+ .sslProvider(SslProvider.OPENSSL)
+ .clientAuth(ClientAuth.REQUIRE)
+ .build()
+
+ protected open fun createSslContextWithConfiguredCerts(secConfig: SecurityConfiguration): SslContextBuilder =
+ SslContextBuilder.forServer(secConfig.cert.toFile(), secConfig.privateKey.toFile())
+ .trustManager(secConfig.trustedCert.toFile())
+
+}
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
new file mode 100644
index 00000000..2b72620b
--- /dev/null
+++ b/hv-collector-core/src/test/kotlin/org/onap/dcae/collectors/veshv/impl/socket/SslContextFactoryTest.kt
@@ -0,0 +1,79 @@
+/*
+ * ============LICENSE_START=======================================================
+ * dcaegen2-collectors-veshv
+ * ================================================================================
+ * Copyright (C) 2018 NOKIA Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.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.it
+import org.jetbrains.spek.api.dsl.xit
+import org.onap.dcae.collectors.veshv.domain.SecurityConfiguration
+import java.nio.file.Paths
+
+/**
+ * @author Piotr Jaszczyk <piotr.jaszczyk@nokia.com>
+ * @since June 2018
+ */
+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"))
+
+ 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"))
+ }
+
+ private fun resource(path: String) = SslContextFactoryTest.javaClass.getResourceAsStream(path)
+ }
+
+ val result = cut.createSslContext(sampleConfig)
+
+ it("should be server context") {
+ assertThat(result.isServer).isTrue()
+ }
+
+ 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) as ClientAuth
+ }
+ assertThat(clientAuth).isEqualTo(ClientAuth.REQUIRE)
+ }
+ }
+})
diff --git a/hv-collector-core/src/test/resources/ssl/ca.crt b/hv-collector-core/src/test/resources/ssl/ca.crt
new file mode 100644
index 00000000..29057f26
--- /dev/null
+++ b/hv-collector-core/src/test/resources/ssl/ca.crt
@@ -0,0 +1,21 @@
+-----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
new file mode 100644
index 00000000..0af22e29
--- /dev/null
+++ b/hv-collector-core/src/test/resources/ssl/server.crt
@@ -0,0 +1,19 @@
+-----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
new file mode 100644
index 00000000..033c99af
--- /dev/null
+++ b/hv-collector-core/src/test/resources/ssl/server.key
@@ -0,0 +1,28 @@
+-----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-----