/** * Tests opening an SSL/TLS connection to redis using the loopback address of 127.0.0.1. This test * should fail because "127.0.0.1" does not match the certificate subject common name and there * are no subject alternative names in the certificate. * * <p>NOTE: This test relies on a feature that is only available as of Java 7 and later. It is * commented out but not removed in case support for Java 6 is dropped or we find a way to have * the CI run a specific set of tests on Java 7 and above. */ @Test public void connectWithShardInfoByIpAddress() throws Exception { final URI uri = URI.create("rediss://127.0.0.1:6390"); final SSLSocketFactory sslSocketFactory = createTrustStoreSslSocketFactory(); // These SSL parameters ensure that we use the same hostname verifier used // for HTTPS. // Note: this options is only available in Java 7. final SSLParameters sslParameters = new SSLParameters(); sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); JedisShardInfo shardInfo = new JedisShardInfo(uri, sslSocketFactory, sslParameters, null); shardInfo.setPassword("foobared"); Jedis jedis = new Jedis(shardInfo); try { jedis.get("foo"); Assert.fail("The code did not throw the expected JedisConnectionException."); } catch (JedisConnectionException e) { Assert.assertEquals( "Unexpected first inner exception.", SSLHandshakeException.class, e.getCause().getClass()); Assert.assertEquals( "Unexpected second inner exception.", CertificateException.class, e.getCause().getCause().getClass()); } try { jedis.close(); } catch (Throwable e1) { // Expected. } }
/** * Tests opening an SSL/TLS connection to redis. NOTE: This test relies on a feature that is only * available as of Java 7 and later. It is commented out but not removed in case support for Java * 6 is dropped or we find a way to have the CI run a specific set of tests on Java 7 and above. */ @Test public void connectWithShardInfo() throws Exception { final URI uri = URI.create("rediss://localhost:6390"); final SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); // These SSL parameters ensure that we use the same hostname verifier used // for HTTPS. // Note: this options is only available in Java 7. final SSLParameters sslParameters = new SSLParameters(); sslParameters.setEndpointIdentificationAlgorithm("HTTPS"); JedisShardInfo shardInfo = new JedisShardInfo(uri, sslSocketFactory, sslParameters, null); shardInfo.setPassword("foobared"); Jedis jedis = new Jedis(shardInfo); jedis.get("foo"); jedis.disconnect(); jedis.close(); }
@Override protected void initChannel(Channel channel) throws Exception { SslContext sslContext; SSLParameters sslParams = new SSLParameters(); if (redisURI.isVerifyPeer()) { sslContext = SslContext.newClientContext(SslProvider.JDK); if (JavaRuntime.AT_LEAST_JDK_7) { sslParams.setEndpointIdentificationAlgorithm("HTTPS"); } } else { sslContext = SslContext.newClientContext(SslProvider.JDK, InsecureTrustManagerFactory.INSTANCE); } SSLEngine sslEngine = sslContext.newEngine(channel.alloc(), redisURI.getHost(), redisURI.getPort()); sslEngine.setSSLParameters(sslParams); removeIfExists(channel.pipeline(), SslHandler.class); if (channel.pipeline().get("first") == null) { channel .pipeline() .addFirst( "first", new ChannelDuplexHandler() { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { eventBus.publish(new ConnectedEvent(local(ctx), remote(ctx))); super.channelActive(ctx); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { eventBus.publish(new DisconnectedEvent(local(ctx), remote(ctx))); super.channelInactive(ctx); } }); } SslHandler sslHandler = new SslHandler(sslEngine, redisURI.isStartTls()); channel.pipeline().addLast(sslHandler); if (channel.pipeline().get("channelActivator") == null) { channel .pipeline() .addLast( "channelActivator", new RedisChannelInitializerImpl() { private Command<?, ?, ?> pingCommand; @Override public Future<Boolean> channelInitialized() { return initializedFuture; } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { initializedFuture = SettableFuture.create(); pingCommand = null; super.channelInactive(ctx); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { if (initializedFuture.isDone()) { super.channelActive(ctx); } } @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof SslHandshakeCompletionEvent && !initializedFuture.isDone()) { SslHandshakeCompletionEvent event = (SslHandshakeCompletionEvent) evt; if (event.isSuccess()) { if (pingBeforeActivate) { pingCommand = INITIALIZING_CMD_BUILDER.ping(); pingBeforeActivate(pingCommand, initializedFuture, ctx, handlers); } else { ctx.fireChannelActive(); } } else { initializedFuture.setException(event.cause()); } } if (evt instanceof ConnectionEvents.Close) { if (ctx.channel().isOpen()) { ctx.channel().close(); } } if (evt instanceof ConnectionEvents.Activated) { if (!initializedFuture.isDone()) { initializedFuture.set(true); eventBus.publish(new ConnectionActivatedEvent(local(ctx), remote(ctx))); } } super.userEventTriggered(ctx, evt); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { if (!initializedFuture.isDone()) { initializedFuture.setException(cause); } super.exceptionCaught(ctx, cause); } }); } for (ChannelHandler handler : handlers) { removeIfExists(channel.pipeline(), handler.getClass()); channel.pipeline().addLast(handler); } }