diff options
-rw-r--r-- | python_moonutilities/python_moonutilities/cache.py | 25 | ||||
-rw-r--r-- | python_moonutilities/python_moonutilities/context.py | 91 | ||||
-rw-r--r-- | python_moonutilities/python_moonutilities/exceptions.py | 2 |
3 files changed, 78 insertions, 40 deletions
diff --git a/python_moonutilities/python_moonutilities/cache.py b/python_moonutilities/python_moonutilities/cache.py index 1ea59d3a..1bb9d09e 100644 --- a/python_moonutilities/python_moonutilities/cache.py +++ b/python_moonutilities/python_moonutilities/cache.py @@ -101,14 +101,14 @@ class Cache(object): raise exceptions.PolicyUnknown("Cannot find policy within policy_id {}".format(policy_id)) if policy_id in self.subjects: - for _subject_id, _subject_dict in self.__SUBJECTS[policy_id].items(): + for _subject_id, _subject_dict in self.subjects[policy_id].items(): if "name" in _subject_dict and _subject_dict["name"] == name: return _subject_id self.__update_subjects(policy_id) if policy_id in self.subjects: - for _subject_id, _subject_dict in self.__SUBJECTS[policy_id].items(): + for _subject_id, _subject_dict in self.subjects[policy_id].items(): if "name" in _subject_dict and _subject_dict["name"] == name: return _subject_id @@ -488,6 +488,20 @@ class Cache(object): logger.warning("Cannot find 'security_pipeline' " "key within pdp ") + def get_meta_rule_ids_from_pdp_value(self, pdp_value): + meta_rules = [] + if "security_pipeline" in pdp_value: + for policy_id in pdp_value["security_pipeline"]: + if policy_id not in self.policies or "model_id" not in self.policies[policy_id]: + raise exceptions.PolicyUnknown("Cannot find 'models' key") + model_id = self.policies[policy_id]["model_id"] + if model_id not in self.models or 'meta_rules' not in self.models[model_id]: + raise exceptions.ModelNotFound("Cannot find 'models' key") + for meta_rule in self.models[model_id]["meta_rules"]: + meta_rules.append(meta_rule) + return meta_rules + raise exceptions.PdpContentError + def get_pdp_from_keystone_project(self, keystone_project_id): for pdp_key, pdp_value in self.pdp.items(): if "keystone_project_id" in pdp_value and \ @@ -566,8 +580,8 @@ class Cache(object): :return: """ if all(k in container_data for k in ("keystone_project_id", "name", "container_id", "policy_id", - "meta_rule_id", "port")) \ - and all(k in container_data['port'] for k in ("PublicPort", "Type", "IP", "PrivatePort")): + "meta_rule_id", "port")) \ + and all(k in container_data['port'] for k in ("PublicPort", "Type", "IP", "PrivatePort")): self.__CONTAINERS[uuid4().hex] = { "keystone_project_id": container_data['keystone_project_id'], @@ -641,7 +655,7 @@ class Cache(object): container_ids = [] for pdp_id, pdp_value, in self.__PDP.items(): if pdp_value: - if all(k in pdp_value for k in ("keystone_project_id", "security_pipeline")) \ + if all(k in pdp_value for k in ("keystone_project_id", "security_pipeline")) \ and pdp_value["keystone_project_id"] == keystone_project_id: for policy_id in pdp_value["security_pipeline"]: if policy_id in self.policies and "model_id" in self.policies[policy_id]: @@ -677,4 +691,3 @@ class Cache(object): "and may not contains 'model_id' key".format(policy_id)) self.__CONTAINER_CHAINING[keystone_project_id] = container_ids - diff --git a/python_moonutilities/python_moonutilities/context.py b/python_moonutilities/python_moonutilities/context.py index 626b25dc..1d25cda2 100644 --- a/python_moonutilities/python_moonutilities/context.py +++ b/python_moonutilities/python_moonutilities/context.py @@ -14,39 +14,35 @@ logger = logging.getLogger("moon.utilities." + __name__) class Context: def __init__(self, init_context, cache): + if init_context is None: + raise Exception("Invalid context content object") + self.cache = cache self.__keystone_project_id = init_context.get("project_id") - self.__pdp_id = None - self.__pdp_value = None - for _pdp_key, _pdp_value in self.cache.pdp.items(): - if _pdp_value["keystone_project_id"] == self.__keystone_project_id: - self.__pdp_id = _pdp_key - self.__pdp_value = copy.deepcopy(_pdp_value) - break - if not self.__pdp_value: + self.__pdp_id = self.cache.get_pdp_from_keystone_project(self.__keystone_project_id) + + if not self.__pdp_id: raise exceptions.AuthzException( "Cannot create context for authz " "with Keystone project ID {}".format( self.__keystone_project_id - )) + )) + self.__pdp_value = copy.deepcopy(self.cache.pdp[self.__pdp_id]) + self.__subject = init_context.get("subject_name") self.__object = init_context.get("object_name") self.__action = init_context.get("action_name") - self.__current_request = None self.__request_id = init_context.get("req_id") self.__cookie = init_context.get("cookie") self.__manager_url = init_context.get("manager_url") self.__interface_name = init_context.get("interface_name") + self.__current_request = None + self.__index = -1 # self.__init_initial_request() - self.__headers = [] - policies = self.cache.policies - models = self.cache.models - for policy_id in self.__pdp_value["security_pipeline"]: - model_id = policies[policy_id]["model_id"] - for meta_rule in models[model_id]["meta_rules"]: - self.__headers.append(meta_rule) + self.__meta_rule_ids = self.cache.get_meta_rule_ids_from_pdp_value(self.__pdp_value) self.__meta_rules = self.cache.meta_rules + self.__pdp_set = {} # self.__init_pdp_set() @@ -63,20 +59,25 @@ class Context: @property def current_state(self): - return self.__pdp_set[self.__headers[self.__index]]['effect'] + self.__validate_meta_rule_content(self.__meta_rule_ids[self.__index]) + return self.__pdp_set[self.__meta_rule_ids[self.__index]]['effect'] @current_state.setter def current_state(self, state): if state not in ("grant", "deny", "passed"): state = "passed" - self.__pdp_set[self.__headers[self.__index]]['effect'] = state + self.__validate_meta_rule_content(self.__meta_rule_ids[self.__index]) + self.__pdp_set[self.__meta_rule_ids[self.__index]]['effect'] = state @current_state.deleter def current_state(self): - self.__pdp_set[self.__headers[self.__index]]['effect'] = "unset" + self.__validate_meta_rule_content(self.__meta_rule_ids[self.__index]) + self.__pdp_set[self.__meta_rule_ids[self.__index]]['effect'] = "unset" @property def current_policy_id(self): + if "security_pipeline" not in self.__pdp_value: + raise exceptions.AuthzException('Cannot find security_pipeline key within pdp.') return self.__pdp_value["security_pipeline"][self.__index] @current_policy_id.setter @@ -88,6 +89,8 @@ class Context: pass def __init_current_request(self): + if "security_pipeline" not in self.__pdp_value: + raise exceptions.PdpContentError self.__subject = self.cache.get_subject( self.__pdp_value["security_pipeline"][self.__index], self.__subject) @@ -100,11 +103,11 @@ class Context: self.__current_request = dict(self.initial_request) def __init_pdp_set(self): - for header in self.__headers: - self.__pdp_set[header] = dict() - self.__pdp_set[header]["meta_rules"] = self.__meta_rules[header] - self.__pdp_set[header]["target"] = self.__add_target(header) - self.__pdp_set[header]["effect"] = "unset" + for meta_rule_id in self.__meta_rule_ids: + self.__pdp_set[meta_rule_id] = dict() + self.__pdp_set[meta_rule_id]["meta_rules"] = self.__meta_rules[meta_rule_id] + self.__pdp_set[meta_rule_id]["target"] = self.__add_target(meta_rule_id) + self.__pdp_set[meta_rule_id]["effect"] = "unset" self.__pdp_set["effect"] = "deny" # def update_target(self, context): @@ -151,23 +154,37 @@ class Context: _subject = self.__current_request["subject"] _object = self.__current_request["object"] _action = self.__current_request["action"] + meta_rules = self.cache.meta_rules policy_id = self.cache.get_policy_from_meta_rules(meta_rule_id) + + if 'subject_categories' not in meta_rules[meta_rule_id]: + raise exceptions.MetaRuleContentError(" 'subject_categories' key not found ") + for sub_cat in meta_rules[meta_rule_id]['subject_categories']: if sub_cat not in result: result[sub_cat] = [] result[sub_cat].extend( self.cache.get_subject_assignments(policy_id, _subject, sub_cat)) + + if 'object_categories' not in meta_rules[meta_rule_id]: + raise exceptions.MetaRuleContentError(" 'object_categories' key not found ") + for obj_cat in meta_rules[meta_rule_id]['object_categories']: if obj_cat not in result: result[obj_cat] = [] result[obj_cat].extend( self.cache.get_object_assignments(policy_id, _object, obj_cat)) + + if 'action_categories' not in meta_rules[meta_rule_id]: + raise exceptions.MetaRuleContentError(" 'action_categories' key not found ") + for act_cat in meta_rules[meta_rule_id]['action_categories']: if act_cat not in result: result[act_cat] = [] result[act_cat].extend( self.cache.get_action_assignments(policy_id, _action, act_cat)) + return result def __repr__(self): @@ -181,7 +198,7 @@ pdp_set: {pdp_set} id=self.__pdp_id, current_request=self.__current_request, request_id=self.__request_id, - headers=self.__headers, + headers=self.__meta_rule_ids, pdp_set=self.__pdp_set, index=self.__index ) @@ -190,7 +207,7 @@ pdp_set: {pdp_set} return { "initial_request": copy.deepcopy(self.initial_request), "current_request": copy.deepcopy(self.__current_request), - "headers": copy.deepcopy(self.__headers), + "headers": copy.deepcopy(self.__meta_rule_ids), "index": copy.deepcopy(self.__index), "pdp_set": copy.deepcopy(self.__pdp_set), "request_id": copy.deepcopy(self.__request_id), @@ -265,11 +282,12 @@ pdp_set: {pdp_set} @property def current_request(self): if not self.__current_request: - self.__current_request = copy.deepcopy(self.initial_request) + self.__current_request = dict(self.initial_request) return self.__current_request @current_request.setter def current_request(self, value): + self.__current_request = copy.deepcopy(value) # Note (asteroide): if the current request is modified, # we must update the PDP Set. @@ -280,17 +298,22 @@ pdp_set: {pdp_set} self.__current_request = {} self.__pdp_set = {} + ''' + [Note ] Refactor name of headers to meta_rule_ids done , + may need to refactor getter and setter of headers + ''' + @property def headers(self): - return self.__headers + return self.__meta_rule_ids @headers.setter - def headers(self, headers): - self.__headers = headers + def headers(self, meta_rule_ids): + self.__meta_rule_ids = meta_rule_ids @headers.deleter def headers(self): - self.__headers = list() + self.__meta_rule_ids = list() @property def index(self): @@ -316,4 +339,6 @@ pdp_set: {pdp_set} def pdp_set(self): self.__pdp_set = {} - + def __validate_meta_rule_content(self, meta_rules): + if 'effect' not in meta_rules: + raise exceptions.PdpContentError diff --git a/python_moonutilities/python_moonutilities/exceptions.py b/python_moonutilities/python_moonutilities/exceptions.py index 6db7bf01..e6621038 100644 --- a/python_moonutilities/python_moonutilities/exceptions.py +++ b/python_moonutilities/python_moonutilities/exceptions.py @@ -444,7 +444,7 @@ class MetaRuleExisting(AdminMetaRule): class MetaRuleContentError(AdminMetaRule): - description = _("Invalid content of pdp.") + description = _("Invalid content of meta rule.") code = 400 title = 'Meta Rule Error' logger = "ERROR" |