Skip to content

Commit

Permalink
feat(core): improve SASL interface
Browse files Browse the repository at this point in the history
* Move SASL configuration out of auth_data into its own dictionary which
  exposes more SASL features (e.g. server service name, client principal,
  ...)
* Remove SASL from auth_data and place it between 'connection' and
  'zookeeper protocol level authentication' to simplify connection logic
  and bring code in line with the protocol stack (SASL wraps Zookeeper,
  not the other way around).
* Consistent exception, `AuthFailedError`, raised during authentication
  failure between SASL and ZK authentication.
* New 'SASLException' exception raised in case of SASL intrisinc
  failures.
* Add support for GSSAPI (Kerberos).

Example connection using Digest-MD5:

  client = KazooClient(
      sasl_options={'mechanism': 'DIGEST-MD5',
                    'username': 'myusername',
                    'password': 'mypassword'}
  )

Example connection using GSSAPI (with some optional settings):

  client = KazooClient(
      sasl_options={'mechanism': 'GSSAPI',
                    'service': 'myzk',                  # optional
                    'principal': 'clt@EXAMPLE.COM'}     # optional
  )
  • Loading branch information
ceache authored and Charles-Henri de Boysson committed Dec 16, 2018
1 parent 4242da8 commit 463face
Show file tree
Hide file tree
Showing 12 changed files with 175 additions and 128 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@ matrix:
env: ZOOKEEPER_VERSION=3.3.6 TOX_VENV=py36
- python: '3.6'
env: ZOOKEEPER_VERSION=3.4.13 TOX_VENV=py36
- python: '3.6'
env: ZOOKEEPER_VERSION=3.4.13 TOX_VENV=py36-sasl
- python: '3.6'
env: ZOOKEEPER_VERSION=3.5.4-beta TOX_VENV=py36
- python: '3.6'
env: ZOOKEEPER_VERSION=3.5.4-beta TOX_VENV=py36-sasl
- python: pypy
env: ZOOKEEPER_VERSION=3.3.6 TOX_VENV=pypy
- python: pypy
Expand Down
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
<a name="2.7.0"></a>
## 2.7.0 (next)


#### Features

* **core:**
* Add `GSSAPI` support to which enables kazoo to authenticate against a
kerberized Zookeeper using `SASL GSSAPI`.


<a name="2.6.0"></a>
## 2.6.0 (2018-11-14)

Expand Down
3 changes: 1 addition & 2 deletions ensure-zookeeper-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ cd $HERE

# Yield execution to venv command

$*

exec $*
25 changes: 8 additions & 17 deletions kazoo/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ class KazooClient(object):
"""
def __init__(self, hosts='127.0.0.1:2181',
timeout=10.0, client_id=None, handler=None,
default_acl=None, auth_data=None, read_only=None,
randomize_hosts=True, connection_retry=None,
default_acl=None, auth_data=None, sasl_options=None,
read_only=None, randomize_hosts=True, connection_retry=None,
command_retry=None, logger=None, keyfile=None,
keyfile_password=None, certfile=None, ca=None,
use_ssl=False, verify_certs=True, **kwargs):
Expand All @@ -123,6 +123,9 @@ def __init__(self, hosts='127.0.0.1:2181',
A list of authentication credentials to use for the
connection. Should be a list of (scheme, credential)
tuples as :meth:`add_auth` takes.
:param sasl_options:
SASL options for the connection. Should be a dict of SASL options
passed to the underlying mechs if SASL support is to be used.
:param read_only: Allow connections to read only servers.
:param randomize_hosts: By default randomize host selection.
:param connection_retry:
Expand Down Expand Up @@ -275,7 +278,8 @@ def __init__(self, hosts='127.0.0.1:2181',

self._conn_retry.interrupt = lambda: self._stopped.is_set()
self._connection = ConnectionHandler(
self, self._conn_retry.copy(), logger=self.logger)
self, self._conn_retry.copy(), logger=self.logger,
sasl_options=sasl_options)

# Every retry call should have its own copy of the retry helper
# to avoid shared retry counts
Expand Down Expand Up @@ -303,15 +307,6 @@ def _retry(*args, **kwargs):
self.Semaphore = partial(Semaphore, self)
self.ShallowParty = partial(ShallowParty, self)

# Managing SASL client
self.use_sasl = False
for scheme, auth in self.auth_data:
if scheme == "sasl":
self.use_sasl = True
# Could be used later for GSSAPI implementation
self.sasl_server_principal = "zk-sasl-md5"
break

# If we got any unhandled keywords, complain like Python would
if kwargs:
raise TypeError('__init__() got unexpected keyword arguments: %s'
Expand Down Expand Up @@ -737,12 +732,8 @@ def add_auth(self, scheme, credential):
"""Send credentials to server.
:param scheme: authentication scheme (default supported:
"digest", "sasl"). Note that "sasl" scheme is
requiring "pure-sasl" library to be
installed.
"digest").
:param credential: the credential -- value depends on scheme.
"digest": user:password
"sasl": user:password
:returns: True if it was successful.
:rtype: bool
Expand Down
7 changes: 7 additions & 0 deletions kazoo/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ class WriterNotClosedException(KazooException):
"""


class SASLException(KazooException):
"""Raised if SASL encountered a (local) error.
.. versionadded:: 2.7.0
"""


def _invalid_error_code():
raise RuntimeError('Invalid error code')

Expand Down
Loading

0 comments on commit 463face

Please sign in to comment.