Skip to content

Commit

Permalink
drop use of authxmanager and authenticatedconnection from core
Browse files Browse the repository at this point in the history
  • Loading branch information
atakavci committed Nov 12, 2024
1 parent a18e632 commit 392b3b0
Show file tree
Hide file tree
Showing 6 changed files with 392 additions and 69 deletions.
39 changes: 17 additions & 22 deletions src/main/java/redis/clients/jedis/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,11 @@
import java.util.function.Supplier;
import java.util.concurrent.atomic.AtomicReference;

import redis.clients.authentication.core.AuthenticatedConnection;
import redis.clients.authentication.core.Token;
import redis.clients.jedis.Protocol.Command;
import redis.clients.jedis.Protocol.Keyword;
import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.args.ClientAttributeOption;
import redis.clients.jedis.args.Rawable;
import redis.clients.jedis.authentication.TokenCredentials;
import redis.clients.jedis.commands.ProtocolCommand;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisDataException;
Expand All @@ -33,7 +30,7 @@
import redis.clients.jedis.util.RedisInputStream;
import redis.clients.jedis.util.RedisOutputStream;

public class Connection implements Closeable, AuthenticatedConnection {
public class Connection implements Closeable {

private ConnectionPool memberOf;
protected RedisProtocol protocol;
Expand All @@ -48,7 +45,8 @@ public class Connection implements Closeable, AuthenticatedConnection {
private String strVal;
protected String server;
protected String version;
protected AtomicReference<Token> currentToken = new AtomicReference<Token>(null);
protected AtomicReference<RedisCredentials> currentCredentials = new AtomicReference<RedisCredentials>(
null);

public Connection() {
this(Protocol.DEFAULT_HOST, Protocol.DEFAULT_PORT);
Expand Down Expand Up @@ -98,8 +96,8 @@ public String toIdentityString() {
SocketAddress remoteAddr = socket.getRemoteSocketAddress();
SocketAddress localAddr = socket.getLocalSocketAddress();
if (remoteAddr != null) {
strVal = String.format("%s{id: 0x%X, L:%s %c R:%s}", className, id,
localAddr, (broken ? '!' : '-'), remoteAddr);
strVal = String.format("%s{id: 0x%X, L:%s %c R:%s}", className, id, localAddr,
(broken ? '!' : '-'), remoteAddr);
} else if (localAddr != null) {
strVal = String.format("%s{id: 0x%X, L:%s}", className, id, localAddr);
} else {
Expand Down Expand Up @@ -443,8 +441,8 @@ private static boolean validateClientInfo(String info) {
for (int i = 0; i < info.length(); i++) {
char c = info.charAt(i);
if (c < '!' || c > '~') {
throw new JedisValidationException("client info cannot contain spaces, "
+ "newlines or special characters.");
throw new JedisValidationException(
"client info cannot contain spaces, " + "newlines or special characters.");
}
}
return true;
Expand Down Expand Up @@ -474,7 +472,8 @@ protected void initializeFromClientConfig(final JedisClientConfig config) {

String clientName = config.getClientName();
if (clientName != null && validateClientInfo(clientName)) {
fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETNAME).add(clientName));
fireAndForgetMsg
.add(new CommandArguments(Command.CLIENT).add(Keyword.SETNAME).add(clientName));
}

ClientSetInfoConfig setInfoConfig = config.getClientSetInfoConfig();
Expand Down Expand Up @@ -530,12 +529,13 @@ private void helloAndAuth(final RedisProtocol protocol, final RedisCredentials c
if (protocol != null && credentials != null && credentials.getUser() != null) {
byte[] rawPass = encodeToBytes(credentials.getPassword());
try {
helloResult = hello(encode(protocol.version()), Keyword.AUTH.getRaw(), encode(credentials.getUser()), rawPass);
helloResult = hello(encode(protocol.version()), Keyword.AUTH.getRaw(),
encode(credentials.getUser()), rawPass);
} finally {
Arrays.fill(rawPass, (byte) 0); // clear sensitive data
}
} else {
auth(credentials);
authenticate(credentials);
helloResult = protocol == null ? null : hello(encode(protocol.version()));
}
if (helloResult != null) {
Expand All @@ -547,11 +547,11 @@ private void helloAndAuth(final RedisProtocol protocol, final RedisCredentials c
// handled in RedisCredentialsProvider.cleanUp()
}

public void setToken(Token token) {
currentToken.set(token);
public void setCredentials(RedisCredentials credentials) {
currentCredentials.set(credentials);
}

private void auth(RedisCredentials credentials) {
public void authenticate(RedisCredentials credentials) {
if (credentials == null || credentials.getPassword() == null) {
return;
}
Expand All @@ -569,9 +569,9 @@ private void auth(RedisCredentials credentials) {
}

public void reAuth() {
Token temp = currentToken.getAndSet(null);
RedisCredentials temp = currentCredentials.getAndSet(null);
if (temp != null) {
auth(new TokenCredentials(temp));
authenticate(temp);
}
}

Expand Down Expand Up @@ -601,9 +601,4 @@ public boolean ping() {
}
return true;
}

@Override
public void authenticate(Token token) {
this.setToken(token);
}
}
18 changes: 4 additions & 14 deletions src/main/java/redis/clients/jedis/ConnectionFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
import java.util.function.Supplier;

import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.authentication.TokenCredentials;
import redis.clients.authentication.core.AuthXManager;
import redis.clients.jedis.authentication.JedisAuthXManager;
import redis.clients.jedis.csc.Cache;
import redis.clients.jedis.csc.CacheConnection;
import redis.clients.jedis.exceptions.JedisException;
Expand All @@ -39,7 +38,7 @@ public ConnectionFactory(final HostAndPort hostAndPort, final JedisClientConfig

@Experimental
public ConnectionFactory(final HostAndPort hostAndPort, final JedisClientConfig clientConfig,
Cache csCache, AuthXManager authXManager) {
Cache csCache, JedisAuthXManager authXManager) {
this(new DefaultJedisSocketFactory(hostAndPort, clientConfig), clientConfig, csCache,
authXManager);
}
Expand All @@ -50,7 +49,7 @@ public ConnectionFactory(final JedisSocketFactory jedisSocketFactory,
}

private ConnectionFactory(final JedisSocketFactory jedisSocketFactory,
final JedisClientConfig clientConfig, Cache csCache, AuthXManager authXManager) {
final JedisClientConfig clientConfig, Cache csCache, JedisAuthXManager authXManager) {

this.jedisSocketFactory = jedisSocketFactory;
this.clientSideCache = csCache;
Expand All @@ -60,7 +59,7 @@ private ConnectionFactory(final JedisSocketFactory jedisSocketFactory,
this.objectMaker = connectionSupplier();
} else {
this.clientConfig = replaceCredentialsProvider(clientConfig,
buildCredentialsProvider(authXManager));
authXManager);
Supplier<Connection> supplier = connectionSupplier();
this.objectMaker = () -> (Connection) authXManager.addConnection(supplier.get());

Expand All @@ -78,15 +77,6 @@ private JedisClientConfig replaceCredentialsProvider(JedisClientConfig origin,
.credentialsProvider(newCredentialsProvider).build();
}

private Supplier<RedisCredentials> buildCredentialsProvider(AuthXManager connManager) {
return new Supplier<RedisCredentials>() {
@Override
public RedisCredentials get() {
return new TokenCredentials(connManager.getCurrentToken());
}
};
}

private Supplier<Connection> connectionSupplier() {
return clientSideCache == null ? () -> new Connection(jedisSocketFactory, clientConfig)
: () -> new CacheConnection(jedisSocketFactory, clientConfig, clientSideCache);
Expand Down
31 changes: 11 additions & 20 deletions src/main/java/redis/clients/jedis/ConnectionPool.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import redis.clients.authentication.core.AuthXManagerFactory;
import redis.clients.authentication.core.Token;
import redis.clients.authentication.core.TokenListener;
import redis.clients.jedis.annots.Experimental;
import redis.clients.jedis.authentication.JedisAuthXManager;
import redis.clients.jedis.csc.Cache;
Expand All @@ -23,7 +20,7 @@ public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig) {
public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig,
JedisAuthXManager authXManager) {
this(new ConnectionFactory(hostAndPort, clientConfig, null, authXManager));
attachAuthXManager(authXManager);
attachAuthenticationListener(authXManager);
}

@Experimental
Expand All @@ -36,7 +33,7 @@ public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig,
public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig,
Cache clientSideCache, JedisAuthXManager authXManager) {
this(new ConnectionFactory(hostAndPort, clientConfig, clientSideCache, authXManager));
attachAuthXManager(authXManager);
attachAuthenticationListener(authXManager);
}

public ConnectionPool(PooledObjectFactory<Connection> factory) {
Expand All @@ -60,7 +57,7 @@ public ConnectionPool(HostAndPort hostAndPort, JedisClientConfig clientConfig,
GenericObjectPoolConfig<Connection> poolConfig) {
this(new ConnectionFactory(hostAndPort, clientConfig, clientSideCache, authXManager),
poolConfig);
attachAuthXManager(authXManager);
attachAuthenticationListener(authXManager);
}

public ConnectionPool(PooledObjectFactory<Connection> factory,
Expand All @@ -85,26 +82,20 @@ public void close() {

private static JedisAuthXManager createAuthXManager(JedisClientConfig config) {
if (config.getTokenAuthConfig() != null) {
return AuthXManagerFactory.create(JedisAuthXManager.class, config.getTokenAuthConfig());
return new JedisAuthXManager(config.getTokenAuthConfig());
}
return null;
}

private void attachAuthXManager(JedisAuthXManager authXManager) {
private void attachAuthenticationListener(JedisAuthXManager authXManager) {
this.authXManager = authXManager;
if (authXManager != null) {
authXManager.setListener(new TokenListener() {
@Override
public void onTokenRenewed(Token token) {
try {
evict();
} catch (Exception e) {
throw new JedisException("Failed to evict connections from pool", e);
}
}

@Override
public void onError(Exception reason) {
authXManager.setListener(token -> {
try {
// this is to trigger validations on each connection via ConnectionFactory
evict();
} catch (Exception e) {
throw new JedisException("Failed to evict connections from pool", e);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,103 @@
package redis.clients.jedis.authentication;

import redis.clients.authentication.core.AuthXManager;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.authentication.core.Token;
import redis.clients.authentication.core.TokenAuthConfig;
import redis.clients.authentication.core.TokenListener;
import redis.clients.authentication.core.TokenManager;
import redis.clients.jedis.Connection;
import redis.clients.jedis.RedisCredentials;

public class JedisAuthXManager implements Supplier<RedisCredentials> {

private static final Logger log = LoggerFactory.getLogger(JedisAuthXManager.class);

public class JedisAuthXManager extends AuthXManager {
private TokenListener listener;
private TokenManager tokenManager;
private List<WeakReference<Connection>> connections = Collections
.synchronizedList(new ArrayList<>());
private Token currentToken;
private AuthenticationListener listener;

public interface AuthenticationListener {
public void onAuthenticate(Token token);
}

public JedisAuthXManager(TokenManager tokenManager) {
super(tokenManager);
this.tokenManager = tokenManager;
}

public void setListener(TokenListener listener) {
this.listener = listener;
public JedisAuthXManager(TokenAuthConfig tokenAuthConfig) {
this(new TokenManager(tokenAuthConfig.getIdentityProviderConfig().getProvider(),
tokenAuthConfig.getTokenManagerConfig()));
}

public void start(boolean blockForInitialToken)
throws InterruptedException, ExecutionException, TimeoutException {

tokenManager.start(new TokenListener() {
@Override
public void onTokenRenewed(Token token) {
currentToken = token;
authenticateConnections(token);
}

@Override
public void onError(Exception reason) {
JedisAuthXManager.this.onError(reason);
}
}, blockForInitialToken);
}

@Override
public void authenticateConnections(Token token) {
super.authenticateConnections(token);
RedisCredentials credentialsFromToken = new TokenCredentials(token);
for (WeakReference<Connection> connectionRef : connections) {
Connection connection = connectionRef.get();
if (connection != null) {
try {
connection.setCredentials(credentialsFromToken);
} catch (Exception e) {
log.error("Failed to authenticate connection!", e);
}
} else {
connections.remove(connectionRef);
}
}
if (listener != null) {
listener.onTokenRenewed(token);
listener.onAuthenticate(token);
}
}

public void onError(Exception reason) {
throw new JedisAuthenticationException(
"Token request/renewal failed with message:" + reason.getMessage(), reason);
}

public Connection addConnection(Connection connection) {
connections.add(new WeakReference<>(connection));
return connection;
}

public void stop() {
tokenManager.stop();
}

public void setListener(AuthenticationListener listener) {
this.listener = listener;
}

@Override
public RedisCredentials get() {
return new TokenCredentials(this.currentToken);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package redis.clients.jedis.authentication;

public class JedisAuthenticationException extends RuntimeException {

public JedisAuthenticationException(String message) {
super(message);
}

public JedisAuthenticationException(String message, Throwable cause) {
super(message, cause);
}
}
Loading

0 comments on commit 392b3b0

Please sign in to comment.