Skip to content

Commit 4e26a72

Browse files
authored
Add authentication with username and password for phpredis RedisCluster (#733)
* Add phpredis cluster auth with username and password to work with ACL system * Add unit test for RedisCluster ACL
1 parent 1577b80 commit 4e26a72

File tree

9 files changed

+65
-7
lines changed

9 files changed

+65
-7
lines changed

.github/workflows/redis-configs/redis-node1/redis.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ cluster-config-file nodes.conf
44
appendonly no
55
save ""
66
bind 0.0.0.0
7-
protected-mode no
7+
protected-mode no
8+
user snc_redis on +@all ~* >snc_password

.github/workflows/redis-configs/redis-node2/redis.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ cluster-config-file nodes.conf
44
appendonly no
55
save ""
66
bind 0.0.0.0
7-
protected-mode no
7+
protected-mode no
8+
user snc_redis on +@all ~* >snc_password

.github/workflows/redis-configs/redis-node3/redis.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ cluster-config-file nodes.conf
44
appendonly no
55
save ""
66
bind 0.0.0.0
7-
protected-mode no
7+
protected-mode no
8+
user snc_redis on +@all ~* >snc_password

.github/workflows/redis-configs/redis-node4/redis.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ cluster-config-file nodes.conf
44
appendonly no
55
save ""
66
bind 0.0.0.0
7-
protected-mode no
7+
protected-mode no
8+
user snc_redis on +@all ~* >snc_password

.github/workflows/redis-configs/redis-node5/redis.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ cluster-config-file nodes.conf
44
appendonly no
55
save ""
66
bind 0.0.0.0
7-
protected-mode no
7+
protected-mode no
8+
user snc_redis on +@all ~* >snc_password

.github/workflows/redis-configs/redis-node6/redis.conf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ cluster-config-file nodes.conf
44
appendonly no
55
save ""
66
bind 0.0.0.0
7-
protected-mode no
7+
protected-mode no
8+
user snc_redis on +@all ~* >snc_password

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ snc_redis:
169169
170170
```
171171

172+
It also works for the Phpredis Cluster mode.
172173

173174
### Sessions ###
174175

src/Factory/PhpredisClientFactory.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,36 @@ public function __construct(string $dsn, string $host, int $port)
187187
*/
188188
private function createClusterClient(array $dsns, string $class, string $alias, array $options, bool $loggingEnabled): RedisCluster
189189
{
190+
$auth = $options['parameters']['password'] ?? null;
191+
$username = $options['parameters']['username'] ?? null;
192+
if ($username !== null && $auth !== null) {
193+
$auth = [$username, $auth];
194+
}
195+
196+
if ($auth === null) {
197+
$uniqueAuth = null;
198+
foreach ($dsns as $index => $dsn) {
199+
$uniqueAuth = $dsn->getPassword();
200+
$username = $dsn->getUsername();
201+
if ($username !== null && $uniqueAuth !== null) {
202+
$uniqueAuth = [$username, $uniqueAuth];
203+
}
204+
205+
if ($index > 0 && $auth !== $uniqueAuth) {
206+
throw new InvalidConfigurationException('DSNs cannot have different authentication for RedisCluster.');
207+
}
208+
209+
$auth = $uniqueAuth;
210+
}
211+
}
212+
190213
$client = new $class(
191214
null,
192215
array_map(static fn (RedisDsn $dsn) => ($dsn->getTls() ? 'tls://' : '') . $dsn->getHost() . ':' . $dsn->getPort(), $dsns),
193216
$options['connection_timeout'],
194217
$options['read_write_timeout'] ?? 0,
195218
(bool) $options['connection_persistent'],
196-
$options['parameters']['password'] ?? null,
219+
$auth,
197220
);
198221

199222
if (isset($options['prefix'])) {

tests/Factory/PhpredisClientFactoryTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,34 @@ public function testCreateMinimalClusterConfig(): void
105105
$this->assertSame(0, $client->getOption(RedisCluster::OPT_SLAVE_FAILOVER));
106106
}
107107

108+
public function testCreateMinimalClusterConfigWithAcl(): void
109+
{
110+
$this->logger->expects($this->never())->method('debug');
111+
$factory = new PhpredisClientFactory(new RedisCallInterceptor($this->redisLogger));
112+
113+
$client = $factory->create(
114+
RedisCluster::class,
115+
['redis://localhost:7079'],
116+
[
117+
'connection_timeout' => 5,
118+
'connection_persistent' => false,
119+
'parameters' => [
120+
'username' => 'snc_redis',
121+
'password' => 'snc_password',
122+
],
123+
],
124+
'phprediscluster',
125+
false,
126+
);
127+
128+
$this->assertInstanceOf(RedisCluster::class, $client);
129+
$this->assertNull($client->getOption(Redis::OPT_PREFIX));
130+
$this->assertSame(0, $client->getOption(Redis::OPT_SERIALIZER));
131+
$this->assertSame(0., $client->getOption(Redis::OPT_READ_TIMEOUT));
132+
$this->assertSame(0, $client->getOption(Redis::OPT_SCAN));
133+
$this->assertSame(0, $client->getOption(RedisCluster::OPT_SLAVE_FAILOVER));
134+
}
135+
108136
/**
109137
* @requires extension relay
110138
* @testWith ["RedisSentinel", "Redis", null, "sentinelauthdefaultpw"]

0 commit comments

Comments
 (0)