use of com.linkedin.r2.transport.http.client.common.ssl.SslSessionValidator in project rest.li by linkedin.
the class SimpleLoadBalancerStateTest method testGetClientWithSSLValidation.
@Test(groups = { "small", "back-end" })
public void testGetClientWithSSLValidation() throws URISyntaxException {
reset(true, true);
URI uri = URI.create("https://cluster-1/test");
List<String> schemes = new ArrayList<>();
Map<Integer, PartitionData> partitionData = new HashMap<>(1);
partitionData.put(DefaultPartitionAccessor.DEFAULT_PARTITION_ID, new PartitionData(1d));
Map<URI, Map<Integer, PartitionData>> uriData = new HashMap<>();
uriData.put(uri, partitionData);
schemes.add("https");
// set up state
_state.listenToCluster("cluster-1", new NullStateListenerCallback());
_state.listenToService("service-1", new NullStateListenerCallback());
Map<String, Object> transportClientProperties = new HashMap<>();
transportClientProperties.put(HttpClientFactory.HTTP_SSL_CONTEXT, _sslContext);
transportClientProperties.put(HttpClientFactory.HTTP_SSL_PARAMS, _sslParameters);
transportClientProperties = Collections.unmodifiableMap(transportClientProperties);
final List<String> sslValidationList = Arrays.asList("validation1", "validation2");
_clusterRegistry.put("cluster-1", new ClusterProperties("cluster-1", Collections.emptyList(), Collections.emptyMap(), Collections.emptySet(), NullPartitionProperties.getInstance(), sslValidationList, (Map<String, Object>) null, false));
_serviceRegistry.put("service-1", new ServiceProperties("service-1", "cluster-1", "/test", Arrays.asList("random"), Collections.<String, Object>emptyMap(), transportClientProperties, null, schemes, null));
_uriRegistry.put("cluster-1", new UriProperties("cluster-1", uriData));
TrackerClient client = _state.getClient("service-1", uri);
assertNotNull(client);
assertEquals(client.getUri(), uri);
RequestContext requestContext = new RequestContext();
client.restRequest(new RestRequestBuilder(URI.create("http://cluster-1/test")).build(), requestContext, new HashMap<>(), response -> {
});
@SuppressWarnings("unchecked") final SslSessionValidator validator = (SslSessionValidator) requestContext.getLocalAttr(R2Constants.REQUESTED_SSL_SESSION_VALIDATOR);
assertNotNull(validator);
}
use of com.linkedin.r2.transport.http.client.common.ssl.SslSessionValidator in project rest.li by linkedin.
the class HttpNettyClient method doWriteRequest.
@Override
protected void doWriteRequest(RestRequest request, RequestContext requestContext, SocketAddress address, Map<String, String> wireAttrs, final TimeoutTransportCallback<RestResponse> callback, long requestTimeout) {
final RestRequest newRequest = new RestRequestBuilder(request).overwriteHeaders(WireAttributeHelper.toWireAttributes(wireAttrs)).build();
requestContext.putLocalAttr(R2Constants.HTTP_PROTOCOL_VERSION, HttpProtocolVersion.HTTP_1_1);
final AsyncPool<Channel> pool;
try {
pool = getChannelPoolManagerPerRequest(request).getPoolForAddress(address);
} catch (IllegalStateException e) {
errorResponse(callback, e);
return;
}
final Cancellable pendingGet = pool.get(new Callback<Channel>() {
@Override
public void onSuccess(final Channel channel) {
// This handler ensures the channel is returned to the pool at the end of the
// Netty pipeline.
channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).set(pool);
callback.addTimeoutTask(() -> {
AsyncPool<Channel> pool1 = channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).getAndSet(null);
if (pool1 != null) {
pool1.dispose(channel);
}
});
TransportCallback<RestResponse> sslTimingCallback = SslHandshakeTimingHandler.getSslTimingCallback(channel, requestContext, callback);
// This handler invokes the callback with the response once it arrives.
channel.attr(RAPResponseHandler.CALLBACK_ATTR_KEY).set(sslTimingCallback);
// Set the session validator requested by the user
SslSessionValidator sslSessionValidator = (SslSessionValidator) requestContext.getLocalAttr(R2Constants.REQUESTED_SSL_SESSION_VALIDATOR);
channel.attr(NettyChannelAttributes.SSL_SESSION_VALIDATOR).set(sslSessionValidator);
final NettyClientState state = _state.get();
if (state == NettyClientState.REQUESTS_STOPPING || state == NettyClientState.SHUTDOWN) {
// In this case, we acquired a channel from the pool as request processing is halting.
// The shutdown task might not timeout this callback, since it may already have scanned
// all the channels for pending requests before we set the callback as the channel
// attachment. The TimeoutTransportCallback ensures the user callback in never
// invoked more than once, so it is safe to invoke it unconditionally.
errorResponse(sslTimingCallback, new TimeoutException("Operation did not complete before shutdown"));
// The channel is usually release in two places: timeout or in the netty pipeline.
// Since we call the callback above, the timeout associated will be never invoked. On top of that
// we never send the request to the pipeline (due to the return statement), and nobody is releasing the channel
// until the channel is forcefully closed by the shutdownTimeout. Therefore we have to release it here
AsyncPool<Channel> pool = channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).getAndSet(null);
if (pool != null) {
pool.put(channel);
}
return;
}
// here we want the exception in outbound operations to be passed back through pipeline so that
// the user callback would be invoked with the exception and the channel can be put back into the pool
channel.writeAndFlush(newRequest).addListener(new ErrorChannelFutureListener());
}
@Override
public void onError(Throwable e) {
errorResponse(callback, e);
}
});
if (pendingGet != null) {
callback.addTimeoutTask(pendingGet::cancel);
}
}
use of com.linkedin.r2.transport.http.client.common.ssl.SslSessionValidator in project rest.li by linkedin.
the class TestHttpsCheckCertificate method testHttpsEchoWithSessionValidator.
private void testHttpsEchoWithSessionValidator(SslSessionValidator sslSessionValidator) throws Exception {
final RestEchoClient client = getEchoClient(_client, Bootstrap.getEchoURI());
final String msg = "This is a simple echo message";
final FutureCallback<String> callback = new FutureCallback<>();
RequestContext requestContext = new RequestContext();
requestContext.putLocalAttr(R2Constants.REQUESTED_SSL_SESSION_VALIDATOR, sslSessionValidator);
client.echo(msg, requestContext, callback);
String actual = callback.get(20, TimeUnit.SECONDS);
Assert.assertEquals(actual, msg);
}
use of com.linkedin.r2.transport.http.client.common.ssl.SslSessionValidator in project rest.li by linkedin.
the class CertificateHandler method write.
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
_sslHandler.handshakeFuture().addListener(future -> {
// SSLValidation, nor send anything on the channel
if (!future.isSuccess()) {
return;
}
SslSessionValidator sslSessionValidator = ctx.channel().attr(NettyChannelAttributes.SSL_SESSION_VALIDATOR).getAndSet(null);
// Also if sslSessionValidator is the same as the previous one we cached, skipping the check.
if (sslSessionValidator != null && !sslSessionValidator.equals(_cachedSessionValidator)) {
_cachedSessionValidator = sslSessionValidator;
try {
sslSessionValidator.validatePeerSession(_sslHandler.engine().getSession());
} catch (SslSessionNotTrustedException e) {
ctx.fireExceptionCaught(e);
return;
}
}
ctx.write(msg, promise);
});
}
Aggregations