Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

Commit

Permalink
Redis password authentication support (#2950)
Browse files Browse the repository at this point in the history
* Added support for password authentication in RedisStandaloneConfiguration, RedisClusterConfiguration and RedisSentinelConfiguration

* - Added a Redis Setup documentation page to the docs
- Added a comment in application.properties
  • Loading branch information
jmigueprieto authored May 4, 2022
1 parent a0cc539 commit 3efbb83
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 7 deletions.
38 changes: 38 additions & 0 deletions docs/docs/how-tos/redis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Redis Configuration

By default conductor runs with an in-memory Redis mock. However, you
can change the configuration by setting the properties `conductor.db.type` and `conductor.redis.hosts`.

## `conductor.db.type`

| Value | Description |
|--------------------------------|----------------------------------------------------------------------------------------|
| dynomite | Dynomite Cluster. Dynomite is a proxy layer that provides sharding and replication. |
| memory | Uses an in-memory Redis mock. Should be used only for development and testing purposes.|
| redis_cluster | Redis Cluster configuration. |
| redis_sentinel | Redis Sentinel configuration. |
| redis_standalone | Redis Standalone configuration. |



## `conductor.redis.hosts`

Expected format is `host:port:rack` separated by semicolon, e.g.:

```properties
conductor.redis.hosts=host0:6379:us-east-1c;host1:6379:us-east-1c;host2:6379:us-east-1c
```

### Auth Support

Password authentication is supported. The password should be set as the 4th param of the first host `host:port:rack:password`, e.g.:

```properties
conductor.redis.hosts=host0:6379:us-east-1c:my_str0ng_pazz;host1:6379:us-east-1c;host2:6379:us-east-1c
```


**Notes**

- In a cluster, all nodes use the same password.
- In a sentinel configuration, sentinels and redis nodes use the same password.
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,35 @@
*/
package com.netflix.conductor.redis.config;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;

import com.netflix.conductor.core.config.ConductorProperties;
import com.netflix.conductor.redis.jedis.JedisCluster;
import com.netflix.dyno.connectionpool.Host;
import com.netflix.dyno.connectionpool.HostSupplier;
import com.netflix.dyno.connectionpool.TokenMapSupplier;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.commands.JedisCommands;

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "conductor.db.type", havingValue = "redis_cluster")
public class RedisClusterConfiguration extends JedisCommandsConfigurer {

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

// Same as redis.clients.jedis.BinaryJedisCluster
protected static final int DEFAULT_MAX_ATTEMPTS = 5;

@Override
protected JedisCommands createJedisCommands(
RedisProperties properties,
Expand All @@ -43,7 +53,25 @@ protected JedisCommands createJedisCommands(
hostSupplier.getHosts().stream()
.map(h -> new HostAndPort(h.getHostName(), h.getPort()))
.collect(Collectors.toSet());
return new JedisCluster(
new redis.clients.jedis.JedisCluster(hosts, genericObjectPoolConfig));
String password = getPassword(hostSupplier.getHosts());

if (password != null) {
log.info("Connecting to Redis Cluster with AUTH");
return new JedisCluster(
new redis.clients.jedis.JedisCluster(
hosts,
Protocol.DEFAULT_TIMEOUT,
Protocol.DEFAULT_TIMEOUT,
DEFAULT_MAX_ATTEMPTS,
password,
genericObjectPoolConfig));
} else {
return new JedisCluster(
new redis.clients.jedis.JedisCluster(hosts, genericObjectPoolConfig));
}
}

private String getPassword(List<Host> hosts) {
return hosts.isEmpty() ? null : hosts.get(0).getPassword();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package com.netflix.conductor.redis.config;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
Expand All @@ -28,6 +29,7 @@
import com.netflix.dyno.connectionpool.TokenMapSupplier;

import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.commands.JedisCommands;

@Configuration(proxyBeanMethods = false)
Expand Down Expand Up @@ -59,8 +61,31 @@ protected JedisCommands createJedisCommands(
for (Host host : hostSupplier.getHosts()) {
sentinels.add(host.getHostName() + ":" + host.getPort());
}
return new JedisSentinel(
new JedisSentinelPool(
properties.getClusterName(), sentinels, genericObjectPoolConfig));
// We use the password of the first sentinel host as password and sentinelPassword
String password = getPassword(hostSupplier.getHosts());
if (password != null) {
return new JedisSentinel(
new JedisSentinelPool(
properties.getClusterName(),
sentinels,
genericObjectPoolConfig,
Protocol.DEFAULT_TIMEOUT,
Protocol.DEFAULT_TIMEOUT,
password,
Protocol.DEFAULT_DATABASE,
null,
Protocol.DEFAULT_TIMEOUT,
Protocol.DEFAULT_TIMEOUT,
password,
null));
} else {
return new JedisSentinel(
new JedisSentinelPool(
properties.getClusterName(), sentinels, genericObjectPoolConfig));
}
}

private String getPassword(List<Host> hosts) {
return hosts.isEmpty() ? null : hosts.get(0).getPassword();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Protocol;
import redis.clients.jedis.commands.JedisCommands;

@Configuration(proxyBeanMethods = false)
Expand All @@ -44,6 +45,20 @@ protected JedisCommands createJedisCommands(
config.setMaxTotal(properties.getMaxConnectionsPerHost());
log.info("Starting conductor server using redis_standalone.");
Host host = hostSupplier.getHosts().get(0);
return new JedisStandalone(new JedisPool(config, host.getHostName(), host.getPort()));
return new JedisStandalone(getJedisPool(config, host));
}

private JedisPool getJedisPool(JedisPoolConfig config, Host host) {
if (host.getPassword() != null) {
log.info("Connecting to Redis Standalone with AUTH");
return new JedisPool(
config,
host.getHostName(),
host.getPort(),
Protocol.DEFAULT_TIMEOUT,
host.getPassword());
} else {
return new JedisPool(config, host.getHostName(), host.getPort());
}
}
}
3 changes: 2 additions & 1 deletion server/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ conductor.db.type=memory

conductor.indexing.enabled=false

#Dynomite Cluster details.
#Redis configuration details.
#format is host:port:rack separated by semicolon
#Auth is supported. Password is taken from host[0]. format: host:port:rack:password
conductor.redis.hosts=host1:port:rack;host2:port:rack:host3:port:rack

#namespace for the keys stored in Dynomite/Redis
Expand Down

0 comments on commit 3efbb83

Please sign in to comment.