Commit 239c63b4 authored by Antoine Millet's avatar Antoine Millet
Browse files

Implemented the new right manager into server

parent 4a6970b3
Loading
Loading
Loading
Loading
+11 −7
Original line number Diff line number Diff line
@@ -27,13 +27,6 @@ class RegisteredCCHandler(CCHandler):
        self.logger.info('Client %s disconnected', self.client.login)
        self.client.shutdown()

    def check(self, method, tql=None):
        """ Check if the client have access to this method.
        """
        allow = self.client.server.check(self.client.login, method, tql)
        if not allow:
            raise RightError('You are not allowed to do this action.')

    #
    # Tags registration handler functions:
    #
@@ -270,3 +263,14 @@ class Client(object):
                tag.cached = value
            if ttl is not None:
                tag.ttl = ttl

    def list(self, query, show=None, method=None):
        return self._server.list(query, show=show, method=method, requester=self.login)

    def check(self, method, query=None):
        if query is not None:
            if not self._server.check(query, self.login, method):
                raise RightError('You don\'t have right to do that')
        else:
            if not self._server.check_method(self.login, method):
                raise RightError('You don\'t have right to do that')
+69 −23
Original line number Diff line number Diff line
@@ -14,11 +14,12 @@ from cloudcontrol.server.exceptions import (AlreadyRegistered,
                                            BadRoleError)
#from cloudcontrol.server.jobs import JobsManager
from cloudcontrol.server.clients import Client
from cloudcontrol.server.rights import RightManager
from cloudcontrol.server.jobs import KillOldCliJob

from cloudcontrol.server.db import SObject, SRequestor
from cloudcontrol.common.tql.db.tag import StaticTag
from cloudcontrol.common.tql.db.db import TqlDatabase
from cloudcontrol.common.tql.db.db import TqlDatabase, TqlResponse
from cloudcontrol.common.jobs import JobsManager, JobsStore
from cloudcontrol.server.jobsinterface import ServerJobsManagerInterface

@@ -86,6 +87,10 @@ class CCServer(object):
        self.jobs = JobsManager(self.logger.getChild('jobs'),
                                ServerJobsManagerInterface(self),
                                JobsStore(os.path.join(conf_dir, 'jobs')))

        # The rights manager:
        self.rights = RightManager(self.logger.getChild('rights'),
                                   os.path.join(conf_dir, 'ruleset'))
        self.logger.info('Server started to running')

    def _update_accounts(self):
@@ -212,31 +217,72 @@ class CCServer(object):
                                           'connected' % login)
        client.shutdown()

    def check(self, login, method, tql=None):
        """ Check if the user can call the specified method with specified TQL.
    def filter(self, tql_response, requester, method):
        """ Filter the provided TqlResponse object using rules matching the
            provided requester.
        """

        requestor = tql_response._requestor

        :param login: the login of the user
        :param method: the method to call
        :param tql: the tql passed in argument of the method
        :return: True if user have rights, else False
        allowed_result = TqlResponse(requestor)
        deny_rules = []
        for rule in self.rights.iter_rules_method(method):
            # Is the rule matching the requester object:
            if requester not in self.db.raw_query(rule.match):
                continue
            if rule.action == rule.ACCEPT:
                allowed_result |= tql_response & self.db.raw_query(rule.tql)
            elif rule.action == rule.DENY:
                # Defer deny action to the end of process:
                deny_rules.append(rule)
        for rule in deny_rules:
            allowed_result = allowed_result - self.db.raw_query(rule.tql)

        return allowed_result

    def check(self, query, requester, method):
        """ Check if the requester have right to call method on objects
            matched by the provided query.
        """

        rights = self.conf.show(login)['rights']
        if tql is not None:
            objects = self.db.raw_query(tql)
        for right in rights:
            if not (right['method'] is None or glob(method, right['method'])):
        matched = self.db.raw_query(query)
        filtered = self.filter(matched, requester, method)
        # Compare len of result is sufficient since the result of
        # a filter operation is warranty to be a subset of its input:
        return len(filtered) != len(matched)

    def check_method(self, requester, method):
        """ Check if the requester have right to call method.
        """
        ok = False  # Default policy is to reject
        for rule in self.rights.iter_rules_method(method):
            if requester not in self.db.raw_query(rule.match):
                continue
            if tql is not None and right['tql']:
                objects_right = self.db.raw_query(right['tql'])
                if set(objects) <= set(objects_right):
                    return right['target'] == 'allow'
            else:
                return right['target'] == 'allow'
            if rule.action == rule.ACCEPT:
                ok = True
            if rule.action == rule.DENY:
                return False
        return ok

    def list(self, query, show=None):
        """ List objects from database.
    def list(self, query, show=None, requester=None, method=None):
        """ List object authorized for requester object, using method.
        """

        if method is not None and requester is None:
            raise ValueError('Method defined but not requester')

        self._update_accounts()
        return self.db.query(query, show)

        result = self.db.raw_query(query)
        if method:
            result = self.filter(result, requester, method)

        # Render the object to dict showing specified tags:
        objects = []
        if show is None:
            show = ()
        for obj in result:
            tags_to_show = set(obj.itermatchingtags(show)) | set(obj.show_tags)
            result._requestor.fetch((obj,), [t.name for t in tags_to_show])
            objects.append(obj.to_dict([t.name for t in tags_to_show]))
        return objects