Skip to content

Commit

Permalink
Fix support for Sentinels with passwords
Browse files Browse the repository at this point in the history
If passwords used for Sentinel servers contained special characters, such as "@", URL parsing did not work anymore and Predis tried to connect without using a password. Event though percent-encoded passwords should work, as per RFC3986, those do not work because Predis does not decode the userinfo part of the URL.

This change uses a different way to pass parameters to Predis and circumvents the error-prone pass via a URL.
robertlemke committed Nov 23, 2022
1 parent 53450ed commit 0ed5907
Showing 3 changed files with 24 additions and 25 deletions.
12 changes: 11 additions & 1 deletion Classes/Command/RedisSentinelCommandController.php
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
use Neos\Flow\Cli\CommandController;
use Predis\Client;
use Predis\Command\Redis\INFO;
use Predis\Connection\Parameters;
use Predis\Connection\Replication\SentinelReplication;

/**
@@ -297,7 +298,16 @@ private function getRedisClient(array $sentinels, string $password, string $serv
}

if ($sentinels !== []) {
$connectionParameters = $sentinels;
$connectionParameters = [];
foreach ($sentinels as $sentinel) {
$parsed = Parameters::parse($sentinel);
$connectionParameters[] = [
'host' => $parsed['host'],
'port' => $parsed['port'],
'password' => $password
];
}

$options['replication'] = 'sentinel';
$options['service'] = $service;
} else {
11 changes: 10 additions & 1 deletion Classes/RedisBackend.php
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@
use Neos\Flow\ObjectManagement\ObjectManagerInterface;
use Predis;
use Predis\Collection\Iterator;
use Predis\Connection\Parameters;
use Psr\Log\LoggerInterface;
use RuntimeException;
use Throwable;
@@ -593,7 +594,15 @@ private function getRedisClient(): \Predis\Client
}

if ($this->sentinels !== []) {
$connectionParameters = $this->sentinels;
$connectionParameters = [];
foreach ($this->sentinels as $sentinel) {
$parsed = Parameters::parse($sentinel);
$connectionParameters[] = [
'host' => $parsed['host'],
'port' => $parsed['port'],
'password' => $this->password
];
}
$options['replication'] = 'sentinel';
$options['service'] = $this->service;
} else {
26 changes: 3 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -84,30 +84,10 @@ Flow_Mvc_Routing_Resolve:
Note that "service" is the name of your Redis cluster (which is "mymaster" in
most default configurations).

If your Sentinels are protected with a password, you must specify the
password via the Sentinel URLs (due to how Predis works internally). Note
that no username is specified, but you must not forget the colon ":" before
the password:
This package will use the same password for all connections, there is
currently no support for specifying different passwords for Sentinel and
client servers.

```yaml
Flow_Mvc_Routing_Route:
backend: 'Flownative\RedisSentinel\RedisBackend'
backendOptions: &backendOptions
sentinels:
- 'redis://:sentinel-password@10.101.213.145:26379'
- 'redis://:sentinel-password@10.101.213.146:26379'
- 'redis://:sentinel-password@10.101.213.147:26379'
service: 'mymaster'
password: 'a-very-long-password'
database: 0
timeout: 0.5
readWriteTimeout: 0.1

Flow_Mvc_Routing_Resolve:
backend: 'Flownative\RedisSentinel\RedisBackend'
backendOptions: *backendOptions
```
## Logging

This cache backend will log errors, such as connection timeouts or other

0 comments on commit 0ed5907

Please sign in to comment.