summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen <stephen.sorriaux@gmail.com>2018-10-08 12:07:05 +0200
committerJeff Widman <jeff@jeffwidman.com>2018-10-08 10:21:43 -0700
commit2320ab391f3804a9ddea9c5c86eb86467bb1dbf8 (patch)
tree7db37f301bc9f1efa12a0a7cd1c5fcd80f980714
parentde20be917855713169863b65a7aa0634fb78b698 (diff)
downloadkazoo-2320ab391f3804a9ddea9c5c86eb86467bb1dbf8.tar.gz
fix(core): allow authentification in RO and RW modes
Fixes the bug introduced by PR #512 where it is not possible to connect in RO mode using authentication. Since the SASL authentification feature, the _session_fallback method should be called only after the SASL authentification is done. A new method is added to the ConnectionHandler class in order to correctly use KeeperState.CONNECTED or KeeperState.CONNECTED_RO.
-rw-r--r--kazoo/protocol/connection.py104
1 files changed, 56 insertions, 48 deletions
diff --git a/kazoo/protocol/connection.py b/kazoo/protocol/connection.py
index 591ee53..7f686c0 100644
--- a/kazoo/protocol/connection.py
+++ b/kazoo/protocol/connection.py
@@ -158,6 +158,7 @@ class ConnectionHandler(object):
self._xid = None
self._rw_server = None
self._ro_mode = False
+ self._ro = False
self._connection_routine = None
@@ -439,9 +440,9 @@ class ConnectionHandler(object):
self._send_sasl_request(challenge=response,
timeout=client._session_timeout)
else:
- # authentication is ok, state is CONNECTED
+ # authentication is ok, state is CONNECTED or CONNECTED_RO
# remove sensible information from the object
- client._session_callback(KeeperState.CONNECTED)
+ self._set_connected_ro_or_rw(client)
self.sasl_cli.dispose()
else:
self.logger.log(BLATHER, 'Reading for header %r', header)
@@ -684,55 +685,52 @@ class ConnectionHandler(object):
read_timeout)
if connect_result.read_only:
- client._session_callback(KeeperState.CONNECTED_RO)
- self._ro_mode = iter(self._server_pinger())
- else:
- self._ro_mode = None
+ self._ro = True
- # Get a copy of the auth data before iterating, in case it is
- # changed.
- client_auth_data_copy = copy.copy(client.auth_data)
-
- if client.use_sasl and self.sasl_cli is None:
- if PURESASL_AVAILABLE:
- for scheme, auth in client_auth_data_copy:
- if scheme == 'sasl':
- username, password = auth.split(":")
- self.sasl_cli = SASLClient(
- host=client.sasl_server_principal,
- service='zookeeper',
- mechanism='DIGEST-MD5',
- username=username,
- password=password
- )
- break
-
- # As described in rfc
- # https://tools.ietf.org/html/rfc2831#section-2.1
- # sending empty challenge
- self._send_sasl_request(challenge=b'',
- timeout=connect_timeout)
- else:
- self.logger.warn('Pure-sasl library is missing while sasl'
- ' authentification is configured. Please'
- ' install pure-sasl library to connect '
- 'using sasl. Now falling back '
- 'connecting WITHOUT any '
- 'authentification.')
- client.use_sasl = False
- client._session_callback(KeeperState.CONNECTED)
- else:
- client._session_callback(KeeperState.CONNECTED)
+ # Get a copy of the auth data before iterating, in case it is
+ # changed.
+ client_auth_data_copy = copy.copy(client.auth_data)
+
+ if client.use_sasl and self.sasl_cli is None:
+ if PURESASL_AVAILABLE:
for scheme, auth in client_auth_data_copy:
- if scheme == "digest":
- ap = Auth(0, scheme, auth)
- zxid = self._invoke(
- connect_timeout / 1000.0,
- ap,
- xid=AUTH_XID
+ if scheme == 'sasl':
+ username, password = auth.split(":")
+ self.sasl_cli = SASLClient(
+ host=client.sasl_server_principal,
+ service='zookeeper',
+ mechanism='DIGEST-MD5',
+ username=username,
+ password=password
)
- if zxid:
- client.last_zxid = zxid
+ break
+
+ # As described in rfc
+ # https://tools.ietf.org/html/rfc2831#section-2.1
+ # sending empty challenge
+ self._send_sasl_request(challenge=b'',
+ timeout=connect_timeout)
+ else:
+ self.logger.warn('Pure-sasl library is missing while sasl'
+ ' authentification is configured. Please'
+ ' install pure-sasl library to connect '
+ 'using sasl. Now falling back '
+ 'connecting WITHOUT any '
+ 'authentification.')
+ client.use_sasl = False
+ self._set_connected_ro_or_rw(client)
+ else:
+ self._set_connected_ro_or_rw(client)
+ for scheme, auth in client_auth_data_copy:
+ if scheme == "digest":
+ ap = Auth(0, scheme, auth)
+ zxid = self._invoke(
+ connect_timeout / 1000.0,
+ ap,
+ xid=AUTH_XID
+ )
+ if zxid:
+ client.last_zxid = zxid
return read_timeout, connect_timeout
@@ -742,3 +740,13 @@ class ConnectionHandler(object):
self._xid = (self._xid % 2147483647) + 1
xid = self._xid
self._submit(sasl_request, timeout / 1000.0, xid)
+
+ def _set_connected_ro_or_rw(self, client):
+ """ Called to decide whether to set the KeeperState to CONNECTED_RO
+ or CONNECTED"""
+ if self._ro:
+ client._session_callback(KeeperState.CONNECTED_RO)
+ self._ro_mode = iter(self._server_pinger())
+ else:
+ client._session_callback(KeeperState.CONNECTED)
+ self._ro_mode = None