Loading cloudcontrol/server/clients/__init__.py +11 −7 Original line number Diff line number Diff line Loading @@ -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: # Loading Loading @@ -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') cloudcontrol/server/server.py +69 −23 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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): Loading Loading @@ -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 Loading
cloudcontrol/server/clients/__init__.py +11 −7 Original line number Diff line number Diff line Loading @@ -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: # Loading Loading @@ -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')
cloudcontrol/server/server.py +69 −23 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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): Loading Loading @@ -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