# license which can be found in the file 'LICENSE' in this package distribution
# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
-import copy
+import hashlib
import itertools
from oslo_log import log as logging
from oslo_config import cfg
-from moon_utilities.security_functions import call, Context
+import oslo_messaging
+from moon_utilities.security_functions import call, Context, notify
from moon_utilities.misc import get_uuid_from_name
from moon_utilities import exceptions
from moon_db.core import PDPManager
meta_rule_id = None
keystone_project_id = None
- def __init__(self, component_id):
- self.component_id = component_id
- LOG.info("ext={}".format(component_id))
- for _id_value in component_id.split("_"):
- LOG.info("_id_value={}".format(_id_value.split(":")))
+ def __init__(self, component_desc):
+ self.component_id = component_desc
+ LOG.info("ext={}".format(component_desc))
+ self.filter_rule = oslo_messaging.NotificationFilter(
+ event_type='^authz$',
+ context={'container_id': "authz_"+hashlib.sha224(component_desc.encode("utf-8")).hexdigest()}
+ )
+
+ for _id_value in component_desc.split("_"):
_type, _id = _id_value.split(":")
if _type == "pdp":
self.pdp_id = _id
self.meta_rule_id = _id
elif _type == "project":
self.keystone_project_id = _id
- # self.manager = IntraExtensionAdminManager
- # self.context = {"id": self.component_id, "user_id": "admin"}
- # self.aggregation_algorithm_dict = ConfigurationManager.driver.get_aggregation_algorithms_dict()
- # self.__subjects = None
- # self.__objects = None
- # self.__actions = None
- # self.__subject_scopes = None
- # self.__object_scopes = None
- # self.__action_scopes = None
- # self.__subject_categories = None
- # self.__object_categories = None
- # self.__action_categories = None
- # self.__subject_assignments = None
- # self.__object_assignments = None
- # self.__action_assignments = None
- # self.__sub_meta_rules = None
- # self.__rules = None
- # self.aggregation_algorithm_id = None
-
- # @property
- # def subjects(self):
- # if not self.__subjects:
- # self.__subjects = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=self.context,
- # method="get_subjects", args={})
- # if "subjects" in self.__subjects:
- # return self.__subjects
- # else:
- # LOG.error("An error occurred {}".format(self.__subjects))
- # return self.__subjects
- #
- # @property
- # def objects(self):
- # if not self.__objects:
- # self.__objects = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=self.context,
- # method="get_objects", args={})
- # if "objects" in self.__objects:
- # return self.__objects
- # else:
- # LOG.error("An error occurred {}".format(self.__objects))
- # return self.__objects
- #
- # @property
- # def actions(self):
- # if not self.__actions:
- # self.__actions = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=self.context,
- # method="get_actions", args={})
- # if "actions" in self.__actions:
- # return self.__actions
- # else:
- # LOG.error("An error occurred {}".format(self.__actions))
- # return self.__actions
- #
- # @property
- # def subject_scopes(self):
- # if not self.__subject_scopes:
- # self.__subject_scopes = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=self.context,
- # method="get_subject_scopes", args={})
- # if "subject_scopes" in self.__subject_scopes:
- # return self.__subject_scopes
- # else:
- # LOG.error("An error occurred {}".format(self.__subject_scopes))
- # return self.__subject_scopes
- #
- # @property
- # def object_scopes(self):
- # if not self.__object_scopes:
- # self.__object_scopes = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=self.context,
- # method="get_object_scopes", args={})
- # if "object_scopes" in self.__object_scopes:
- # return self.__object_scopes
- # else:
- # LOG.error("An error occurred {}".format(self.__object_scopes))
- # return self.__object_scopes
- #
- # @property
- # def action_scopes(self):
- # if not self.__action_scopes:
- # self.__action_scopes = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=self.context,
- # method="get_action_scopes", args={})
- # if "action_scopes" in self.__action_scopes:
- # return self.__action_scopes
- # else:
- # LOG.error("An error occurred {}".format(self.__action_scopes))
- # return self.__action_scopes
- #
- # @property
- # def subject_categories(self):
- # if not self.__subject_categories:
- # self.__subject_categories = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=self.context,
- # method="get_subject_categories", args={})
- # if "subject_categories" in self.__subject_categories:
- # return self.__subject_categories
- # else:
- # LOG.error("An error occurred {}".format(self.__subject_categories))
- # return self.__subject_categories
- #
- # @property
- # def object_categories(self):
- # if not self.__object_categories:
- # self.__object_categories = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=self.context,
- # method="get_object_categories", args={})
- # if "object_categories" in self.__object_categories:
- # return self.__object_categories
- # else:
- # LOG.error("An error occurred {}".format(self.__object_categories))
- # return self.__object_categories
- #
- # @property
- # def action_categories(self):
- # if not self.__action_categories:
- # self.__action_categories = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=self.context,
- # method="get_action_categories", args={})
- # if "action_categories" in self.__action_categories:
- # return self.__action_categories
- # else:
- # LOG.error("An error occurred {}".format(self.__action_categories))
- # return self.__action_categories
- #
- # @property
- # def subject_assignments(self):
- # if not self.__subject_assignments:
- # context = copy.deepcopy(self.context)
- # context['sid'] = None
- # context['scid'] = None
- # args = {'ssid': None}
- # self.__subject_assignments = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=context,
- # method="get_subject_assignments", args=args)
- # if "subject_assignments" in self.__subject_assignments:
- # return self.__subject_assignments
- # else:
- # LOG.error("An error occurred {}".format(self.__subject_assignments))
- # return self.__subject_assignments
- #
- # @property
- # def object_assignments(self):
- # if not self.__object_assignments:
- # context = copy.deepcopy(self.context)
- # context['sid'] = None
- # context['scid'] = None
- # args = {'ssid': None}
- # self.__object_assignments = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=context,
- # method="get_object_assignments", args=args)
- # if "object_assignments" in self.__object_assignments:
- # return self.__object_assignments
- # else:
- # LOG.error("An error occurred {}".format(self.__object_assignments))
- # return self.__object_assignments
- #
- # @property
- # def action_assignments(self):
- # if not self.__action_assignments:
- # context = copy.deepcopy(self.context)
- # context['sid'] = None
- # context['scid'] = None
- # args = {'ssid': None}
- # self.__action_assignments = call("moon_secpolicy_{}".format(self.intra_extension_id), ctx=context,
- # method="get_action_assignments", args=args)
- # if "action_assignments" in self.__action_assignments:
- # return self.__action_assignments
- # else:
- # LOG.error("An error occurred {}".format(self.__action_assignments))
- # return self.__action_assignments
- #
- # @property
- # def sub_meta_rules(self):
- # if not self.__sub_meta_rules:
- # self.__sub_meta_rules = call("moon_secfunction_{}".format(self.intra_extension_id), ctx=self.context,
- # method="get_sub_meta_rules", args={})
- # if "sub_meta_rules" in self.__sub_meta_rules:
- # return self.__sub_meta_rules
- # else:
- # LOG.error("An error occurred {}".format(self.__sub_meta_rules))
- # return self.__sub_meta_rules
- #
- # @property
- # def rules(self):
- # if not self.__rules:
- # self.__rules = dict()
- # for _id, _value in self.sub_meta_rules["sub_meta_rules"].items():
- # context = copy.deepcopy(self.context)
- # context["sub_meta_rule_id"] = _id
- # __elements = call("moon_secfunction_{}".format(self.intra_extension_id), ctx=context,
- # method="get_rules", args={})
- # if "rules" in __elements:
- # self.__rules[_id] = __elements
- # else:
- # LOG.error("An error occurred {}".format(__elements))
- # return self.__rules
-
- # def __get_authz_buffer(self, subject_id, object_id, action_id):
- # """
- # :param intra_extension_id:
- # :param subject_id:
- # :param object_id:
- # :param action_id:
- # :return: authz_buffer = {
- # 'subject_id': xxx,
- # 'object_id': yyy,
- # 'action_id': zzz,
- # 'subject_assignments': {
- # 'subject_category1': [],
- # 'subject_category2': [],
- # ...
- # },
- # 'object_assignments': {},
- # 'action_assignments': {},
- # }
- # """
- # authz_buffer = dict()
- # # Sometimes it is not the subject ID but the User Keystone ID, so, we have to check
- # subjects_dict = copy.deepcopy(self.subjects)
- # if subject_id not in subjects_dict["subjects"].keys():
- # for _subject_id in subjects_dict["subjects"]:
- # if subjects_dict["subjects"][_subject_id]['keystone_id']:
- # subject_id = _subject_id
- # break
- # authz_buffer['subject_id'] = subject_id
- # authz_buffer['object_id'] = object_id
- # authz_buffer['action_id'] = action_id
- # meta_data_dict = dict()
- # meta_data_dict["subject_categories"] = copy.deepcopy(self.subject_categories["subject_categories"])
- # meta_data_dict["object_categories"] = copy.deepcopy(self.object_categories["object_categories"])
- # meta_data_dict["action_categories"] = copy.deepcopy(self.action_categories["action_categories"])
- # subject_assignment_dict = copy.deepcopy(self.subject_assignments['subject_assignments'][subject_id])
- # LOG.info("__get_authz_buffer self.object_assignments['object_assignments']={}".format(self.object_assignments['object_assignments']))
- # LOG.info("__get_authz_buffer object_id={}".format(object_id))
- # object_assignment_dict = copy.deepcopy(self.object_assignments['object_assignments'][object_id])
- # action_assignment_dict = copy.deepcopy(self.action_assignments['action_assignments'][action_id])
- #
- # authz_buffer['subject_assignments'] = dict()
- # authz_buffer['object_assignments'] = dict()
- # authz_buffer['action_assignments'] = dict()
- #
- # for _subject_category in meta_data_dict['subject_categories']:
- # authz_buffer['subject_assignments'][_subject_category] = list(subject_assignment_dict[_subject_category])
- # for _object_category in meta_data_dict['object_categories']:
- # authz_buffer['object_assignments'][_object_category] = list(object_assignment_dict[_object_category])
- # for _action_category in meta_data_dict['action_categories']:
- # authz_buffer['action_assignments'][_action_category] = list(action_assignment_dict[_action_category])
- # return authz_buffer
- #
- # def __get_decision_dict(self, subject_id, object_id, action_id):
- # """Check authorization for a particular action.
- #
- # :param intra_extension_id: UUID of an IntraExtension
- # :param subject_id: subject UUID of the request
- # :param object_id: object UUID of the request
- # :param action_id: action UUID of the request
- # :return: True or False or raise an exception
- # :raises:
- # """
- # authz_buffer = self.__get_authz_buffer(subject_id, object_id, action_id)
- # decision_buffer = dict()
- #
- # meta_rule_dict = copy.deepcopy(self.sub_meta_rules['sub_meta_rules'])
- # rules_dict = copy.deepcopy(self.rules)
- # for sub_meta_rule_id in meta_rule_dict:
- # if meta_rule_dict[sub_meta_rule_id]['algorithm'] == 'inclusion':
- # decision_buffer[sub_meta_rule_id] = algorithms.inclusion(
- # authz_buffer,
- # meta_rule_dict[sub_meta_rule_id],
- # rules_dict[sub_meta_rule_id]['rules'].values())
- # elif meta_rule_dict[sub_meta_rule_id]['algorithm'] == 'comparison':
- # decision_buffer[sub_meta_rule_id] = algorithms.comparison(
- # authz_buffer,
- # meta_rule_dict[sub_meta_rule_id],
- # rules_dict[sub_meta_rule_id]['rules'].values())
- #
- # return decision_buffer
- #
- # def __authz(self, subject_id, object_id, action_id):
- # decision = False
- # decision_dict = dict()
- # try:
- # decision_dict = self.__get_decision_dict(subject_id, object_id, action_id)
- # except (exceptions.SubjectUnknown, exceptions.ObjectUnknown, exceptions.ActionUnknown) as e:
- # # maybe we need to synchronize with the master
- # pass
- # # if CONF.slave.slave_name and CONF.slave.master_url:
- # # self.get_data_from_master()
- # # decision_dict = self.__get_decision_dict(subject_id, object_id, action_id)
- #
- # try:
- # # aggregation_algorithm_id = IntraExtensionAdminManager.get_aggregation_algorithm_id(
- # # "admin",
- # # self.intra_extension_id)['aggregation_algorithm']
- # if not self.aggregation_algorithm_id:
- # self.aggregation_algorithm_id = self.intra_extension['aggregation_algorithm']
- # except Exception as e:
- # LOG.error(e, exc_info=True)
- # LOG.error(self.intra_extension)
- # return {
- # 'authz': False,
- # 'comment': "Aggregation algorithm not set"
- # }
- # if self.aggregation_algorithm_dict[self.aggregation_algorithm_id]['name'] == 'all_true':
- # decision = algorithms.all_true(decision_dict)
- # elif self.aggregation_algorithm_dict[self.aggregation_algorithm_id]['name'] == 'one_true':
- # decision = algorithms.one_true(decision_dict)
- # if not decision_dict or not decision:
- # raise exceptions.AuthzException("{} {}-{}-{}".format(self.intra_extension['id'], subject_id, action_id, object_id))
- # return {
- # 'authz': decision,
- # 'comment': "{} {}-{}-{}".format(self.intra_extension['id'], subject_id, action_id, object_id)
- # }
- #
- # def authz_bak(self, ctx, args):
- # """Return the authorization for a specific request
- #
- # :param ctx: {
- # "subject_name" : "string name",
- # "action_name" : "string name",
- # "object_name" : "string name"
- # }
- # :param args: {}
- # :return: {
- # "authz": "True or False",
- # "message": "optional message"
- # }
- # """
- # intra_extension_id = ctx["id"]
- # try:
- # subject_id = get_uuid_from_name(ctx["subject_name"], self.subjects['subjects'])
- # object_id = get_uuid_from_name(ctx["object_name"], self.objects['objects'])
- # action_id = get_uuid_from_name(ctx["action_name"], self.actions['actions'])
- # authz_result = self.__authz(subject_id, object_id, action_id)
- # return authz_result
- # except Exception as e:
- # LOG.error(e, exc_info=True)
- # return {"authz": False,
- # "error": str(e),
- # "intra_extension_id": intra_extension_id,
- # "ctx": ctx, "args": args}
- #
- # return {"authz": False}
def __check_rules(self, context):
scopes_list = list()
- current_header_id = context.headers[context.index]['id']
- current_pdp = context.pdp_set[current_header_id]
+ current_header_id = context['headers'][context['index']]
+ current_pdp = context['pdp_set'][current_header_id]
category_list = list()
category_list.extend(current_pdp["meta_rules"]["subject_categories"])
- category_list.extend(current_pdp["meta_rules"]["action_categories"])
category_list.extend(current_pdp["meta_rules"]["object_categories"])
+ category_list.extend(current_pdp["meta_rules"]["action_categories"])
for category in category_list:
- if not current_pdp['target'][category]:
- LOG.warning("Empty assignment detected: {} target={}".format(category, current_pdp['target']))
- return False, "Empty assignment detected..."
+ # if not current_pdp['target'][category]:
+ # LOG.warning("Empty assignment detected: {} target={}".format(category, current_pdp['target']))
scopes_list.append(current_pdp['target'][category])
- scopes_list.append([True, ])
- rules = PolicyManager.get_rules_dict(user_id="admin",
- policy_id=self.policy_id,
- meta_rule_id=current_header_id).values()
+ policy_id = PolicyManager.get_policy_from_meta_rules("admin", current_header_id)
+ rules = PolicyManager.get_rules(user_id="admin",
+ policy_id=policy_id,
+ meta_rule_id=current_header_id)
+ rules = list(map(lambda x: x['rule'], rules['rules']))
for item in itertools.product(*scopes_list):
- if list(item) in rules:
+ req = list(item)
+ if req in rules:
return True, ""
LOG.warning("No rule match the request...")
return False, "No rule match the request..."
- def authz(self, ctx, args):
- LOG.info("authz {}".format(ctx))
- keystone_project_id = ctx["id"]
+ def critical(self, ctxt, publisher_id, event_type, payload, metadata):
+ """This is the authz endpoint
+ but due to the oslo_messaging notification architecture, we must call it "critical"
+
+ :param ctxt: context of the request
+ :param publisher_id: ID of the publisher
+ :param event_type: type of event ("authz" here)
+ :param payload: content of the authz request
+ :param metadata: metadata of the notification
+ :return: result of the authorization for the current component
+ """
+ LOG.info("authz {} {}".format(ctxt, payload))
+ keystone_project_id = payload["id"]
try:
- if "authz_context" not in ctx:
- ctx["authz_context"] = Context(keystone_project_id,
- ctx["subject_name"],
- ctx["object_name"],
- ctx["action_name"],
- ctx["request_id"]).to_dict()
- LOG.info("Context={}".format(ctx["authz_context"]))
+ if "authz_context" not in payload:
+ payload["authz_context"] = Context(keystone_project_id,
+ payload["subject_name"],
+ payload["object_name"],
+ payload["action_name"],
+ payload["request_id"]).to_dict()
+ else:
+ payload["authz_context"]["index"] += 1
+ result, message = self.__check_rules(payload["authz_context"])
+ current_header_id = payload["authz_context"]['headers'][payload["authz_context"]['index']]
+ # current_pdp = payload["authz_context"]['pdp_set'][current_header_id]
+ if result:
+ payload["authz_context"]['pdp_set'][current_header_id]["effect"] = "grant"
+ if payload["authz_context"]["index"]+1 < len(payload["authz_context"]["headers"]):
+ next_index = payload["authz_context"]["index"]+1
+ notify(
+ request_id=payload["authz_context"]["request_id"],
+ container_id=payload["container_chaining"][next_index],
+ payload=payload)
else:
- ctx["authz_context"].index += 1
- result, message = self.__check_rules(ctx["authz_context"])
- # if ctx["authz_context"].index < len(ctx["authz_context"].headers):
- del ctx["authz_context"]
+ ret = call(endpoint="security_router",
+ ctx={"id": self.component_id,
+ "call_master": False,
+ "method": "return_authz",
+ "request_id": payload["authz_context"]["request_id"]},
+ method="route",
+ args=payload["authz_context"])
+ del payload["authz_context"]
return {"authz": result,
"error": message,
"pdp_id": self.pdp_id,
- "ctx": ctx, "args": args}
+ "ctx": ctxt, "args": payload}
except Exception as e:
try:
- LOG.error(ctx["authz_context"])
+ LOG.error(payload["authz_context"])
# del ctx["authz_context"]
except KeyError:
LOG.error("Cannot find \"authz_context\" in context")
return {"authz": False,
"error": str(e),
"pdp_id": self.pdp_id,
- "ctx": ctx, "args": args}
+ "ctx": ctxt, "args": payload}
import copy
import time
+import itertools
+from uuid import uuid4
from oslo_log import log as logging
-from moon_utilities.security_functions import call
+from moon_utilities.security_functions import call, notify
from oslo_config import cfg
from moon_secrouter.api.generic import Status, Logs
),
"function": (
"authz",
+ "return_authz",
),
}
class Cache(object):
# TODO (asteroide): set cache integer in CONF file
- __UPDATE_INTERVAL = 300
+ __UPDATE_INTERVAL = 10
+
__CONTAINERS = {}
- __LAST_UPDATE = 0
+ __CONTAINERS_UPDATE = 0
+
+ __CONTAINER_CHAINING_UPDATE = 0
+ __CONTAINER_CHAINING = {}
+
+ __PDP = {}
+ __PDP_UPDATE = 0
+
+ __POLICIES = {}
+ __POLICIES_UPDATE = 0
+
+ __MODELS = {}
+ __MODELS_UPDATE = 0
+
+ __AUTHZ_REQUESTS = {}
+
+ def update(self, component=None):
+ self.__update_container()
+ self.__update_pdp()
+ self.__update_policies()
+ self.__update_models()
+ for key, value in self.__PDP.items():
+ self.__update_container_chaining(value["keystone_project_id"])
+
+ @property
+ def authz_requests(self):
+ return self.__AUTHZ_REQUESTS
+
+ def __update_pdp(self):
+ pdp = call("moon_manager", method="get_pdp", ctx={"user_id": "admin"}, args={})
+ for _pdp in pdp["pdps"].values():
+ if _pdp['keystone_project_id'] not in self.__CONTAINER_CHAINING:
+ self.__CONTAINER_CHAINING[_pdp['keystone_project_id']] = {}
+ # Note (asteroide): force update of chaining
+ self.__update_container_chaining(_pdp['keystone_project_id'])
+ for key, value in pdp["pdps"].items():
+ self.__PDP[key] = value
+
+ @property
+ def pdp(self):
+ current_time = time.time()
+ if self.__PDP_UPDATE + self.__UPDATE_INTERVAL < current_time:
+ self.__update_pdp()
+ self.__PDP_UPDATE = current_time
+ return self.__PDP
+
+ def __update_policies(self):
+ policies = call("moon_manager", method="get_policies", ctx={"user_id": "admin"}, args={})
+ for key, value in policies["policies"].items():
+ self.__POLICIES[key] = value
+
+ @property
+ def policies(self):
+ current_time = time.time()
+ if self.__POLICIES_UPDATE + self.__UPDATE_INTERVAL < current_time:
+ self.__update_policies()
+ self.__POLICIES_UPDATE = current_time
+ return self.__POLICIES
+
+ def __update_models(self):
+ models = call("moon_manager", method="get_models", ctx={"user_id": "admin"}, args={})
+ for key, value in models["models"].items():
+ self.__MODELS[key] = value
+
+ @property
+ def models(self):
+ current_time = time.time()
+ if self.__MODELS_UPDATE + self.__UPDATE_INTERVAL < current_time:
+ self.__update_models()
+ self.__MODELS_UPDATE = current_time
+ return self.__MODELS
def __update_container(self):
containers = call("orchestrator", method="get_container", ctx={}, args={})
- LOG.info("container={}".format(containers))
for key, value in containers["containers"].items():
self.__CONTAINERS[key] = value
- def update(self, component=None):
- self.__update_container()
+ @property
+ def container_chaining(self):
+ current_time = time.time()
+ if self.__CONTAINER_CHAINING_UPDATE + self.__UPDATE_INTERVAL < current_time:
+ for key, value in self.pdp.items():
+ self.__update_container_chaining(value["keystone_project_id"])
+ self.__CONTAINER_CHAINING_UPDATE = current_time
+ return self.__CONTAINER_CHAINING
+
+ def __update_container_chaining(self, keystone_project_id):
+ container_ids = []
+ for pdp_id, pdp_value, in CACHE.pdp.items():
+ if pdp_value:
+ if pdp_value["keystone_project_id"] == keystone_project_id:
+ for policy_id in pdp_value["security_pipeline"]:
+ model_id = CACHE.policies[policy_id]['model_id']
+ for meta_rule_id in CACHE.models[model_id]["meta_rules"]:
+ for container_id, container_values, in CACHE.containers.items():
+ for container_value in container_values:
+ if container_value["meta_rule_id"] == meta_rule_id:
+ container_ids.append(container_value["container_id"])
+ break
+ self.__CONTAINER_CHAINING[keystone_project_id] = container_ids
@property
def containers(self):
:return:
"""
current_time = time.time()
- if self.__LAST_UPDATE + self.__UPDATE_INTERVAL < current_time:
+ if self.__CONTAINERS_UPDATE + self.__UPDATE_INTERVAL < current_time:
self.__update_container()
- self.__LAST_UPDATE = current_time
+ self.__CONTAINERS_UPDATE = current_time
return self.__CONTAINERS
CACHE = Cache()
+class AuthzRequest:
+
+ result = None
+ req_max_delay = 5
+
+ def __init__(self, ctx, args):
+ self.ctx = ctx
+ self.args = args
+ self.request_id = ctx["request_id"]
+ self.container_chaining = CACHE.container_chaining[self.ctx['id']]
+ ctx["container_chaining"] = copy.deepcopy(self.container_chaining)
+ self.pdp_container = str(self.container_chaining[0])
+ self.run()
+
+ def run(self):
+ notify(request_id=self.request_id, container_id=self.pdp_container, payload=self.ctx)
+ cpt = 0
+ while cpt < self.req_max_delay*10:
+ time.sleep(0.1)
+ cpt += 1
+ if CACHE.authz_requests[self.request_id]:
+ self.result = CACHE.authz_requests[self.request_id]
+ return
+ LOG.warning("Request {} has timed out".format(self.request_id))
+
+ def is_authz(self):
+ if not self.result:
+ return False
+ authz_results = []
+ for key in self.result["pdp_set"]:
+ if "effect" in self.result["pdp_set"][key]:
+ if self.result["pdp_set"][key]["effect"] == "grant":
+ authz_results.append(True)
+ else:
+ authz_results.append(False)
+ if list(itertools.accumulate(authz_results, lambda x, y: x & y))[-1]:
+ self.result["pdp_set"]["effect"] = "grant"
+ if self.result:
+ if "pdp_set" in self.result and self.result["pdp_set"]["effect"] == "grant":
+ return True
+ return False
+
+
class Router(object):
"""
Route requests to all components.
"""
__version__ = "0.1.0"
+ cache_requests = {}
def __init__(self, add_master_cnx):
if CONF.slave.slave_name and add_master_cnx:
LOG.info("SLAVE CONNECTION ENDED!")
LOG.info(result)
- @staticmethod
- def __get_first_container(keystone_project_id):
- for container_id, container_value, in CACHE.containers.items():
- if container_value:
- if container_value[0]["keystone_project_id"] == keystone_project_id:
- return container_value[0]["container_id"]
-
@staticmethod
def check_pdp(ctx):
_ctx = copy.deepcopy(ctx)
if component == "orchestrator":
return call(component, method=ctx["method"], ctx=ctx, args=args)
if component == "manager":
- LOG.info("Call Manager {}".format(ctx))
result = call("moon_manager", method=ctx["method"], ctx=ctx, args=args)
self.send_update(api=ctx["method"], ctx=ctx, args=args)
return result
if component == "function":
- if self.check_pdp(ctx):
- LOG.info("Tenant ID={}".format(ctx['id']))
- pdp_container = self.__get_first_container(ctx['id'])
- LOG.info("pdp_container={}".format(pdp_container))
- # TODO (asteroide): call the first security function through a notification
- # and not an RPC call (need to play with ID in context)
- result = call(pdp_container, method=ctx["method"], ctx=ctx, args=args)
- return result
+ if ctx["method"] == "return_authz":
+ request_id = ctx["request_id"]
+ CACHE.authz_requests[request_id] = args
+ return args
+ elif self.check_pdp(ctx):
+ req_id = uuid4().hex
+ CACHE.authz_requests[req_id] = {}
+ ctx["request_id"] = req_id
+ req = AuthzRequest(ctx, args)
+ # result = copy.deepcopy(req.result)
+ if req.is_authz():
+ return {"authz": True,
+ "pdp_id": ctx["id"],
+ "ctx": ctx, "args": args}
+ return {"authz": False,
+ "error": {'code': 403, 'title': 'Authz Error',
+ 'description': "The authz request is refused."},
+ "pdp_id": ctx["id"],
+ "ctx": ctx, "args": args}
return {"result": False,
- "error": {'code': 500, 'title': 'Moon Error', 'description': "Function component not found."},
+ "error": {'code': 500, 'title': 'Moon Error',
+ 'description': "Function component not found."},
"pdp_id": ctx["id"],
"ctx": ctx, "args": args}
import re
import types
import requests
-from uuid import uuid4
from oslo_log import log as logging
from oslo_config import cfg
import oslo_messaging
from moon_utilities import exceptions
-from oslo_config.cfg import ConfigOpts
-# from moon_db.core import PDPManager, ModelManager, PolicyManager
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
__transport_master = oslo_messaging.get_transport(cfg.CONF, CONF.slave.master_url)
__transport = oslo_messaging.get_transport(CONF)
+__n_transport = oslo_messaging.get_notification_transport(CONF)
+__n_notifier = oslo_messaging.Notifier(__n_transport,
+ 'router.host',
+ driver='messagingv2',
+ topics=['authz-workers'])
+__n_notifier = __n_notifier.prepare(publisher_id='router')
+
+
+def notify(request_id, container_id, payload, event_type="authz"):
+ ctxt = {
+ 'request_id': request_id,
+ 'container_id': container_id
+ }
+ result = __n_notifier.critical(ctxt, event_type, payload=payload)
+ return result
+
def call(endpoint, ctx=None, method="get_status", **kwargs):
if not ctx:
self.__keystone_project_id = _keystone_project_id
self.__pdp_id = None
self.__pdp_value = None
- LOG.info("Context pdp={}".format(PDPManager.get_pdp("admin")))
for _pdp_key, _pdp_value in PDPManager.get_pdp("admin").items():
if _pdp_value["keystone_project_id"] == _keystone_project_id:
self.__pdp_id = _pdp_key
self.__pdp_value = copy.deepcopy(_pdp_value)
break
- LOG.info("Context pdp_value={}".format(self.__pdp_value))
self.__subject = _subject
self.__object = _object
self.__action = _action
self.__headers = []
policies = PolicyManager.get_policies("admin")
models = ModelManager.get_models("admin")
- LOG.info("Context policies={}".format(policies))
- LOG.info("Context models={}".format(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_rules = ModelManager.get_meta_rules("admin")
- LOG.info("Context meta_rules={}".format(self.__meta_rules))
- LOG.info("Context headers={}".format(self.__headers))
- # call("moon_manager",
- # method="get_meta_rules",
- # ctx={"id": self.__intra_extension_id,
- # "user_id": "admin",
- # "method": "get_sub_meta_rules"},
- # args={})["sub_meta_rules"]
- # for key in self.__intra_extension["pdp_pipeline"]:
- # LOG.info("__meta_rules={}".format(self.__meta_rules))
- # for meta_rule_key in self.__meta_rules:
- # if self.__meta_rules[meta_rule_key]['name'] == key.split(":", maxsplit=1)[-1]:
- # self.__headers.append({"name": self.__meta_rules[meta_rule_key]['name'], "id": meta_rule_key})
- # break
- # else:
- # LOG.warning("Cannot find meta_rule_key {}".format(key))
self.__pdp_set = {}
self.__init_pdp_set()
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()
+ self.__pdp_set[header]["target"] = self.__add_target(header)
# TODO (asteroide): the following information must be retrieve somewhere
self.__pdp_set[header]["instruction"] = list()
- self.__pdp_set[header]["effect"] = "grant"
- self.__pdp_set["effect"] = "grant"
+ self.__pdp_set[header]["effect"] = "deny"
+ self.__pdp_set["effect"] = "deny"
- def __add_target(self):
+ def __add_target(self, meta_rule_id):
result = dict()
_subject = self.__current_request["subject"]
_object = self.__current_request["object"]
_action = self.__current_request["action"]
- categories = self.ModelManager.get_subject_categories("admin")
- # TODO (asteroide): end the dev of that part
- # for category in categories:
- # result[category] = list()
- # assignments = call("moon_secpolicy_{}".format(self.__intra_extension_id),
- # method="get_subject_assignments",
- # ctx={"id": self.__intra_extension_id,
- # "sid": _subject,
- # "scid": category,
- # "user_id": "admin"},
- # args={})["subject_assignments"]
- # result[category].extend(assignments[_subject][category])
- # categories = call("moon_secpolicy_{}".format(self.__intra_extension_id),
- # method="get_object_categories",
- # ctx={"id": self.__intra_extension_id,
- # "user_id": "admin"},
- # args={})["object_categories"]
- # for category in categories:
- # result[category] = list()
- # assignments = call("moon_secpolicy_{}".format(self.__intra_extension_id),
- # method="get_object_assignments",
- # ctx={"id": self.__intra_extension_id,
- # "sid": _object,
- # "scid": category,
- # "user_id": "admin"},
- # args={})["object_assignments"]
- # result[category].extend(assignments[_object][category])
- # categories = call("moon_secpolicy_{}".format(self.__intra_extension_id),
- # method="get_action_categories",
- # ctx={"id": self.__intra_extension_id,
- # "user_id": "admin"},
- # args={})["action_categories"]
- # for category in categories:
- # result[category] = list()
- # assignments = call("moon_secpolicy_{}".format(self.__intra_extension_id),
- # method="get_action_assignments",
- # ctx={"id": self.__intra_extension_id,
- # "sid": _action,
- # "scid": category,
- # "user_id": "admin"},
- # args={})["action_assignments"]
- # result[category].extend(assignments[_action][category])
+ meta_rules = self.ModelManager.get_meta_rules("admin")
+ for header in self.__headers:
+ policy_id = self.PolicyManager.get_policy_from_meta_rules("admin", header)
+ for meta_rule_id in meta_rules:
+ for sub_cat in meta_rules[meta_rule_id]['subject_categories']:
+ if sub_cat not in result:
+ result[sub_cat] = []
+ for assign in self.PolicyManager.get_subject_assignments("admin", policy_id, _subject, sub_cat).values():
+ result[sub_cat].extend(assign["assignments"])
+ for obj_cat in meta_rules[meta_rule_id]['object_categories']:
+ if obj_cat not in result:
+ result[obj_cat] = []
+ for assign in self.PolicyManager.get_object_assignments("admin", policy_id, _object, obj_cat).values():
+ result[obj_cat].extend(assign["assignments"])
+ for act_cat in meta_rules[meta_rule_id]['action_categories']:
+ if act_cat not in result:
+ result[act_cat] = []
+ for assign in self.PolicyManager.get_action_assignments("admin", policy_id, _action, act_cat).values():
+ result[act_cat].extend(assign["assignments"])
return result
def __repr__(self):
"request_id": copy.deepcopy(self.__request_id),
}
+ @property
+ def request_id(self):
+ return self.__request_id
+
+ @request_id.setter
+ def request_id(self, value):
+ raise Exception("You cannot update the request_id")
+
+ @request_id.deleter
+ def request_id(self):
+ raise Exception("You cannot update the request_id")
+
@property
def initial_request(self):
return {