This is an automated email from the ASF dual-hosted git repository.

vongosling pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/rocketmq.git


The following commit(s) were added to refs/heads/develop by this push:
     new 96b74a3  [ROCKETMQ-315][ROCKETMQ-327] Enhance TLS feature (#202)
96b74a3 is described below

commit 96b74a3a01053e6b4d0c5e5c1caafad0c467412d
Author: yukon <[email protected]>
AuthorDate: Wed Dec 13 19:39:16 2017 +0800

    [ROCKETMQ-315][ROCKETMQ-327] Enhance TLS feature (#202)
    
    * Add an interface DecryptionStrategy for SslHelper
    
    * Centralize the TLS related configurations
    
    * Use tls test mode by default
    
    * Add SSL related tests
    
    * Add tls related tests
    
    * Add tls config related unit tests
    
    * Pass TLS unit tests
---
 .../org/apache/rocketmq/broker/BrokerStartup.java  |   9 +-
 .../org/apache/rocketmq/client/ClientConfig.java   |   3 +-
 .../remoting/common/{SslMode.java => TlsMode.java} |  12 +-
 .../remoting/netty/NettyRemotingClient.java        |   6 +-
 .../remoting/netty/NettyRemotingServer.java        |  26 +-
 .../rocketmq/remoting/netty/NettySystemConfig.java |  22 --
 .../apache/rocketmq/remoting/netty/SslHelper.java  | 133 ---------
 .../apache/rocketmq/remoting/netty/TlsHelper.java  | 234 ++++++++++++++++
 .../rocketmq/remoting/netty/TlsSystemConfig.java   | 125 +++++++++
 .../rocketmq/remoting/RemotingServerTest.java      |   7 +-
 .../java/org/apache/rocketmq/remoting/TlsTest.java | 298 +++++++++++++++++++++
 remoting/src/test/resources/certs/badClient.key    |  17 ++
 remoting/src/test/resources/certs/badClient.pem    |  18 ++
 remoting/src/test/resources/certs/badServer.key    |  16 ++
 remoting/src/test/resources/certs/badServer.pem    |  18 ++
 remoting/src/test/resources/certs/ca.pem           |  23 ++
 remoting/src/test/resources/certs/client.key       |  17 ++
 remoting/src/test/resources/certs/client.pem       |  18 ++
 remoting/src/test/resources/certs/privkey.pem      |  30 +++
 remoting/src/test/resources/certs/server.key       |  16 ++
 remoting/src/test/resources/certs/server.pem       |  18 ++
 21 files changed, 884 insertions(+), 182 deletions(-)

diff --git a/broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup.java 
b/broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup.java
index a066652..e768c7f 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/BrokerStartup.java
@@ -32,10 +32,11 @@ import org.apache.rocketmq.common.MQVersion;
 import org.apache.rocketmq.common.MixAll;
 import org.apache.rocketmq.common.constant.LoggerName;
 import org.apache.rocketmq.remoting.common.RemotingUtil;
-import org.apache.rocketmq.remoting.common.SslMode;
+import org.apache.rocketmq.remoting.common.TlsMode;
 import org.apache.rocketmq.remoting.netty.NettyClientConfig;
 import org.apache.rocketmq.remoting.netty.NettyServerConfig;
 import org.apache.rocketmq.remoting.netty.NettySystemConfig;
+import org.apache.rocketmq.remoting.netty.TlsSystemConfig;
 import org.apache.rocketmq.remoting.protocol.RemotingCommand;
 import org.apache.rocketmq.srvutil.ServerUtil;
 import org.apache.rocketmq.store.config.BrokerRole;
@@ -43,6 +44,8 @@ import org.apache.rocketmq.store.config.MessageStoreConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_ENABLE;
+
 public class BrokerStartup {
     public static Properties properties = null;
     public static CommandLine commandLine = null;
@@ -98,7 +101,9 @@ public class BrokerStartup {
             final BrokerConfig brokerConfig = new BrokerConfig();
             final NettyServerConfig nettyServerConfig = new 
NettyServerConfig();
             final NettyClientConfig nettyClientConfig = new 
NettyClientConfig();
-            nettyClientConfig.setUseTLS(NettySystemConfig.sslMode == 
SslMode.ENFORCING);
+
+            
nettyClientConfig.setUseTLS(Boolean.parseBoolean(System.getProperty(TLS_ENABLE,
+                String.valueOf(TlsSystemConfig.tlsMode == 
TlsMode.ENFORCING))));
             nettyServerConfig.setListenPort(10911);
             final MessageStoreConfig messageStoreConfig = new 
MessageStoreConfig();
 
diff --git a/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java 
b/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java
index 8f255f0..a9eabfe 100644
--- a/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java
+++ b/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java
@@ -19,6 +19,7 @@ package org.apache.rocketmq.client;
 import org.apache.rocketmq.common.MixAll;
 import org.apache.rocketmq.common.UtilAll;
 import org.apache.rocketmq.remoting.common.RemotingUtil;
+import org.apache.rocketmq.remoting.netty.TlsSystemConfig;
 
 /**
  * Client Common configuration
@@ -45,7 +46,7 @@ public class ClientConfig {
     private String unitName;
     private boolean vipChannelEnabled = 
Boolean.parseBoolean(System.getProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, 
"true"));
 
-    private boolean useTLS;
+    private boolean useTLS = TlsSystemConfig.tlsEnable;
 
     public String buildMQClientId() {
         StringBuilder sb = new StringBuilder();
diff --git 
a/remoting/src/main/java/org/apache/rocketmq/remoting/common/SslMode.java 
b/remoting/src/main/java/org/apache/rocketmq/remoting/common/TlsMode.java
similarity index 87%
rename from 
remoting/src/main/java/org/apache/rocketmq/remoting/common/SslMode.java
rename to 
remoting/src/main/java/org/apache/rocketmq/remoting/common/TlsMode.java
index cb1e85a..996ef0d 100644
--- a/remoting/src/main/java/org/apache/rocketmq/remoting/common/SslMode.java
+++ b/remoting/src/main/java/org/apache/rocketmq/remoting/common/TlsMode.java
@@ -25,7 +25,7 @@ package org.apache.rocketmq.remoting.common;
  *     <li><strong>enforcing:</strong> SSL is required, aka, non SSL 
connection will be rejected.</li>
  * </ol>
  */
-public enum SslMode {
+public enum TlsMode {
 
     DISABLED("disabled"),
     PERMISSIVE("permissive"),
@@ -33,14 +33,14 @@ public enum SslMode {
 
     private String name;
 
-    SslMode(String name) {
+    TlsMode(String name) {
         this.name = name;
     }
 
-    public static SslMode parse(String mode) {
-        for (SslMode sslMode: SslMode.values()) {
-            if (sslMode.name.equals(mode)) {
-                return sslMode;
+    public static TlsMode parse(String mode) {
+        for (TlsMode tlsMode : TlsMode.values()) {
+            if (tlsMode.name.equals(mode)) {
+                return tlsMode;
             }
         }
 
diff --git 
a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingClient.java
 
b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingClient.java
index 6dc0457..dcc80cb 100644
--- 
a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingClient.java
+++ 
b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingClient.java
@@ -34,6 +34,7 @@ import io.netty.handler.timeout.IdleState;
 import io.netty.handler.timeout.IdleStateEvent;
 import io.netty.handler.timeout.IdleStateHandler;
 import io.netty.util.concurrent.DefaultEventExecutorGroup;
+import java.io.IOException;
 import java.net.SocketAddress;
 import java.security.cert.CertificateException;
 import java.util.Collections;
@@ -52,7 +53,6 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
-import javax.net.ssl.SSLException;
 import org.apache.rocketmq.remoting.ChannelEventListener;
 import org.apache.rocketmq.remoting.InvokeCallback;
 import org.apache.rocketmq.remoting.RPCHook;
@@ -131,9 +131,9 @@ public class NettyRemotingClient extends 
NettyRemotingAbstract implements Remoti
 
         if (nettyClientConfig.isUseTLS()) {
             try {
-                sslContext = SslHelper.buildSslContext(true);
+                sslContext = TlsHelper.buildSslContext(true);
                 log.info("SSL enabled for client");
-            } catch (SSLException e) {
+            } catch (IOException e) {
                 log.error("Failed to create SSLContext", e);
             } catch (CertificateException e) {
                 log.error("Failed to create SSLContext", e);
diff --git 
a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingServer.java
 
b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingServer.java
index ec1927a..cd6ed47 100644
--- 
a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingServer.java
+++ 
b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettyRemotingServer.java
@@ -37,6 +37,7 @@ import io.netty.handler.timeout.IdleState;
 import io.netty.handler.timeout.IdleStateEvent;
 import io.netty.handler.timeout.IdleStateHandler;
 import io.netty.util.concurrent.DefaultEventExecutorGroup;
+import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.security.cert.CertificateException;
 import java.util.NoSuchElementException;
@@ -46,7 +47,6 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicInteger;
-import javax.net.ssl.SSLException;
 import org.apache.rocketmq.remoting.ChannelEventListener;
 import org.apache.rocketmq.remoting.InvokeCallback;
 import org.apache.rocketmq.remoting.RPCHook;
@@ -54,7 +54,7 @@ import org.apache.rocketmq.remoting.RemotingServer;
 import org.apache.rocketmq.remoting.common.Pair;
 import org.apache.rocketmq.remoting.common.RemotingHelper;
 import org.apache.rocketmq.remoting.common.RemotingUtil;
-import org.apache.rocketmq.remoting.common.SslMode;
+import org.apache.rocketmq.remoting.common.TlsMode;
 import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
 import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
 import org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException;
@@ -139,16 +139,16 @@ public class NettyRemotingServer extends 
NettyRemotingAbstract implements Remoti
             });
         }
 
-        SslMode sslMode = NettySystemConfig.sslMode;
-        log.info("Server is running in TLS {} mode", sslMode.getName());
+        TlsMode tlsMode = TlsSystemConfig.tlsMode;
+        log.info("Server is running in TLS {} mode", tlsMode.getName());
 
-        if (sslMode != SslMode.DISABLED) {
+        if (tlsMode != TlsMode.DISABLED) {
             try {
-                sslContext = SslHelper.buildSslContext(false);
+                sslContext = TlsHelper.buildSslContext(false);
                 log.info("SSLContext created for server");
             } catch (CertificateException e) {
                 log.error("Failed to create SSLContext for server", e);
-            } catch (SSLException e) {
+            } catch (IOException e) {
                 log.error("Failed to create SSLContext for server", e);
             }
         }
@@ -189,7 +189,7 @@ public class NettyRemotingServer extends 
NettyRemotingAbstract implements Remoti
                     public void initChannel(SocketChannel ch) throws Exception 
{
                         ch.pipeline()
                             .addLast(defaultEventExecutorGroup, 
HANDSHAKE_HANDLER_NAME,
-                                new 
HandshakeHandler(NettySystemConfig.sslMode))
+                                new HandshakeHandler(TlsSystemConfig.tlsMode))
                             .addLast(defaultEventExecutorGroup,
                                 new NettyEncoder(),
                                 new NettyDecoder(),
@@ -326,12 +326,12 @@ public class NettyRemotingServer extends 
NettyRemotingAbstract implements Remoti
 
     class HandshakeHandler extends SimpleChannelInboundHandler<ByteBuf> {
 
-        private final SslMode sslMode;
+        private final TlsMode tlsMode;
 
         private static final byte HANDSHAKE_MAGIC_CODE = 0x16;
 
-        HandshakeHandler(SslMode sslMode) {
-            this.sslMode = sslMode;
+        HandshakeHandler(TlsMode tlsMode) {
+            this.tlsMode = tlsMode;
         }
 
         @Override
@@ -344,7 +344,7 @@ public class NettyRemotingServer extends 
NettyRemotingAbstract implements Remoti
             byte b = msg.getByte(0);
 
             if (b == HANDSHAKE_MAGIC_CODE) {
-                switch (sslMode) {
+                switch (tlsMode) {
                     case DISABLED:
                         ctx.close();
                         log.warn("Clients intend to establish a SSL connection 
while this server is running in SSL disabled mode");
@@ -366,7 +366,7 @@ public class NettyRemotingServer extends 
NettyRemotingAbstract implements Remoti
                         log.warn("Unknown TLS mode");
                         break;
                 }
-            } else if (sslMode == SslMode.ENFORCING) {
+            } else if (tlsMode == TlsMode.ENFORCING) {
                 ctx.close();
                 log.warn("Clients intend to establish an insecure connection 
while this server is running in SSL enforcing mode");
             }
diff --git 
a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettySystemConfig.java
 
b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettySystemConfig.java
index b9c1f3f..6357c03 100644
--- 
a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettySystemConfig.java
+++ 
b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/NettySystemConfig.java
@@ -17,8 +17,6 @@
 
 package org.apache.rocketmq.remoting.netty;
 
-import org.apache.rocketmq.remoting.common.SslMode;
-
 public class NettySystemConfig {
     public static final String 
COM_ROCKETMQ_REMOTING_NETTY_POOLED_BYTE_BUF_ALLOCATOR_ENABLE =
         "com.rocketmq.remoting.nettyPooledByteBufAllocatorEnable";
@@ -31,12 +29,6 @@ public class NettySystemConfig {
     public static final String 
COM_ROCKETMQ_REMOTING_CLIENT_ONEWAY_SEMAPHORE_VALUE =
         "com.rocketmq.remoting.clientOnewaySemaphoreValue";
 
-    public static final String ORG_APACHE_ROCKETMQ_REMOTING_SSL_MODE = //
-        "org.apache.rocketmq.remoting.ssl.mode";
-
-    public static final String ORG_APACHE_ROCKETMQ_REMOTING_SSL_CONFIG_FILE = 
//
-        "org.apache.rocketmq.remoting.ssl.config.file";
-
     public static final boolean NETTY_POOLED_BYTE_BUF_ALLOCATOR_ENABLE = //
         
Boolean.parseBoolean(System.getProperty(COM_ROCKETMQ_REMOTING_NETTY_POOLED_BYTE_BUF_ALLOCATOR_ENABLE,
 "false"));
     public static final int CLIENT_ASYNC_SEMAPHORE_VALUE = //
@@ -47,18 +39,4 @@ public class NettySystemConfig {
         
Integer.parseInt(System.getProperty(COM_ROCKETMQ_REMOTING_SOCKET_SNDBUF_SIZE, 
"65535"));
     public static int socketRcvbufSize =
         
Integer.parseInt(System.getProperty(COM_ROCKETMQ_REMOTING_SOCKET_RCVBUF_SIZE, 
"65535"));
-
-    /**
-     * For server, three SSL modes are supported: disabled, permissive and 
enforcing.
-     * <ol>
-     *     <li><strong>disabled:</strong> SSL is not supported; any incoming 
SSL handshake will be rejected, causing connection closed.</li>
-     *     <li><strong>permissive:</strong> SSL is optional, aka, server in 
this mode can serve client connections with or without SSL;</li>
-     *     <li><strong>enforcing:</strong> SSL is required, aka, non SSL 
connection will be rejected.</li>
-     * </ol>
-     */
-    public static SslMode sslMode = //
-        
SslMode.parse(System.getProperty(ORG_APACHE_ROCKETMQ_REMOTING_SSL_MODE, 
"permissive"));
-
-    public static String sslConfigFile = //
-        System.getProperty(ORG_APACHE_ROCKETMQ_REMOTING_SSL_CONFIG_FILE, 
"/etc/rocketmq/ssl.properties");
 }
diff --git 
a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/SslHelper.java 
b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/SslHelper.java
deleted file mode 100644
index ebadd96..0000000
--- a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/SslHelper.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-
-package org.apache.rocketmq.remoting.netty;
-
-import io.netty.handler.ssl.ClientAuth;
-import io.netty.handler.ssl.OpenSsl;
-import io.netty.handler.ssl.SslContext;
-import io.netty.handler.ssl.SslContextBuilder;
-import io.netty.handler.ssl.SslProvider;
-import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
-import io.netty.handler.ssl.util.SelfSignedCertificate;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.cert.CertificateException;
-import java.util.Properties;
-import javax.net.ssl.SSLException;
-import org.apache.rocketmq.remoting.common.RemotingHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SslHelper {
-
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(RemotingHelper.ROCKETMQ_REMOTING);
-
-    public static SslContext buildSslContext(boolean forClient) throws 
SSLException, CertificateException {
-
-        File configFile = new File(NettySystemConfig.sslConfigFile);
-        boolean testMode = !(configFile.exists() && configFile.isFile() && 
configFile.canRead());
-        Properties properties = null;
-
-        if (!testMode) {
-            properties = new Properties();
-            InputStream inputStream = null;
-            try {
-                inputStream = new FileInputStream(configFile);
-                properties.load(inputStream);
-            } catch (FileNotFoundException ignore) {
-            } catch (IOException ignore) {
-            } finally {
-                if (null != inputStream) {
-                    try {
-                        inputStream.close();
-                    } catch (IOException ignore) {
-                    }
-                }
-            }
-        }
-
-        SslProvider provider = null;
-        if (OpenSsl.isAvailable()) {
-            provider = SslProvider.OPENSSL;
-            LOGGER.info("Using OpenSSL provider");
-        } else {
-            provider = SslProvider.JDK;
-            LOGGER.info("Using JDK SSL provider");
-        }
-
-        if (forClient) {
-            if (testMode) {
-                return SslContextBuilder
-                    .forClient()
-                    .sslProvider(SslProvider.JDK)
-                    .trustManager(InsecureTrustManagerFactory.INSTANCE)
-                    .build();
-            } else {
-                SslContextBuilder sslContextBuilder = 
SslContextBuilder.forClient().sslProvider(SslProvider.JDK);
-
-                if 
("false".equals(properties.getProperty("client.auth.server"))) {
-                    
sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
-                } else {
-                    if (properties.containsKey("client.trustManager")) {
-                        sslContextBuilder.trustManager(new 
File(properties.getProperty("client.trustManager")));
-                    }
-                }
-
-                return sslContextBuilder.keyManager(
-                    properties.containsKey("client.keyCertChainFile") ? new 
File(properties.getProperty("client.keyCertChainFile")) : null,
-                    properties.containsKey("client.keyFile") ? new 
File(properties.getProperty("client.keyFile")) : null,
-                    properties.containsKey("client.password") ? 
properties.getProperty("client.password") : null)
-                    .build();
-            }
-        } else {
-
-            if (testMode) {
-                SelfSignedCertificate selfSignedCertificate = new 
SelfSignedCertificate();
-                return SslContextBuilder
-                    .forServer(selfSignedCertificate.certificate(), 
selfSignedCertificate.privateKey())
-                    .sslProvider(SslProvider.JDK)
-                    .clientAuth(ClientAuth.OPTIONAL)
-                    .build();
-            } else {
-                return SslContextBuilder.forServer(
-                    properties.containsKey("server.keyCertChainFile") ? new 
File(properties.getProperty("server.keyCertChainFile")) : null,
-                    properties.containsKey("server.keyFile") ? new 
File(properties.getProperty("server.keyFile")) : null,
-                    properties.containsKey("server.password") ? 
properties.getProperty("server.password") : null)
-                    .sslProvider(provider)
-                    .trustManager(new 
File(properties.getProperty("server.trustManager")))
-                    
.clientAuth(parseClientAuthMode(properties.getProperty("server.auth.client")))
-                    .build();
-            }
-        }
-    }
-
-    private static ClientAuth parseClientAuthMode(String authMode) {
-        if (null == authMode || authMode.trim().isEmpty()) {
-            return ClientAuth.NONE;
-        }
-
-        if ("optional".equalsIgnoreCase(authMode)) {
-            return ClientAuth.OPTIONAL;
-        }
-
-        return ClientAuth.REQUIRE;
-    }
-}
diff --git 
a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/TlsHelper.java 
b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/TlsHelper.java
new file mode 100644
index 0000000..3a74b4b
--- /dev/null
+++ b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/TlsHelper.java
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.rocketmq.remoting.netty;
+
+import io.netty.handler.ssl.ClientAuth;
+import io.netty.handler.ssl.OpenSsl;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.SslProvider;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+import io.netty.handler.ssl.util.SelfSignedCertificate;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.CertificateException;
+import java.util.Properties;
+import org.apache.rocketmq.remoting.common.RemotingHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_CLIENT_AUTHSERVER;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_CLIENT_CERTPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_CLIENT_KEYPASSWORD;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_CLIENT_KEYPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_CLIENT_TRUSTCERTPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_AUTHCLIENT;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_CERTPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_KEYPASSWORD;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_KEYPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_NEED_CLIENT_AUTH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_TRUSTCERTPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_TEST_MODE_ENABLE;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsClientAuthServer;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsClientCertPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsClientKeyPassword;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsClientKeyPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsClientTrustCertPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerAuthClient;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerCertPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerKeyPassword;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerKeyPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerNeedClientAuth;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerTrustCertPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsTestModeEnable;
+
+public class TlsHelper {
+
+    public interface DecryptionStrategy {
+        /**
+         * Decrypt the target encrpted private key file.
+         *
+         * @param privateKeyEncryptPath A pathname string
+         * @param forClient tells whether it's a client-side key file
+         * @return An input stream for a decrypted key file
+         * @throws IOException if an I/O error has occurred
+         */
+        InputStream decryptPrivateKey(String privateKeyEncryptPath, boolean 
forClient) throws IOException;
+    }
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(RemotingHelper.ROCKETMQ_REMOTING);
+
+    private static DecryptionStrategy decryptionStrategy = new 
DecryptionStrategy() {
+        @Override
+        public InputStream decryptPrivateKey(final String 
privateKeyEncryptPath,
+            final boolean forClient) throws IOException {
+            return new FileInputStream(privateKeyEncryptPath);
+        }
+    };
+
+
+    public static void registerDecryptionStrategy(final DecryptionStrategy 
decryptionStrategy) {
+        TlsHelper.decryptionStrategy = decryptionStrategy;
+    }
+
+    public static SslContext buildSslContext(boolean forClient) throws 
IOException, CertificateException {
+        File configFile = new File(TlsSystemConfig.tlsConfigFile);
+        extractTlsConfigFromFile(configFile);
+        logTheFinalUsedTlsConfig();
+
+        SslProvider provider;
+        if (OpenSsl.isAvailable()) {
+            provider = SslProvider.OPENSSL;
+            LOGGER.info("Using OpenSSL provider");
+        } else {
+            provider = SslProvider.JDK;
+            LOGGER.info("Using JDK SSL provider");
+        }
+
+        if (forClient) {
+            if (tlsTestModeEnable) {
+                return SslContextBuilder
+                    .forClient()
+                    .sslProvider(SslProvider.JDK)
+                    .trustManager(InsecureTrustManagerFactory.INSTANCE)
+                    .build();
+            } else {
+                SslContextBuilder sslContextBuilder = 
SslContextBuilder.forClient().sslProvider(SslProvider.JDK);
+
+
+                if (!tlsClientAuthServer) {
+                    
sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
+                } else {
+                    if (!isNullOrEmpty(tlsClientTrustCertPath)) {
+                        sslContextBuilder.trustManager(new 
File(tlsClientTrustCertPath));
+                    }
+                }
+
+                return sslContextBuilder.keyManager(
+                    !isNullOrEmpty(tlsClientCertPath) ? new 
FileInputStream(tlsClientCertPath) : null,
+                    !isNullOrEmpty(tlsClientKeyPath) ? 
decryptionStrategy.decryptPrivateKey(tlsClientKeyPath, true) : null,
+                    !isNullOrEmpty(tlsClientKeyPassword) ? 
tlsClientKeyPassword : null)
+                    .build();
+            }
+        } else {
+
+            if (tlsTestModeEnable) {
+                SelfSignedCertificate selfSignedCertificate = new 
SelfSignedCertificate();
+                return SslContextBuilder
+                    .forServer(selfSignedCertificate.certificate(), 
selfSignedCertificate.privateKey())
+                    .sslProvider(SslProvider.JDK)
+                    .clientAuth(ClientAuth.OPTIONAL)
+                    .build();
+            } else {
+                SslContextBuilder sslContextBuilder = 
SslContextBuilder.forServer(
+                    !isNullOrEmpty(tlsServerCertPath) ? new 
FileInputStream(tlsServerCertPath) : null,
+                    !isNullOrEmpty(tlsServerKeyPath) ? 
decryptionStrategy.decryptPrivateKey(tlsServerKeyPath, false) : null,
+                    !isNullOrEmpty(tlsServerKeyPassword) ? 
tlsServerKeyPassword : null)
+                    .sslProvider(provider);
+
+                if (!tlsServerAuthClient) {
+                    
sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
+                } else {
+                    if (!isNullOrEmpty(tlsServerTrustCertPath)) {
+                        sslContextBuilder.trustManager(new 
File(tlsServerTrustCertPath));
+                    }
+                }
+
+                
sslContextBuilder.clientAuth(parseClientAuthMode(tlsServerNeedClientAuth));
+                return sslContextBuilder.build();
+            }
+        }
+    }
+
+    private static void extractTlsConfigFromFile(final File configFile) {
+        if (!(configFile.exists() && configFile.isFile() && 
configFile.canRead())) {
+            LOGGER.info("Tls config file doesn't exist, skip it");
+            return;
+        }
+
+        Properties properties;
+        properties = new Properties();
+        InputStream inputStream = null;
+        try {
+            inputStream = new FileInputStream(configFile);
+            properties.load(inputStream);
+        } catch (IOException ignore) {
+        } finally {
+            if (null != inputStream) {
+                try {
+                    inputStream.close();
+                } catch (IOException ignore) {
+                }
+            }
+        }
+
+        tlsTestModeEnable = 
Boolean.parseBoolean(properties.getProperty(TLS_TEST_MODE_ENABLE, 
String.valueOf(tlsTestModeEnable)));
+        tlsServerNeedClientAuth = 
properties.getProperty(TLS_SERVER_NEED_CLIENT_AUTH, tlsServerNeedClientAuth);
+        tlsServerKeyPath = properties.getProperty(TLS_SERVER_KEYPATH, 
tlsServerKeyPath);
+        tlsServerKeyPassword = properties.getProperty(TLS_SERVER_KEYPASSWORD, 
tlsServerKeyPassword);
+        tlsServerCertPath = properties.getProperty(TLS_SERVER_CERTPATH, 
tlsServerCertPath);
+        tlsServerAuthClient = 
Boolean.parseBoolean(properties.getProperty(TLS_SERVER_AUTHCLIENT, 
String.valueOf(tlsServerAuthClient)));
+        tlsServerTrustCertPath = 
properties.getProperty(TLS_SERVER_TRUSTCERTPATH, tlsServerTrustCertPath);
+
+        tlsClientKeyPath = properties.getProperty(TLS_CLIENT_KEYPATH, 
tlsClientKeyPath);
+        tlsClientKeyPassword = properties.getProperty(TLS_CLIENT_KEYPASSWORD, 
tlsClientKeyPassword);
+        tlsClientCertPath = properties.getProperty(TLS_CLIENT_CERTPATH, 
tlsClientCertPath);
+        tlsClientAuthServer = 
Boolean.parseBoolean(properties.getProperty(TLS_CLIENT_AUTHSERVER, 
String.valueOf(tlsClientAuthServer)));
+        tlsClientTrustCertPath = 
properties.getProperty(TLS_CLIENT_TRUSTCERTPATH, tlsClientTrustCertPath);
+    }
+
+    private static void logTheFinalUsedTlsConfig() {
+        LOGGER.info("Log the final used tls related configuration");
+        LOGGER.info("{} = {}", TLS_TEST_MODE_ENABLE, tlsTestModeEnable);
+        LOGGER.info("{} = {}", TLS_SERVER_NEED_CLIENT_AUTH, 
tlsServerNeedClientAuth);
+        LOGGER.info("{} = {}", TLS_SERVER_KEYPATH, tlsServerKeyPath);
+        LOGGER.info("{} = {}", TLS_SERVER_KEYPASSWORD, tlsServerKeyPassword);
+        LOGGER.info("{} = {}", TLS_SERVER_CERTPATH, tlsServerCertPath);
+        LOGGER.info("{} = {}", TLS_SERVER_AUTHCLIENT, tlsServerAuthClient);
+        LOGGER.info("{} = {}", TLS_SERVER_TRUSTCERTPATH, 
tlsServerTrustCertPath);
+
+        LOGGER.info("{} = {}", TLS_CLIENT_KEYPATH, tlsClientKeyPath);
+        LOGGER.info("{} = {}", TLS_CLIENT_KEYPASSWORD, tlsClientKeyPassword);
+        LOGGER.info("{} = {}", TLS_CLIENT_CERTPATH, tlsClientCertPath);
+        LOGGER.info("{} = {}", TLS_CLIENT_AUTHSERVER, tlsClientAuthServer);
+        LOGGER.info("{} = {}", TLS_CLIENT_TRUSTCERTPATH, 
tlsClientTrustCertPath);
+    }
+
+    private static ClientAuth parseClientAuthMode(String authMode) {
+        if (null == authMode || authMode.trim().isEmpty()) {
+            return ClientAuth.NONE;
+        }
+
+        for (ClientAuth clientAuth : ClientAuth.values()) {
+            if (clientAuth.name().equals(authMode.toUpperCase())) {
+                return clientAuth;
+            }
+        }
+
+        return ClientAuth.NONE;
+    }
+
+    /**
+     * Determine if a string is {@code null} or {@link String#isEmpty()} 
returns {@code true}.
+     */
+    private static boolean isNullOrEmpty(String s) {
+        return s == null || s.isEmpty();
+    }
+}
diff --git 
a/remoting/src/main/java/org/apache/rocketmq/remoting/netty/TlsSystemConfig.java
 
b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/TlsSystemConfig.java
new file mode 100644
index 0000000..403bd6c
--- /dev/null
+++ 
b/remoting/src/main/java/org/apache/rocketmq/remoting/netty/TlsSystemConfig.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.rocketmq.remoting.netty;
+
+import io.netty.handler.ssl.SslContext;
+import org.apache.rocketmq.remoting.common.TlsMode;
+
+public class TlsSystemConfig {
+    public static final String TLS_SERVER_MODE = "tls.server.mode";
+    public static final String TLS_ENABLE = "tls.enable";
+    public static final String TLS_CONFIG_FILE = "tls.config.file";
+    public static final String TLS_TEST_MODE_ENABLE = "tls.test.mode.enable";
+
+    public static final String TLS_SERVER_NEED_CLIENT_AUTH = 
"tls.server.need.client.auth";
+    public static final String TLS_SERVER_KEYPATH = "tls.server.keyPath";
+    public static final String TLS_SERVER_KEYPASSWORD = 
"tls.server.keyPassword";
+    public static final String TLS_SERVER_CERTPATH = "tls.server.certPath";
+    public static final String TLS_SERVER_AUTHCLIENT = "tls.server.authClient";
+    public static final String TLS_SERVER_TRUSTCERTPATH = 
"tls.server.trustCertPath";
+
+    public static final String TLS_CLIENT_KEYPATH = "tls.client.keyPath";
+    public static final String TLS_CLIENT_KEYPASSWORD = 
"tls.client.keyPassword";
+    public static final String TLS_CLIENT_CERTPATH = "tls.client.certPath";
+    public static final String TLS_CLIENT_AUTHSERVER = "tls.client.authServer";
+    public static final String TLS_CLIENT_TRUSTCERTPATH = 
"tls.client.trustCertPath";
+
+
+    /**
+     * To determine whether use SSL in client-side, include SDK client and 
BrokerOuterAPI
+     */
+    public static boolean tlsEnable = 
Boolean.parseBoolean(System.getProperty(TLS_ENABLE, "false"));
+
+    /**
+     * To determine whether use test mode when initialize TLS context
+     */
+    public static boolean tlsTestModeEnable = 
Boolean.parseBoolean(System.getProperty(TLS_TEST_MODE_ENABLE, "true"));
+
+    /**
+     * Indicates the state of the {@link javax.net.ssl.SSLEngine} with respect 
to client authentication.
+     * This configuration item really only applies when building the 
server-side {@link SslContext},
+     * and can be set to none, require or optional.
+     */
+    public static String tlsServerNeedClientAuth = 
System.getProperty(TLS_SERVER_NEED_CLIENT_AUTH, "none");
+    /**
+     * The store path of server-side private key
+     */
+    public static String tlsServerKeyPath = 
System.getProperty(TLS_SERVER_KEYPATH, null);
+
+    /**
+     * The  password of the server-side private key
+     */
+    public static String tlsServerKeyPassword = 
System.getProperty(TLS_SERVER_KEYPASSWORD, null);
+
+    /**
+     * The store path of server-side X.509 certificate chain in PEM format
+     */
+    public static String tlsServerCertPath = 
System.getProperty(TLS_SERVER_CERTPATH, null);
+
+    /**
+     * To determine whether verify the client endpoint's certificate strictly
+     */
+    public static boolean tlsServerAuthClient = 
Boolean.parseBoolean(System.getProperty(TLS_SERVER_AUTHCLIENT, "false"));
+
+    /**
+     * The store path of trusted certificates for verifying the client 
endpoint's certificate
+     */
+    public static String tlsServerTrustCertPath = 
System.getProperty(TLS_SERVER_TRUSTCERTPATH, null);
+
+    /**
+     * The store path of client-side private key
+     */
+    public static String tlsClientKeyPath = 
System.getProperty(TLS_CLIENT_KEYPATH, null);
+
+    /**
+     * The  password of the client-side private key
+     */
+    public static String tlsClientKeyPassword = 
System.getProperty(TLS_CLIENT_KEYPASSWORD, null);
+
+    /**
+     * The store path of client-side X.509 certificate chain in PEM format
+     */
+    public static String tlsClientCertPath = 
System.getProperty(TLS_CLIENT_CERTPATH, null);
+
+    /**
+     * To determine whether verify the server endpoint's certificate strictly
+     */
+    public static boolean tlsClientAuthServer = 
Boolean.parseBoolean(System.getProperty(TLS_CLIENT_AUTHSERVER, "false"));
+
+    /**
+     * The store path of trusted certificates for verifying the server 
endpoint's certificate
+     */
+    public static String tlsClientTrustCertPath = 
System.getProperty(TLS_CLIENT_TRUSTCERTPATH, null);
+
+    /**
+     * For server, three SSL modes are supported: disabled, permissive and 
enforcing.
+     * For client, use {@link TlsSystemConfig#tlsEnable} to determine whether 
use SSL.
+     * <ol>
+     *     <li><strong>disabled:</strong> SSL is not supported; any incoming 
SSL handshake will be rejected, causing connection closed.</li>
+     *     <li><strong>permissive:</strong> SSL is optional, aka, server in 
this mode can serve client connections with or without SSL;</li>
+     *     <li><strong>enforcing:</strong> SSL is required, aka, non SSL 
connection will be rejected.</li>
+     * </ol>
+     */
+    public static TlsMode tlsMode = 
TlsMode.parse(System.getProperty(TLS_SERVER_MODE, "permissive"));
+
+    /**
+     * A config file to store the above TLS related configurations,
+     * except {@link TlsSystemConfig#tlsMode} and {@link 
TlsSystemConfig#tlsEnable}
+     */
+    public static String tlsConfigFile = System.getProperty(TLS_CONFIG_FILE, 
"/etc/rocketmq/tls.properties");
+}
diff --git 
a/remoting/src/test/java/org/apache/rocketmq/remoting/RemotingServerTest.java 
b/remoting/src/test/java/org/apache/rocketmq/remoting/RemotingServerTest.java
index 31c2647..0ecfaaa 100644
--- 
a/remoting/src/test/java/org/apache/rocketmq/remoting/RemotingServerTest.java
+++ 
b/remoting/src/test/java/org/apache/rocketmq/remoting/RemotingServerTest.java
@@ -67,8 +67,11 @@ public class RemotingServerTest {
     }
 
     public static RemotingClient createRemotingClient() {
-        NettyClientConfig config = new NettyClientConfig();
-        RemotingClient client = new NettyRemotingClient(config);
+        return createRemotingClient(new NettyClientConfig());
+    }
+
+    public static RemotingClient createRemotingClient(NettyClientConfig 
nettyClientConfig) {
+        RemotingClient client = new NettyRemotingClient(nettyClientConfig);
         client.start();
         return client;
     }
diff --git a/remoting/src/test/java/org/apache/rocketmq/remoting/TlsTest.java 
b/remoting/src/test/java/org/apache/rocketmq/remoting/TlsTest.java
new file mode 100644
index 0000000..5e516dd
--- /dev/null
+++ b/remoting/src/test/java/org/apache/rocketmq/remoting/TlsTest.java
@@ -0,0 +1,298 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.rocketmq.remoting;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import org.apache.rocketmq.remoting.common.TlsMode;
+import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
+import org.apache.rocketmq.remoting.netty.NettyClientConfig;
+import org.apache.rocketmq.remoting.netty.TlsHelper;
+import org.apache.rocketmq.remoting.protocol.LanguageCode;
+import org.apache.rocketmq.remoting.protocol.RemotingCommand;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_CLIENT_AUTHSERVER;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_CLIENT_CERTPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_CLIENT_KEYPASSWORD;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_CLIENT_KEYPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_CLIENT_TRUSTCERTPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_AUTHCLIENT;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_CERTPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_KEYPASSWORD;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_KEYPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_NEED_CLIENT_AUTH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.TLS_SERVER_TRUSTCERTPATH;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsClientAuthServer;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsClientCertPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsClientKeyPassword;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsClientKeyPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsClientTrustCertPath;
+import static org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsConfigFile;
+import static org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsMode;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerAuthClient;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerCertPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerKeyPassword;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerKeyPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerNeedClientAuth;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsServerTrustCertPath;
+import static 
org.apache.rocketmq.remoting.netty.TlsSystemConfig.tlsTestModeEnable;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TlsTest {
+    private RemotingServer remotingServer;
+    private RemotingClient remotingClient;
+
+    @Rule
+    public TestName name = new TestName();
+
+    @Rule
+    public TemporaryFolder tempFolder = new TemporaryFolder();
+
+    @Before
+    public void setUp() throws InterruptedException {
+        tlsMode = TlsMode.ENFORCING;
+        tlsTestModeEnable = false;
+        tlsServerNeedClientAuth = "require";
+        tlsServerKeyPath = getCertsPath("server.key");
+        tlsServerCertPath = getCertsPath("server.pem");
+        tlsServerAuthClient = true;
+        tlsServerTrustCertPath = getCertsPath("ca.pem");
+        tlsClientKeyPath = getCertsPath("client.key");
+        tlsClientCertPath = getCertsPath("client.pem");
+        tlsClientAuthServer = true;
+        tlsClientTrustCertPath = getCertsPath("ca.pem");
+        tlsClientKeyPassword = "1234";
+        tlsServerKeyPassword = "";
+
+        NettyClientConfig clientConfig = new NettyClientConfig();
+        clientConfig.setUseTLS(true);
+
+        if ("serverRejectsUntrustedClientCert".equals(name.getMethodName())) {
+            // Create a client. Its credentials come from a CA that the server 
does not trust. The client
+            // trusts both test CAs to ensure the handshake failure is due to 
the server rejecting the client's cert.
+            tlsClientKeyPath = getCertsPath("badClient.key");
+            tlsClientCertPath = getCertsPath("badClient.pem");
+        } else if 
("serverAcceptsUntrustedClientCert".equals(name.getMethodName())) {
+            tlsClientKeyPath = getCertsPath("badClient.key");
+            tlsClientCertPath = getCertsPath("badClient.pem");
+            tlsServerAuthClient = false;
+        }
+        else if ("noClientAuthFailure".equals(name.getMethodName())) {
+            //Clear the client cert config to ensure produce the handshake 
error
+            tlsClientKeyPath = "";
+            tlsClientCertPath = "";
+        } else if 
("clientRejectsUntrustedServerCert".equals(name.getMethodName())) {
+            tlsServerKeyPath = getCertsPath("badServer.key");
+            tlsServerCertPath = getCertsPath("badServer.pem");
+        } else if 
("clientAcceptsUntrustedServerCert".equals(name.getMethodName())) {
+            tlsServerKeyPath = getCertsPath("badServer.key");
+            tlsServerCertPath = getCertsPath("badServer.pem");
+            tlsClientAuthServer = false;
+        } else if ("serverNotNeedClientAuth".equals(name.getMethodName())) {
+            tlsServerNeedClientAuth = "none";
+            tlsClientKeyPath = "";
+            tlsClientCertPath = "";
+        } else if ("serverWantClientAuth".equals(name.getMethodName())) {
+            tlsServerNeedClientAuth = "optional";
+        } else if 
("serverWantClientAuth_ButClientNoCert".equals(name.getMethodName())) {
+            tlsServerNeedClientAuth = "optional";
+            tlsClientKeyPath = "";
+            tlsClientCertPath = "";
+        } else if ("serverAcceptsUnAuthClient".equals(name.getMethodName())) {
+            tlsMode = TlsMode.PERMISSIVE;
+            tlsClientKeyPath = "";
+            tlsClientCertPath = "";
+            clientConfig.setUseTLS(false);
+        } else if ("serverRejectsSSLClient".equals(name.getMethodName())) {
+            tlsMode = TlsMode.DISABLED;
+        }
+
+        remotingServer = RemotingServerTest.createRemotingServer();
+        remotingClient = RemotingServerTest.createRemotingClient(clientConfig);
+    }
+
+    @After
+    public void tearDown() {
+        remotingClient.shutdown();
+        remotingServer.shutdown();
+        tlsMode = TlsMode.PERMISSIVE;
+    }
+
+    /**
+     * Tests that a client and a server configured using two-way SSL auth can 
successfully
+     * communicate with each other.
+     */
+    @Test
+    public void basicClientServerIntegrationTest() throws Exception {
+        requestThenAssertResponse();
+    }
+
+    @Test
+    public void serverNotNeedClientAuth() throws Exception {
+        requestThenAssertResponse();
+    }
+
+    @Test
+    public void serverWantClientAuth_ButClientNoCert() throws Exception {
+        requestThenAssertResponse();
+    }
+
+    @Test
+    public void serverAcceptsUnAuthClient() throws Exception {
+        requestThenAssertResponse();
+    }
+
+    @Test
+    public void serverRejectsSSLClient() throws Exception {
+        try {
+            RemotingCommand response = 
remotingClient.invokeSync("localhost:8888", createRequest(), 1000 * 5);
+            
failBecauseExceptionWasNotThrown(RemotingSendRequestException.class);
+        } catch (RemotingSendRequestException ignore) {
+        }
+    }
+
+    /**
+     * Tests that a server configured to require client authentication refuses 
to accept connections
+     * from a client that has an untrusted certificate.
+     */
+    @Test
+    public void serverRejectsUntrustedClientCert() throws Exception {
+        try {
+            RemotingCommand response = 
remotingClient.invokeSync("localhost:8888", createRequest(), 1000 * 5);
+            
failBecauseExceptionWasNotThrown(RemotingSendRequestException.class);
+        } catch (RemotingSendRequestException ignore) {
+        }
+    }
+
+    @Test
+    public void serverAcceptsUntrustedClientCert() throws Exception {
+        requestThenAssertResponse();
+    }
+
+    /**
+     * Tests that a server configured to require client authentication 
actually does require client
+     * authentication.
+     */
+    @Test
+    public void noClientAuthFailure() throws Exception {
+        try {
+            RemotingCommand response = 
remotingClient.invokeSync("localhost:8888", createRequest(), 1000 * 3);
+            
failBecauseExceptionWasNotThrown(RemotingSendRequestException.class);
+        } catch (RemotingSendRequestException ignore) {
+        }
+    }
+
+    /**
+     * Tests that a client configured using GrpcSslContexts refuses to talk to 
a server that has an
+     * an untrusted certificate.
+     */
+    @Test
+    public void clientRejectsUntrustedServerCert() throws Exception {
+        try {
+            RemotingCommand response = 
remotingClient.invokeSync("localhost:8888", createRequest(), 1000 * 3);
+            
failBecauseExceptionWasNotThrown(RemotingSendRequestException.class);
+        } catch (RemotingSendRequestException ignore) {
+        }
+    }
+
+    @Test
+    public void clientAcceptsUntrustedServerCert() throws Exception {
+        requestThenAssertResponse();
+    }
+
+    @Test
+    public void testTlsConfigThroughFile() throws Exception {
+        File file = tempFolder.newFile("tls.config");
+        tlsTestModeEnable = true;
+
+        tlsConfigFile = file.getAbsolutePath();
+
+        StringBuilder sb = new StringBuilder();
+        sb.append(TLS_SERVER_NEED_CLIENT_AUTH + "=require\n");
+        sb.append(TLS_SERVER_KEYPATH + "=/server.key\n");
+        sb.append(TLS_SERVER_CERTPATH + "=/server.pem\n");
+        sb.append(TLS_SERVER_KEYPASSWORD + "=2345\n");
+        sb.append(TLS_SERVER_AUTHCLIENT + "=true\n");
+        sb.append(TLS_SERVER_TRUSTCERTPATH + "=/ca.pem\n");
+        sb.append(TLS_CLIENT_KEYPATH + "=/client.key\n");
+        sb.append(TLS_CLIENT_KEYPASSWORD + "=1234\n");
+        sb.append(TLS_CLIENT_CERTPATH + "=/client.pem\n");
+        sb.append(TLS_CLIENT_AUTHSERVER + "=false\n");
+        sb.append(TLS_CLIENT_TRUSTCERTPATH + "=/ca.pem\n");
+
+        writeStringToFile(file.getAbsolutePath(), sb.toString());
+        TlsHelper.buildSslContext(false);
+
+        assertThat(tlsServerNeedClientAuth).isEqualTo("require");
+        assertThat(tlsServerKeyPath).isEqualTo("/server.key");
+        assertThat(tlsServerCertPath).isEqualTo("/server.pem");
+        assertThat(tlsServerKeyPassword).isEqualTo("2345");
+        assertThat(tlsServerAuthClient).isEqualTo(true);
+        assertThat(tlsServerTrustCertPath).isEqualTo("/ca.pem");
+        assertThat(tlsClientKeyPath).isEqualTo("/client.key");
+        assertThat(tlsClientKeyPassword).isEqualTo("1234");
+        assertThat(tlsClientCertPath).isEqualTo("/client.pem");
+        assertThat(tlsClientAuthServer).isEqualTo(false);
+        assertThat(tlsClientTrustCertPath).isEqualTo("/ca.pem");
+
+        tlsConfigFile = "/notFound";
+    }
+
+    private static void writeStringToFile(String path, String content) {
+        try {
+            PrintWriter out = new PrintWriter(new BufferedWriter(new 
FileWriter(path, true)));
+            out.println(content);
+            out.close();
+        } catch (IOException ignore) {
+        }
+    }
+
+    private static String getCertsPath(String fileName) {
+        File resourcesDirectory = new File("src/test/resources/certs");
+        return resourcesDirectory.getAbsolutePath() + "/" + fileName;
+    }
+
+    private static RemotingCommand createRequest() {
+        RequestHeader requestHeader = new RequestHeader();
+        requestHeader.setCount(1);
+        requestHeader.setMessageTitle("Welcome");
+        return RemotingCommand.createRequestCommand(0, requestHeader);
+    }
+
+    private void requestThenAssertResponse() throws Exception {
+        RemotingCommand response = remotingClient.invokeSync("localhost:8888", 
createRequest(), 1000 * 3);
+        assertTrue(response != null);
+        assertThat(response.getLanguage()).isEqualTo(LanguageCode.JAVA);
+        assertThat(response.getExtFields()).hasSize(2);
+        
assertThat(response.getExtFields().get("messageTitle")).isEqualTo("Welcome");
+    }
+}
diff --git a/remoting/src/test/resources/certs/badClient.key 
b/remoting/src/test/resources/certs/badClient.key
new file mode 100644
index 0000000..2dfd7ab
--- /dev/null
+++ b/remoting/src/test/resources/certs/badClient.key
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICoTAbBgkqhkiG9w0BBQMwDgQIc2h7vaLYK6gCAggABIICgNrkvD1Xxez79Jgk
+WhRJg06CG8UthncfeuymR4hgp9HIneUzUHOoaf64mpxUbDWe3YOzA29REcBQsjF0
+Rpv+Uyg3cyDG14TmeRoSufOxB3MWLcIenoPPyNNtxe3XXmdkJTXX2YR0j7EOzH2v
+qlmuxmN4A7UonV5RdGxCz0sm7bU7EyZKdLO/DwBNxlX7ukcVLxAAqsc7ondclYj0
+SFJKk1nzfysCsk/Pq+q3PAVVpG6x5RFaLVS7Zt+gU6IEp+0S0eeYukkTjGh9PMPl
+wjCOcRiR3O+g4b3DevmW8TcoBqAZ2cFaf4lGhYlNBfa9PaQ3spJLL8l8xBbRIs8T
+3UnaFIa49r9DO/ZpCwpDeUE+URCx/SpcO6lchWQhdEuFt+DnFKOPYDSCHtHJSWHf
+9Z2bltjcYYPy/8nkPeqsO9vn4/r6jo+l7MYWKyWolLCW+7RYbpx5R2s4SBGtBP6w
+bwQOtOASbpG+mqTf7+ARpffHaZm9cKoKwobXigjDojPeaBCg5DgRuLIS1tO46Pjg
+USJ8sZilXifUwc6qRZ/2KiTSiJYCPMJD2ZTvK2Inkv2qzg6X3kw7CYCaW+iDL9zN
+e3ES7bps1wZ6D8cGq80WUQgrtpaGAXLzIv4FvM5yDoqrre/dh/XDO9l2hYfUmRVv
+rynKdSxjhhyHaK2ei8cX4LGEIlRNiu9ZIxSYeUAy37IJ0rVC7vtBWTh30JTeMRop
+iIPmygBMX2FEhQ2l/eS2lRhiybR0QXA4kCeJkVQas3aMMBGp2ThPNahLpzP82B7V
+f9137okQC95/KXRz/ZLYFsJtY/53206mG7gU/+dYsYI4slLAlnSe8k2sS0D9qkWJ
+VV9F7PM=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/remoting/src/test/resources/certs/badClient.pem 
b/remoting/src/test/resources/certs/badClient.pem
new file mode 100644
index 0000000..1d264d3
--- /dev/null
+++ b/remoting/src/test/resources/certs/badClient.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC8zCCAdsCAQIwDQYJKoZIhvcNAQEFBQAwfDELMAkGA1UEBhMCemgxCzAJBgNV
+BAgMAnpqMQswCQYDVQQHDAJoejEPMA0GA1UECgwGYXBhY2hlMREwDwYDVQQLDAhy
+b2NrZXRtcTEOMAwGA1UEAwwFeXVrb24xHzAdBgkqhkiG9w0BCQEWEHl1a29uQGFw
+YWNoZS5vcmcwHhcNMTcxMjExMDk0NDExWhcNMTgwMTEwMDk0NDExWjCBhjELMAkG
+A1UEBhMCemgxCzAJBgNVBAgMAnpqMQswCQYDVQQHDAJoejEPMA0GA1UECgwGYXBh
+Y2hlMREwDwYDVQQLDAhyb2NrZXRtcTEWMBQGA1UEAwwNZm9vYmFyLmNsaWVudDEh
+MB8GCSqGSIb3DQEJARYSZm9vQGJhci5jbGllbnQuY29tMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQC+3bvrKGF1Y9/kN5UBtf8bXRtxn6L1W6mCRrX6aHBb+vQp
+BEYk3Pwu/OLd7TkOC5zwjCIPIlwV4FaYnWh0KooqpmvXuKJLAQBFa8yGWERYys73
+9a/U31cu6lndnG2lZfb47NTy+KdzDYsqB4GfnASqA7PbxJHDU4Fu7wp7gN3HRQID
+AQABMA0GCSqGSIb3DQEBBQUAA4IBAQBsFroSKr3MbCq1HjWpCLDEz2uS4LQV6L1G
+smNfGNY17ELOcY9uweBBXOsfKVOEizYJJqatbJlz6FmPkIbfsGW2Wospkp1gvYMy
+NGL27vX3rB5vOo5vdFITaaV9/dEu53A0iWdsn3wH/FJnMsqBmynb+/3FY+Lff9d1
+XBaXLr+DeBx4lrE8rWTvhWh8gqDkuNLBTygdH0+g8/xkqhQhLqjIlMCSnrG2cTfj
+LewizVcX/VZ6DNC2M2vjEFbCShclZHocG80N7udl5KNsLEU2jyO1F61Q0yo+VYGS
+7n8dRYgbOKyCjMdu69fAfZvp4aoy1SXqtjMphDh5R7y7mhP60e0A
+-----END CERTIFICATE-----
diff --git a/remoting/src/test/resources/certs/badServer.key 
b/remoting/src/test/resources/certs/badServer.key
new file mode 100644
index 0000000..de4f7c5
--- /dev/null
+++ b/remoting/src/test/resources/certs/badServer.key
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALBvxESq2VvSpJl1
+skv8SzyPYKgU8bZx37hEOCmoeYvd9gWNfeYZuITng2/5mpWX+zuAgKsgPU66YG0v
+++dT5GBQPr0Imb25IMl3xOY2eEiLeMokYiWbnA1C+pw1a27zMqk6pgbcRaMfLdh5
+npusWtqBzZIxqo1TpaOGEmyQTNRlAgMBAAECgYBSigbUZOTIWxObov7lI0MDMsPx
+/dJSGpWhe3CWtHUgJJdKY7XpJlE3A6Nuh+N0ZiQm4ufOpodnxDMGAXOj9ZAZY16Y
+i7I0ayXepcpTqYqo0o0+ze2x7SECAXe26bqvLRuKG2hpUyM59vAmll9gmQM5n8z4
+ZzoAzqRqkRHdo5bTxQJBAOF6SwSSfb8KEtTjWpJ48W1PO/NmKbW3QsNCWuk/w5p7
+E8L2g3nwakJiFmVNCga74rUbcgbCkw7y/lLeM8yC74MCQQDIUgCN/vuHm+eT85xk
+QoVKhDljXzLoog6wTUf5SMtrmUFTbQqyvw5xjHYdp3TWJM/Px8IyLxOr97sSnnft
+l7/3AkEAukYLv6U+GRs7X4DMDIG6AjIZNwXJo4PYtfMVo+i3seHH+6MoDw8c2eaq
+1dmFVPbXXgNkek04rHr2vIMxi90H/QJAAMOfUOtaFkhX986EGDXQwFoExgZE8XI8
+0BtbXO4UKJLrFuBhnBDygyhgAvjyjyaQzGAcs4hOcOd/BTEpj/R2PQJBANUKa9T9
+qWYhDhWN1Uj7qXhC1j2z/vTAzcYuwhpPRjt3RaVl27itI7cqiGquFhwfKZZFaOh5
+pnnWHv63YbGQ2Qc=
+-----END PRIVATE KEY-----
diff --git a/remoting/src/test/resources/certs/badServer.pem 
b/remoting/src/test/resources/certs/badServer.pem
new file mode 100644
index 0000000..ada0a94
--- /dev/null
+++ b/remoting/src/test/resources/certs/badServer.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC5DCCAcwCAQEwDQYJKoZIhvcNAQEFBQAwfDELMAkGA1UEBhMCemgxCzAJBgNV
+BAgMAnpqMQswCQYDVQQHDAJoejEPMA0GA1UECgwGYXBhY2hlMREwDwYDVQQLDAhy
+b2NrZXRtcTEOMAwGA1UEAwwFeXVrb24xHzAdBgkqhkiG9w0BCQEWEHl1a29uQGFw
+YWNoZS5vcmcwHhcNMTcxMjExMDk0MzE3WhcNMTgwMTEwMDk0MzE3WjB4MQswCQYD
+VQQGEwJ6aDELMAkGA1UECAwCemoxCzAJBgNVBAcMAmh6MQ8wDQYDVQQKDAZhcGFj
+aGUxETAPBgNVBAsMCHJvY2tldG1xMQ8wDQYDVQQDDAZmb29iYXIxGjAYBgkqhkiG
+9w0BCQEWC2Zvb0BiYXIuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw
+b8REqtlb0qSZdbJL/Es8j2CoFPG2cd+4RDgpqHmL3fYFjX3mGbiE54Nv+ZqVl/s7
+gICrID1OumBtL/vnU+RgUD69CJm9uSDJd8TmNnhIi3jKJGIlm5wNQvqcNWtu8zKp
+OqYG3EWjHy3YeZ6brFragc2SMaqNU6WjhhJskEzUZQIDAQABMA0GCSqGSIb3DQEB
+BQUAA4IBAQAx+0Se3yIvUOe23oQp6UecaHtfXJCZmi1p5WbwJi7jUcYz78JB8oBj
+tVsa+1jftJG+cJJxqgxo2IeIAVbcEteO19xm7dc8tgfH/Bl0rxQz4WEYKb2oF/EQ
+eRgcvj4uZ0d9WuprAvJgA4r0Slu2ZZ0cVkzi06NevTweTBYIKFzHaPShqUWEw8ki
+42V5jAtRve7sT0c4TH/01dd2fs3V4Ul3E2U3LOP6VizIfKckdht0Bh6B6/5L8wvH
+4l1f4ni7w34vXGANpmTP2FGjQQ3kYjKL7GzgMphh3Kozhil6g1GLMhxvp6ccCA9W
+m5g0cPa3RZnjI/FoD0lZ5S1Q5s9qXbLm
+-----END CERTIFICATE-----
diff --git a/remoting/src/test/resources/certs/ca.pem 
b/remoting/src/test/resources/certs/ca.pem
new file mode 100644
index 0000000..d33cb49
--- /dev/null
+++ b/remoting/src/test/resources/certs/ca.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIIDyzCCArOgAwIBAgIJAKzXC2VLdPclMA0GCSqGSIb3DQEBBQUAMHwxCzAJBgNV
+BAYTAnpoMQswCQYDVQQIDAJ6ajELMAkGA1UEBwwCaHoxDzANBgNVBAoMBmFwYWNo
+ZTERMA8GA1UECwwIcm9ja2V0bXExDjAMBgNVBAMMBXl1a29uMR8wHQYJKoZIhvcN
+AQkBFhB5dWtvbkBhcGFjaGUub3JnMB4XDTE3MTIxMTA5MjUxNFoXDTE4MDExMDA5
+MjUxNFowfDELMAkGA1UEBhMCemgxCzAJBgNVBAgMAnpqMQswCQYDVQQHDAJoejEP
+MA0GA1UECgwGYXBhY2hlMREwDwYDVQQLDAhyb2NrZXRtcTEOMAwGA1UEAwwFeXVr
+b24xHzAdBgkqhkiG9w0BCQEWEHl1a29uQGFwYWNoZS5vcmcwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDLUZi/zPj+7sYbfTng/gJeHpvvrWZkiudNwh1t
+5kxAusrJyGBkGm+xmRPJeQPZzbhfwfrz/UiQSbjlyV4K+SEZuNIHBSU80aTnXFWg
+wIgIAKvu3ZwYkcTjSDBvZv1DgbRkuqAB5ExsJ4vovoNqZcsLFLKsqT1G7lTAwRKU
+/FTKgD4g/zvhEoolonzKuk7CPivfKWFzcTpe8zRQlI0O9+j9Pq38F+5yxP7atK/b
+uYw36Efgt8nbkjusWIyXibpDMbAUroJNNYlFnunb+XKLpslkrIrfLGiMUq2Ru940
+ooQaANYWzogRQeIofsMN6H9CCRXtVIzcgJJU3wWXGXPRuNr7AgMBAAGjUDBOMB0G
+A1UdDgQWBBTd3bmAcazOY2/TI/h4zaGhni+nJzAfBgNVHSMEGDAWgBTd3bmAcazO
+Y2/TI/h4zaGhni+nJzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBp
+KRcnYsVtFZJejyt02+7SaMudTNRgh5SexFWsl1O7qWUc+fMVgMHHDzGRbkdevcdZ
+9uKDwUoa6M1wlOeosTTfQlH9b/AwW6QT7KqdpcpMXlmoV/PNCAVt2QeVclmplvqo
+Rx8qUHNckvvzNZt1W6AkBG93P0BLK/3FMJDyYmxkstwnpBPf/3A+t5k2INUI7yQf
+B3Tqzs/4iQ3idCLqz2WhTNUYpZOREtpJMcFaOdMsGNnIF+LvkKGij0MPVd/mwJtL
+UvQXwbOWpCS7A73sWFqPnrSzpi4VwcvAsi8lUYXsc0H064oagb58zvYz3kXqybcb
+KQntj5dP4C3lLHUTTcAV
+-----END CERTIFICATE-----
diff --git a/remoting/src/test/resources/certs/client.key 
b/remoting/src/test/resources/certs/client.key
new file mode 100644
index 0000000..c30daea
--- /dev/null
+++ b/remoting/src/test/resources/certs/client.key
@@ -0,0 +1,17 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIICoTAbBgkqhkiG9w0BBQMwDgQI1vtPpDhOYRcCAggABIICgMHwgw0p9fx95R/+
+cWnNdEq8I3ZOOy2wDjammFvPrYXcCJzS3Xg/0GDJ8pdJRKrI7253e4u3mxf5oMuY
+RrvpB3KfdelU1k/5QKqOxL/N0gQafQLViN53f6JelyBEAmO1UxQtKZtkTrdZg8ZP
+0u1cPPWxmgNdn1Xx3taMw+Wo05ysHjnHJhOEDQ2WT3VXigiRmFSX3H567yjYMRD+
+zmvBq+qqR9JPbH9Cn7X1oRXX6c8VsZHWF/Ds0I4i+5zJxsSIuNZxjZw9XXNgXtFv
+7FEFC0HDgDQQUY/FNPUbmjQUp1y0YxoOBjlyIqBIx5FWxu95p2xITS0OimQPFT0o
+IngaSb+EKRDhqpLxxIVEbDdkQrdRqcmmLGJioAysExTBDsDwkaEJGOp44bLDM4QW
+SIA9SB01omuCXgn7RjUyVXb5g0Lz+Nvsfp1YXUkPDO9hILfz3eMHDSW7/FzbB81M
+r8URaTagQxBZnvIoCoWszLDXn3JwEjpZEA6y55Naptps3mMRf7+XMt42lX0e4y9a
+ogNu5Zw/RZD9YcaTjC2z5XeKiMCs1Ymhy9iuzbo+eRGESqzvUE4VirtsiEwxJRci
+JHAvuAl3X4XnpTty4ahOU+DihM9lALxdU68CN9++7mx581pYuvjzrV+Z5+PuptZX
+AjCZmkZLDh8TCHSzWRqvP/Hcvo9BjW8l1Lq6tOa222PefSNCc6gs6Hq+jUghbabZ
+/ux4WuFc0Zd6bfQWAZohSvd78/ixsdJPNGm2OP+LUIrEDKIkLuH1PM0uq4wzJZNu
+Bo7oJ5iFWF67u3MC8oq+BqOVKDNWaCMi7iiSrN2XW8FBo/rpx4Lf/VYREL+Y0mP6
+vzJrZqw=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/remoting/src/test/resources/certs/client.pem 
b/remoting/src/test/resources/certs/client.pem
new file mode 100644
index 0000000..31412fe
--- /dev/null
+++ b/remoting/src/test/resources/certs/client.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC8zCCAdsCAQIwDQYJKoZIhvcNAQEFBQAwfDELMAkGA1UEBhMCemgxCzAJBgNV
+BAgMAnpqMQswCQYDVQQHDAJoejEPMA0GA1UECgwGYXBhY2hlMREwDwYDVQQLDAhy
+b2NrZXRtcTEOMAwGA1UEAwwFeXVrb24xHzAdBgkqhkiG9w0BCQEWEHl1a29uQGFw
+YWNoZS5vcmcwHhcNMTcxMjExMDkyOTUyWhcNMTgwMTEwMDkyOTUyWjCBhjELMAkG
+A1UEBhMCemgxCzAJBgNVBAgMAnpqMQswCQYDVQQHDAJoejEPMA0GA1UECgwGYXBh
+Y2hlMREwDwYDVQQLDAhyb2NrZXRtcTEWMBQGA1UEAwwNZm9vYmFyLmNsaWVudDEh
+MB8GCSqGSIb3DQEJARYSZm9vQGJhci5jbGllbnQuY29tMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQDoz5Uo2ZN+1ywSQXORv6kDbDXVQ72ZxBp7a6ltFLh4xdk/
+yz7bBjmryz+cAh759s8DEdngl2cCnSiM0r5NC91zox/12Di4EWt3IPdJVe1s5/VD
+Bqt5zoxbYyDgz47c95cGALgLdTB/itBPgobghQYBanWPVBNLLltw19DLf1gd6QID
+AQABMA0GCSqGSIb3DQEBBQUAA4IBAQDEpVFFcFILdnEXjyDSbgJ8rxXaUYV2aK+a
+lgrYfoHBv83MlEuHbydmHBoTL7BmPIL7JCIfufvRnnyBwcECi0E6qFbvMYNoMy6b
+OUiTq3nAnPSSoOgi2MxFxpGaOE0s2dp4K9U5nV6bXKLIwIZbJAiZT6aPVenNYJbv
+4arzFDe0Yjs/l3VYn2k9TjiiU2fxaW/8Ikx6o9nGWLTKeX/WtXfBNISqOPIL5dPF
+eaf0YKCVzvBQ3dIJiUyanRP1BCJJFrCsrPpyu4xFprbjRmDTnOpYB6CdIas5TMC8
+6HzB1fSFoltNEiCjlnLlfjpb5ueSLSbs6h1A7VH7NUEmLmncSlHf
+-----END CERTIFICATE-----
diff --git a/remoting/src/test/resources/certs/privkey.pem 
b/remoting/src/test/resources/certs/privkey.pem
new file mode 100644
index 0000000..6955568
--- /dev/null
+++ b/remoting/src/test/resources/certs/privkey.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIBTqUKpwFlcUCAggA
+MBQGCCqGSIb3DQMHBAii5M3Oni0WEwSCBMj5amhdPBva0QxgsWWrSBkfvmc3QQbl
+YQE5gHXzL5oaG0lbXCLQe19pr9jFckdDH8uPIi+aRie3WpZXzYLdihjsV0CgE7iy
+90ac9fgzIZbJIk/WQIDgwUZm5dEYo2v+B0WwKiD5IHzlTlXM6HVv+DRdPwKjHjAt
+TCcCSPUgjKVxHWFtQzY7mqo8P8wcNQHGkEfoQQub6tEsUDeesjS0FoK5Z2oYsmhW
+d0PNuGXw3UIMbG109DmC2ILFuTf5WSc7mxI11qL9Z5wTmcFqN7KKb8+MIQEoteni
+HICOFfKQWn8er14lmYw9anQAyaeyF/JnYkmVB8vaHBFYs/5EFZtvznpEIIhLKCuG
+lve8PJQmfWuBlPdwwJhCXHrLvjfwku4jUF8febU0BHZ5HETaB195g8r9RWfdZcrG
+f3fMO4Kq/YoP6oSxKhMP4L2pwj57EMV9N5P87ZyDFNp9BwgIjCawDRUc1Gi9YKak
+rpDNabTCr0I3NW27VGGF9m/mby7BLragc01LgTH7SFWS+1D/61/V2YBDFmWn2yV4
+4eKGeBkR3w0m/nWWfNXko8UzM/hjJ4P7Njq8HXdvEpnbDRZWzwdTGWTEvn/TAI3h
+j7vmWUHdpOQgb0WGlvEUx3V9wi2Fc1rCseHtYZgLf3KdKYHauPAMSON7KBtKaFuU
+6685sUoJbhahN7ILfP3sDxM3VYjSvlPL00lgOdqDT/iO6pNXvnNnQROCCE4kcOQT
+uSnEu+wmFHj+QlC60ftRl6zGVqjBxf1+TGmzTEByAOfZtEQ8V/clzRI4BCxYbCAG
+mJSa+q1RSju8yClBkXGT2zfhUeNqJnXEIaD/uXCPVGg7hfLyCcVVSmL97aw9QAIe
+lBJN/4bdxXLnJaHFKyztRe9N97JAKY9HAPMKKhKtqprWB7LedTIPHtXnpoSjyTrG
+SEtlOTQ38s3v9bUPXqF7TYZb+ytj5bIQpl6+WqF9ZNj3gRyx7rcsILhBBg08olVQ
+WZwr7LlIxUcDlrbYmrwd9lsMz2nOW2CLCD7mVqJQa2Wm35l6vJHQAI0WiQlHnopC
+M2Y49JruWWim2lC8ZzHgTyiU54bIfkXKQxua8G5WGxpW4dDRrM1d0uYe9M1TOqvP
+jFxq+XEIj/LntJpY7XIZs+33wuNLIVvkee9zsap++zYNH+KIGmbXz/HUO6gYeJYw
+EeaBTLfXtNlgHV9TpMjj3Js6p8hMoVDx27kzPOXa3nrFbHiHmUYY39ZSBCE53Wew
+SKIr/FlKtthzJwJkoMNxxsZ1QcI6WgmRANSC4oP9OyM+hPnWlISJZsy9UlXRZNEJ
+1lI8P/FUbdk/hsRN98j4pb/hzI0yyG1tKaj0TBipjdEsxfthKdwS2sE1wG+F2hrg
+A1jG+UOYmreQjCbrzEiq0J0H4wSL6/s/zN7SyXIWBG0UFalWFiehG5242mEOyX03
+0Yi94mPhF/kcqYsWZ/JJo6cq/EqgIeIqEzkbKx+TOsXk13K2y6apgvCxeHDDv3yT
+DqQueRgFicl0319yEK8ARnREFBm8D5oqwMHjJzVzjrqhFGLW1jfQG9HEW5A+s8WF
+d+2OtH1o/jVdAPXoP1DnxdF+G7fNXDI4cyjejC7uhLuxHCOx648UpRE9+mCiI2IO
+LDM=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/remoting/src/test/resources/certs/server.key 
b/remoting/src/test/resources/certs/server.key
new file mode 100644
index 0000000..30df696
--- /dev/null
+++ b/remoting/src/test/resources/certs/server.key
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOsmp4YtrIRsBdBQ
+LyPImafCRynTJls3NNF4g6nZr9e0efBY830gw9kBebcm603sdZNl95fzRr2+srXi
+5FJbG7Fmq1+F0xLNK/kKWirGtNMT2DubmhVdKyXYJSvInoGRkrQzbOG0MdAyzE6Q
+O6OjjNN+xGkmadWyCyNF6S8YqMJTAgMBAAECgYEAj0OlnOIG0Ube4+N2VN7KfqKm
+qJy0Ka6gx14dGUY/E7Qo9n27GujzaSq09RkJExiVKZBeIH1fBAtC5f2uDV7kpy0l
+uNpTpQkbw0g2EQLxDsVwaUEYbu+t9qVeXoDd1vFeoXHBuRwvI9UW1BrxVtvKODia
+5StU8Lw4yjcm2lQalwECQQD/sKj56thIsIY7D9qBHk7fnFLd8aYzhnP2GsbZX4V/
+T1KHRxr/8MqdNQX53DE5qcyM/Mqu95FIpTAniUtvcBujAkEA62+fAMYFTAEWj4Z4
+vCmcoPqfVPWhBKFR/wo3L8uUARiIzlbYNU3LIqC2s16QO50+bLUd41oVHNw9Y+uM
+fxQpkQJACg/WpncSadHghmR6UchyjCQnsqo2wyJQX+fv2VAD/d2OPtqSem3sW0Fh
+6dI7cax36zhrdXUyl2xAt92URV9hBwJALX93sdWSxnpbWsc449wCydVFH00MnfFz
+AB+ARLtJ0eBk58M+qyZqgDmgtQ8sPmkH3EgwC3SoKdiiAIJPt2s1EQJBAKnISZZr
+qB2F2PfAW2JJbQlrPyVzkxhv9XYdiVNOErmuxLFae3AI7nECgGuFBtvmeqzm2yRj
+7RBMCmzyWG7MF3o=
+-----END PRIVATE KEY-----
diff --git a/remoting/src/test/resources/certs/server.pem 
b/remoting/src/test/resources/certs/server.pem
new file mode 100644
index 0000000..b73e33e
--- /dev/null
+++ b/remoting/src/test/resources/certs/server.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC5DCCAcwCAQEwDQYJKoZIhvcNAQEFBQAwfDELMAkGA1UEBhMCemgxCzAJBgNV
+BAgMAnpqMQswCQYDVQQHDAJoejEPMA0GA1UECgwGYXBhY2hlMREwDwYDVQQLDAhy
+b2NrZXRtcTEOMAwGA1UEAwwFeXVrb24xHzAdBgkqhkiG9w0BCQEWEHl1a29uQGFw
+YWNoZS5vcmcwHhcNMTcxMjExMDkyNjIwWhcNMTgwMTEwMDkyNjIwWjB4MQswCQYD
+VQQGEwJ6aDELMAkGA1UECAwCemoxCzAJBgNVBAcMAmh6MQ8wDQYDVQQKDAZhcGFj
+aGUxETAPBgNVBAsMCHJvY2tldG1xMQ8wDQYDVQQDDAZmb29iYXIxGjAYBgkqhkiG
+9w0BCQEWC2Zvb0BiYXIuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDr
+JqeGLayEbAXQUC8jyJmnwkcp0yZbNzTReIOp2a/XtHnwWPN9IMPZAXm3JutN7HWT
+ZfeX80a9vrK14uRSWxuxZqtfhdMSzSv5CloqxrTTE9g7m5oVXSsl2CUryJ6BkZK0
+M2zhtDHQMsxOkDujo4zTfsRpJmnVsgsjRekvGKjCUwIDAQABMA0GCSqGSIb3DQEB
+BQUAA4IBAQCmhSgxU5PRhBD2qahj2eWKcmz3FCevXgfyN/EUrwI2dZTU5fXPP+m9
+YBLAYUINI0eYGWt0wlGJ6UFyEgt1fcXP3gqsye9fjECmWoae1kVjvYdaxYGsEXrM
+bxSum1D1bz6yRA+eSOaT5aesfw1ZL74AkIq5aRKQ4cgLGzlbIYeoa62XcAj6GrBo
+V2s/mvKCc1FPrqnpUlTTYFM9eRbEyC7HkOm9c+NAy6FqoLFr3tegH+q8ZxENDw4k
+z9gojQ6t1LDPOAmLGHwvMshHa841CwfOduSvzldtxzjnLVUvYB9cyXS1JXvuC9jj
+Q6BOXIYI+0HVgkJbcPOIYDlgC+g6QJqf
+-----END CERTIFICATE-----

-- 
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].

Reply via email to