Hi Folks,

I'm trying to use zookeeper via zkpython to set an acl on a node, and then
test that acl. I've configured a super user, and create a node with an acl
with the all permission and a digest scheme. However i find that i end up
not being able to touch the node with the credentials as per the configured
acl user, perhaps even more oddly i can't access the node with the super
user (passed in via system property on the cli via
Dzookeeper.DigestAuthenticationProvider.superDigest). Any attempt to acces
the node raises an exception
zookeeper.NoAuthException: not authenticated

i've attached a demonstration script that exhibits the problem. Is there
something i'm doing wrong here or is it an issue with zkpython?

thanks,

Kapil
import zookeeper
import threading
import hashlib
import base64

ZOO_OPEN_ACL_UNSAFE = {'scheme': 'world',
                       'id': 'anyone',
                       'perms': zookeeper.PERM_ALL}


class Connection(object):

    def __init__(self, servers):
        self.servers = servers
        self.connected = False
        self.timeout = 10000
        self.cv = threading.Condition()
        self.handle = None

        self.cv.acquire()
        self.handle = zookeeper.init(
            servers, self.connection_watcher, self.timeout)

        self.cv.wait(self.timeout/1000)
        if not self.connected:
            raise RuntimeError("unable to connect %s" % servers)

    def connection_watcher(self, handle, type, state, path):
        print type, state, path
        self.handle = handle
        self.cv.acquire()
        self.connected = True
        self.cv.notifyAll()
        self.cv.release()

    def close(self):
        return zookeeper.close(self.handle)

    def authenticate(self, scheme, credentials):

        def callback(handle, result):
            self.cv.acquire()
            assert self.handle == handle
            self.cv.notify()
            self.cv.release()

        self.cv.acquire()
        zookeeper.add_auth(
            self.handle, scheme, credentials, callback)
        self.cv.wait()

    def create(self, path, data="", acl=[ZOO_OPEN_ACL_UNSAFE]):
        return zookeeper.create(self.handle, path, data, acl,
                                zookeeper.EPHEMERAL)

    def get_children(self, path):
        return zookeeper.get_children(self.handle, path)


def identity(credentials):
    user, password = credentials.split(":")
    return "%s:%s" % (user,
               base64.b64encode(hashlib.new("sha1", password).digest()))


USER_ROOT = "super:pass"
USER_TRUCKS = "trucks:foobar"


def main():
    conn = Connection("127.0.0.1:2181")
    conn.authenticate("digest", USER_ROOT)
    conn.create("/cars")

    children = conn.get_children("/cars")
    assert not children

    truck_acl = [
        {'scheme': 'digest',
         'perms': zookeeper.PERM_ALL,
         'id': identity(USER_TRUCKS)},
        {'scheme': 'digest',
         'perms': zookeeper.PERM_ALL,
         'id': identity(USER_ROOT)}]

    # create an ephemeral truck node with the given acl
    conn.create("/trucks", acl=truck_acl)

    # this also fails, but demonstrating with another conn for completeness.
    #conn.get_children("/trucks")

    conn2 = Connection("127.0.0.1:2181")
    conn2.authenticate("digest", USER_TRUCKS)

    try:
        conn2.get_children("/trucks")
    finally:
        conn.close()
        conn2.close()

if __name__ == '__main__':
    main()

Reply via email to