Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connect to Sentinel with username: how to implement right ? #1427

Open
linuxmail opened this issue Jan 9, 2024 · 3 comments
Open

Connect to Sentinel with username: how to implement right ? #1427

linuxmail opened this issue Jan 9, 2024 · 3 comments
Labels
feature redis-sentinel Replication (managed by redis-sentinel)

Comments

@linuxmail
Copy link

linuxmail commented Jan 9, 2024

Describe the bug
We try to connect to ACL enabled Sentinel, but it fails, because just password will be used

To Reproduce

We have this code:

<?php
namespace App\Lib;
use App\Lib\Consts;
class Redis
{

[...]

    public function info()
    {    	 
    	$this->logger->writeLog(Consts::DEBUG,  "[Redis]" . $this->host . $this->port . $this->password );
    }

    private function connect()
    {
    	$logPrefix = '[Redis:connect]';

    	if ( !$this->redis || $this->redis->ping() != 'PONG' )
		{
            if( self::DEBUG_MODE )
            {
                $this->logger->writeLog(Consts::DEBUG, $logPrefix ."Connecting to redis..." );
            }

            try{
        	    	if ( $this->redis_sentinel == 1 )
        	    	{
                        $sentinels = explode(",", $this->redis_sentinel_ips);
                        
                        $sentinels = array_map(function($value) { return 'tcp://'.$value.'?timeout='.$this->redis_cnx_timeout; }, $sentinels);

                        $options = array(
                                'replication' => 'sentinel',
                                'service' => $this->redis_sentinel_service,
                                'parameters' => [
                                        'password' => $this->redis_sentinel_password,
                                ],
                        );

                        if ( !empty($this->redis_sentinel_username) && !empty($this->redis_sentinel_password) )
                        {
                            $sentinels = explode(",", $this->redis_sentinel_ips);
                            $sentinels = array_map(function($value) { return 'tcp://' . $value . '?user=' . $this->redis_sentinel_username . '&pass=' . $this->redis_sentinel_password; }, $sentinels);

                            $options = array(
                                'replication' => 'sentinel',
                                'service' => $this->redis_sentinel_service,
                                'parameters' => [
                                    'username' => $this->redis_sentinel_username,
                                    'password' => $this->redis_sentinel_password,
                                ],
                            );
                        }

                        $this->redis = new \Predis\Client($sentinels, $options);
        	    	}
        	    	else
        	    	{
        	    		$connection_array = array(
        				"scheme" 	=> "tcp",
        				"host" 		=> $this->host,
        				"port" 		=> $this->port
        		);
        				if( $this->password != "")
        				{
        					$connection_array["password"] = $this->password;
        				}        				
        				$this->redis = new \Predis\Client($connection_array);
                    }        								
    				if ( isset($this->redis) && $this->redis->ping() == 'PONG' )
    				{
                        if( self::DEBUG_MODE )
                        {
    				$this->logger->writeLog(Consts::DEBUG, $logPrefix . "Connected to redis..." . $this->redis->ping());
                        }
    				return 1;
    				}
    				else
    				{
    				   $this->logger->writeLog(Consts::ERROR, $logPrefix . "Redis did not respond to Ping. Check connection settings" );
    					return 0;
    				}
                }
                catch(\Predis\Connection\ConnectionException $e)
                {
                    $msg = $logPrefix . "Redis could not connect to server: " . $e->getMessage();

                    $this->logger->writeLog(Consts::ERROR, $msg);                                    
                     
                    return 0;
                }
		}
		return 1;		 
    }
...

It works for Redis .. so I can see in TCPdump AUTH + Username + password, but if we connect to Sentinel .. I see only Auth and password.

Expected behavior

Use Username AND password for Sentinel

Versions (please complete the following information):

  • Predis: 6.0.1
  • PHP 8.3
  • Redis Server 6.x
  • Docker

It would be great to have a snippet .. how it should look like.

cu denny

@linuxmail linuxmail added the bug label Jan 9, 2024
@tillkruss tillkruss added feature redis-sentinel Replication (managed by redis-sentinel) and removed bug labels Jan 9, 2024
@tillkruss
Copy link
Member

Feel free to open a PR to add support for using ACL with Redis Sentinel.

Ping @vladvildanov

@vladvildanov
Copy link
Contributor

@linuxmail When the Redis Sentinel support was added into Predis there was no support for ACL authentication on Sentinel connections, but since Redis 6.2 there is and I added a PR to fix this issue 👍

After it will be merged and released your client initialisation code should looks like this:

$client = new Client(
    [
        'tcp://127.0.0.1:26379?username=username&password=password',
        'tcp://127.0.0.1:26380?username=username&password=password',
        'tcp://127.0.0.1:26381?username=username&password=password',
    ], [
    'replication' => 'sentinel',
    'service' => 'mymaster'
]);

For sentinel connections you should provide username and password per connection. If your node requires authentication as well it should be provided from parameters, like this:

$client = new Client(
    [
        'tcp://127.0.0.1:26379?username=username&password=password',
        'tcp://127.0.0.1:26380?username=username&password=password',
        'tcp://127.0.0.1:26381?username=username&password=password',
    ], [
    'replication' => 'sentinel',
    'service' => 'mymaster',
    'parameters' => [
            'username' => 'username',
            'password' => 'password',
    ],
]);

@linuxmail
Copy link
Author

Hi @vladvildanov

AWESOME ! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature redis-sentinel Replication (managed by redis-sentinel)
Development

Successfully merging a pull request may close this issue.

3 participants