Commit daea6098 authored by Ignacio Corderi's avatar Ignacio Corderi
Browse files

Merge branch 'feature/security' into develop

parents dd878969 6208eb61
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
Changes since 0.7.0
===================
Changes since 0.7.1
===========================
This section will document changes to the library since the last release

Changes from 0.7.0 to 0.7.1
===========================

## New features
- Added setSecurity on AdminClient
- Added getVersion and getVersionAsync to the library.

## Bug Fixes
- Fixed tests not running and testcases with hardcoded 'localhost'
- Fixed flush operation build parameters (Merge #5, contributed by @rpcope1).
- AsyncClient returns NotConnected exception when an operation is attempted on a client before calling connect().
- Lowered default number of keys asked on ranges to 200 (ASKOVAD-287).
+1 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@

# Protocol version
protocol_version = '2.0.3'
version = '0.7.0'
version = '0.7.1'

#utils
from utils import buildRange
+8 −0
Original line number Diff line number Diff line
@@ -56,6 +56,14 @@ class AdminClient(baseclient.BaseClient):
    def updateFirmware(self, binary, pin=None):
        return self._process(operations.Setup, firmware=binary, pin=pin)

    def setSecurity(self, acls):
        """
            Set the access control lists to lock users out of different permissions.
            Arguments: aclList -> A list of ACL (Access Control List) objects.
        """
        return self._process(operations.Security, acls=acls)


def main():
    from kinetic.common import LogTypes
    from kinetic import Client
+62 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import kinetic_pb2 as messages
MAX_KEY_SIZE = 4*1024
MAX_VALUE_SIZE = 1024*1024


class Entry(object):

    #RPC: Note, you could build this as a class method, if you wanted the fromMessage to build
@@ -51,6 +52,7 @@ class Entry(object):
        else:
            return self.key


class EntryMetadata(object):

    @staticmethod
@@ -67,6 +69,7 @@ class EntryMetadata(object):
    def __str__(self):
        return self.version or "None"


class KeyRange(object):

    def __init__(self, startKey, endKey, startKeyInclusive=True,
@@ -79,6 +82,7 @@ class KeyRange(object):
    def getFrom(self, client, max=1024):
        return client.getKeyRange(self.startKey, self.endKey, self.startKeyInclusive, self.endKeyInclusive, max)


class P2pOp(object):

    def __init__(self, key, version=None, newKey=None, force=None):
@@ -87,6 +91,7 @@ class P2pOp(object):
        self.newKey = newKey
        self.force = force


class Peer(object):

    def __init__(self, hostname='localhost', port=8123, tls=None):
@@ -133,12 +138,68 @@ class KineticMessageException(KineticException):
    def __str__(self):
        return self.code + (': %s' % self.value if self.value else '')


class HmacAlgorithms:
    INVALID_HMAC_ALGORITHM = -1 # Must come first, so default is invalid
    HmacSHA1 = 1 # this is the default


class ACL(object):

    DEFAULT_IDENTITY=1
    DEFAULT_KEY = "asdfasdf"

    def __init__(self, identity=DEFAULT_IDENTITY, key=DEFAULT_KEY, algorithm=HmacAlgorithms.HmacSHA1):
        self.identity = identity
        self.key = key
        self.hmacAlgorithm = algorithm
        self.domains = set()


class Domain(object):
    """
        Domain object, which corresponds to the domain object in the Java client,
        and is the Scope object in the protobuf.
    """
    def __init__(self, roles=None, tlsRequried=False, offset=None, value=None):
        if roles:
            self.roles = set(roles)
        else:
            self.roles = set()
        self.tlsRequired = tlsRequried
        self.offset = offset
        self.value = value


class Roles(object):
    """
        Role enumeration, which is the same thing as the permission field for each
        scope in the protobuf ACL list.
    """
    READ = 0
    WRITE = 1
    DELETE = 2
    RANGE = 3
    SETUP = 4
    P2POP = 5
    GETLOG = 7
    SECURITY = 8

    @classmethod
    def all(cls):
        """
            Return the set of all possible roles.
        """
        return [cls.READ, cls.WRITE, cls.DELETE, cls.RANGE, cls.SETUP, cls.P2POP, cls.GETLOG, cls.SECURITY]


class Synchronization:
    INVALID_SYNCHRONIZATION = -1
    WRITETHROUGH = 1 # Sync
    WRITEBACK = 2 # Async
    FLUSH = 3


class IntegrityAlgorithms:
    SHA1 = 1
    SHA2 = 2
@@ -148,6 +209,7 @@ class IntegrityAlgorithms:
    # 6-99 are reserverd.
    # 100-inf are private algorithms


class LogTypes:
    INVALID_TYPE = -1
    UTILIZATIONS = 0
+46 −1
Original line number Diff line number Diff line
@@ -422,7 +422,52 @@ class Setup(object):
    @staticmethod
    def parse(m, value):
        Entry.fromResponse(m, value)
        return True
        return

    @staticmethod
    def onError(e):
        raise e

class Security(object):

    @staticmethod
    def build(acls):
        m = messages.Message()
        m.command.header.messageType = messages.Message.SECURITY

        proto_acls = []

        for acl in acls:
            proto_acl = messages.Message.Security.ACL(identity=acl.identity,
                                                      key=acl.key,
                                                      hmacAlgorithm=acl.hmacAlgorithm)

            proto_domains = []

            for domain in acl.domains:
                proto_d = messages.Message.Security.ACL.Scope(
                            TlsRequired=domain.tlsRequired)

                proto_d.permission.extend(domain.roles)

                if domain.offset:
                    proto_d.offset = domain.offset
                if domain.value:
                    proto_d.value = domain.value

                proto_domains.append(proto_d)

            proto_acl.scope.extend(proto_domains)
            proto_acls.append(proto_acl)

        m.command.body.security.acl.extend(proto_acls)

        return (m, None)

    @staticmethod
    def parse(m, value):
        Entry.fromResponse(m, value)
        return

    @staticmethod
    def onError(e):
Loading