Committed by
Gerrit Code Review
Adding TLS for NettyMessaging and configurable on NettyMessagingManager through JAVA_OPTS
Change-Id: I5e77658cbae70d3facbe9e1f56c9fa9fcf0e00cc
Showing
3 changed files
with
145 additions
and
14 deletions
| 1 | package org.onosproject.store.cluster.messaging.impl; | 1 | package org.onosproject.store.cluster.messaging.impl; |
| 2 | 2 | ||
| 3 | +import com.google.common.base.Strings; | ||
| 3 | import org.apache.felix.scr.annotations.Activate; | 4 | import org.apache.felix.scr.annotations.Activate; |
| 4 | import org.apache.felix.scr.annotations.Component; | 5 | import org.apache.felix.scr.annotations.Component; |
| 5 | import org.apache.felix.scr.annotations.Deactivate; | 6 | import org.apache.felix.scr.annotations.Deactivate; |
| ... | @@ -22,12 +23,15 @@ public class NettyMessagingManager extends NettyMessaging { | ... | @@ -22,12 +23,15 @@ public class NettyMessagingManager extends NettyMessaging { |
| 22 | 23 | ||
| 23 | private final Logger log = LoggerFactory.getLogger(getClass()); | 24 | private final Logger log = LoggerFactory.getLogger(getClass()); |
| 24 | 25 | ||
| 26 | + private static final short MIN_KS_LENGTH = 6; | ||
| 27 | + | ||
| 25 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 28 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
| 26 | protected ClusterDefinitionService clusterDefinitionService; | 29 | protected ClusterDefinitionService clusterDefinitionService; |
| 27 | 30 | ||
| 28 | @Activate | 31 | @Activate |
| 29 | public void activate() throws Exception { | 32 | public void activate() throws Exception { |
| 30 | ControllerNode localNode = clusterDefinitionService.localNode(); | 33 | ControllerNode localNode = clusterDefinitionService.localNode(); |
| 34 | + getTLSParameters(); | ||
| 31 | super.start(new Endpoint(localNode.ip(), localNode.tcpPort())); | 35 | super.start(new Endpoint(localNode.ip(), localNode.tcpPort())); |
| 32 | log.info("Started"); | 36 | log.info("Started"); |
| 33 | } | 37 | } |
| ... | @@ -37,4 +41,32 @@ public class NettyMessagingManager extends NettyMessaging { | ... | @@ -37,4 +41,32 @@ public class NettyMessagingManager extends NettyMessaging { |
| 37 | super.stop(); | 41 | super.stop(); |
| 38 | log.info("Stopped"); | 42 | log.info("Stopped"); |
| 39 | } | 43 | } |
| 40 | -} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 44 | + | ||
| 45 | + private void getTLSParameters() { | ||
| 46 | + String tempString = System.getProperty("enableNettyTLS"); | ||
| 47 | + enableNettyTLS = Strings.isNullOrEmpty(tempString) ? TLS_DISABLED : Boolean.parseBoolean(tempString); | ||
| 48 | + log.info("enableNettyTLS = {}", enableNettyTLS); | ||
| 49 | + if (enableNettyTLS) { | ||
| 50 | + ksLocation = System.getProperty("javax.net.ssl.keyStore"); | ||
| 51 | + if (Strings.isNullOrEmpty(ksLocation)) { | ||
| 52 | + enableNettyTLS = TLS_DISABLED; | ||
| 53 | + return; | ||
| 54 | + } | ||
| 55 | + tsLocation = System.getProperty("javax.net.ssl.trustStore"); | ||
| 56 | + if (Strings.isNullOrEmpty(tsLocation)) { | ||
| 57 | + enableNettyTLS = TLS_DISABLED; | ||
| 58 | + return; | ||
| 59 | + } | ||
| 60 | + ksPwd = System.getProperty("javax.net.ssl.keyStorePassword").toCharArray(); | ||
| 61 | + if (MIN_KS_LENGTH > ksPwd.length) { | ||
| 62 | + enableNettyTLS = TLS_DISABLED; | ||
| 63 | + return; | ||
| 64 | + } | ||
| 65 | + tsPwd = System.getProperty("javax.net.ssl.trustStorePassword").toCharArray(); | ||
| 66 | + if (MIN_KS_LENGTH > tsPwd.length) { | ||
| 67 | + enableNettyTLS = TLS_DISABLED; | ||
| 68 | + return; | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | +} | ... | ... |
| ... | @@ -6,6 +6,10 @@ | ... | @@ -6,6 +6,10 @@ |
| 6 | # uncomment the following line for performance testing | 6 | # uncomment the following line for performance testing |
| 7 | #export JAVA_OPTS="${JAVA_OPTS:--Xms8G -Xmx8G -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+PrintGCDetails -XX:+PrintGCTimeStamps}" | 7 | #export JAVA_OPTS="${JAVA_OPTS:--Xms8G -Xmx8G -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+PrintGCDetails -XX:+PrintGCTimeStamps}" |
| 8 | 8 | ||
| 9 | +# uncomment the following line for Netty TLS encryption | ||
| 10 | +# Do modify the keystore location/password and truststore location/password accordingly | ||
| 11 | +#export JAVA_OPTS="${JAVA_OPTS:--DenableNettyTLS=true -Djavax.net.ssl.keyStore=/home/ubuntu/onos.jks -Djavax.net.ssl.keyStorePassword=222222 -Djavax.net.ssl.trustStore=/home/ubuntu/onos.jks -Djavax.net.ssl.trustStorePassword=222222}" | ||
| 12 | + | ||
| 9 | ONOS_HOME=/opt/onos | 13 | ONOS_HOME=/opt/onos |
| 10 | 14 | ||
| 11 | [ -d $ONOS_HOME ] && cd $ONOS_HOME || ONOS_HOME=$(dirname $0)/.. | 15 | [ -d $ONOS_HOME ] && cd $ONOS_HOME || ONOS_HOME=$(dirname $0)/.. | ... | ... |
| ... | @@ -35,7 +35,10 @@ import io.netty.channel.socket.SocketChannel; | ... | @@ -35,7 +35,10 @@ import io.netty.channel.socket.SocketChannel; |
| 35 | import io.netty.channel.socket.nio.NioServerSocketChannel; | 35 | import io.netty.channel.socket.nio.NioServerSocketChannel; |
| 36 | import io.netty.channel.socket.nio.NioSocketChannel; | 36 | import io.netty.channel.socket.nio.NioSocketChannel; |
| 37 | 37 | ||
| 38 | +import java.io.FileInputStream; | ||
| 38 | import java.io.IOException; | 39 | import java.io.IOException; |
| 40 | +import java.security.KeyStore; | ||
| 41 | + | ||
| 39 | import java.util.Map; | 42 | import java.util.Map; |
| 40 | import java.util.concurrent.CompletableFuture; | 43 | import java.util.concurrent.CompletableFuture; |
| 41 | import java.util.concurrent.ConcurrentHashMap; | 44 | import java.util.concurrent.ConcurrentHashMap; |
| ... | @@ -60,6 +63,11 @@ import com.google.common.cache.CacheBuilder; | ... | @@ -60,6 +63,11 @@ import com.google.common.cache.CacheBuilder; |
| 60 | import com.google.common.cache.RemovalListener; | 63 | import com.google.common.cache.RemovalListener; |
| 61 | import com.google.common.cache.RemovalNotification; | 64 | import com.google.common.cache.RemovalNotification; |
| 62 | 65 | ||
| 66 | +import javax.net.ssl.KeyManagerFactory; | ||
| 67 | +import javax.net.ssl.SSLContext; | ||
| 68 | +import javax.net.ssl.SSLEngine; | ||
| 69 | +import javax.net.ssl.TrustManagerFactory; | ||
| 70 | + | ||
| 63 | /** | 71 | /** |
| 64 | * Implementation of MessagingService based on <a href="http://netty.io/">Netty</a> framework. | 72 | * Implementation of MessagingService based on <a href="http://netty.io/">Netty</a> framework. |
| 65 | */ | 73 | */ |
| ... | @@ -93,6 +101,14 @@ public class NettyMessaging implements MessagingService { | ... | @@ -93,6 +101,14 @@ public class NettyMessaging implements MessagingService { |
| 93 | private Class<? extends ServerChannel> serverChannelClass; | 101 | private Class<? extends ServerChannel> serverChannelClass; |
| 94 | private Class<? extends Channel> clientChannelClass; | 102 | private Class<? extends Channel> clientChannelClass; |
| 95 | 103 | ||
| 104 | + protected static final boolean TLS_DISABLED = false; | ||
| 105 | + protected boolean enableNettyTLS = TLS_DISABLED; | ||
| 106 | + | ||
| 107 | + protected String ksLocation; | ||
| 108 | + protected String tsLocation; | ||
| 109 | + protected char[] ksPwd; | ||
| 110 | + protected char[] tsPwd; | ||
| 111 | + | ||
| 96 | private void initEventLoopGroup() { | 112 | private void initEventLoopGroup() { |
| 97 | // try Epoll first and if that does work, use nio. | 113 | // try Epoll first and if that does work, use nio. |
| 98 | try { | 114 | try { |
| ... | @@ -216,9 +232,9 @@ public class NettyMessaging implements MessagingService { | ... | @@ -216,9 +232,9 @@ public class NettyMessaging implements MessagingService { |
| 216 | handler.apply(message.payload()).whenComplete((result, error) -> { | 232 | handler.apply(message.payload()).whenComplete((result, error) -> { |
| 217 | if (error == null) { | 233 | if (error == null) { |
| 218 | InternalMessage response = new InternalMessage(message.id(), | 234 | InternalMessage response = new InternalMessage(message.id(), |
| 219 | - localEp, | 235 | + localEp, |
| 220 | - REPLY_MESSAGE_TYPE, | 236 | + REPLY_MESSAGE_TYPE, |
| 221 | - result); | 237 | + result); |
| 222 | sendAsync(message.sender(), response).whenComplete((r, e) -> { | 238 | sendAsync(message.sender(), response).whenComplete((r, e) -> { |
| 223 | if (e != null) { | 239 | if (e != null) { |
| 224 | log.debug("Failed to respond", e); | 240 | log.debug("Failed to respond", e); |
| ... | @@ -241,11 +257,15 @@ public class NettyMessaging implements MessagingService { | ... | @@ -241,11 +257,15 @@ public class NettyMessaging implements MessagingService { |
| 241 | b.option(ChannelOption.SO_RCVBUF, 1048576); | 257 | b.option(ChannelOption.SO_RCVBUF, 1048576); |
| 242 | b.option(ChannelOption.TCP_NODELAY, true); | 258 | b.option(ChannelOption.TCP_NODELAY, true); |
| 243 | b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); | 259 | b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT); |
| 244 | - b.group(serverGroup, clientGroup) | 260 | + b.group(serverGroup, clientGroup); |
| 245 | - .channel(serverChannelClass) | 261 | + b.channel(serverChannelClass); |
| 246 | - .childHandler(new OnosCommunicationChannelInitializer()) | 262 | + if (enableNettyTLS) { |
| 247 | - .option(ChannelOption.SO_BACKLOG, 128) | 263 | + b.childHandler(new SSLServerCommunicationChannelInitializer()); |
| 248 | - .childOption(ChannelOption.SO_KEEPALIVE, true); | 264 | + } else { |
| 265 | + b.childHandler(new OnosCommunicationChannelInitializer()); | ||
| 266 | + } | ||
| 267 | + b.option(ChannelOption.SO_BACKLOG, 128); | ||
| 268 | + b.childOption(ChannelOption.SO_KEEPALIVE, true); | ||
| 249 | 269 | ||
| 250 | // Bind and start to accept incoming connections. | 270 | // Bind and start to accept incoming connections. |
| 251 | b.bind(localEp.port()).sync().addListener(future -> { | 271 | b.bind(localEp.port()).sync().addListener(future -> { |
| ... | @@ -283,7 +303,11 @@ public class NettyMessaging implements MessagingService { | ... | @@ -283,7 +303,11 @@ public class NettyMessaging implements MessagingService { |
| 283 | // http://normanmaurer.me/presentations/2014-facebook-eng-netty/slides.html#37.0 | 303 | // http://normanmaurer.me/presentations/2014-facebook-eng-netty/slides.html#37.0 |
| 284 | bootstrap.channel(clientChannelClass); | 304 | bootstrap.channel(clientChannelClass); |
| 285 | bootstrap.option(ChannelOption.SO_KEEPALIVE, true); | 305 | bootstrap.option(ChannelOption.SO_KEEPALIVE, true); |
| 286 | - bootstrap.handler(new OnosCommunicationChannelInitializer()); | 306 | + if (enableNettyTLS) { |
| 307 | + bootstrap.handler(new SSLClientCommunicationChannelInitializer()); | ||
| 308 | + } else { | ||
| 309 | + bootstrap.handler(new OnosCommunicationChannelInitializer()); | ||
| 310 | + } | ||
| 287 | // Start the client. | 311 | // Start the client. |
| 288 | ChannelFuture f = bootstrap.connect(ep.host().toString(), ep.port()).sync(); | 312 | ChannelFuture f = bootstrap.connect(ep.host().toString(), ep.port()).sync(); |
| 289 | log.debug("Established a new connection to {}", ep); | 313 | log.debug("Established a new connection to {}", ep); |
| ... | @@ -301,6 +325,77 @@ public class NettyMessaging implements MessagingService { | ... | @@ -301,6 +325,77 @@ public class NettyMessaging implements MessagingService { |
| 301 | } | 325 | } |
| 302 | } | 326 | } |
| 303 | 327 | ||
| 328 | + private class SSLServerCommunicationChannelInitializer extends ChannelInitializer<SocketChannel> { | ||
| 329 | + | ||
| 330 | + private final ChannelHandler dispatcher = new InboundMessageDispatcher(); | ||
| 331 | + private final ChannelHandler encoder = new MessageEncoder(); | ||
| 332 | + | ||
| 333 | + @Override | ||
| 334 | + protected void initChannel(SocketChannel channel) throws Exception { | ||
| 335 | + TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); | ||
| 336 | + KeyStore ts = KeyStore.getInstance("JKS"); | ||
| 337 | + ts.load(new FileInputStream(tsLocation), tsPwd); | ||
| 338 | + tmFactory.init(ts); | ||
| 339 | + | ||
| 340 | + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); | ||
| 341 | + KeyStore ks = KeyStore.getInstance("JKS"); | ||
| 342 | + ks.load(new FileInputStream(ksLocation), ksPwd); | ||
| 343 | + kmf.init(ks, ksPwd); | ||
| 344 | + | ||
| 345 | + SSLContext serverContext = SSLContext.getInstance("TLS"); | ||
| 346 | + serverContext.init(kmf.getKeyManagers(), tmFactory.getTrustManagers(), null); | ||
| 347 | + | ||
| 348 | + SSLEngine serverSSLEngine = serverContext.createSSLEngine(); | ||
| 349 | + | ||
| 350 | + serverSSLEngine.setNeedClientAuth(true); | ||
| 351 | + serverSSLEngine.setUseClientMode(false); | ||
| 352 | + serverSSLEngine.setEnabledProtocols(serverSSLEngine.getSupportedProtocols()); | ||
| 353 | + serverSSLEngine.setEnabledCipherSuites(serverSSLEngine.getSupportedCipherSuites()); | ||
| 354 | + serverSSLEngine.setEnableSessionCreation(true); | ||
| 355 | + | ||
| 356 | + channel.pipeline().addLast("ssl", new io.netty.handler.ssl.SslHandler(serverSSLEngine)) | ||
| 357 | + .addLast("encoder", encoder) | ||
| 358 | + .addLast("decoder", new MessageDecoder()) | ||
| 359 | + .addLast("handler", dispatcher); | ||
| 360 | + } | ||
| 361 | + | ||
| 362 | + } | ||
| 363 | + | ||
| 364 | + private class SSLClientCommunicationChannelInitializer extends ChannelInitializer<SocketChannel> { | ||
| 365 | + | ||
| 366 | + private final ChannelHandler dispatcher = new InboundMessageDispatcher(); | ||
| 367 | + private final ChannelHandler encoder = new MessageEncoder(); | ||
| 368 | + | ||
| 369 | + @Override | ||
| 370 | + protected void initChannel(SocketChannel channel) throws Exception { | ||
| 371 | + TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); | ||
| 372 | + KeyStore ts = KeyStore.getInstance("JKS"); | ||
| 373 | + ts.load(new FileInputStream(tsLocation), tsPwd); | ||
| 374 | + tmFactory.init(ts); | ||
| 375 | + | ||
| 376 | + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); | ||
| 377 | + KeyStore ks = KeyStore.getInstance("JKS"); | ||
| 378 | + ks.load(new FileInputStream(ksLocation), ksPwd); | ||
| 379 | + kmf.init(ks, ksPwd); | ||
| 380 | + | ||
| 381 | + SSLContext clientContext = SSLContext.getInstance("TLS"); | ||
| 382 | + clientContext.init(kmf.getKeyManagers(), tmFactory.getTrustManagers(), null); | ||
| 383 | + | ||
| 384 | + SSLEngine clientSSLEngine = clientContext.createSSLEngine(); | ||
| 385 | + | ||
| 386 | + clientSSLEngine.setUseClientMode(true); | ||
| 387 | + clientSSLEngine.setEnabledProtocols(clientSSLEngine.getSupportedProtocols()); | ||
| 388 | + clientSSLEngine.setEnabledCipherSuites(clientSSLEngine.getSupportedCipherSuites()); | ||
| 389 | + clientSSLEngine.setEnableSessionCreation(true); | ||
| 390 | + | ||
| 391 | + channel.pipeline().addLast("ssl", new io.netty.handler.ssl.SslHandler(clientSSLEngine)) | ||
| 392 | + .addLast("encoder", encoder) | ||
| 393 | + .addLast("decoder", new MessageDecoder()) | ||
| 394 | + .addLast("handler", dispatcher); | ||
| 395 | + } | ||
| 396 | + | ||
| 397 | + } | ||
| 398 | + | ||
| 304 | private class OnosCommunicationChannelInitializer extends ChannelInitializer<SocketChannel> { | 399 | private class OnosCommunicationChannelInitializer extends ChannelInitializer<SocketChannel> { |
| 305 | 400 | ||
| 306 | private final ChannelHandler dispatcher = new InboundMessageDispatcher(); | 401 | private final ChannelHandler dispatcher = new InboundMessageDispatcher(); |
| ... | @@ -308,10 +403,10 @@ public class NettyMessaging implements MessagingService { | ... | @@ -308,10 +403,10 @@ public class NettyMessaging implements MessagingService { |
| 308 | 403 | ||
| 309 | @Override | 404 | @Override |
| 310 | protected void initChannel(SocketChannel channel) throws Exception { | 405 | protected void initChannel(SocketChannel channel) throws Exception { |
| 311 | - channel.pipeline() | 406 | + channel.pipeline() |
| 312 | - .addLast("encoder", encoder) | 407 | + .addLast("encoder", encoder) |
| 313 | - .addLast("decoder", new MessageDecoder()) | 408 | + .addLast("decoder", new MessageDecoder()) |
| 314 | - .addLast("handler", dispatcher); | 409 | + .addLast("handler", dispatcher); |
| 315 | } | 410 | } |
| 316 | } | 411 | } |
| 317 | 412 | ... | ... |
-
Please register or login to post a comment