diff options
-rw-r--r-- | CHANGES | 9 | ||||
-rw-r--r-- | redis/__init__.py | 2 | ||||
-rwxr-xr-x | redis/connection.py | 16 | ||||
-rw-r--r-- | redis/exceptions.py | 8 |
4 files changed, 34 insertions, 1 deletions
@@ -1,3 +1,12 @@ +* 3.4.1 (in development) + * Prior to ACL support, redis-py ignored the username component of + Connection URLs. With ACL support, usernames are no longer ignored and + are used to authenticate against an ACL rule. Some cloud vendors with + managed Redis instances (like Heroku) provide connection URLs with a + username component pre-ACL that is not intended to be used. Sending that + username to Redis servers < 6.0.0 results in an error. Attempt to detect + this condition and retry the AUTH command with only the password such + that authentication continues to work for these users. #1274 * 3.4.0 * Allow empty pipelines to be executed if there are WATCHed keys. This is a convenient way to test if any of the watched keys changed diff --git a/redis/__init__.py b/redis/__init__.py index 369d39e..57deb86 100644 --- a/redis/__init__.py +++ b/redis/__init__.py @@ -9,6 +9,7 @@ from redis.connection import ( from redis.utils import from_url from redis.exceptions import ( AuthenticationError, + AuthenticationWrongNumberOfArgsError, BusyLoadingError, ChildDeadlockedError, ConnectionError, @@ -35,6 +36,7 @@ VERSION = tuple(map(int_or_str, __version__.split('.'))) __all__ = [ 'AuthenticationError', + 'AuthenticationWrongNumberOfArgsError', 'BlockingConnectionPool', 'BusyLoadingError', 'ChildDeadlockedError', diff --git a/redis/connection.py b/redis/connection.py index 7efb0a2..a013145 100755 --- a/redis/connection.py +++ b/redis/connection.py @@ -17,6 +17,7 @@ from redis._compat import (xrange, imap, byte_to_chr, unicode, long, sendall, shutdown, ssl_wrap_socket) from redis.exceptions import ( AuthenticationError, + AuthenticationWrongNumberOfArgsError, BusyLoadingError, ChildDeadlockedError, ConnectionError, @@ -135,6 +136,8 @@ class BaseParser(object): 'max number of clients reached': ConnectionError, 'Client sent AUTH, but no password is set': AuthenticationError, 'invalid password': AuthenticationError, + 'wrong number of arguments for \'auth\' command': + AuthenticationWrongNumberOfArgsError, }, 'EXECABORT': ExecAbortError, 'LOADING': BusyLoadingError, @@ -630,7 +633,18 @@ class Connection(object): # avoid checking health here -- PING will fail if we try # to check the health prior to the AUTH self.send_command('AUTH', *auth_args, check_health=False) - if nativestr(self.read_response()) != 'OK': + + try: + auth_response = self.read_response() + except AuthenticationWrongNumberOfArgsError: + # a username and password were specified but the Redis + # server seems to be < 6.0.0 which expects a single password + # arg. retry auth with just the password. + # https://github.com/andymccurdy/redis-py/issues/1274 + self.send_command('AUTH', self.password, check_health=False) + auth_response = self.read_response() + + if nativestr(auth_response) != 'OK': raise AuthenticationError('Invalid Username or Password') # if a client_name is given, set it diff --git a/redis/exceptions.py b/redis/exceptions.py index 6f47024..760af66 100644 --- a/redis/exceptions.py +++ b/redis/exceptions.py @@ -72,3 +72,11 @@ class LockNotOwnedError(LockError): class ChildDeadlockedError(Exception): "Error indicating that a child process is deadlocked after a fork()" pass + + +class AuthenticationWrongNumberOfArgsError(ResponseError): + """ + An error to indicate that the wrong number of args + were sent to the AUTH command + """ + pass |