You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2020/03/15 00:15:44 UTC

[skywalking] branch master updated: Enable OAP gRPC SSL transportation (#4470)

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

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new 78d14eb  Enable OAP gRPC SSL transportation (#4470)
78d14eb is described below

commit 78d14ebbd6a62f3b90cf7e60d6d1c719754fadeb
Author: Gao Hongtao <ha...@gmail.com>
AuthorDate: Sun Mar 15 08:15:28 2020 +0800

    Enable OAP gRPC SSL transportation (#4470)
    
    * Enable OAP gRPC SSL transportation
    
    Porting to OpenSSL to enable SSL transportation. The server private
    key is in the format of PCKS#8, certificates is x509 though.
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Add netty-tcnative-boringssl-static 2.0.26 licnese
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Update docs/en/setup/backend/grpc-ssl.md
    
    Co-Authored-By: kezhenxu94 <ke...@apache.org>
    
    * Update docs/en/setup/backend/grpc-ssl.md
    
    Co-Authored-By: kezhenxu94 <ke...@apache.org>
    
    * Add SSL to grpc remote client and sharing server
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Update documents
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Fix nits
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Fix test case
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Add e2e-ssl and remove other test cases temporarily
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Add TLS relevant files
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Decrease timeout
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Test config works
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * triger CI on oap-ssl branch
    
    * Disable agent ca
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Switch to sharing server
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Add agent log to console
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Upload log files
    
    * Change backend
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Revert "Change backend"
    
    This reverts commit 7a085711e3653d3bf642aa84f73650e22595e383.
    
    * Update backend
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Revert e2e
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Ignore TSL relevant files
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Polish codes
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    * Update certificates expires year to 2120
    
    Signed-off-by: Gao Hongtao <ha...@gmail.com>
    
    Co-authored-by: 吴晟 Wu Sheng <wu...@foxmail.com>
    Co-authored-by: kezhenxu94 <ke...@apache.org>
---
 .github/workflows/e2e.yaml                         |   7 +
 dist-material/application.yml                      |   4 +
 dist-material/release-docs/LICENSE                 |   1 +
 docker/oap-es7/docker-entrypoint.sh                |   7 +
 docker/oap/docker-entrypoint.sh                    |   7 +
 docs/en/setup/backend/grpc-ssl.md                  |  44 +++
 docs/en/setup/service-agent/java-agent/TLS.md      |   3 +-
 oap-server/pom.xml                                 |   2 +-
 .../src/main/resources/application.yml             |   7 +
 .../oap/server/core/CoreModuleConfig.java          |   8 +
 .../oap/server/core/CoreModuleProvider.java        |  16 +-
 .../core/remote/client/GRPCRemoteClient.java       |  18 +-
 .../core/remote/client/RemoteClientManager.java    |  30 +-
 .../remote/client/GRPCRemoteClientRealClient.java  |   2 +-
 .../remote/client/GRPCRemoteClientTestCase.java    |   2 +-
 oap-server/server-library/library-client/pom.xml   |   4 +
 .../oap/server/library/client/grpc/GRPCClient.java |  15 +-
 .../oap/server/library/server/grpc/GRPCServer.java |   3 +-
 .../sharing/server/SharingServerConfig.java        |   3 +
 .../server/SharingServerModuleProvider.java        |  12 +-
 pom.xml                                            |   6 +-
 test/e2e/e2e-ssl/pom.xml                           | 151 +++++++++
 test/e2e/e2e-ssl/src/docker/ca/ca.crt              |  28 ++
 test/e2e/e2e-ssl/src/docker/certs/ca.crt           |  28 ++
 test/e2e/e2e-ssl/src/docker/certs/server-key.pem   |  28 ++
 test/e2e/e2e-ssl/src/docker/certs/server.crt       |  25 ++
 test/e2e/e2e-ssl/src/docker/hosts                  |  26 ++
 test/e2e/e2e-ssl/src/docker/rc.d/rc1-startup.sh    |  50 +++
 .../e2e/sample/client/SampleClientApplication.java |  33 +-
 .../e2e/sample/client/TestController.java          |  46 +++
 .../apache/skywalking/e2e/sample/client/User.java  |  59 ++--
 .../skywalking/e2e/sample/client/UserRepo.java     |  26 +-
 .../e2e/e2e-ssl/src/main/resources/application.yml |  35 ++
 .../skywalking/e2e/SampleVerificationITCase.java   | 360 +++++++++++++++++++++
 ...king.e2e.SampleVerificationITCase.endpoints.yml |  27 ++
 ...king.e2e.SampleVerificationITCase.instances.yml |  34 ++
 ...ampleVerificationITCase.serviceInstanceTopo.yml |  41 +++
 ...lking.e2e.SampleVerificationITCase.services.yml |  25 ++
 ...kywalking.e2e.SampleVerificationITCase.topo.yml |  46 +++
 ...walking.e2e.SampleVerificationITCase.traces.yml |  31 ++
 test/e2e/pom.xml                                   |   1 +
 .../known-oap-backend-dependencies-es7.txt         |   2 +-
 .../known-oap-backend-dependencies.txt             |   2 +-
 43 files changed, 1212 insertions(+), 93 deletions(-)

diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml
index 513f9e8..e8add44 100644
--- a/.github/workflows/e2e.yaml
+++ b/.github/workflows/e2e.yaml
@@ -58,6 +58,13 @@ jobs:
         run: export E2E_VERSION=jdk8-1.5 && bash -x test/e2e/run.sh e2e-agent-reboot
       - name: Agent Auth Tests(JDK8)
         run: export E2E_VERSION=jdk8-1.5 && bash -x test/e2e/run.sh e2e-agent-auth
+      - name: Agent and OAP SSL Tests(JDK8)
+        run: export E2E_VERSION=jdk8-1.5 && bash -x test/e2e/run.sh e2e-ssl
+      - uses: actions/upload-artifact@v1.0.0
+        if: always()
+        with:
+          name: logs
+          path: /tmp/logs
 
   Cluster:
     runs-on: ubuntu-latest
diff --git a/dist-material/application.yml b/dist-material/application.yml
index 8defe81..404a9d6 100644
--- a/dist-material/application.yml
+++ b/dist-material/application.yml
@@ -59,6 +59,10 @@ core:
     restContextPath: ${SW_CORE_REST_CONTEXT_PATH:/}
     gRPCHost: ${SW_CORE_GRPC_HOST:0.0.0.0}
     gRPCPort: ${SW_CORE_GRPC_PORT:11800}
+    gRPCSslEnabled: ${SW_CORE_GRPC_SSL_ENABLED:false}
+    gRPCSslKeyPath: ${SW_CORE_GRPC_SSL_KEY_PATH:""}
+    gRPCSslCertChainPath: ${SW_CORE_GRPC_SSL_CERT_CHAIN_PATH:""}
+    gRPCSslTrustedCAPath: ${SW_CORE_GRPC_SSL_TRUSTED_CA_PATH:""}
     downsampling:
       - Hour
       - Day
diff --git a/dist-material/release-docs/LICENSE b/dist-material/release-docs/LICENSE
index b72e0bf..79c643f 100755
--- a/dist-material/release-docs/LICENSE
+++ b/dist-material/release-docs/LICENSE
@@ -217,6 +217,7 @@ The text of each license is also included at licenses/LICENSE-[project].txt.
 
     Apache: httpcomponents 4.x.x: http://hc.apache.org/index.html, Apache 2.0
     Apache: fastjson 1.2.47:  https://github.com/alibaba/fastjson, Apache 2.0
+    Apache: netty-tcnative-boringssl-static 2.0.26:  https://github.com/netty/netty-tcnative, Apache 2.0
 
 ========================================================================
 Apache 2.0 licenses
diff --git a/docker/oap-es7/docker-entrypoint.sh b/docker/oap-es7/docker-entrypoint.sh
index 07e02c1..18619d3 100755
--- a/docker/oap-es7/docker-entrypoint.sh
+++ b/docker/oap-es7/docker-entrypoint.sh
@@ -332,6 +332,10 @@ core:
     restContextPath: \${SW_CORE_REST_CONTEXT_PATH:/}
     gRPCHost: \${SW_CORE_GRPC_HOST:0.0.0.0}
     gRPCPort: \${SW_CORE_GRPC_PORT:11800}
+    gRPCSslEnabled: \${SW_CORE_GRPC_SSL_ENABLED:false}
+    gRPCSslKeyPath: \${SW_CORE_GRPC_SSL_KEY_PATH:""}
+    gRPCSslCertChainPath: \${SW_CORE_GRPC_SSL_CERT_CHAIN_PATH:""}
+    gRPCSslTrustedCAPath: \${SW_CORE_GRPC_SSL_TRUSTED_CA_PATH:""}
     downsampling:
     - Hour
     - Day
@@ -371,6 +375,9 @@ receiver-sharing-server:
    gRPCThreadPoolSize: \${SW_RECEIVER_SHARING_GRPC_THREAD_POOL_SIZE:0}
    gRPCThreadPoolQueueSize: \${SW_RECEIVER_SHARING_GRPC_THREAD_POOL_QUEUE_SIZE:0}
    authentication: \${SW_AUTHENTICATION:""}
+   gRPCSslEnabled: \${SW_RECEIVER_SHARING_GRPC_SSL_ENABLED:false}
+   gRPCSslKeyPath: \${SW_RECEIVER_SHARING_GRPC_SSL_KEY_PATH:""}
+   gRPCSslCertChainPath: \${SW_RECEIVER_SHARING_GRPC_SSL_CERT_CHAIN_PATH:""}
 receiver-register:
   default:
 receiver-trace:
diff --git a/docker/oap/docker-entrypoint.sh b/docker/oap/docker-entrypoint.sh
index 3069334..a7467c6 100755
--- a/docker/oap/docker-entrypoint.sh
+++ b/docker/oap/docker-entrypoint.sh
@@ -333,6 +333,10 @@ core:
     restContextPath: \${SW_CORE_REST_CONTEXT_PATH:/}
     gRPCHost: \${SW_CORE_GRPC_HOST:0.0.0.0}
     gRPCPort: \${SW_CORE_GRPC_PORT:11800}
+    gRPCSslEnabled: \${SW_CORE_GRPC_SSL_ENABLED:false}
+    gRPCSslKeyPath: \${SW_CORE_GRPC_SSL_KEY_PATH:""}
+    gRPCSslCertChainPath: \${SW_CORE_GRPC_SSL_CERT_CHAIN_PATH:""}
+    gRPCSslTrustedCAPath: \${SW_CORE_GRPC_SSL_TRUSTED_CA_PATH:""}
     downsampling:
     - Hour
     - Day
@@ -372,6 +376,9 @@ receiver-sharing-server:
    gRPCThreadPoolSize: \${SW_RECEIVER_SHARING_GRPC_THREAD_POOL_SIZE:0}
    gRPCThreadPoolQueueSize: \${SW_RECEIVER_SHARING_GRPC_THREAD_POOL_QUEUE_SIZE:0}
    authentication: \${SW_AUTHENTICATION:""}
+   gRPCSslEnabled: \${SW_RECEIVER_SHARING_GRPC_SSL_ENABLED:false}
+   gRPCSslKeyPath: \${SW_RECEIVER_SHARING_GRPC_SSL_KEY_PATH:""}
+   gRPCSslCertChainPath: \${SW_RECEIVER_SHARING_GRPC_SSL_CERT_CHAIN_PATH:""}
 receiver-register:
   default:
 receiver-trace:
diff --git a/docs/en/setup/backend/grpc-ssl.md b/docs/en/setup/backend/grpc-ssl.md
new file mode 100644
index 0000000..2247694
--- /dev/null
+++ b/docs/en/setup/backend/grpc-ssl.md
@@ -0,0 +1,44 @@
+# Support gRPC SSL transportation for OAP server
+
+For OAP communication we are currently using gRPC, a multi-platform RPC framework that uses protocol buffers for
+message serialization. The nice part about gRPC is that it promotes the use of SSL/TLS to authenticate and encrypt
+exchanges. Now OAP supports to enable SSL transportation for gRPC receivers.
+
+You can follow below steps to enable this feature
+
+## Creating SSL/TLS Certificates
+
+It seems like step one is to generate certificates and key files for encrypting communication. I thought this would be
+fairly straightforward using `openssl` from the command line.
+
+Use this [script](../../../../../tools/TLS/tls_key_generate.sh) if you are not familiar with how to generate key files.
+
+We need below files:
+ - `server.pem` a private RSA key to sign and authenticate the public key.
+ - `server.crt` self-signed X.509 public keys for distribution.
+ - `ca.crt` a certificate authority public key for a client to validate the server's certificate.
+
+## Config OAP server 
+
+You can enable gRPC SSL by add following lines to `application.yml/core/default`.
+```json
+gRPCSslEnabled: true
+gRPCSslKeyPath: /path/to/server.pem
+gRPCSslCertChainPath: /path/to/server.crt
+gRPCSslTrustedCAPath: /path/to/ca.crt
+```
+
+`gRPCSslKeyPath` and `gRPCSslCertChainPath` are loaded by OAP server to encrypt the communication. `gRPCSslTrustedCAPath`
+helps gRPC client to verify server certificates in cluster mode.
+
+If you enable `sharding-server` to ingest data from external, add following lines to `application.yml/receiver-sharing-server/default`:
+
+```json
+gRPCSslEnabled: true
+gRPCSslKeyPath: /path/to/server.pem
+gRPCSslCertChainPath: /path/to/server.crt
+```
+
+Because `sharding-server` only receives data from external, so it doesn't need CA at all.
+
+If you port to java agent, refer to [TLS.md](../service-agent/java-agent/TLS.md) to config java agent to enable TLS.
diff --git a/docs/en/setup/service-agent/java-agent/TLS.md b/docs/en/setup/service-agent/java-agent/TLS.md
index cfdc921..1815c3e 100644
--- a/docs/en/setup/service-agent/java-agent/TLS.md
+++ b/docs/en/setup/service-agent/java-agent/TLS.md
@@ -11,7 +11,8 @@ at the same time, the SkyWalking backend is in another region (VPC).
 Only support **no mutual auth**.
 - Use this [script](../../../../../tools/TLS/tls_key_generate.sh) if you are not familiar with how to generate key files.
 - Find `ca.crt`, and use it at client side
-- Find `server.crt` and `server.pem`. Use them at server side.
+- Find `server.crt` ,`server.pem` and `ca.crt`. Use them at server side. Please refer to [gRPC SSL](../../backend/grpc-ssl.md) 
+  for more details.
 
 ## Open and config TLS
 
diff --git a/oap-server/pom.xml b/oap-server/pom.xml
index 88562cb..9dcb66f 100755
--- a/oap-server/pom.xml
+++ b/oap-server/pom.xml
@@ -58,7 +58,7 @@
         <graphql-java-tools.version>5.2.3</graphql-java-tools.version>
         <graphql-java.version>8.0</graphql-java.version>
         <zookeeper.version>3.4.10</zookeeper.version>
-        <netty-tcnative-boringssl-static.version>2.0.7.Final</netty-tcnative-boringssl-static.version>
+        <netty-tcnative-boringssl-static.version>2.0.26.Final</netty-tcnative-boringssl-static.version>
         <jetty.version>9.4.2.v20170220</jetty.version>
         <h2.version>1.4.196</h2.version>
         <commons-dbcp.version>1.4</commons-dbcp.version>
diff --git a/oap-server/server-bootstrap/src/main/resources/application.yml b/oap-server/server-bootstrap/src/main/resources/application.yml
index 53b5f9b..ee10672 100755
--- a/oap-server/server-bootstrap/src/main/resources/application.yml
+++ b/oap-server/server-bootstrap/src/main/resources/application.yml
@@ -58,6 +58,10 @@ core:
     restContextPath: ${SW_CORE_REST_CONTEXT_PATH:/}
     gRPCHost: ${SW_CORE_GRPC_HOST:0.0.0.0}
     gRPCPort: ${SW_CORE_GRPC_PORT:11800}
+    gRPCSslEnabled: ${SW_CORE_GRPC_SSL_ENABLED:false}
+    gRPCSslKeyPath: ${SW_CORE_GRPC_SSL_KEY_PATH:""}
+    gRPCSslCertChainPath: ${SW_CORE_GRPC_SSL_CERT_CHAIN_PATH:""}
+    gRPCSslTrustedCAPath: ${SW_CORE_GRPC_SSL_TRUSTED_CA_PATH:""}
     downsampling:
       - Hour
       - Day
@@ -173,6 +177,9 @@ storage:
 receiver-sharing-server:
   default:
     authentication: ${SW_AUTHENTICATION:""}
+    gRPCSslEnabled: ${SW_RECEIVER_SHARING_GRPC_SSL_ENABLED:false}
+    gRPCSslKeyPath: ${SW_RECEIVER_SHARING_GRPC_SSL_KEY_PATH:""}
+    gRPCSslCertChainPath: ${SW_RECEIVER_SHARING_GRPC_SSL_CERT_CHAIN_PATH:""}
 receiver-register:
   default:
 receiver-trace:
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleConfig.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleConfig.java
index 5a08d62..e59ae44 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleConfig.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleConfig.java
@@ -44,6 +44,14 @@ public class CoreModuleConfig extends ModuleConfig {
     @Setter
     private int gRPCPort;
     @Setter
+    private boolean gRPCSslEnabled = false;
+    @Setter
+    private String gRPCSslKeyPath;
+    @Setter
+    private String gRPCSslCertChainPath;
+    @Setter
+    private String gRPCSslTrustedCAPath;
+    @Setter
     private int maxConcurrentCallsPerConnection;
     @Setter
     private int maxMessageSize;
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
index 4175877..cd4c639 100755
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/CoreModuleProvider.java
@@ -19,6 +19,7 @@
 package org.apache.skywalking.oap.server.core;
 
 import java.io.IOException;
+import java.nio.file.Paths;
 import org.apache.skywalking.oap.server.configuration.api.ConfigurationModule;
 import org.apache.skywalking.oap.server.configuration.api.DynamicConfigurationService;
 import org.apache.skywalking.oap.server.core.analysis.ApdexThresholdConfig;
@@ -166,7 +167,13 @@ public class CoreModuleProvider extends ModuleProvider {
             throw new ModuleStartException(e.getMessage(), e);
         }
 
-        grpcServer = new GRPCServer(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort());
+        if (moduleConfig.isGRPCSslEnabled()) {
+            grpcServer = new GRPCServer(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort(),
+                                        Paths.get(moduleConfig.getGRPCSslCertChainPath()).toFile(),
+                                        Paths.get(moduleConfig.getGRPCSslKeyPath()).toFile());
+        } else {
+            grpcServer = new GRPCServer(moduleConfig.getGRPCHost(), moduleConfig.getGRPCPort());
+        }
         if (moduleConfig.getMaxConcurrentCallsPerConnection() > 0) {
             grpcServer.setMaxConcurrentCallsPerConnection(moduleConfig.getMaxConcurrentCallsPerConnection());
         }
@@ -245,7 +252,12 @@ public class CoreModuleProvider extends ModuleProvider {
 
         annotationScan.registerListener(streamAnnotationListener);
 
-        this.remoteClientManager = new RemoteClientManager(getManager(), moduleConfig.getRemoteTimeout());
+        if (moduleConfig.isGRPCSslEnabled()) {
+            this.remoteClientManager = new RemoteClientManager(getManager(), moduleConfig.getRemoteTimeout(),
+                                                               Paths.get(moduleConfig.getGRPCSslTrustedCAPath()).toFile());
+        } else {
+            this.remoteClientManager = new RemoteClientManager(getManager(), moduleConfig.getRemoteTimeout());
+        }
         this.registerServiceImplementation(RemoteClientManager.class, remoteClientManager);
 
         MetricsStreamProcessor.getInstance().setEnableDatabaseSession(moduleConfig.isEnableDatabaseSession());
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClient.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClient.java
index 5ce949f..21bf88e 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClient.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClient.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.remote.client;
 
 import io.grpc.ManagedChannel;
 import io.grpc.stub.StreamObserver;
+import io.netty.handler.ssl.SslContext;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;
@@ -51,6 +52,7 @@ public class GRPCRemoteClient implements RemoteClient {
     private final int bufferSize;
     private final Address address;
     private final AtomicInteger concurrentStreamObserverNumber = new AtomicInteger(0);
+    private SslContext sslContext;
     private GRPCClient client;
     private DataCarrier<RemoteMessage> carrier;
     private boolean isConnect;
@@ -58,23 +60,29 @@ public class GRPCRemoteClient implements RemoteClient {
     private CounterMetrics remoteOutErrorCounter;
     private int remoteTimeout;
 
-    public GRPCRemoteClient(ModuleDefineHolder moduleDefineHolder, Address address, int channelSize, int bufferSize,
-        int remoteTimeout) {
+    public GRPCRemoteClient(final ModuleDefineHolder moduleDefineHolder,
+                            final Address address,
+                            final int channelSize,
+                            final int bufferSize,
+                            final int remoteTimeout,
+                            final SslContext sslContext) {
+
         this.address = address;
         this.channelSize = channelSize;
         this.bufferSize = bufferSize;
         this.remoteTimeout = remoteTimeout;
+        this.sslContext = sslContext;
 
         remoteOutCounter = moduleDefineHolder.find(TelemetryModule.NAME)
                                              .provider()
                                              .getService(MetricsCreator.class)
                                              .createCounter("remote_out_count", "The number(client side) of inside remote inside aggregate rpc.", new MetricsTag.Keys("dest", "self"), new MetricsTag.Values(address
-                                                 .toString(), "N"));
+                                                                                                                                                                                                                 .toString(), "N"));
         remoteOutErrorCounter = moduleDefineHolder.find(TelemetryModule.NAME)
                                                   .provider()
                                                   .getService(MetricsCreator.class)
                                                   .createCounter("remote_out_error_count", "The error number(client side) of inside remote inside aggregate rpc.", new MetricsTag.Keys("dest", "self"), new MetricsTag.Values(address
-                                                      .toString(), "N"));
+                                                                                                                                                                                                                                  .toString(), "N"));
     }
 
     @Override
@@ -99,7 +107,7 @@ public class GRPCRemoteClient implements RemoteClient {
         if (Objects.isNull(client)) {
             synchronized (GRPCRemoteClient.class) {
                 if (Objects.isNull(client)) {
-                    this.client = new GRPCClient(address.getHost(), address.getPort());
+                    this.client = new GRPCClient(address.getHost(), address.getPort(), sslContext);
                 }
             }
         }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/remote/client/RemoteClientManager.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/remote/client/RemoteClientManager.java
index 3927d01..7470204 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/remote/client/RemoteClientManager.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/remote/client/RemoteClientManager.java
@@ -20,6 +20,9 @@ package org.apache.skywalking.oap.server.core.remote.client;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Sets;
+import io.grpc.netty.GrpcSslContexts;
+import io.netty.handler.ssl.SslContext;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
@@ -31,6 +34,7 @@ import java.util.Set;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
+import javax.net.ssl.SSLException;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Setter;
@@ -55,6 +59,7 @@ public class RemoteClientManager implements Service {
     private static final Logger logger = LoggerFactory.getLogger(RemoteClientManager.class);
 
     private final ModuleDefineHolder moduleDefineHolder;
+    private SslContext sslContext;
     private ClusterNodesQuery clusterNodesQuery;
     private volatile List<RemoteClient> usingClients;
     private GaugeMetrics gauge;
@@ -62,11 +67,29 @@ public class RemoteClientManager implements Service {
 
     /**
      * Initial the manager for all remote communication clients.
-     *
      * @param moduleDefineHolder for looking up other modules
      * @param remoteTimeout      for cluster internal communication, in second unit.
+     * @param trustedCAFile         SslContext to verify server certificates.
+     */
+    public RemoteClientManager(ModuleDefineHolder moduleDefineHolder,
+                               int remoteTimeout,
+                               File trustedCAFile) {
+        this(moduleDefineHolder, remoteTimeout);
+        try {
+            sslContext = GrpcSslContexts.forClient().trustManager(trustedCAFile).build();
+        } catch (SSLException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    /**
+     * Initial the manager for all remote communication clients.
+     *
+     * Initial the manager for all remote communication clients.
+     *  @param moduleDefineHolder for looking up other modules
+     * @param remoteTimeout      for cluster internal communication, in second unit.
      */
-    public RemoteClientManager(ModuleDefineHolder moduleDefineHolder, int remoteTimeout) {
+    public RemoteClientManager(final ModuleDefineHolder moduleDefineHolder, final int remoteTimeout) {
         this.moduleDefineHolder = moduleDefineHolder;
         this.usingClients = ImmutableList.of();
         this.remoteTimeout = remoteTimeout;
@@ -197,7 +220,8 @@ public class RemoteClientManager implements Service {
                         RemoteClient client = new SelfRemoteClient(moduleDefineHolder, address);
                         newRemoteClients.add(client);
                     } else {
-                        RemoteClient client = new GRPCRemoteClient(moduleDefineHolder, address, 1, 3000, remoteTimeout);
+                        RemoteClient client;
+                        client = new GRPCRemoteClient(moduleDefineHolder, address, 1, 3000, remoteTimeout, sslContext);
                         client.connect();
                         newRemoteClients.add(client);
                     }
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClientRealClient.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClientRealClient.java
index 5793189..3180b6d 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClientRealClient.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClientRealClient.java
@@ -56,7 +56,7 @@ public class GRPCRemoteClientRealClient {
         moduleManager.put(TelemetryModule.NAME, telemetryModuleDefine);
         telemetryModuleDefine.provider().registerServiceImplementation(MetricsCreator.class, metricsCreator);
 
-        GRPCRemoteClient remoteClient = spy(new GRPCRemoteClient(moduleManager, address, 1, 10, 10));
+        GRPCRemoteClient remoteClient = spy(new GRPCRemoteClient(moduleManager, address, 1, 10, 10, null));
         remoteClient.connect();
 
         for (int i = 0; i < 10000; i++) {
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClientTestCase.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClientTestCase.java
index 8b7a580..5239e82 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClientTestCase.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/remote/client/GRPCRemoteClientTestCase.java
@@ -101,7 +101,7 @@ public class GRPCRemoteClientTestCase {
         grpcServerRule.getServiceRegistry().addService(new RemoteServiceHandler(moduleManager));
 
         Address address = new Address("not-important", 11, false);
-        GRPCRemoteClient remoteClient = spy(new GRPCRemoteClient(moduleManager, address, 1, 10, 10));
+        GRPCRemoteClient remoteClient = spy(new GRPCRemoteClient(moduleManager, address, 1, 10, 10, null));
         remoteClient.connect();
 
         doReturn(grpcServerRule.getChannel()).when(remoteClient).getChannel();
diff --git a/oap-server/server-library/library-client/pom.xml b/oap-server/server-library/library-client/pom.xml
index 4b52c60..5146acc 100755
--- a/oap-server/server-library/library-client/pom.xml
+++ b/oap-server/server-library/library-client/pom.xml
@@ -35,6 +35,10 @@
             <artifactId>grpc-core</artifactId>
         </dependency>
         <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-netty</artifactId>
+        </dependency>
+        <dependency>
             <groupId>com.google.code.gson</groupId>
             <artifactId>gson</artifactId>
         </dependency>
diff --git a/oap-server/server-library/library-client/src/main/java/org/apache/skywalking/oap/server/library/client/grpc/GRPCClient.java b/oap-server/server-library/library-client/src/main/java/org/apache/skywalking/oap/server/library/client/grpc/GRPCClient.java
index d096813..91bef88 100644
--- a/oap-server/server-library/library-client/src/main/java/org/apache/skywalking/oap/server/library/client/grpc/GRPCClient.java
+++ b/oap-server/server-library/library-client/src/main/java/org/apache/skywalking/oap/server/library/client/grpc/GRPCClient.java
@@ -20,6 +20,8 @@ package org.apache.skywalking.oap.server.library.client.grpc;
 
 import io.grpc.ManagedChannel;
 import io.grpc.ManagedChannelBuilder;
+import io.grpc.netty.NettyChannelBuilder;
+import io.netty.handler.ssl.SslContext;
 import lombok.Getter;
 import org.apache.skywalking.oap.server.library.client.Client;
 import org.slf4j.Logger;
@@ -35,6 +37,8 @@ public class GRPCClient implements Client {
     @Getter
     private final int port;
 
+    private SslContext sslContext;
+
     private ManagedChannel channel;
 
     public GRPCClient(String host, int port) {
@@ -42,9 +46,18 @@ public class GRPCClient implements Client {
         this.port = port;
     }
 
+    public GRPCClient(String host, int port, final SslContext sslContext) {
+        this(host, port);
+        this.sslContext = sslContext;
+    }
+
     @Override
     public void connect() {
-        channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
+        if (sslContext == null) {
+            channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext().build();
+            return;
+        }
+        channel = NettyChannelBuilder.forAddress(host, port).sslContext(sslContext).build();
     }
 
     @Override
diff --git a/oap-server/server-library/library-server/src/main/java/org/apache/skywalking/oap/server/library/server/grpc/GRPCServer.java b/oap-server/server-library/library-server/src/main/java/org/apache/skywalking/oap/server/library/server/grpc/GRPCServer.java
index 031b2aa..452484f 100644
--- a/oap-server/server-library/library-server/src/main/java/org/apache/skywalking/oap/server/library/server/grpc/GRPCServer.java
+++ b/oap-server/server-library/library-server/src/main/java/org/apache/skywalking/oap/server/library/server/grpc/GRPCServer.java
@@ -84,8 +84,7 @@ public class GRPCServer implements Server {
      * @param privateKeyFile `server.pem` file
      */
     public GRPCServer(String host, int port, File certChainFile, File privateKeyFile) {
-        this.host = host;
-        this.port = port;
+        this(host, port);
         this.certChainFile = certChainFile;
         this.privateKeyFile = privateKeyFile;
         this.sslContextBuilder = SslContextBuilder.forServer(certChainFile, privateKeyFile);
diff --git a/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java b/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java
index 084e098..f64604c 100644
--- a/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java
+++ b/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java
@@ -41,4 +41,7 @@ public class SharingServerConfig extends ModuleConfig {
     private int gRPCThreadPoolSize;
     private int gRPCThreadPoolQueueSize;
     private String authentication;
+    private boolean gRPCSslEnabled = false;
+    private String gRPCSslKeyPath;
+    private String gRPCSslCertChainPath;
 }
diff --git a/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerModuleProvider.java b/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerModuleProvider.java
index 9635e32..db0bc4b 100644
--- a/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerModuleProvider.java
+++ b/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerModuleProvider.java
@@ -18,6 +18,7 @@
 
 package org.apache.skywalking.oap.server.receiver.sharing.server;
 
+import java.nio.file.Paths;
 import java.util.Objects;
 import org.apache.logging.log4j.util.Strings;
 import org.apache.skywalking.apm.util.StringUtil;
@@ -78,8 +79,15 @@ public class SharingServerModuleProvider extends ModuleProvider {
         }
 
         if (config.getGRPCPort() != 0) {
-            grpcServer = new GRPCServer(Strings.isBlank(config.getGRPCHost()) ? "0.0.0.0" : config.getGRPCHost(), config
-                .getGRPCPort());
+            if (config.isGRPCSslEnabled()) {
+                grpcServer = new GRPCServer(Strings.isBlank(config.getGRPCHost()) ? "0.0.0.0" : config.getGRPCHost(),
+                                            config.getGRPCPort(),
+                                            Paths.get(config.getGRPCSslCertChainPath()).toFile(),
+                                            Paths.get(config.getGRPCSslKeyPath()).toFile());
+            } else {
+                grpcServer = new GRPCServer(Strings.isBlank(config.getGRPCHost()) ? "0.0.0.0" : config.getGRPCHost(),
+                                            config.getGRPCPort());
+            }
             if (config.getMaxMessageSize() > 0) {
                 grpcServer.setMaxMessageSize(config.getMaxMessageSize());
             }
diff --git a/pom.xml b/pom.xml
index 2cd9fcc..5bf24bf 100755
--- a/pom.xml
+++ b/pom.xml
@@ -195,7 +195,7 @@
         <protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
         <com.google.protobuf.protoc.version>3.3.0</com.google.protobuf.protoc.version>
         <protoc-gen-grpc-java.plugin.version>1.8.0</protoc-gen-grpc-java.plugin.version>
-        <netty-tcnative-boringssl-static.version>2.0.25.Final</netty-tcnative-boringssl-static.version>
+        <netty-tcnative-boringssl-static.version>2.0.26.Final</netty-tcnative-boringssl-static.version>
 
         <!-- Plugin versions -->
         <docker.plugin.version>0.4.13</docker.plugin.version>
@@ -464,6 +464,10 @@
                         <!-- generated file from test agent plugin scenarios -->
                         <exclude>**/test/plugin/workspace/**</exclude>
 
+                        <!-- TSL relevant files for e2e test -->
+                        <exclude>**/*.crt</exclude>
+                        <exclude>**/*.pem</exclude>
+
                         <exclude>.m2/**</exclude>
                     </excludes>
                 </configuration>
diff --git a/test/e2e/e2e-ssl/pom.xml b/test/e2e/e2e-ssl/pom.xml
new file mode 100644
index 0000000..9bc8264
--- /dev/null
+++ b/test/e2e/e2e-ssl/pom.xml
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>apache-skywalking-e2e</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>1.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>e2e-ssl</artifactId>
+
+    <properties>
+        <e2e.container.version>1.1</e2e.container.version>
+        <e2e.container.name.prefix>skywalking-e2e-container-${build.id}-agent-auth</e2e.container.name.prefix>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-jpa</artifactId>
+            <version>${spring.boot.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <version>${h2.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>e2e-base</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring.boot.version}</version>
+                <configuration>
+                    <executable>true</executable>
+                    <addResources>true</addResources>
+                    <excludeDevtools>true</excludeDevtools>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>io.fabric8</groupId>
+                <artifactId>docker-maven-plugin</artifactId>
+                <configuration>
+                    <containerNamePattern>%a-%t-%i</containerNamePattern>
+                    <images>
+                        <image>
+                            <name>skyapm/e2e-container:${e2e.container.version}</name>
+                            <alias>${e2e.container.name.prefix}</alias>
+                            <run>
+                                <env>
+                                    <INSTRUMENTED_SERVICE>${project.build.finalName}.jar</INSTRUMENTED_SERVICE>
+                                    <INSTRUMENTED_SERVICE_OPTS>-Dskywalking.collector.backend_service=oap.skywalking:11800 -Dskywalking.logging.dir=/tmp/logs/agent</INSTRUMENTED_SERVICE_OPTS>
+                                </env>
+                                <ports>
+                                    <port>+webapp.host:webapp.port:8080</port>
+                                    <port>+client.host:client.port:9090</port>
+                                </ports>
+                                <volumes>
+                                    <bind>
+                                        <volume>${sw.home}:/sw</volume>
+                                        <volume>${project.build.directory}:/home</volume>
+                                        <volume>${project.basedir}/src/docker/rc.d:/rc.d:ro</volume>
+                                        <volume>${project.basedir}/src/docker/certs:/sw/certs:ro</volume>
+                                        <volume>${project.basedir}/src/docker/ca:/sw/agent/ca:ro</volume>
+                                        <volume>${project.basedir}/src/docker/hosts:/etc/hosts:ro</volume>
+                                        <volume>/tmp/logs:/tmp/logs:rw</volume>
+                                    </bind>
+                                </volumes>
+                                <wait>
+                                    <http>
+                                        <url>
+                                            http://${docker.host.address}:${client.port}/e2e/health-check
+                                        </url>
+                                        <method>GET</method>
+                                        <status>200</status>
+                                    </http>
+                                    <time>300000</time>
+                                </wait>
+                            </run>
+                        </image>
+                    </images>
+                </configuration>
+            </plugin>
+
+            <!-- set the system properties that can be used in test codes -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <configuration>
+                    <systemPropertyVariables>
+                        <sw.webapp.host>
+                            ${webapp.host}
+                        </sw.webapp.host>
+                        <sw.webapp.port>
+                            ${webapp.port}
+                        </sw.webapp.port>
+                        <client.host>
+                            ${client.host}
+                        </client.host>
+                        <client.port>
+                            ${client.port}
+                        </client.port>
+                    </systemPropertyVariables>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/test/e2e/e2e-ssl/src/docker/ca/ca.crt b/test/e2e/e2e-ssl/src/docker/ca/ca.crt
new file mode 100644
index 0000000..da668c5
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/docker/ca/ca.crt
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIE3DCCAsSgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDEwJjYTAg
+Fw0yMDAzMTQxMTAyMzJaGA8yMTIwMDMxNDExMDIyN1owDTELMAkGA1UEAxMCY2Ew
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzC+MyVQhw8fstg0sZtAJO
+u1LGGN6uk0Dto4dXiqjeJ5NNDlwFCa4JZQzPXR5h3LN5ztvSPp9cYB3KXhRmQL/D
+sjdnJEL07mMGF5Om6yZgvE/xY1p7xzkpNfmrMrdjbCsHCX8mHV5RBWAs+dWdF8K0
+JxjuoY4sbOIugKBdIYX+BaKTnywcl2f6vnvbACGzR2DHNa0gdceradYkurxia6dD
+JC46N+E3PofhIGuOzUgBMad7L1Ju1OLNxI8bK2XT/nVHvjhUL50MJDEqaPpHXRgg
+7Mcvb6CwCeUeWjFJPcKHPG8L55j2HijMV4uukZmTzeiiYmocnMlrDm7NWeVeT9V+
+207i/fx2dd0o7xoec3vP9WAd/8dF6rxkgLC3cE09dTLlTaVSbWs3glwZNh1NizpH
+hMV2Ifl4e/BP6sxyuQk8TPjGqP+2nSkzvqiAmi7hyHYv3BPJXbG5FF2jGcXIbMpi
+i+0tRrAUFvvsFwvdZ01ElfsIeZ50Cwo21HObDO9Y3vu8K1z/4+anm+dtYPrzlWK2
+/oUKkzkAViKODQq8hyzHvIkky2iclfZTm+I3XXAMahwk8Uq1yD/3pHIkWomwp5YE
+YZqglIV7Vddsox5rBVCeFx4OFYYIUXoJ+G/L7Bm+L3F/iAdtEpFI08PAaVMBEPGc
+3M2dF8OYv9PFlXlzsWp9HwIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0T
+AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUtdnblxrM2bUBOcdFx/AV5xyCb5MwDQYJ
+KoZIhvcNAQELBQADggIBAGpHU5iRp6Ook8Uu/W0RdsM2uZWM7Nqfcm2AVngQEJ+z
+IO3FIoL4NGmR2/r12CnPe/p0c74fQTv2xlzWiV5yFpqEb9UujfKhj9tUpZnqucyu
+zy4sACld3Rxpro2PbIgzslNRkr9lMEpcDEIwGx+HiqBgSrvWjQv3Cn/f8eIV8sXr
+7hC93N7AC29TROdj+xiImGakK3fy3qRusEAFWv49EsQKX1sQ6WmcniLJ/J82w2cf
+BDytrMlzhX4ecAYZGCrwObS85cBLNZY7U5CzIVk76x2VHny38/ikcHZDQmThk1d0
+Rhcb5JPf/v3VdzfmIc5cvHMcdx0ZFOTG8Gg1tsTFOOXWR91VWpbCelRZ6H+J2ubV
+5ZRVwqyGOP3K40rEGvBoRANtBrStqqv8QHBdAAVRsga4MyzIv3+pSNeFtoEJn3i3
+NFGqow5z1xdWSIQsqzkqLxUVX7ErMlmCb9gOfn/VHVr1iJ0/Y295cWpCH+HQ4D1h
+Hk//XciqIOSF1TceRymC4a2MZCHXZHuztYZ5ULDXRSco6xFnEfjHWKNNqpkDUjQv
+xfVJ6UMS1QV+xrcmd9SPz0B+eIFGjWtgos+OmubhrJuroSLQTXFpse3BsFcKATtE
+JNrEYxN2pIHV2yVSXolc73barRd1Gm0SZEawnhgA+422p/U2o1i30HXgoESZT3hN
+-----END CERTIFICATE-----
diff --git a/test/e2e/e2e-ssl/src/docker/certs/ca.crt b/test/e2e/e2e-ssl/src/docker/certs/ca.crt
new file mode 100644
index 0000000..da668c5
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/docker/certs/ca.crt
@@ -0,0 +1,28 @@
+-----BEGIN CERTIFICATE-----
+MIIE3DCCAsSgAwIBAgIBATANBgkqhkiG9w0BAQsFADANMQswCQYDVQQDEwJjYTAg
+Fw0yMDAzMTQxMTAyMzJaGA8yMTIwMDMxNDExMDIyN1owDTELMAkGA1UEAxMCY2Ew
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzC+MyVQhw8fstg0sZtAJO
+u1LGGN6uk0Dto4dXiqjeJ5NNDlwFCa4JZQzPXR5h3LN5ztvSPp9cYB3KXhRmQL/D
+sjdnJEL07mMGF5Om6yZgvE/xY1p7xzkpNfmrMrdjbCsHCX8mHV5RBWAs+dWdF8K0
+JxjuoY4sbOIugKBdIYX+BaKTnywcl2f6vnvbACGzR2DHNa0gdceradYkurxia6dD
+JC46N+E3PofhIGuOzUgBMad7L1Ju1OLNxI8bK2XT/nVHvjhUL50MJDEqaPpHXRgg
+7Mcvb6CwCeUeWjFJPcKHPG8L55j2HijMV4uukZmTzeiiYmocnMlrDm7NWeVeT9V+
+207i/fx2dd0o7xoec3vP9WAd/8dF6rxkgLC3cE09dTLlTaVSbWs3glwZNh1NizpH
+hMV2Ifl4e/BP6sxyuQk8TPjGqP+2nSkzvqiAmi7hyHYv3BPJXbG5FF2jGcXIbMpi
+i+0tRrAUFvvsFwvdZ01ElfsIeZ50Cwo21HObDO9Y3vu8K1z/4+anm+dtYPrzlWK2
+/oUKkzkAViKODQq8hyzHvIkky2iclfZTm+I3XXAMahwk8Uq1yD/3pHIkWomwp5YE
+YZqglIV7Vddsox5rBVCeFx4OFYYIUXoJ+G/L7Bm+L3F/iAdtEpFI08PAaVMBEPGc
+3M2dF8OYv9PFlXlzsWp9HwIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0T
+AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUtdnblxrM2bUBOcdFx/AV5xyCb5MwDQYJ
+KoZIhvcNAQELBQADggIBAGpHU5iRp6Ook8Uu/W0RdsM2uZWM7Nqfcm2AVngQEJ+z
+IO3FIoL4NGmR2/r12CnPe/p0c74fQTv2xlzWiV5yFpqEb9UujfKhj9tUpZnqucyu
+zy4sACld3Rxpro2PbIgzslNRkr9lMEpcDEIwGx+HiqBgSrvWjQv3Cn/f8eIV8sXr
+7hC93N7AC29TROdj+xiImGakK3fy3qRusEAFWv49EsQKX1sQ6WmcniLJ/J82w2cf
+BDytrMlzhX4ecAYZGCrwObS85cBLNZY7U5CzIVk76x2VHny38/ikcHZDQmThk1d0
+Rhcb5JPf/v3VdzfmIc5cvHMcdx0ZFOTG8Gg1tsTFOOXWR91VWpbCelRZ6H+J2ubV
+5ZRVwqyGOP3K40rEGvBoRANtBrStqqv8QHBdAAVRsga4MyzIv3+pSNeFtoEJn3i3
+NFGqow5z1xdWSIQsqzkqLxUVX7ErMlmCb9gOfn/VHVr1iJ0/Y295cWpCH+HQ4D1h
+Hk//XciqIOSF1TceRymC4a2MZCHXZHuztYZ5ULDXRSco6xFnEfjHWKNNqpkDUjQv
+xfVJ6UMS1QV+xrcmd9SPz0B+eIFGjWtgos+OmubhrJuroSLQTXFpse3BsFcKATtE
+JNrEYxN2pIHV2yVSXolc73barRd1Gm0SZEawnhgA+422p/U2o1i30HXgoESZT3hN
+-----END CERTIFICATE-----
diff --git a/test/e2e/e2e-ssl/src/docker/certs/server-key.pem b/test/e2e/e2e-ssl/src/docker/certs/server-key.pem
new file mode 100644
index 0000000..c9f7ecb
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/docker/certs/server-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDapRERykKZD+Be
+W8KDr0NdrW9FNiBMe6GgPVCEE3C822c83mEaSxx7daVZNJYXXIL4u4evkQLkSqAf
+7dNSv+Rznl0EwxZGZVJBBJb7PYwg+2WYYM6CUYQ7X8EnH7X8/3n8xGKfra6vS4vy
+mvGmYMkLHtf0JgrnsF+O5uTTYOIdHsCSO6hAz6lN2xRJo1O8DpB4WjkzJI8ZaofC
+mkLKoMXKWeOKqTJc9CewTNwuxQsx0EQdShdrkZvyft1CXL/5oMBvQu4h6/dAI4TF
+F37MYvYX9DfsRpULpuFx01QUUj54/A1JH27aw89Z6yAyBAjsnhqcdVJaiM6F6d8i
+iZpVyrxdAgMBAAECggEAAVMQqGfuQVkcRdYOdpfAM7gSPXwXc/8nun3EmBg6DZrS
+pEbAldUwpfrPdpvf8OJJlNIl/0VEnDdrguYA6rZo3t5tt9KqtuB0QBqUA4+a4rRD
+KEol1hpCT83DsMX7Zz3w8jwKUOdPcJZnkZ+oqRZbAWs9aag1VrP10DrL1g/3Lq/3
+Icpue1ll2JXYpLUvqhmhukiIsq2n5GIZqnL3m3kvPmUemS4wrQO9mBraLqlX93Ks
+reAoyZDQVvaAM5M2ZwFxG+GdOwLeZOCEBZ5MOpUfQA8e8k9e/QcRsA5vCrFIbGhJ
+M3vtwPXS01qSUWsI3iGriz1VfCWMpH2qOQoEk13zYQKBgQD52qc9gZXsBMiYlaLM
+S5Qp4C2txfif3UTkido7R9On3iyAZqE3FRA805wQuN2GQk6qI+UiMyIS68/nq+Ll
+uTXJNKqaajmT5gx77Wxpwv/CpJ3ZMkIEfzLQxHOOrjPoWgTjwPw7n3dV7O2FYtZ0
+RQXWjU4nLhdzvEAsnh3Rj18VuQKBgQDgBeLpRrgAW/iK0mtU9R+XAwxQnAQ7TOrt
+BgtwVcwCdzpJzHhGmDnu1KopRn4BhfwJ0inZq3lE0UPPflmgE2E4JiOKIBin3lbw
+QJIIN5blTvy78zQXD/aBcVN0toOAPCulfRdwkAt75Ad9J0sPEQBLNewFdpOquLLo
+39UkF/mtxQKBgQDx4OholcviqhrcBHiPGFe+VmVCRlZTxSzNplqbawSPDXm9cB2A
+KqcGi8EZOy5RrF1lPsyy2BeTg7BI0lEdHbjhKVhDlrRY5quNSaLbnEhnUV/yhUH+
+AnnaO2S3axObS5JSPmCxA8bOa0jiCXYdJzjopPFU4r0XcNYbm5K4bfiaGQKBgHyK
+iTWKvSxl9OyoQkc+5sr7RNNjiO62ujv/CkjvSbVtNxhj9dG5OyvNSrQbnl2WcSG8
+lsuOCqL5e6tU4NqfK4MdoNBfO5XHg6mZHBY5YUgl+1c5w5G2rCIWMIFIHh8iVFly
+C5/mVJwRjyBCwfWkS/eECKyY2Usl10Cjf0jLk2DJAoGAZRQgdvDTGMVCDzkwYbKm
+0xEQJj6RoU5wLehCmNbCBWU4aKyVmkj2lspEtOjM5Hw+kI1Cjq01Bq7N5EYCIelb
+rO7sTDDtQ+2Jr4OKJgnBrgjwlE8C99LHboiKTHkgFWCQpGHEcgfszWaCCIRBru2l
+wmqJLv4IKD9ZHYu4zLNjhCE=
+-----END PRIVATE KEY-----
diff --git a/test/e2e/e2e-ssl/src/docker/certs/server.crt b/test/e2e/e2e-ssl/src/docker/certs/server.crt
new file mode 100644
index 0000000..bde1a01
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/docker/certs/server.crt
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEQDCCAiigAwIBAgIQa1fDhEPRaEtB2J+Ircp50DANBgkqhkiG9w0BAQsFADAN
+MQswCQYDVQQDEwJjYTAgFw0yMDAzMTQxMTA5MDlaGA8yMTIwMDMxNDExMDIyN1ow
+GTEXMBUGA1UEAxMOb2FwLnNreXdhbGtpbmcwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDapRERykKZD+BeW8KDr0NdrW9FNiBMe6GgPVCEE3C822c83mEa
+Sxx7daVZNJYXXIL4u4evkQLkSqAf7dNSv+Rznl0EwxZGZVJBBJb7PYwg+2WYYM6C
+UYQ7X8EnH7X8/3n8xGKfra6vS4vymvGmYMkLHtf0JgrnsF+O5uTTYOIdHsCSO6hA
+z6lN2xRJo1O8DpB4WjkzJI8ZaofCmkLKoMXKWeOKqTJc9CewTNwuxQsx0EQdShdr
+kZvyft1CXL/5oMBvQu4h6/dAI4TFF37MYvYX9DfsRpULpuFx01QUUj54/A1JH27a
+w89Z6yAyBAjsnhqcdVJaiM6F6d8iiZpVyrxdAgMBAAGjgY0wgYowDgYDVR0PAQH/
+BAQDAgO4MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQU
+2GUzQtLkl/rY9dV3zXjVJ3iEmGswHwYDVR0jBBgwFoAUtdnblxrM2bUBOcdFx/AV
+5xyCb5MwGQYDVR0RBBIwEIIOb2FwLnNreXdhbGtpbmcwDQYJKoZIhvcNAQELBQAD
+ggIBAHH21tY+8SrHecDX9FBPObDJbsqqWqLHXqhqYOKKhfCIxm2F+FK35KeVOc+c
+6rGYvI62Dml3UHezYBLKgA3Ol/l1jzFU/UdLdTyzoybxljrb9TtQV5NViwk6XdVr
+jKR805LkSpQhDPO6GogSWT5cV5yDIBHjA1DMEG45CB4pX5Y4P4LA5VpmTJe/sox+
+01HmmzIU2CTt9/F3CRmC8WlMEHrT6gVuSzOh1WfYAanlggLK01F/RI5WXX+mSNoZ
+a/psQAwkX3rQaekxgYhA0puwV6GU1A7bwexw6yHK9SSiaDsmNazq5QnMGBbNv1F5
+NuxBz04IOxtrOJ0wtIld8VvePQXvYxWD9/XlQCLFnw7RXkHxZlqu/52A5KJKWxU8
+H1n5l50nP4rYH/EVmyqwzzZMQYr3HXOmijAPi0ma8oGgBDOpQos8GUZEZ+82ELgQ
+NCKucqbnaB5xC5kNEwIqf1sEyCTNginmGObDYexN+EtuT6ixutIQoSMkJ4TdPwO+
+1+caCrXmFI82/WEHartqhB36dLAix1pnRIn19cejO2AWoUacxJ4qZDShn8uQerVx
+Obfys6kfzGCwFd+bmh+pF181nNy95lqGQgAFiPqiNFsD3ioZwdCmfFJXsq0ObNFe
+I1qEbVBJy3JeU19wQr22XVx+5QpUkegxHEfZsChunH8rIr1K
+-----END CERTIFICATE-----
diff --git a/test/e2e/e2e-ssl/src/docker/hosts b/test/e2e/e2e-ssl/src/docker/hosts
new file mode 100644
index 0000000..fca2eb2
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/docker/hosts
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+# Licensed to the SkyAPM 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.
+
+# Host Database
+#
+# localhost is used to configure the loopback interface
+# when the system is booting.  Do not change this entry.
+##
+127.0.0.1	localhost
+255.255.255.255	broadcasthost
+::1             localhost
+127.0.0.1   oap.skywalking
diff --git a/test/e2e/e2e-ssl/src/docker/rc.d/rc1-startup.sh b/test/e2e/e2e-ssl/src/docker/rc.d/rc1-startup.sh
new file mode 100755
index 0000000..449a983
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/docker/rc.d/rc1-startup.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+# Licensed to the SkyAPM 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.
+
+cat /etc/hosts
+
+echo 'starting OAP server...' \
+    && export SW_CORE_GRPC_SSL_ENABLED=true \
+    && export SW_CORE_GRPC_SSL_KEY_PATH="${SW_HOME}/certs/server-key.pem" \
+    && export SW_CORE_GRPC_SSL_CERT_CHAIN_PATH="${SW_HOME}/certs/server.crt" \
+    && export SW_CORE_GRPC_SSL_TRUSTED_CA_PATH="${SW_HOME}/certs/ca.crt" \
+    && start_oap 'init'
+
+echo 'starting Web app...' \
+    && start_webapp '0.0.0.0' 8080
+
+echo 'starting instrumented services...' \
+    && start_instrumented_services
+
+check_tcp 127.0.0.1 \
+          9090 \
+          60 \
+          10 \
+          "waiting for the instrumented service to be ready"
+
+if [[ $? -ne 0 ]]; then
+    echo "instrumented service failed to start in 30 * 10 seconds: "
+    cat ${SERVICE_LOG}/*
+    exit 1
+fi
+
+echo "SkyWalking e2e container is ready for tests"
+
+tail -f ${OAP_LOG_DIR}/* \
+        ${WEBAPP_LOG_DIR}/* \
+        ${SERVICE_LOG}/* \
+        ${ES_HOME}/logs/stdout.log
diff --git a/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java b/test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/SampleClientApplication.java
similarity index 51%
copy from oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java
copy to test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/SampleClientApplication.java
index 084e098..67ba54e 100644
--- a/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java
+++ b/test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/SampleClientApplication.java
@@ -16,29 +16,16 @@
  *
  */
 
-package org.apache.skywalking.oap.server.receiver.sharing.server;
+package org.apache.skywalking.e2e.sample.client;
 
-import lombok.Getter;
-import lombok.Setter;
-import org.apache.skywalking.oap.server.library.module.ModuleConfig;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 
-@Getter
-@Setter
-public class SharingServerConfig extends ModuleConfig {
-    private String restHost;
-    /**
-     * Only setting the real port(not 0) makes the jetty server online.
-     */
-    private int restPort;
-    private String restContextPath;
-    private String gRPCHost;
-    /**
-     * Only setting the real port(not 0) makes the gRPC server online.
-     */
-    private int gRPCPort;
-    private int maxConcurrentCallsPerConnection;
-    private int maxMessageSize;
-    private int gRPCThreadPoolSize;
-    private int gRPCThreadPoolQueueSize;
-    private String authentication;
+@EnableJpaRepositories
+@SpringBootApplication
+public class SampleClientApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(SampleClientApplication.class, args);
+    }
 }
diff --git a/test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/TestController.java b/test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/TestController.java
new file mode 100644
index 0000000..1a344ab
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/TestController.java
@@ -0,0 +1,46 @@
+/*
+ * 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.skywalking.e2e.sample.client;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/e2e")
+public class TestController {
+    private final UserRepo userRepo;
+
+    public TestController(final UserRepo userRepo) {
+        this.userRepo = userRepo;
+    }
+
+    @GetMapping("/health-check")
+    public String hello() {
+        return "healthy";
+    }
+
+    @PostMapping("/users")
+    public User createAuthor(@RequestBody final User user) throws InterruptedException {
+        Thread.sleep(1000L);
+        return userRepo.save(user);
+    }
+}
diff --git a/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java b/test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/User.java
similarity index 51%
copy from oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java
copy to test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/User.java
index 084e098..3b6c317 100644
--- a/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java
+++ b/test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/User.java
@@ -16,29 +16,38 @@
  *
  */
 
-package org.apache.skywalking.oap.server.receiver.sharing.server;
-
-import lombok.Getter;
-import lombok.Setter;
-import org.apache.skywalking.oap.server.library.module.ModuleConfig;
-
-@Getter
-@Setter
-public class SharingServerConfig extends ModuleConfig {
-    private String restHost;
-    /**
-     * Only setting the real port(not 0) makes the jetty server online.
-     */
-    private int restPort;
-    private String restContextPath;
-    private String gRPCHost;
-    /**
-     * Only setting the real port(not 0) makes the gRPC server online.
-     */
-    private int gRPCPort;
-    private int maxConcurrentCallsPerConnection;
-    private int maxMessageSize;
-    private int gRPCThreadPoolSize;
-    private int gRPCThreadPoolQueueSize;
-    private String authentication;
+package org.apache.skywalking.e2e.sample.client;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class User {
+    public User() {
+    }
+
+    @Id
+    @GeneratedValue
+    private Long id;
+
+    @Column
+    private String name;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(final Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
 }
diff --git a/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java b/test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/UserRepo.java
similarity index 51%
copy from oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java
copy to test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/UserRepo.java
index 084e098..2ee38a6 100644
--- a/oap-server/server-receiver-plugin/skywalking-sharing-server-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/sharing/server/SharingServerConfig.java
+++ b/test/e2e/e2e-ssl/src/main/java/org/apache/skywalking/e2e/sample/client/UserRepo.java
@@ -16,29 +16,9 @@
  *
  */
 
-package org.apache.skywalking.oap.server.receiver.sharing.server;
+package org.apache.skywalking.e2e.sample.client;
 
-import lombok.Getter;
-import lombok.Setter;
-import org.apache.skywalking.oap.server.library.module.ModuleConfig;
+import org.springframework.data.jpa.repository.JpaRepository;
 
-@Getter
-@Setter
-public class SharingServerConfig extends ModuleConfig {
-    private String restHost;
-    /**
-     * Only setting the real port(not 0) makes the jetty server online.
-     */
-    private int restPort;
-    private String restContextPath;
-    private String gRPCHost;
-    /**
-     * Only setting the real port(not 0) makes the gRPC server online.
-     */
-    private int gRPCPort;
-    private int maxConcurrentCallsPerConnection;
-    private int maxMessageSize;
-    private int gRPCThreadPoolSize;
-    private int gRPCThreadPoolQueueSize;
-    private String authentication;
+public interface UserRepo extends JpaRepository<User, Long> {
 }
diff --git a/test/e2e/e2e-ssl/src/main/resources/application.yml b/test/e2e/e2e-ssl/src/main/resources/application.yml
new file mode 100644
index 0000000..ef3ed01
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/main/resources/application.yml
@@ -0,0 +1,35 @@
+# 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.
+
+server:
+  port: 9090
+
+spring:
+  main:
+    banner-mode: 'off'
+  datasource:
+    url: jdbc:h2:mem:testdb
+    driver-class-name: org.h2.Driver
+    data-username: sa
+    password: sa
+    platform: org.hibernate.dialect.H2Dialect
+  jpa:
+    generate-ddl: true
+    hibernate:
+      ddl-auto: create-drop
+    properties:
+      hibernate.format_sql: true
+    show-sql: true
diff --git a/test/e2e/e2e-ssl/src/test/java/org/apache/skywalking/e2e/SampleVerificationITCase.java b/test/e2e/e2e-ssl/src/test/java/org/apache/skywalking/e2e/SampleVerificationITCase.java
new file mode 100644
index 0000000..398b8f2
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/test/java/org/apache/skywalking/e2e/SampleVerificationITCase.java
@@ -0,0 +1,360 @@
+/*
+ * 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.skywalking.e2e;
+
+import java.io.InputStream;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.skywalking.e2e.metrics.AtLeastOneOfMetricsMatcher;
+import org.apache.skywalking.e2e.metrics.Metrics;
+import org.apache.skywalking.e2e.metrics.MetricsQuery;
+import org.apache.skywalking.e2e.metrics.MetricsValueMatcher;
+import org.apache.skywalking.e2e.service.Service;
+import org.apache.skywalking.e2e.service.ServicesMatcher;
+import org.apache.skywalking.e2e.service.ServicesQuery;
+import org.apache.skywalking.e2e.service.endpoint.Endpoint;
+import org.apache.skywalking.e2e.service.endpoint.EndpointQuery;
+import org.apache.skywalking.e2e.service.endpoint.Endpoints;
+import org.apache.skywalking.e2e.service.endpoint.EndpointsMatcher;
+import org.apache.skywalking.e2e.service.instance.Instance;
+import org.apache.skywalking.e2e.service.instance.Instances;
+import org.apache.skywalking.e2e.service.instance.InstancesMatcher;
+import org.apache.skywalking.e2e.service.instance.InstancesQuery;
+import org.apache.skywalking.e2e.topo.Call;
+import org.apache.skywalking.e2e.topo.ServiceInstanceTopoData;
+import org.apache.skywalking.e2e.topo.ServiceInstanceTopoMatcher;
+import org.apache.skywalking.e2e.topo.ServiceInstanceTopoQuery;
+import org.apache.skywalking.e2e.topo.TopoData;
+import org.apache.skywalking.e2e.topo.TopoMatcher;
+import org.apache.skywalking.e2e.topo.TopoQuery;
+import org.apache.skywalking.e2e.trace.Trace;
+import org.apache.skywalking.e2e.trace.TracesMatcher;
+import org.apache.skywalking.e2e.trace.TracesQuery;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.web.client.RestTemplate;
+import org.yaml.snakeyaml.Yaml;
+
+import static org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyMetrics;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_ENDPOINT_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_INSTANCE_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_CLIENT_METRICS;
+import static org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_SERVER_METRICS;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+public class SampleVerificationITCase {
+    private static final Logger LOGGER = LoggerFactory.getLogger(SampleVerificationITCase.class);
+
+    private final RestTemplate restTemplate = new RestTemplate();
+    private final int retryInterval = 30;
+
+    private SimpleQueryClient queryClient;
+    private String instrumentedServiceUrl;
+
+    @Before
+    public void setUp() {
+        final String swWebappHost = System.getProperty("sw.webapp.host", "127.0.0.1");
+        final String swWebappPort = System.getProperty("sw.webapp.port", "32783");
+        final String instrumentedServiceHost = System.getProperty("client.host", "127.0.0.1");
+        final String instrumentedServicePort = System.getProperty("client.port", "32782");
+        queryClient = new SimpleQueryClient(swWebappHost, swWebappPort);
+        instrumentedServiceUrl = "http://" + instrumentedServiceHost + ":" + instrumentedServicePort;
+    }
+
+    @Test(timeout = 2 * 60 * 1000)
+    @DirtiesContext
+    public void verify() throws Exception {
+        final LocalDateTime minutesAgo = LocalDateTime.now(ZoneOffset.UTC);
+
+        while (true) {
+            try {
+                final Map<String, String> user = new HashMap<>();
+                user.put("name", "SkyWalking");
+                final ResponseEntity<String> responseEntity = restTemplate.postForEntity(
+                    instrumentedServiceUrl + "/e2e/users", user, String.class);
+                LOGGER.info("responseEntity: {}", responseEntity);
+                assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
+                final List<Trace> traces = queryClient.traces(new TracesQuery().start(minutesAgo)
+                                                                               .end(LocalDateTime.now())
+                                                                               .orderByDuration());
+                if (!traces.isEmpty()) {
+                    break;
+                }
+                Thread.sleep(10000L);
+            } catch (Exception ignored) {
+            }
+        }
+
+        doRetryableVerification(() -> {
+            try {
+                verifyTraces(minutesAgo);
+            } catch (Exception e) {
+                LOGGER.warn(e.getMessage(), e);
+            }
+        });
+
+        doRetryableVerification(() -> {
+            try {
+                verifyServices(minutesAgo);
+            } catch (Exception e) {
+                LOGGER.warn(e.getMessage(), e);
+            }
+        });
+
+        doRetryableVerification(() -> {
+            try {
+                verifyTopo(minutesAgo);
+            } catch (Exception e) {
+                LOGGER.warn(e.getMessage(), e);
+            }
+        });
+
+        doRetryableVerification(() -> {
+            try {
+                verifyServiceInstanceTopo(minutesAgo);
+            } catch (Exception e) {
+                LOGGER.warn(e.getMessage(), e);
+            }
+        });
+    }
+
+    private void verifyTopo(LocalDateTime minutesAgo) throws Exception {
+        final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
+
+        final TopoData topoData = queryClient.topo(new TopoQuery().stepByMinute()
+                                                                  .start(minutesAgo.minusDays(1))
+                                                                  .end(now));
+        LOGGER.info("topoData: {}", topoData);
+
+        InputStream expectedInputStream = new ClassPathResource(
+            "expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.topo.yml")
+            .getInputStream();
+
+        final TopoMatcher topoMatcher = new Yaml().loadAs(expectedInputStream, TopoMatcher.class);
+        topoMatcher.verify(topoData);
+        verifyServiceRelationMetrics(topoData.getCalls(), minutesAgo);
+    }
+
+    private void verifyServiceInstanceTopo(LocalDateTime minutesAgo) throws Exception {
+        final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
+
+        final ServiceInstanceTopoData topoData = queryClient.serviceInstanceTopo(
+            new ServiceInstanceTopoQuery().stepByMinute()
+                                          .start(minutesAgo
+                                                     .minusDays(1))
+                                          .end(now)
+                                          .clientServiceId("1")
+                                          .serverServiceId("2"));
+        LOGGER.info("instanceTopoData: {}", topoData);
+
+        InputStream expectedInputStream = new ClassPathResource(
+            "expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.serviceInstanceTopo.yml")
+            .getInputStream();
+
+        final ServiceInstanceTopoMatcher topoMatcher = new Yaml().loadAs(
+            expectedInputStream, ServiceInstanceTopoMatcher.class);
+        topoMatcher.verify(topoData);
+        verifyServiceInstanceRelationMetrics(topoData.getCalls(), minutesAgo);
+    }
+
+    private void verifyServices(LocalDateTime minutesAgo) throws Exception {
+        final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
+
+        final List<Service> services = queryClient.services(new ServicesQuery().start(minutesAgo).end(now));
+        LOGGER.info("services: {}", services);
+
+        InputStream expectedInputStream = new ClassPathResource(
+            "expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.services.yml")
+            .getInputStream();
+
+        final ServicesMatcher servicesMatcher = new Yaml().loadAs(expectedInputStream, ServicesMatcher.class);
+        servicesMatcher.verify(services);
+
+        for (Service service : services) {
+            LOGGER.info("verifying service instances: {}", service);
+
+            verifyServiceMetrics(service);
+
+            Instances instances = verifyServiceInstances(minutesAgo, now, service);
+
+            verifyInstancesMetrics(instances);
+
+            Endpoints endpoints = verifyServiceEndpoints(minutesAgo, now, service);
+
+            verifyEndpointsMetrics(endpoints);
+        }
+    }
+
+    private Instances verifyServiceInstances(LocalDateTime minutesAgo, LocalDateTime now,
+                                             Service service) throws Exception {
+        InputStream expectedInputStream;
+        Instances instances = queryClient.instances(new InstancesQuery().serviceId(service.getKey())
+                                                                        .start(minutesAgo)
+                                                                        .end(now));
+        LOGGER.info("instances: {}", instances);
+        expectedInputStream = new ClassPathResource(
+            "expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.instances.yml")
+            .getInputStream();
+        final InstancesMatcher instancesMatcher = new Yaml().loadAs(expectedInputStream, InstancesMatcher.class);
+        instancesMatcher.verify(instances);
+        return instances;
+    }
+
+    private Endpoints verifyServiceEndpoints(LocalDateTime minutesAgo, LocalDateTime now,
+                                             Service service) throws Exception {
+        Endpoints instances = queryClient.endpoints(new EndpointQuery().serviceId(service.getKey()));
+        LOGGER.info("instances: {}", instances);
+        InputStream expectedInputStream = new ClassPathResource(
+            "expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.endpoints.yml")
+            .getInputStream();
+        final EndpointsMatcher endpointsMatcher = new Yaml().loadAs(expectedInputStream, EndpointsMatcher.class);
+        endpointsMatcher.verify(instances);
+        return instances;
+    }
+
+    private void verifyInstancesMetrics(Instances instances) throws Exception {
+        for (Instance instance : instances.getInstances()) {
+            for (String metricsName : ALL_INSTANCE_METRICS) {
+                LOGGER.info("verifying service instance response time: {}", instance);
+                final Metrics instanceMetrics = queryClient.metrics(new MetricsQuery().stepByMinute()
+                                                                                      .metricsName(metricsName)
+                                                                                      .id(instance.getKey()));
+                LOGGER.info("instanceMetrics: {}", instanceMetrics);
+                AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
+                MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
+                greaterThanZero.setValue("gt 0");
+                instanceRespTimeMatcher.setValue(greaterThanZero);
+                instanceRespTimeMatcher.verify(instanceMetrics);
+                LOGGER.info("{}: {}", metricsName, instanceMetrics);
+            }
+        }
+    }
+
+    private void verifyEndpointsMetrics(Endpoints endpoints) throws Exception {
+        for (Endpoint endpoint : endpoints.getEndpoints()) {
+            if (!endpoint.getLabel().equals("/e2e/users")) {
+                continue;
+            }
+            for (String metricName : ALL_ENDPOINT_METRICS) {
+                LOGGER.info("verifying endpoint {}, metrics: {}", endpoint, metricName);
+                final Metrics metrics = queryClient.metrics(new MetricsQuery().stepByMinute()
+                                                                              .metricsName(metricName)
+                                                                              .id(endpoint.getKey()));
+                LOGGER.info("metrics: {}", metrics);
+                AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
+                MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
+                greaterThanZero.setValue("gt 0");
+                instanceRespTimeMatcher.setValue(greaterThanZero);
+                instanceRespTimeMatcher.verify(metrics);
+                LOGGER.info("{}: {}", metricName, metrics);
+            }
+        }
+    }
+
+    private void verifyServiceMetrics(Service service) throws Exception {
+        for (String metricName : ALL_SERVICE_METRICS) {
+            LOGGER.info("verifying service {}, metrics: {}", service, metricName);
+            final Metrics serviceMetrics = queryClient.metrics(new MetricsQuery().stepByMinute()
+                                                                                 .metricsName(metricName)
+                                                                                 .id(service.getKey()));
+            LOGGER.info("serviceMetrics: {}", serviceMetrics);
+            AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
+            MetricsValueMatcher greaterThanZero = new MetricsValueMatcher();
+            greaterThanZero.setValue("gt 0");
+            instanceRespTimeMatcher.setValue(greaterThanZero);
+            instanceRespTimeMatcher.verify(serviceMetrics);
+            LOGGER.info("{}: {}", metricName, serviceMetrics);
+        }
+    }
+
+    private void verifyTraces(LocalDateTime minutesAgo) throws Exception {
+        final LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
+
+        final List<Trace> traces = queryClient.traces(new TracesQuery().start(minutesAgo).end(now).orderByDuration());
+        LOGGER.info("traces: {}", traces);
+
+        InputStream expectedInputStream = new ClassPathResource(
+            "expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.traces.yml")
+            .getInputStream();
+
+        final TracesMatcher tracesMatcher = new Yaml().loadAs(expectedInputStream, TracesMatcher.class);
+        tracesMatcher.verifyLoosely(traces);
+    }
+
+    private void verifyServiceInstanceRelationMetrics(List<Call> calls,
+                                                      final LocalDateTime minutesAgo) throws Exception {
+        verifyRelationMetrics(
+            calls, minutesAgo, ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS,
+            ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS
+        );
+    }
+
+    private void verifyServiceRelationMetrics(List<Call> calls, final LocalDateTime minutesAgo) throws Exception {
+        verifyRelationMetrics(
+            calls, minutesAgo, ALL_SERVICE_RELATION_CLIENT_METRICS, ALL_SERVICE_RELATION_SERVER_METRICS);
+    }
+
+    private void verifyRelationMetrics(List<Call> calls, final LocalDateTime minutesAgo, String[] relationClientMetrics,
+                                       String[] relationServerMetrics) throws Exception {
+        for (Call call : calls) {
+            for (String detectPoint : call.getDetectPoints()) {
+                switch (detectPoint) {
+                    case "CLIENT": {
+                        for (String metricName : relationClientMetrics) {
+                            verifyMetrics(queryClient, metricName, call.getId(), minutesAgo);
+                        }
+                        break;
+                    }
+                    case "SERVER": {
+                        for (String metricName : relationServerMetrics) {
+                            verifyMetrics(queryClient, metricName, call.getId(), minutesAgo);
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    private void doRetryableVerification(Runnable runnable) throws InterruptedException {
+        while (true) {
+            try {
+                runnable.run();
+                break;
+            } catch (Throwable ignored) {
+                Thread.sleep(retryInterval);
+            }
+        }
+    }
+}
diff --git a/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.endpoints.yml b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.endpoints.yml
new file mode 100644
index 0000000..a1f5b45
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.endpoints.yml
@@ -0,0 +1,27 @@
+# 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.
+
+# 1 health-check by docker-maven-plugin
+# 1 drop table if exists, because we have `ddl-auto: create-drop`
+# 1 drop sequence
+# 1 create sequence
+# 1 create table statement
+
+endpoints:
+  - key: not null
+    label: /e2e/health-check
+  - key: not null
+    label: /e2e/users
diff --git a/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.instances.yml b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.instances.yml
new file mode 100644
index 0000000..26bb314
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.instances.yml
@@ -0,0 +1,34 @@
+# 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.
+
+# 1 health-check by docker-maven-plugin
+# 1 drop table if exists, because we have `ddl-auto: create-drop`
+# 1 drop sequence
+# 1 create sequence
+# 1 create table statement
+
+instances:
+  - key: 2
+    label: not null
+    attributes:
+      - name: os_name
+        value: not null
+      - name: host_name
+        value: not null
+      - name: process_no
+        value: gt 0
+      - name: ipv4s
+        value: not null
diff --git a/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.serviceInstanceTopo.yml b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.serviceInstanceTopo.yml
new file mode 100644
index 0000000..d312bd8
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.serviceInstanceTopo.yml
@@ -0,0 +1,41 @@
+# 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.
+
+# 1 health-check by docker-maven-plugin
+# 1 drop table if exists, because we have `ddl-auto: create-drop`
+# 1 drop sequence
+# 1 create sequence
+# 1 create table statement
+
+nodes:
+  - id: 1
+    name: User
+    type: USER
+    serviceId: 1
+    serviceName: User
+    isReal: false
+  - id: 2
+    name: not null
+    serviceId: 2
+    serviceName: Your_ApplicationName
+    type: Tomcat
+    isReal: true
+calls:
+  - id: 1_2
+    source: 1
+    detectPoints:
+      - SERVER
+    target: 2
diff --git a/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.services.yml b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.services.yml
new file mode 100644
index 0000000..07ff835
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.services.yml
@@ -0,0 +1,25 @@
+# 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.
+
+# 1 health-check by docker-maven-plugin
+# 1 drop table if exists, because we have `ddl-auto: create-drop`
+# 1 drop sequence
+# 1 create sequence
+# 1 create table statement
+
+services:
+  - key: 2
+    label: "Your_ApplicationName"
diff --git a/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.topo.yml b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.topo.yml
new file mode 100644
index 0000000..3a455f5
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.topo.yml
@@ -0,0 +1,46 @@
+# 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.
+
+# 1 health-check by docker-maven-plugin
+# 1 drop table if exists, because we have `ddl-auto: create-drop`
+# 1 drop sequence
+# 1 create sequence
+# 1 create table statement
+
+nodes:
+  - id: 1
+    name: User
+    type: USER
+    isReal: false
+  - id: 2
+    name: Your_ApplicationName
+    type: Tomcat
+    isReal: true
+  - id: 3
+    name: "localhost:-1"
+    type: H2
+    isReal: false
+calls:
+  - id: 2_3
+    source: 2
+    detectPoints:
+      - CLIENT
+    target: 3
+  - id: 1_2
+    source: 1
+    detectPoints:
+      - SERVER
+    target: 2
diff --git a/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.traces.yml b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.traces.yml
new file mode 100644
index 0000000..2052aad
--- /dev/null
+++ b/test/e2e/e2e-ssl/src/test/resources/expected-data/org.apache.skywalking.e2e.SampleVerificationITCase.traces.yml
@@ -0,0 +1,31 @@
+# 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.
+
+# 1 health-check by docker-maven-plugin
+# 1 drop table if exists, because we have `ddl-auto: create-drop`
+# 1 drop sequence
+# 1 create sequence
+# 1 create table statement
+
+traces:
+  - key: not null
+    endpointNames:
+      - /e2e/users
+    duration: ge 0
+    start: gt 0
+    isError: false
+    traceIds:
+      - not null
diff --git a/test/e2e/pom.xml b/test/e2e/pom.xml
index 31790ae..1d37b35 100644
--- a/test/e2e/pom.xml
+++ b/test/e2e/pom.xml
@@ -45,6 +45,7 @@
         <module>e2e-profile</module>
         <module>e2e-protocol</module>
         <module>e2e-http-api-with-nginx-lua</module>
+        <module>e2e-ssl</module>
     </modules>
 
     <properties>
diff --git a/tools/dependencies/known-oap-backend-dependencies-es7.txt b/tools/dependencies/known-oap-backend-dependencies-es7.txt
index 2f20ac2..49f2780 100755
--- a/tools/dependencies/known-oap-backend-dependencies-es7.txt
+++ b/tools/dependencies/known-oap-backend-dependencies-es7.txt
@@ -131,7 +131,7 @@ netty-handler-4.1.42.Final.jar
 netty-handler-proxy-4.1.42.Final.jar
 netty-resolver-4.1.42.Final.jar
 netty-resolver-dns-4.1.42.Final.jar
-netty-tcnative-boringssl-static-2.0.7.Final.jar
+netty-tcnative-boringssl-static-2.0.26.Final.jar
 netty-transport-4.1.42.Final.jar
 okhttp-2.7.5.jar
 okhttp-3.9.0.jar
diff --git a/tools/dependencies/known-oap-backend-dependencies.txt b/tools/dependencies/known-oap-backend-dependencies.txt
index 8b9e854..68db51a 100755
--- a/tools/dependencies/known-oap-backend-dependencies.txt
+++ b/tools/dependencies/known-oap-backend-dependencies.txt
@@ -129,7 +129,7 @@ netty-handler-4.1.42.Final.jar
 netty-handler-proxy-4.1.42.Final.jar
 netty-resolver-4.1.42.Final.jar
 netty-resolver-dns-4.1.42.Final.jar
-netty-tcnative-boringssl-static-2.0.7.Final.jar
+netty-tcnative-boringssl-static-2.0.26.Final.jar
 netty-transport-4.1.42.Final.jar
 okhttp-2.7.5.jar
 okhttp-3.9.0.jar