diff options
author | John Molakvoæ <skjnldsv@users.noreply.github.com> | 2021-07-22 12:47:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-22 12:47:26 +0200 |
commit | f14b8aa34bfb9f7af7b23cfecc09e2fb8f604c1b (patch) | |
tree | 7f02c9fcb169d6b091e39b5db65599a098822c54 /lib | |
parent | dd4668f935f59cdb21deea38cfd16e6226798da0 (diff) | |
parent | 6e00fe8c26c8d1cd68497911371c3b4b785d903c (diff) | |
download | nextcloud-server-f14b8aa34bfb9f7af7b23cfecc09e2fb8f604c1b.tar.gz nextcloud-server-f14b8aa34bfb9f7af7b23cfecc09e2fb8f604c1b.zip |
Merge pull request #27888 from nextcloud/fix/redis-auth
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/RedisFactory.php | 116 |
1 files changed, 92 insertions, 24 deletions
diff --git a/lib/private/RedisFactory.php b/lib/private/RedisFactory.php index 61168c3dd86..7609a75d52d 100644 --- a/lib/private/RedisFactory.php +++ b/lib/private/RedisFactory.php @@ -27,7 +27,10 @@ namespace OC; class RedisFactory { - /** @var \Redis */ + public const REDIS_MINIMAL_VERSION = '2.2.5'; + public const REDIS_EXTRA_PARAMETERS_MINIMAL_VERSION = '5.3.0'; + + /** @var \Redis|\RedisCluster */ private $instance; /** @var SystemConfig */ @@ -43,25 +46,51 @@ class RedisFactory { } private function create() { - if ($config = $this->config->getValue('redis.cluster', [])) { - if (!class_exists('RedisCluster')) { - throw new \Exception('Redis Cluster support is not available'); - } - // cluster config - if (isset($config['timeout'])) { - $timeout = $config['timeout']; - } else { - $timeout = null; - } - if (isset($config['read_timeout'])) { - $readTimeout = $config['read_timeout']; + $isCluster = in_array('redis.cluster', $this->config->getKeys()); + $config = $isCluster + ? $this->config->getValue('redis.cluster', []) + : $this->config->getValue('redis', []); + + if (empty($config)) { + throw new \Exception('Redis config is empty'); + } + + if ($isCluster && !class_exists('RedisCluster')) { + throw new \Exception('Redis Cluster support is not available'); + } + + if (isset($config['timeout'])) { + $timeout = $config['timeout']; + } else { + $timeout = 0.0; + } + + if (isset($config['read_timeout'])) { + $readTimeout = $config['read_timeout']; + } else { + $readTimeout = 0.0; + } + + $auth = null; + if (isset($config['password']) && $config['password'] !== '') { + if (isset($config['user']) && $config['user'] !== '') { + $auth = [$config['user'], $config['password']]; } else { - $readTimeout = null; + $auth = $config['password']; } - if (isset($config['password']) && $config['password'] !== '') { - $this->instance = new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout, false, $config['password']); + } + + // # TLS support + // # https://github.com/phpredis/phpredis/issues/1600 + $connectionParameters = $this->getSslContext($config); + + // cluster config + if ($isCluster) { + // Support for older phpredis versions not supporting connectionParameters + if ($connectionParameters !== null) { + $this->instance = new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout, false, $auth, $connectionParameters); } else { - $this->instance = new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout); + $this->instance = new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout, false, $auth); } if (isset($config['failover_mode'])) { @@ -69,12 +98,13 @@ class RedisFactory { } } else { $this->instance = new \Redis(); - $config = $this->config->getValue('redis', []); + if (isset($config['host'])) { $host = $config['host']; } else { $host = '127.0.0.1'; } + if (isset($config['port'])) { $port = $config['port']; } elseif ($host[0] !== '/') { @@ -82,15 +112,22 @@ class RedisFactory { } else { $port = null; } - if (isset($config['timeout'])) { - $timeout = $config['timeout']; + + // Support for older phpredis versions not supporting connectionParameters + if ($connectionParameters !== null) { + // Non-clustered redis requires connection parameters to be wrapped inside `stream` + $connectionParameters = [ + 'stream' => $this->getSslContext($config) + ]; + $this->instance->connect($host, $port, $timeout, null, 0, $readTimeout, $connectionParameters); } else { - $timeout = 0.0; // unlimited + $this->instance->connect($host, $port, $timeout, null, 0, $readTimeout); } - $this->instance->connect($host, $port, $timeout); - if (isset($config['password']) && $config['password'] !== '') { - $this->instance->auth($config['password']); + + // Auth if configured + if ($auth !== null) { + $this->instance->auth($auth); } if (isset($config['dbindex'])) { @@ -99,6 +136,26 @@ class RedisFactory { } } + /** + * Get the ssl context config + * + * @param Array $config the current config + * @return Array|null + * @throws \UnexpectedValueException + */ + private function getSslContext($config) { + if (isset($config['ssl_context'])) { + if (!$this->isConnectionParametersSupported()) { + throw new \UnexpectedValueException(\sprintf( + 'php-redis extension must be version %s or higher to support ssl context', + self::REDIS_EXTRA_PARAMETERS_MINIMAL_VERSION + )); + } + return $config['ssl_context']; + } + return null; + } + public function getInstance() { if (!$this->isAvailable()) { throw new \Exception('Redis support is not available'); @@ -114,4 +171,15 @@ class RedisFactory { return extension_loaded('redis') && version_compare(phpversion('redis'), '2.2.5', '>='); } + + /** + * Php redis does support configurable extra parameters since version 5.3.0, see: https://github.com/phpredis/phpredis#connect-open. + * We need to check if the current version supports extra connection parameters, otherwise the connect method will throw an exception + * + * @return boolean + */ + private function isConnectionParametersSupported(): bool { + return \extension_loaded('redis') && + \version_compare(\phpversion('redis'), self::REDIS_EXTRA_PARAMETERS_MINIMAL_VERSION, '>='); + } } |