Skip to content

Commit

Permalink
Enable encrypted connections with TLS (#129)
Browse files Browse the repository at this point in the history
* Enable encrypted connections with TLS

Use standalone PHP driver because PHP Redis extension doesn't work with TLS.
Syntax `$redis = new Credis_Client('tls://host[:port][/persistence_identifier]')`

* Enable encrypted connections with TLS
  • Loading branch information
lorextera authored and colinmollenhour committed Oct 25, 2019
1 parent a692d8d commit ee56982
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 7 deletions.
27 changes: 22 additions & 5 deletions Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ class Credis_Client {
*/
protected $host;

/**
* Scheme of the Redis server (tcp, tls, unix)
* @var string
*/
protected $scheme;

/**
* Port on which the Redis server is running
* @var integer
Expand Down Expand Up @@ -310,12 +316,17 @@ public function __construct($host = '127.0.0.1', $port = 6379, $timeout = null,
{
$this->host = (string) $host;
$this->port = (int) $port;
$this->scheme = null;
$this->timeout = $timeout;
$this->persistent = (string) $persistent;
$this->standalone = ! extension_loaded('redis');
$this->authPassword = $password;
$this->selectedDb = (int)$db;
$this->convertHost();
if ($this->scheme == 'tls') {
// PHP Redis extension doesn't work with TLS
$this->standalone = true;
}
}

public function __destruct()
Expand Down Expand Up @@ -402,24 +413,30 @@ public function setCloseOnDestruct($flag)
}
protected function convertHost()
{
if (preg_match('#^(tcp|unix)://(.*)$#', $this->host, $matches)) {
if($matches[1] == 'tcp') {
if (preg_match('#^(tcp|tls|unix)://(.*)$#', $this->host, $matches)) {
if($matches[1] == 'tcp' || $matches[1] == 'tls') {
$this->scheme = $matches[1];
if ( ! preg_match('#^([^:]+)(:([0-9]+))?(/(.+))?$#', $matches[2], $matches)) {
throw new CredisException('Invalid host format; expected tcp://host[:port][/persistence_identifier]');
throw new CredisException('Invalid host format; expected '.$this->scheme.'://host[:port][/persistence_identifier]');
}
$this->host = $matches[1];
$this->port = (int) (isset($matches[3]) ? $matches[3] : 6379);
$this->persistent = isset($matches[5]) ? $matches[5] : '';
} else {
$this->host = $matches[2];
$this->port = NULL;
$this->scheme = 'unix';
if (substr($this->host,0,1) != '/') {
throw new CredisException('Invalid unix socket format; expected unix:///path/to/redis.sock');
}
}
}
if ($this->port !== NULL && substr($this->host,0,1) == '/') {
$this->port = NULL;
$this->scheme = 'unix';
}
if (!$this->scheme) {
$this->scheme = 'tcp';
}
}
/**
Expand All @@ -436,8 +453,8 @@ public function connect()
if ($this->standalone) {
$flags = STREAM_CLIENT_CONNECT;
$remote_socket = $this->port === NULL
? 'unix://'.$this->host
: 'tcp://'.$this->host.':'.$this->port;
? $this->scheme.'://'.$this->host
: $this->scheme.'://'.$this->host.':'.$this->port;
if ($this->persistent && $this->port !== NULL) {
// Persistent connections to UNIX sockets are not supported
$remote_socket .= '/'.$this->persistent;
Expand Down
33 changes: 33 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,39 @@ Credis_Client also supports transparent command renaming. Write code using the o
client will send the aliased commands to the server transparently. Specify the renamed commands using a prefix
for md5, a callable function, individual aliases, or an array map of aliases. See "Redis Security":http://redis.io/topics/security for more info.

## Supported connection string formats

```php
$redis = new Credis_Client(/* connection string */);
```

### Unix socket connection string

`unix:///path/to/redis.sock`

### TCP connection string

`tcp://host[:port][/persistence_identifier]`

### TLS connection string

`tls://host[:port][/persistence_identifier]`

#### Enable transport level security (TLS)

Use TLS connection string `tls://127.0.0.1:6379` instead of TCP connection `tcp://127.0.0.1:6379` string in order to enable transport level security.

```php
require 'Credis/Client.php';
$redis = new Credis_Client('tls://127.0.0.1:6379');
$redis->set('awesome', 'absolutely');
echo sprintf('Is Credis awesome? %s.\n', $redis->get('awesome'));

// When arrays are given as arguments they are flattened automatically
$redis->rpush('particles', array('proton','electron','neutron'));
$particles = $redis->lrange('particles', 0, -1);
```

## Clustering your servers

Credis also includes a way for developers to fully utilize the scalability of Redis with multiple servers and [consistent hashing](http://en.wikipedia.org/wiki/Consistent_hashing).
Expand Down
35 changes: 33 additions & 2 deletions tests/CredisTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,27 @@ public function testConnectionStrings()
$this->assertEquals('abc123',$this->credis->getPersistence());
}

public function testConnectionStringsTls()
{
$this->credis->close();
$this->credis = new Credis_Client('tls://'.$this->redisConfig[0]['host'] . ':' . $this->redisConfig[0]['port']);
if ($this->useStandalone) {
$this->credis->forceStandalone();
}
$this->assertEquals($this->credis->getHost(),$this->redisConfig[0]['host']);
$this->assertEquals($this->credis->getPort(),$this->redisConfig[0]['port']);
$this->credis = new Credis_Client('tls://'.$this->redisConfig[0]['host']);
if ($this->useStandalone) {
$this->credis->forceStandalone();
}
$this->assertEquals($this->credis->getPort(),$this->redisConfig[0]['port']);
$this->credis = new Credis_Client('tls://'.$this->redisConfig[0]['host'] . ':' . $this->redisConfig[0]['port'] . '/abc123');
if ($this->useStandalone) {
$this->credis->forceStandalone();
}
$this->assertEquals('abc123',$this->credis->getPersistence());
}

/**
* @group UnixSocket
*/
Expand All @@ -665,7 +686,7 @@ public function testConnectionStringsSocket()
$this->assertEquals('value',$this->credis->get('key'));
}

public function testInvalidTcpConnectionstring()
public function testInvalidTcpConnectionString()
{
$this->credis->close();
$this->setExpectedExceptionShim('CredisException','Invalid host format; expected tcp://host[:port][/persistence_identifier]');
Expand All @@ -675,7 +696,17 @@ public function testInvalidTcpConnectionstring()
}
}

public function testInvalidUnixSocketConnectionstring()
public function testInvalidTlsConnectionString()
{
$this->credis->close();
$this->setExpectedExceptionShim('CredisException','Invalid host format; expected tls://host[:port][/persistence_identifier]');
$this->credis = new Credis_Client('tls://'.$this->redisConfig[0]['host'] . ':abc');
if ($this->useStandalone) {
$this->credis->forceStandalone();
}
}

public function testInvalidUnixSocketConnectionString()
{
$this->credis->close();
$this->setExpectedExceptionShim('CredisException','Invalid unix socket format; expected unix:///path/to/redis.sock');
Expand Down

0 comments on commit ee56982

Please sign in to comment.