From f4fb1fe3e4fbedd85dae6b6f84b414fa4e037363 Mon Sep 17 00:00:00 2001 From: Evgeny Anisiforov Date: Fri, 24 Aug 2018 16:51:02 +0200 Subject: [PATCH 1/7] allow tls as scheme in DSN string for predis library --- pkg/redis/RedisConnectionFactory.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pkg/redis/RedisConnectionFactory.php b/pkg/redis/RedisConnectionFactory.php index 3ed90dc5d..398e6d359 100644 --- a/pkg/redis/RedisConnectionFactory.php +++ b/pkg/redis/RedisConnectionFactory.php @@ -116,8 +116,10 @@ private function createRedis() */ private function parseDsn($dsn) { - if (false === strpos($dsn, 'redis:')) { - throw new \LogicException(sprintf('The given DSN "%s" is not supported. Must start with "redis:".', $dsn)); + $unsupportedError = 'The given DSN "%s" is not supported. Must start with "redis:".'; + + if ((false === strpos($dsn, 'redis:')) and (false === strpos($dsn, 'tls:'))) { + throw new \LogicException(sprintf($unsupportedError, $dsn)); } if (false === $config = parse_url($dsn)) { @@ -131,7 +133,12 @@ private function parseDsn($dsn) $config = array_replace($queryConfig, $config); } - unset($config['query'], $config['scheme']); + //predis additionaly supports tls as scheme, but it must remain in the $config array + if ($config['vendor']!='predis') { + if ($config['scheme']!='redis') throw new \LogicException(sprintf($unsupportedError, $dsn)); + unset($config['scheme']); + } + unset($config['query']); $config['lazy'] = empty($config['lazy']) ? false : true; $config['persisted'] = empty($config['persisted']) ? false : true; From 24cba0773635e16331c887243e15b1d5f4aadd25 Mon Sep 17 00:00:00 2001 From: Evgeny Anisiforov Date: Fri, 24 Aug 2018 17:58:05 +0200 Subject: [PATCH 2/7] allow rediss as scheme in DSN string for predis library --- pkg/redis/RedisConnectionFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/redis/RedisConnectionFactory.php b/pkg/redis/RedisConnectionFactory.php index 398e6d359..bc1142e29 100644 --- a/pkg/redis/RedisConnectionFactory.php +++ b/pkg/redis/RedisConnectionFactory.php @@ -118,7 +118,7 @@ private function parseDsn($dsn) { $unsupportedError = 'The given DSN "%s" is not supported. Must start with "redis:".'; - if ((false === strpos($dsn, 'redis:')) and (false === strpos($dsn, 'tls:'))) { + if ((false === strpos($dsn, 'redis:')) and (false === strpos($dsn, 'rediss:'))) { throw new \LogicException(sprintf($unsupportedError, $dsn)); } From e9fad4b179e6a81e71eb93d830c560a47a5dfc39 Mon Sep 17 00:00:00 2001 From: Evgeny Anisiforov Date: Thu, 30 Aug 2018 12:38:13 +0200 Subject: [PATCH 3/7] add tests for rediss connection --- pkg/redis/RedisConnectionFactory.php | 18 +++++++-- .../RedisConnectionFactoryConfigTest.php | 40 +++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/pkg/redis/RedisConnectionFactory.php b/pkg/redis/RedisConnectionFactory.php index bc1142e29..c591c8224 100644 --- a/pkg/redis/RedisConnectionFactory.php +++ b/pkg/redis/RedisConnectionFactory.php @@ -50,13 +50,18 @@ public function __construct($config = 'redis:') } $this->config = array_replace($this->defaultConfig(), $config); + if (isset($this->config['vendor'])) { + $vendor = $this->config['vendor']; + } else { + $vendor = ""; + } $supportedVendors = ['predis', 'phpredis', 'custom']; - if (false == in_array($this->config['vendor'], $supportedVendors, true)) { + if (false == in_array($vendor, $supportedVendors, true)) { throw new \LogicException(sprintf( 'Unsupported redis vendor given. It must be either "%s". Got "%s"', implode('", "', $supportedVendors), - $this->config['vendor'] + $vendor )); } } @@ -133,8 +138,15 @@ private function parseDsn($dsn) $config = array_replace($queryConfig, $config); } + if (isset($config['vendor'])) { + $vendor = $config['vendor']; + } else { + $vendor = ""; + } + + //predis additionaly supports tls as scheme, but it must remain in the $config array - if ($config['vendor']!='predis') { + if ($vendor!='predis') { if ($config['scheme']!='redis') throw new \LogicException(sprintf($unsupportedError, $dsn)); unset($config['scheme']); } diff --git a/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php b/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php index cfcdf959b..cec0b1945 100644 --- a/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php +++ b/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php @@ -125,6 +125,46 @@ public static function provideConfigs() ], ]; + //check normal redis connection for predis library + yield [ + 'redis://localhost:1234?foo=bar&lazy=0&vendor=predis', + [ + 'host' => 'localhost', + 'port' => 1234, + 'timeout' => null, + 'reserved' => null, + 'retry_interval' => null, + 'vendor' => 'predis', + 'persisted' => false, + 'lazy' => false, + 'foo' => 'bar', + 'database' => 0, + 'scheme' => 'redis', + 'redis' => null, + ], + ]; + + //check tls connection for predis library + yield [ + 'rediss://localhost:1234?foo=bar&lazy=0&vendor=predis', + [ + 'host' => 'localhost', + 'port' => 1234, + 'timeout' => null, + 'reserved' => null, + 'retry_interval' => null, + 'vendor' => 'predis', + 'persisted' => false, + 'lazy' => false, + 'foo' => 'bar', + 'database' => 0, + 'scheme' => 'rediss', + 'redis' => null, + ], + ]; + + + yield [ ['host' => 'localhost', 'port' => 1234, 'foo' => 'bar'], [ From e4f9187cd668f0f10baaae11f1c2f3523fc3dcf2 Mon Sep 17 00:00:00 2001 From: Evgeny Anisiforov Date: Sun, 2 Sep 2018 00:07:23 +0200 Subject: [PATCH 4/7] remove not required param check --- pkg/redis/RedisConnectionFactory.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkg/redis/RedisConnectionFactory.php b/pkg/redis/RedisConnectionFactory.php index c591c8224..0cdbe7caa 100644 --- a/pkg/redis/RedisConnectionFactory.php +++ b/pkg/redis/RedisConnectionFactory.php @@ -50,11 +50,7 @@ public function __construct($config = 'redis:') } $this->config = array_replace($this->defaultConfig(), $config); - if (isset($this->config['vendor'])) { - $vendor = $this->config['vendor']; - } else { - $vendor = ""; - } + $vendor = $this->config['vendor']; $supportedVendors = ['predis', 'phpredis', 'custom']; if (false == in_array($vendor, $supportedVendors, true)) { From ed54a516e7cec69eff105db2307a8210cb3f2654 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Fri, 7 Sep 2018 15:03:12 +0300 Subject: [PATCH 5/7] [redis] PR-515 fixes --- pkg/redis/PRedis.php | 1 + pkg/redis/PhpRedis.php | 5 +++++ pkg/redis/RedisConnectionFactory.php | 21 +++------------------ 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/pkg/redis/PRedis.php b/pkg/redis/PRedis.php index 799cf53f0..12f3f44ce 100644 --- a/pkg/redis/PRedis.php +++ b/pkg/redis/PRedis.php @@ -26,6 +26,7 @@ class PRedis implements Redis public function __construct(array $config) { $this->config = $this->config = array_replace([ + 'scheme' => null, 'host' => null, 'port' => null, 'pass' => null, diff --git a/pkg/redis/PhpRedis.php b/pkg/redis/PhpRedis.php index e373add32..6fd277e8b 100644 --- a/pkg/redis/PhpRedis.php +++ b/pkg/redis/PhpRedis.php @@ -20,6 +20,7 @@ class PhpRedis implements Redis public function __construct(array $config) { $this->config = array_replace([ + 'scheme' => null, 'host' => null, 'port' => null, 'pass' => null, @@ -73,6 +74,10 @@ public function connect(): void return; } + if ('rediss' == $this->config['scheme']) { + throw new \LogicException('The phpredis extension does not support secured connections. Try to use predis library as vendor.'); + } + $this->redis = new \Redis(); if ($this->config['persisted']) { diff --git a/pkg/redis/RedisConnectionFactory.php b/pkg/redis/RedisConnectionFactory.php index 8d487e40c..ad063ffb9 100644 --- a/pkg/redis/RedisConnectionFactory.php +++ b/pkg/redis/RedisConnectionFactory.php @@ -65,14 +65,13 @@ public function __construct($config = 'redis:') } $this->config = array_replace($this->defaultConfig(), $config); - $vendor = $this->config['vendor']; $supportedVendors = ['predis', 'phpredis', 'custom']; - if (false == in_array($vendor, $supportedVendors, true)) { + if (false == in_array($this->config['vendor'], $supportedVendors, true)) { throw new \LogicException(sprintf( 'Unsupported redis vendor given. It must be either "%s". Got "%s"', implode('", "', $supportedVendors), - $vendor + $this->config['vendor'] )); } } @@ -122,10 +121,8 @@ private function createRedis(): Redis private function parseDsn(string $dsn): array { - $unsupportedError = 'The given DSN "%s" is not supported. Must start with "redis:".'; - if ((false === strpos($dsn, 'redis:')) and (false === strpos($dsn, 'rediss:'))) { - throw new \LogicException(sprintf($unsupportedError, $dsn)); + throw new \LogicException(sprintf('The given DSN "%s" is not supported. Must start with "redis:" or "rediss:".', $dsn)); } if (false === $config = parse_url($dsn)) { @@ -143,18 +140,6 @@ private function parseDsn(string $dsn): array $config = array_replace($queryConfig, $config); } - if (isset($config['vendor'])) { - $vendor = $config['vendor']; - } else { - $vendor = ""; - } - - - //predis additionaly supports tls as scheme, but it must remain in the $config array - if ($vendor!='predis') { - if ($config['scheme']!='redis') throw new \LogicException(sprintf($unsupportedError, $dsn)); - unset($config['scheme']); - } unset($config['query']); $config['lazy'] = empty($config['lazy']) ? false : true; From 414f32265527044456160da1618dd53fcfeb0274 Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Fri, 7 Sep 2018 15:13:22 +0300 Subject: [PATCH 6/7] [redis][doc] add example of secure connection. --- docs/transport/redis.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/transport/redis.md b/docs/transport/redis.md index 871a5d8d2..8a51c61cc 100644 --- a/docs/transport/redis.md +++ b/docs/transport/redis.md @@ -67,6 +67,9 @@ $psrContext = (new \Enqueue\ConnectionFactoryFactory())->create('redis:')->creat $redis = new \Enqueue\Redis\PhpRedis([ /** redis connection options */ ]); $redis->connect(); +// Secure\TLS connection. Works only with predis library. Note second "S" in scheme. +$factory = new RedisConnectionFactory('rediss://user:pass@host/0?vendor=predis'); + $factory = new RedisConnectionFactory($redis); ``` From 856968cdc5b20a6aa2a41bd8fe4fdf10519b4a8b Mon Sep 17 00:00:00 2001 From: Maksim Kotlyar Date: Fri, 7 Sep 2018 15:13:45 +0300 Subject: [PATCH 7/7] [redis] add test, fix tests. --- pkg/redis/RedisConnectionFactory.php | 1 + .../RedisConnectionFactoryConfigTest.php | 23 +++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/pkg/redis/RedisConnectionFactory.php b/pkg/redis/RedisConnectionFactory.php index ad063ffb9..22e9e6e76 100644 --- a/pkg/redis/RedisConnectionFactory.php +++ b/pkg/redis/RedisConnectionFactory.php @@ -152,6 +152,7 @@ private function defaultConfig(): array { return [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 6379, 'timeout' => .0, 'reserved' => null, diff --git a/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php b/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php index 0441320e7..25704ba11 100644 --- a/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php +++ b/pkg/redis/Tests/RedisConnectionFactoryConfigTest.php @@ -25,7 +25,7 @@ public function testThrowNeitherArrayStringNorNullGivenAsConfig() public function testThrowIfSchemeIsNotAmqp() { $this->expectException(\LogicException::class); - $this->expectExceptionMessage('The given DSN "http://example.com" is not supported. Must start with "redis:".'); + $this->expectExceptionMessage('The given DSN "http://example.com" is not supported. Must start with "redis:" or "rediss:".'); new RedisConnectionFactory('http://example.com'); } @@ -57,6 +57,15 @@ public function testCouldBeCreatedWithRedisInstance() $this->assertSame($redisMock, $context->getRedis()); } + public function testThrowIfRedissConnectionUsedWithPhpRedisExtension() + { + $factory = new RedisConnectionFactory('rediss:?vendor=phpredis'); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('The phpredis extension does not support secured connections. Try to use predis library as vendor.'); + $factory->createContext(); + } + /** * @dataProvider provideConfigs * @@ -76,6 +85,7 @@ public static function provideConfigs() null, [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 6379, 'timeout' => null, 'reserved' => null, @@ -92,6 +102,7 @@ public static function provideConfigs() 'redis:', [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 6379, 'timeout' => null, 'reserved' => null, @@ -108,6 +119,7 @@ public static function provideConfigs() [], [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 6379, 'timeout' => null, 'reserved' => null, @@ -124,6 +136,7 @@ public static function provideConfigs() 'redis://localhost:1234?foo=bar&lazy=0&persisted=true&database=5', [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 1234, 'timeout' => null, 'reserved' => null, @@ -142,6 +155,7 @@ public static function provideConfigs() 'redis://localhost:1234?foo=bar&lazy=0&vendor=predis', [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 1234, 'timeout' => null, 'reserved' => null, @@ -151,7 +165,6 @@ public static function provideConfigs() 'lazy' => false, 'foo' => 'bar', 'database' => 0, - 'scheme' => 'redis', 'redis' => null, ], ]; @@ -161,6 +174,7 @@ public static function provideConfigs() 'rediss://localhost:1234?foo=bar&lazy=0&vendor=predis', [ 'host' => 'localhost', + 'scheme' => 'rediss', 'port' => 1234, 'timeout' => null, 'reserved' => null, @@ -170,17 +184,15 @@ public static function provideConfigs() 'lazy' => false, 'foo' => 'bar', 'database' => 0, - 'scheme' => 'rediss', 'redis' => null, ], ]; - - yield [ ['host' => 'localhost', 'port' => 1234, 'foo' => 'bar'], [ 'host' => 'localhost', + 'scheme' => 'redis', 'port' => 1234, 'timeout' => null, 'reserved' => null, @@ -199,6 +211,7 @@ public static function provideConfigs() 'redis://h:asdfqwer1234asdf@ec2-111-1-1-1.compute-1.amazonaws.com:111', [ 'host' => 'ec2-111-1-1-1.compute-1.amazonaws.com', + 'scheme' => 'redis', 'port' => 111, 'timeout' => null, 'reserved' => null,