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>