Skip to content

Commit 3511016

Browse files
authored
Merge pull request #476 from TharmiganK/ssl-context
Initialise SSL context in the client initialisation
2 parents f794bf9 + 2f08735 commit 3511016

28 files changed

+266
-83
lines changed

components/org.wso2.transport.http.netty/src/main/java/org/wso2/transport/http/netty/contract/HttpClientConnector.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,11 @@ public interface HttpClientConnector {
9393
* @return returns the status of the asynchronous push response fetch action
9494
*/
9595
HttpResponseFuture getPushResponse(Http2PushPromise pushPromise);
96+
97+
/**
98+
* Initialize the SSL context.
99+
*
100+
* @throws Exception if an error occurs while initializing the SSL context.
101+
*/
102+
void initializeSSLContext() throws Exception;
96103
}

components/org.wso2.transport.http.netty/src/main/java/org/wso2/transport/http/netty/contract/HttpWsConnectorFactory.java

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ ServerConnector createServerConnector(ServerBootstrapConfiguration serverBootstr
5353
HttpClientConnector createHttpClientConnector(Map<String, Object> transportProperties,
5454
SenderConfiguration senderConfiguration);
5555

56+
/**
57+
* This method can be used to get http client connectors with SSL context initialized.
58+
*
59+
* @param transportProperties configTargetHandler stuff like global timeout, number of outbound connections, etc.
60+
* @param senderConfiguration contains SSL configuration and endpoint details.
61+
* @throws Exception if the connector creation fails.
62+
* @return HttpClientConnector.
63+
*/
64+
HttpClientConnector createHttpsClientConnector(Map<String, Object> transportProperties,
65+
SenderConfiguration senderConfiguration) throws Exception;
66+
5667
/**
5768
* Creates a client connector with a given connection manager.
5869
*
@@ -62,7 +73,21 @@ HttpClientConnector createHttpClientConnector(Map<String, Object> transportPrope
6273
* @return the HttpClientConnector
6374
*/
6475
HttpClientConnector createHttpClientConnector(Map<String, Object> transportProperties,
65-
SenderConfiguration senderConfiguration, ConnectionManager connectionManager);
76+
SenderConfiguration senderConfiguration,
77+
ConnectionManager connectionManager);
78+
79+
/**
80+
* Creates a client connector with a given connection manager and SSL context.
81+
*
82+
* @param transportProperties Represents the configurations related to HTTP client
83+
* @param senderConfiguration Represents the configurations related to client channel creation
84+
* @param connectionManager Manages the client pool
85+
* @throws Exception if the connector creation fails.
86+
* @return the HttpClientConnector
87+
*/
88+
HttpClientConnector createHttpsClientConnector(Map<String, Object> transportProperties,
89+
SenderConfiguration senderConfiguration,
90+
ConnectionManager connectionManager) throws Exception;
6691

6792
/**
6893
* Creates a client connector with given client bootstrap configuration and connection manager.
@@ -76,6 +101,19 @@ HttpClientConnector createHttpClientConnector(BootstrapConfiguration bootstrapCo
76101
SenderConfiguration senderConfiguration,
77102
ConnectionManager connectionManager);
78103

104+
/**
105+
* Creates a client connector with given client bootstrap configuration, connection manager and SSL context.
106+
*
107+
* @param bootstrapConfiguration Represents the client bootstrap configurations.
108+
* @param senderConfiguration Represents the configurations related to client channel creation
109+
* @param connectionManager Manages the client pool
110+
* @throws Exception if the connector creation fails.
111+
* @return the HttpClientConnector
112+
*/
113+
HttpClientConnector createHttpsClientConnector(BootstrapConfiguration bootstrapConfiguration,
114+
SenderConfiguration senderConfiguration,
115+
ConnectionManager connectionManager) throws Exception;
116+
79117
/**
80118
* This method is used to get WebSocket client connector.
81119
*
@@ -84,6 +122,17 @@ HttpClientConnector createHttpClientConnector(BootstrapConfiguration bootstrapCo
84122
*/
85123
WebSocketClientConnector createWsClientConnector(WebSocketClientConnectorConfig clientConnectorConfig);
86124

125+
126+
/**
127+
* This method is used to get WebSocket client connector with SSL context initialized.
128+
*
129+
* @param clientConnectorConfig Properties to create a client connector.
130+
* @throws Exception if the connector creation fails.
131+
* @return WebSocketClientConnector.
132+
*/
133+
WebSocketClientConnector createWsClientConnectorWithSSL(WebSocketClientConnectorConfig clientConnectorConfig)
134+
throws Exception;
135+
87136
/**
88137
* Shutdown all the server channels and the accepted channels. It also shutdown all the eventloop groups.
89138
* @throws InterruptedException when interrupted by some other event

components/org.wso2.transport.http.netty/src/main/java/org/wso2/transport/http/netty/contract/websocket/WebSocketClientConnector.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,11 @@ public interface WebSocketClientConnector {
3030
* @return ClientHandshakeFuture for the newly created connection.
3131
*/
3232
ClientHandshakeFuture connect();
33+
34+
/**
35+
* Initialize the SSL context.
36+
*
37+
* @throws Exception if an error occurs while initializing the SSL context.
38+
*/
39+
void initializeSSLContext() throws Exception;
3340
}

components/org.wso2.transport.http.netty/src/main/java/org/wso2/transport/http/netty/contractimpl/DefaultHttpClientConnector.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import java.io.IOException;
5959
import java.net.InetSocketAddress;
6060
import java.util.NoSuchElementException;
61+
import java.util.Objects;
6162

6263
import static org.wso2.transport.http.netty.contract.Constants.REMOTE_SERVER_CLOSED_BEFORE_INITIATING_OUTBOUND_REQUEST;
6364

@@ -363,4 +364,10 @@ private void initTargetChannelProperties(SenderConfiguration senderConfiguration
363364
this.sslConfig = senderConfiguration.getClientSSLConfig();
364365
this.forwardedExtensionConfig = senderConfiguration.getForwardedExtensionConfig();
365366
}
367+
368+
public void initializeSSLContext() throws Exception {
369+
if (Objects.nonNull(sslConfig)) {
370+
sslConfig.initializeSSLContext(isHttp2);
371+
}
372+
}
366373
}

components/org.wso2.transport.http.netty/src/main/java/org/wso2/transport/http/netty/contractimpl/DefaultHttpWsConnectorFactory.java

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,26 +147,66 @@ public HttpClientConnector createHttpClientConnector(
147147
}
148148

149149
@Override
150-
public HttpClientConnector createHttpClientConnector(
151-
Map<String, Object> transportProperties, SenderConfiguration senderConfiguration,
152-
ConnectionManager connectionManager) {
150+
public HttpClientConnector createHttpsClientConnector(Map<String, Object> transportProperties,
151+
SenderConfiguration senderConfiguration) throws Exception {
152+
BootstrapConfiguration bootstrapConfig = new BootstrapConfiguration(transportProperties);
153+
ConnectionManager connectionManager = new ConnectionManager(senderConfiguration.getPoolConfiguration());
154+
HttpClientConnector httpClientConnector = new DefaultHttpClientConnector(connectionManager,
155+
senderConfiguration, bootstrapConfig, clientGroup);
156+
httpClientConnector.initializeSSLContext();
157+
return httpClientConnector;
158+
}
159+
160+
@Override
161+
public HttpClientConnector createHttpClientConnector(Map<String, Object> transportProperties,
162+
SenderConfiguration senderConfiguration,
163+
ConnectionManager connectionManager) {
153164
BootstrapConfiguration bootstrapConfig = new BootstrapConfiguration(transportProperties);
154165
return new DefaultHttpClientConnector(connectionManager, senderConfiguration, bootstrapConfig, clientGroup);
155166
}
156167

168+
@Override
169+
public HttpClientConnector createHttpsClientConnector(Map<String, Object> transportProperties,
170+
SenderConfiguration senderConfiguration,
171+
ConnectionManager connectionManager) throws Exception {
172+
BootstrapConfiguration bootstrapConfig = new BootstrapConfiguration(transportProperties);
173+
HttpClientConnector httpClientConnector = new DefaultHttpClientConnector(connectionManager,
174+
senderConfiguration, bootstrapConfig, clientGroup);
175+
httpClientConnector.initializeSSLContext();
176+
return httpClientConnector;
177+
}
178+
157179
@Override
158180
public HttpClientConnector createHttpClientConnector(BootstrapConfiguration bootstrapConfig,
159181
SenderConfiguration senderConfiguration,
160182
ConnectionManager connectionManager) {
161-
162183
return new DefaultHttpClientConnector(connectionManager, senderConfiguration, bootstrapConfig, clientGroup);
163184
}
164185

186+
@Override
187+
public HttpClientConnector createHttpsClientConnector(BootstrapConfiguration bootstrapConfig,
188+
SenderConfiguration senderConfiguration,
189+
ConnectionManager connectionManager) throws Exception {
190+
HttpClientConnector httpClientConnector = new DefaultHttpClientConnector(connectionManager,
191+
senderConfiguration, bootstrapConfig, clientGroup);
192+
httpClientConnector.initializeSSLContext();
193+
return httpClientConnector;
194+
}
195+
165196
@Override
166197
public WebSocketClientConnector createWsClientConnector(WebSocketClientConnectorConfig clientConnectorConfig) {
167198
return new DefaultWebSocketClientConnector(clientConnectorConfig, clientGroup);
168199
}
169200

201+
@Override
202+
public WebSocketClientConnector createWsClientConnectorWithSSL(
203+
WebSocketClientConnectorConfig clientConnectorConfig) throws Exception {
204+
WebSocketClientConnector webSocketClientConnector = new DefaultWebSocketClientConnector(clientConnectorConfig,
205+
clientGroup);
206+
webSocketClientConnector.initializeSSLContext();
207+
return webSocketClientConnector;
208+
}
209+
170210
@Override
171211
public void shutdown() throws InterruptedException {
172212
allChannels.close().sync();

components/org.wso2.transport.http.netty/src/main/java/org/wso2/transport/http/netty/contractimpl/common/Util.java

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -359,19 +359,16 @@ public static boolean shouldEnforceChunkingforHttpOneZero(ChunkConfig chunkConfi
359359
* @param host host of the connection
360360
* @param port port of the connection
361361
* @return the {@link SSLEngine} which enables secure communication
362-
* @throws SSLException if any error occurs in the SSL connection
363362
*/
364363
public static SSLEngine configureHttpPipelineForSSL(SocketChannel socketChannel, String host, int port,
365-
SSLConfig sslConfig) throws SSLException {
364+
SSLConfig sslConfig) {
366365
LOG.debug("adding ssl handler");
367366
SSLEngine sslEngine = null;
368367
SslHandler sslHandler;
369368
ChannelPipeline pipeline = socketChannel.pipeline();
370-
SSLHandlerFactory sslHandlerFactory = new SSLHandlerFactory(sslConfig);
371369
if (sslConfig.isOcspStaplingEnabled()) {
372-
sslHandlerFactory.createSSLContextFromKeystores(false);
373-
ReferenceCountedOpenSslContext referenceCountedOpenSslContext = sslHandlerFactory
374-
.buildClientReferenceCountedOpenSslContext();
370+
ReferenceCountedOpenSslContext referenceCountedOpenSslContext =
371+
sslConfig.getReferenceCountedOpenSslContext();
375372

376373
if (referenceCountedOpenSslContext != null) {
377374
sslHandler = referenceCountedOpenSslContext.newHandler(socketChannel.alloc());
@@ -382,14 +379,12 @@ public static SSLEngine configureHttpPipelineForSSL(SocketChannel socketChannel,
382379
}
383380
} else {
384381
if (sslConfig.isDisableSsl()) {
385-
sslEngine = createInsecureSslEngine(socketChannel, host, port);
382+
sslEngine = createInsecureSslEngine(socketChannel, host, port, sslConfig.getSslContext());
386383
} else {
387384
if (sslConfig.getTrustStore() != null) {
388-
sslHandlerFactory.createSSLContextFromKeystores(false);
389-
sslEngine = instantiateAndConfigSSL(sslConfig, host, port,
390-
sslConfig.isHostNameVerificationEnabled(), sslHandlerFactory);
385+
sslEngine = instantiateAndConfigSSL(sslConfig, host, port);
391386
} else {
392-
sslEngine = getSslEngineForCerts(socketChannel, host, port, sslConfig, sslHandlerFactory);
387+
sslEngine = getSslEngineForCerts(socketChannel, host, port, sslConfig);
393388
}
394389
}
395390
sslHandler = new SslHandler(sslEngine);
@@ -404,8 +399,9 @@ public static SSLEngine configureHttpPipelineForSSL(SocketChannel socketChannel,
404399
}
405400

406401
private static SSLEngine getSslEngineForCerts(SocketChannel socketChannel, String host, int port,
407-
SSLConfig sslConfig, SSLHandlerFactory sslHandlerFactory) throws SSLException {
408-
SslContext sslContext = sslHandlerFactory.createHttpTLSContextForClient();
402+
SSLConfig sslConfig) {
403+
SSLHandlerFactory sslHandlerFactory = sslConfig.getSslHandlerFactory();
404+
SslContext sslContext = sslConfig.getSslContext();
409405
SslHandler sslHandler = sslContext.newHandler(socketChannel.alloc(), host, port);
410406
SSLEngine sslEngine = sslHandler.engine();
411407
sslHandlerFactory.addCommonConfigs(sslEngine);
@@ -416,10 +412,8 @@ private static SSLEngine getSslEngineForCerts(SocketChannel socketChannel, Strin
416412
return sslEngine;
417413
}
418414

419-
private static SSLEngine createInsecureSslEngine(SocketChannel socketChannel, String host, int port)
420-
throws SSLException {
421-
SslContext sslContext = SslContextBuilder.forClient().sslProvider(SslProvider.JDK)
422-
.trustManager(InsecureTrustManagerFactory.INSTANCE).build();
415+
private static SSLEngine createInsecureSslEngine(SocketChannel socketChannel, String host, int port,
416+
SslContext sslContext) {
423417
SslHandler sslHandler = sslContext.newHandler(socketChannel.alloc(), host, port);
424418
return sslHandler.engine();
425419
}
@@ -447,21 +441,17 @@ public static SslContext createInsecureSslEngineForHttp2() throws SSLException {
447441
* @param sslConfig ssl related configurations
448442
* @param host host of the connection
449443
* @param port port of the connection
450-
* @param hostNameVerificationEnabled true if host name verification is enabled
451-
* @param sslHandlerFactory an instance of sslHandlerFactory
452444
* @return ssl engine
453445
*/
454-
private static SSLEngine instantiateAndConfigSSL(SSLConfig sslConfig, String host, int port,
455-
boolean hostNameVerificationEnabled, SSLHandlerFactory sslHandlerFactory) {
446+
private static SSLEngine instantiateAndConfigSSL(SSLConfig sslConfig, String host, int port) {
456447
// set the pipeline factory, which creates the pipeline for each newly created channels
457-
SSLEngine sslEngine = null;
458-
if (sslConfig != null) {
459-
sslEngine = sslHandlerFactory.buildClientSSLEngine(host, port);
460-
sslEngine.setUseClientMode(true);
461-
sslHandlerFactory.setSNIServerNames(sslEngine, host);
462-
if (hostNameVerificationEnabled) {
463-
sslHandlerFactory.setHostNameVerfication(sslEngine);
464-
}
448+
SSLHandlerFactory sslHandlerFactory = sslConfig.getSslHandlerFactory();
449+
boolean hostNameVerificationEnabled = sslConfig.isHostNameVerificationEnabled();
450+
SSLEngine sslEngine = sslHandlerFactory.buildClientSSLEngine(host, port);
451+
sslEngine.setUseClientMode(true);
452+
sslHandlerFactory.setSNIServerNames(sslEngine, host);
453+
if (hostNameVerificationEnabled) {
454+
sslHandlerFactory.setHostNameVerfication(sslEngine);
465455
}
466456
return sslEngine;
467457
}

components/org.wso2.transport.http.netty/src/main/java/org/wso2/transport/http/netty/contractimpl/common/ssl/SSLConfig.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,17 @@
1818
*/
1919
package org.wso2.transport.http.netty.contractimpl.common.ssl;
2020

21+
import io.netty.handler.ssl.ReferenceCountedOpenSslContext;
22+
import io.netty.handler.ssl.SslContext;
23+
import io.netty.handler.ssl.SslContextBuilder;
24+
import io.netty.handler.ssl.SslProvider;
25+
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
2126
import org.slf4j.Logger;
2227
import org.slf4j.LoggerFactory;
28+
import org.wso2.transport.http.netty.contractimpl.common.Util;
2329

2430
import java.io.File;
31+
import java.util.Objects;
2532

2633
/**
2734
* A class that encapsulates SSLContext configuration.
@@ -65,6 +72,9 @@ public class SSLConfig {
6572
private long handshakeTimeOut;
6673
private boolean disableSsl = false;
6774
private boolean useJavaDefaults = false;
75+
private ReferenceCountedOpenSslContext referenceCountedOpenSslContext;
76+
private SslContext sslContext;
77+
private SSLHandlerFactory sslHandlerFactory;
6878

6979
public SSLConfig() {}
7080

@@ -353,4 +363,62 @@ public boolean useJavaDefaults() {
353363
public void setUseJavaDefaults() {
354364
this.useJavaDefaults = true;
355365
}
366+
367+
public SslContext getSslContext() {
368+
return sslContext;
369+
}
370+
371+
public ReferenceCountedOpenSslContext getReferenceCountedOpenSslContext() {
372+
return referenceCountedOpenSslContext;
373+
}
374+
375+
public SSLHandlerFactory getSslHandlerFactory() {
376+
return sslHandlerFactory;
377+
}
378+
379+
public void initializeSSLContext(boolean isHttp2) throws Exception {
380+
if (isHttp2) {
381+
initializeSSLContextForHTTP2();
382+
} else {
383+
initializeSSLContextForHTTP();
384+
}
385+
}
386+
387+
private void initializeSSLContextForHTTP() throws Exception {
388+
sslHandlerFactory = new SSLHandlerFactory(this);
389+
if (isOcspStaplingEnabled()) {
390+
sslHandlerFactory.createSSLContextFromKeystores(false);
391+
referenceCountedOpenSslContext = sslHandlerFactory.buildClientReferenceCountedOpenSslContext();
392+
} else {
393+
if (disableSsl) {
394+
sslContext = SslContextBuilder.forClient()
395+
.sslProvider(SslProvider.JDK)
396+
.trustManager(InsecureTrustManagerFactory.INSTANCE)
397+
.build();
398+
} else {
399+
if (getTrustStore() != null) {
400+
sslHandlerFactory.createSSLContextFromKeystores(false);
401+
} else {
402+
sslContext = sslHandlerFactory.createHttpTLSContextForClient();
403+
}
404+
}
405+
}
406+
}
407+
408+
private void initializeSSLContextForHTTP2() throws Exception {
409+
sslHandlerFactory = new SSLHandlerFactory(this);
410+
if (isOcspStaplingEnabled()) {
411+
referenceCountedOpenSslContext = (ReferenceCountedOpenSslContext) sslHandlerFactory
412+
.createHttp2TLSContextForClient(isOcspStaplingEnabled());
413+
} else if (isDisableSsl()) {
414+
sslContext = Util.createInsecureSslEngineForHttp2();
415+
} else {
416+
sslHandlerFactory.createSSLContextFromKeystores(false);
417+
sslContext = sslHandlerFactory.createHttp2TLSContextForClient(false);
418+
}
419+
}
420+
421+
public boolean hasSslCtxInitialized() {
422+
return Objects.nonNull(sslHandlerFactory);
423+
}
356424
}

0 commit comments

Comments
 (0)