Fixed - CertificateException while connecting to Azure or AWS Elasticache config endpoint. #1296

pull/1344/head
Nikita 7 years ago
parent 0a49fdb050
commit 9a179e14cd

@ -55,6 +55,7 @@ public class RedisClientConfig {
private boolean keepAlive;
private boolean tcpNoDelay;
private String sslHostname;
private boolean sslEnableEndpointIdentification = true;
private SslProvider sslProvider = SslProvider.JDK;
private URI sslTruststore;
@ -89,8 +90,17 @@ public class RedisClientConfig {
this.sslKeystore = config.sslKeystore;
this.sslKeystorePassword = config.sslKeystorePassword;
this.resolverGroup = config.resolverGroup;
this.sslHostname = config.sslHostname;
}
public String getSslHostname() {
return sslHostname;
}
public RedisClientConfig setSslHostname(String sslHostname) {
this.sslHostname = sslHostname;
return this;
}
public RedisClientConfig setAddress(String host, int port) {
this.address = URIBuilder.create("redis://" + host + ":" + port);
return this;

@ -33,6 +33,7 @@ import org.redisson.client.RedisClient;
import org.redisson.client.RedisClientConfig;
import org.redisson.client.RedisConnection;
import org.redisson.config.SslProvider;
import org.redisson.misc.URIBuilder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
@ -162,7 +163,12 @@ public class RedisChannelInitializer extends ChannelInitializer<Channel> {
}
SslContext sslContext = sslContextBuilder.build();
SSLEngine sslEngine = sslContext.newEngine(ch.alloc(), config.getAddress().getHost(), config.getAddress().getPort());
String hostname = config.getSslHostname();
if (hostname == null || URIBuilder.isValidIP(hostname)) {
hostname = config.getAddress().getHost();
}
SSLEngine sslEngine = sslContext.newEngine(ch.alloc(), hostname, config.getAddress().getPort());
sslEngine.setSSLParameters(sslParams);
SslHandler sslHandler = new SslHandler(sslEngine);

@ -82,6 +82,8 @@ public class ClusterConnectionManager extends MasterSlaveConnectionManager {
private RedisStrictCommand<List<ClusterNodeInfo>> clusterNodesCommand;
private String configEndpointHostName;
private boolean isConfigEndpoint;
private AddressResolver<InetSocketAddress> resolver;
@ -95,7 +97,7 @@ public class ClusterConnectionManager extends MasterSlaveConnectionManager {
Throwable lastException = null;
List<String> failedMasters = new ArrayList<String>();
for (URI addr : cfg.getNodeAddresses()) {
RFuture<RedisConnection> connectionFuture = connectToNode(cfg, addr, null);
RFuture<RedisConnection> connectionFuture = connectToNode(cfg, addr, null, addr.getHost());
try {
RedisConnection connection = connectionFuture.syncUninterruptibly().getNow();
@ -104,6 +106,7 @@ public class ClusterConnectionManager extends MasterSlaveConnectionManager {
Future<List<InetSocketAddress>> addrsFuture = resolver.resolveAll(InetSocketAddress.createUnresolved(addr.getHost(), addr.getPort()));
List<InetSocketAddress> allAddrs = addrsFuture.syncUninterruptibly().getNow();
if (allAddrs.size() > 1) {
configEndpointHostName = addr.getHost();
isConfigEndpoint = true;
} else {
resolver.close();
@ -178,8 +181,8 @@ public class ClusterConnectionManager extends MasterSlaveConnectionManager {
}
@Override
protected RedisClientConfig createRedisConfig(NodeType type, URI address, int timeout, int commandTimeout) {
RedisClientConfig result = super.createRedisConfig(type, address, timeout, commandTimeout);
protected RedisClientConfig createRedisConfig(NodeType type, URI address, int timeout, int commandTimeout, String sslHostname) {
RedisClientConfig result = super.createRedisConfig(type, address, timeout, commandTimeout, sslHostname);
result.setReadOnly(type == NodeType.SLAVE && config.getReadMode() != ReadMode.MASTER);
return result;
}
@ -198,7 +201,7 @@ public class ClusterConnectionManager extends MasterSlaveConnectionManager {
}
final RPromise<Collection<RFuture<Void>>> result = new RedissonPromise<Collection<RFuture<Void>>>();
RFuture<RedisConnection> connectionFuture = connectToNode(cfg, partition.getMasterAddress(), null);
RFuture<RedisConnection> connectionFuture = connectToNode(cfg, partition.getMasterAddress(), null, configEndpointHostName);
connectionFuture.addListener(new FutureListener<RedisConnection>() {
@Override
public void operationComplete(Future<RedisConnection> future) throws Exception {
@ -351,7 +354,7 @@ public class ClusterConnectionManager extends MasterSlaveConnectionManager {
return;
}
final URI uri = iterator.next();
RFuture<RedisConnection> connectionFuture = connectToNode(cfg, uri, null);
RFuture<RedisConnection> connectionFuture = connectToNode(cfg, uri, null, configEndpointHostName);
connectionFuture.addListener(new FutureListener<RedisConnection>() {
@Override
public void operationComplete(Future<RedisConnection> future) throws Exception {
@ -651,6 +654,10 @@ public class ClusterConnectionManager extends MasterSlaveConnectionManager {
}
}
}
public String getConfigEndpointHostName() {
return configEndpointHostName;
}
@Override
public int calcSlot(String key) {

@ -97,11 +97,11 @@ public interface ConnectionManager {
RFuture<RedisConnection> connectionWriteOp(NodeSource source, RedisCommand<?> command);
RedisClient createClient(NodeType type, URI address, int timeout, int commandTimeout);
RedisClient createClient(NodeType type, URI address, int timeout, int commandTimeout, String sslHostname);
RedisClient createClient(NodeType type, InetSocketAddress address, URI uri);
RedisClient createClient(NodeType type, InetSocketAddress address, URI uri, String sslHostname);
RedisClient createClient(NodeType type, URI address);
RedisClient createClient(NodeType type, URI address, String sslHostname);
MasterSlaveEntry getEntry(RedisClient redisClient);

@ -250,7 +250,7 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
}
}
protected RFuture<RedisConnection> connectToNode(BaseMasterSlaveServersConfig<?> cfg, final URI addr, RedisClient client) {
protected RFuture<RedisConnection> connectToNode(BaseMasterSlaveServersConfig<?> cfg, final URI addr, RedisClient client, String sslHostname) {
final Object key;
if (client != null) {
key = client;
@ -263,7 +263,7 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
}
if (addr != null) {
client = createClient(NodeType.MASTER, addr, cfg.getConnectTimeout(), cfg.getRetryInterval() * cfg.getRetryAttempts());
client = createClient(NodeType.MASTER, addr, cfg.getConnectTimeout(), cfg.getRetryInterval() * cfg.getRetryAttempts(), sslHostname);
}
final RPromise<RedisConnection> result = new RedissonPromise<RedisConnection>();
RFuture<RedisConnection> future = client.connectAsync();
@ -430,15 +430,15 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
}
@Override
public RedisClient createClient(NodeType type, URI address) {
RedisClient client = createClient(type, address, config.getConnectTimeout(), config.getRetryInterval() * config.getRetryAttempts());
public RedisClient createClient(NodeType type, URI address, String sslHostname) {
RedisClient client = createClient(type, address, config.getConnectTimeout(), config.getRetryInterval() * config.getRetryAttempts(), sslHostname);
clientEntries.put(client, new RedisClientEntry(client, commandExecutor, type));
return client;
}
@Override
public RedisClient createClient(NodeType type, InetSocketAddress address, URI uri) {
RedisClient client = createClient(type, address, uri, config.getConnectTimeout(), config.getRetryInterval() * config.getRetryAttempts());
public RedisClient createClient(NodeType type, InetSocketAddress address, URI uri, String sslHostname) {
RedisClient client = createClient(type, address, uri, config.getConnectTimeout(), config.getRetryInterval() * config.getRetryAttempts(), sslHostname);
clientEntries.put(client, new RedisClientEntry(client, commandExecutor, type));
return client;
}
@ -452,19 +452,19 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
}
@Override
public RedisClient createClient(NodeType type, URI address, int timeout, int commandTimeout) {
RedisClientConfig redisConfig = createRedisConfig(type, address, timeout, commandTimeout);
public RedisClient createClient(NodeType type, URI address, int timeout, int commandTimeout, String sslHostname) {
RedisClientConfig redisConfig = createRedisConfig(type, address, timeout, commandTimeout, sslHostname);
return RedisClient.create(redisConfig);
}
private RedisClient createClient(NodeType type, InetSocketAddress address, URI uri, int timeout, int commandTimeout) {
RedisClientConfig redisConfig = createRedisConfig(type, null, timeout, commandTimeout);
private RedisClient createClient(NodeType type, InetSocketAddress address, URI uri, int timeout, int commandTimeout, String sslHostname) {
RedisClientConfig redisConfig = createRedisConfig(type, null, timeout, commandTimeout, sslHostname);
redisConfig.setAddress(address, uri);
return RedisClient.create(redisConfig);
}
protected RedisClientConfig createRedisConfig(NodeType type, URI address, int timeout, int commandTimeout) {
protected RedisClientConfig createRedisConfig(NodeType type, URI address, int timeout, int commandTimeout, String sslHostname) {
RedisClientConfig redisConfig = new RedisClientConfig();
redisConfig.setAddress(address)
.setTimer(timer)
@ -474,6 +474,7 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
.setSocketChannelClass(socketChannelClass)
.setConnectTimeout(timeout)
.setCommandTimeout(commandTimeout)
.setSslHostname(sslHostname)
.setSslEnableEndpointIdentification(config.isSslEnableEndpointIdentification())
.setSslProvider(config.getSslProvider())
.setSslTruststore(config.getSslTruststore())

@ -35,6 +35,7 @@ import org.redisson.client.protocol.CommandData;
import org.redisson.client.protocol.RedisCommand;
import org.redisson.client.protocol.RedisCommands;
import org.redisson.client.protocol.pubsub.PubSubType;
import org.redisson.cluster.ClusterConnectionManager;
import org.redisson.cluster.ClusterSlotRange;
import org.redisson.config.MasterSlaveServersConfig;
import org.redisson.config.ReadMode;
@ -77,6 +78,8 @@ public class MasterSlaveEntry {
final AtomicBoolean active = new AtomicBoolean(true);
String sslHostname;
public MasterSlaveEntry(Set<ClusterSlotRange> slotRanges, ConnectionManager connectionManager, MasterSlaveServersConfig config) {
for (ClusterSlotRange clusterSlotRange : slotRanges) {
for (int i = clusterSlotRange.getStartSlot(); i < clusterSlotRange.getEndSlot() + 1; i++) {
@ -89,6 +92,10 @@ public class MasterSlaveEntry {
slaveBalancer = new LoadBalancerManager(config, connectionManager, this);
writeConnectionPool = new MasterConnectionPool(config, connectionManager, this);
pubSubConnectionPool = new MasterPubSubConnectionPool(config, connectionManager, this);
if (connectionManager instanceof ClusterConnectionManager) {
sslHostname = ((ClusterConnectionManager) connectionManager).getConfigEndpointHostName();
}
}
public MasterSlaveServersConfig getConfig() {
@ -111,13 +118,13 @@ public class MasterSlaveEntry {
}
public RFuture<RedisClient> setupMasterEntry(InetSocketAddress address, URI uri) {
RedisClient client = connectionManager.createClient(NodeType.MASTER, address, uri);
RedisClient client = connectionManager.createClient(NodeType.MASTER, address, uri, sslHostname);
return setupMasterEntry(client);
}
public RFuture<RedisClient> setupMasterEntry(URI address) {
RedisClient client = connectionManager.createClient(NodeType.MASTER, address);
RedisClient client = connectionManager.createClient(NodeType.MASTER, address, sslHostname);
return setupMasterEntry(client);
}
@ -404,12 +411,12 @@ public class MasterSlaveEntry {
}
private RFuture<Void> addSlave(InetSocketAddress address, URI uri, final boolean freezed, final NodeType nodeType) {
RedisClient client = connectionManager.createClient(NodeType.SLAVE, address, uri);
RedisClient client = connectionManager.createClient(NodeType.SLAVE, address, uri, sslHostname);
return addSlave(client, freezed, nodeType);
}
private RFuture<Void> addSlave(URI address, final boolean freezed, final NodeType nodeType) {
RedisClient client = connectionManager.createClient(NodeType.SLAVE, address);
RedisClient client = connectionManager.createClient(NodeType.SLAVE, address, sslHostname);
return addSlave(client, freezed, nodeType);
}

@ -67,7 +67,7 @@ public class ReplicatedConnectionManager extends MasterSlaveConnectionManager {
initTimer(this.config);
for (URI addr : cfg.getNodeAddresses()) {
RFuture<RedisConnection> connectionFuture = connectToNode(cfg, addr, null);
RFuture<RedisConnection> connectionFuture = connectToNode(cfg, addr, null, addr.getHost());
connectionFuture.awaitUninterruptibly();
RedisConnection connection = connectionFuture.getNow();
if (connection == null) {
@ -119,7 +119,7 @@ public class ReplicatedConnectionManager extends MasterSlaveConnectionManager {
return;
}
RFuture<RedisConnection> connectionFuture = connectToNode(cfg, addr, null);
RFuture<RedisConnection> connectionFuture = connectToNode(cfg, addr, null, addr.getHost());
connectionFuture.addListener(new FutureListener<RedisConnection>() {
@Override
public void operationComplete(Future<RedisConnection> future) throws Exception {

@ -90,7 +90,7 @@ public class SentinelConnectionManager extends MasterSlaveConnectionManager {
this.sentinelResolver = resolverGroup.getResolver(getGroup().next());
for (URI addr : cfg.getSentinelAddresses()) {
RedisClient client = createClient(NodeType.SENTINEL, addr, this.config.getConnectTimeout(), this.config.getRetryInterval() * this.config.getRetryAttempts());
RedisClient client = createClient(NodeType.SENTINEL, addr, this.config.getConnectTimeout(), this.config.getRetryInterval() * this.config.getRetryAttempts(), null);
try {
RedisConnection connection = client.connect();
if (!connection.isActive()) {
@ -261,7 +261,7 @@ public class SentinelConnectionManager extends MasterSlaveConnectionManager {
}
RedisClient client = iterator.next();
RFuture<RedisConnection> connectionFuture = connectToNode(null, null, client);
RFuture<RedisConnection> connectionFuture = connectToNode(null, null, client, null);
connectionFuture.addListener(new FutureListener<RedisConnection>() {
@Override
public void operationComplete(Future<RedisConnection> future) throws Exception {
@ -433,7 +433,7 @@ public class SentinelConnectionManager extends MasterSlaveConnectionManager {
return RedissonPromise.newSucceededFuture(null);
}
client = createClient(NodeType.SENTINEL, addr, c.getConnectTimeout(), c.getRetryInterval() * c.getRetryAttempts());
client = createClient(NodeType.SENTINEL, addr, c.getConnectTimeout(), c.getRetryInterval() * c.getRetryAttempts(), null);
RedisClient oldClient = sentinels.putIfAbsent(key, client);
if (oldClient != null) {
return RedissonPromise.newSucceededFuture(null);

@ -17,34 +17,44 @@ package org.redisson.misc;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.regex.Pattern;
/**
*
* @author Rui Gu (https://github.com/jackygurui)
*/
public class URIBuilder {
private static final Pattern ipv4Pattern = Pattern.compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])", Pattern.CASE_INSENSITIVE);
private static final Pattern ipv6Pattern = Pattern.compile("([0-9a-f]{1,4}:){7}([0-9a-f]){1,4}", Pattern.CASE_INSENSITIVE);
public static URI create(String uri) {
URI u = URI.create(uri);
//Let's assuming most of the time it is OK.
// Let's assuming most of the time it is OK.
if (u.getHost() != null) {
return u;
}
String s = uri.substring(0, uri.lastIndexOf(":"))
.replaceFirst("redis://", "")
.replaceFirst("rediss://", "");
//Assuming this is an IPv6 format, other situations will be handled by
//Netty at a later stage.
String s = uri.substring(0, uri.lastIndexOf(":")).replaceFirst("redis://", "").replaceFirst("rediss://", "");
// Assuming this is an IPv6 format, other situations will be handled by
// Netty at a later stage.
return URI.create(uri.replace(s, "[" + s + "]"));
}
public static boolean isValidIP(String host) {
if (ipv4Pattern.matcher(host).matches()) {
return true;
}
return ipv6Pattern.matcher(host).matches();
}
public static boolean compare(InetSocketAddress entryAddr, URI addr) {
if (((entryAddr.getHostName() != null && entryAddr.getHostName().equals(addr.getHost()))
|| entryAddr.getAddress().getHostAddress().equals(addr.getHost()))
&& entryAddr.getPort() == addr.getPort()) {
&& entryAddr.getPort() == addr.getPort()) {
return true;
}
return false;
}
}

Loading…
Cancel
Save