KNOX-2239 - Websocket use the configured truststore in gateway-site config file (#269)

diff --git a/gateway-server/pom.xml b/gateway-server/pom.xml
index ed3b7d6..5b43d7a 100644
--- a/gateway-server/pom.xml
+++ b/gateway-server/pom.xml
@@ -324,6 +324,16 @@
         </dependency>
 
         <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-client</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty.websocket</groupId>
+            <artifactId>websocket-client</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
         </dependency>
diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/websockets/GatewayWebsocketHandler.java b/gateway-server/src/main/java/org/apache/knox/gateway/websockets/GatewayWebsocketHandler.java
index 8fff20b..0d6d8d2 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/websockets/GatewayWebsocketHandler.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/websockets/GatewayWebsocketHandler.java
@@ -20,11 +20,13 @@
 import org.apache.commons.lang3.StringUtils;
 import org.apache.knox.gateway.config.GatewayConfig;
 import org.apache.knox.gateway.i18n.messages.MessagesFactory;
-import org.apache.knox.gateway.services.ServiceType;
 import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.services.ServiceType;
 import org.apache.knox.gateway.services.registry.ServiceDefEntry;
 import org.apache.knox.gateway.services.registry.ServiceDefinitionRegistry;
 import org.apache.knox.gateway.services.registry.ServiceRegistry;
+import org.apache.knox.gateway.services.security.KeystoreService;
+import org.apache.knox.gateway.services.security.KeystoreServiceException;
 import org.eclipse.jetty.websocket.server.WebSocketHandler;
 import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
 import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
@@ -35,6 +37,7 @@
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URL;
+import java.security.KeyStore;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -80,7 +83,6 @@
     this.config = config;
     this.services = services;
     pool = Executors.newFixedThreadPool(POOL_SIZE);
-
   }
 
   @Override
@@ -118,14 +120,28 @@
       LOG.debugLog("Generated backend URL for websocket connection: " + backendURL);
 
       /* Upgrade happens here */
-      return new ProxyWebSocketAdapter
-              (URI.create(backendURL), pool, getClientEndpointConfig(req), config);
+      final ClientEndpointConfig clientConfig = getClientEndpointConfig(req);
+      clientConfig.getUserProperties().put("org.apache.knox.gateway.websockets.truststore", getTruststore());
+      return new ProxyWebSocketAdapter(URI.create(backendURL), pool, clientConfig, config);
     } catch (final Exception e) {
       LOG.failedCreatingWebSocket(e);
-      throw e;
+      throw new RuntimeException(e);
     }
   }
 
+
+  private KeyStore getTruststore() throws KeystoreServiceException {
+    final KeystoreService ks = this.services
+        .getService(ServiceType.KEYSTORE_SERVICE);
+    KeyStore trustKeystore = null;
+    trustKeystore = ks.getTruststoreForHttpClient();
+    if (trustKeystore == null) {
+      trustKeystore = ks.getKeystoreForGateway();
+    }
+    return trustKeystore;
+  }
+
+
   /**
    * Returns a {@link ClientEndpointConfig} config that contains the headers
    * to be passed to the backend.
diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/websockets/ProxyWebSocketAdapter.java b/gateway-server/src/main/java/org/apache/knox/gateway/websockets/ProxyWebSocketAdapter.java
index 9d5015d..95687ab 100644
--- a/gateway-server/src/main/java/org/apache/knox/gateway/websockets/ProxyWebSocketAdapter.java
+++ b/gateway-server/src/main/java/org/apache/knox/gateway/websockets/ProxyWebSocketAdapter.java
@@ -40,7 +40,7 @@
 import org.eclipse.jetty.websocket.api.Session;
 import org.eclipse.jetty.websocket.api.StatusCode;
 import org.eclipse.jetty.websocket.api.WebSocketAdapter;
-
+import java.security.KeyStore;
 /**
  * Handles outbound/inbound Websocket connections and sessions.
  *
@@ -100,6 +100,23 @@
     container.setAsyncSendTimeout(frontEndSession.getPolicy().getAsyncWriteTimeout());
     container.setDefaultMaxSessionIdleTimeout(frontEndSession.getPolicy().getIdleTimeout());
 
+    KeyStore ks = null;
+    if(clientConfig != null) {
+      ks = (KeyStore) clientConfig.getUserProperties().get("org.apache.knox.gateway.websockets.truststore");
+    }
+
+    /*
+       Currently javax.websocket API has no provisions to configure SSL
+       https://github.com/eclipse-ee4j/websocket-api/issues/210
+       Until that gets fixed we'll have to resort to this.
+    */
+    if(container instanceof org.eclipse.jetty.websocket.jsr356.ClientContainer &&
+        ((org.eclipse.jetty.websocket.jsr356.ClientContainer)container).getClient() != null &&
+        ((org.eclipse.jetty.websocket.jsr356.ClientContainer)container).getClient().getSslContextFactory() != null ) {
+      ((org.eclipse.jetty.websocket.jsr356.ClientContainer)container).getClient().getHttpClient().getSslContextFactory().setTrustStore(ks);
+      LOG.logMessage("Truststore for websocket setup");
+    }
+
     final ProxyInboundClient backendSocket = new ProxyInboundClient(getMessageCallback());
 
     /* build the configuration */
diff --git a/pom.xml b/pom.xml
index a49e717..132a920 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1953,6 +1953,16 @@
 
             <!-- Websocket support -->
             <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-client</artifactId>
+                <version>${jetty.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty.websocket</groupId>
+                <artifactId>websocket-client</artifactId>
+                <version>${jetty.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>javax.websocket</groupId>
                 <artifactId>javax.websocket-api</artifactId>
                 <version>${javax.websocket-api.version}</version>