aboutsummaryrefslogtreecommitdiffstats
path: root/moonv4/moon_authz
diff options
context:
space:
mode:
authorasteroide <thomas.duval@orange.com>2017-05-05 11:16:38 +0200
committerasteroide <thomas.duval@orange.com>2017-05-05 11:16:38 +0200
commit94aa78ca23c4db13a0752fbdd0df96730b1e7288 (patch)
tree4e77ef8776d5f93b12eae84696f953faf7c3ea6e /moonv4/moon_authz
parent67369036badcb4ae84fb7c1c7d7dabfab27326e6 (diff)
Code update for chaining policies.
Change-Id: If9f6c2640492f69d0f3af2118fade72700df47e6
Diffstat (limited to 'moonv4/moon_authz')
-rw-r--r--moonv4/moon_authz/moon_authz/api/authorization.py437
-rw-r--r--moonv4/moon_authz/moon_authz/messenger.py37
2 files changed, 79 insertions, 395 deletions
diff --git a/moonv4/moon_authz/moon_authz/api/authorization.py b/moonv4/moon_authz/moon_authz/api/authorization.py
index 248a9565..5968178e 100644
--- a/moonv4/moon_authz/moon_authz/api/authorization.py
+++ b/moonv4/moon_authz/moon_authz/api/authorization.py
@@ -3,11 +3,12 @@
# 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
@@ -40,11 +41,15 @@ class Authorization(object):
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
@@ -52,388 +57,80 @@ class Authorization(object):
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")
@@ -441,5 +138,5 @@ class Authorization(object):
return {"authz": False,
"error": str(e),
"pdp_id": self.pdp_id,
- "ctx": ctx, "args": args}
+ "ctx": ctxt, "args": payload}
diff --git a/moonv4/moon_authz/moon_authz/messenger.py b/moonv4/moon_authz/moon_authz/messenger.py
index 8ebd1633..6fa34770 100644
--- a/moonv4/moon_authz/moon_authz/messenger.py
+++ b/moonv4/moon_authz/moon_authz/messenger.py
@@ -5,12 +5,10 @@
from oslo_config import cfg
import oslo_messaging
-import hashlib
import time
from oslo_log import log as logging
from moon_authz.api.generic import Status, Logs
from moon_authz.api.authorization import Authorization
-from moon_utilities.security_functions import call
from moon_utilities.api import APIList
LOG = logging.getLogger(__name__)
@@ -20,44 +18,33 @@ CONF = cfg.CONF
class Server:
def __init__(self, component_id, keystone_project_id):
- self.TOPIC = "authz_"+hashlib.sha224(component_id.encode("utf-8")).hexdigest()
- self.transport = oslo_messaging.get_transport(cfg.CONF)
- self.target = oslo_messaging.Target(topic=self.TOPIC, server='moon_authz_server1')
- # ctx = {'user_id': 'admin', 'id': component_id, 'method': 'get_intra_extensions'}
- # if CONF.slave.slave_name:
- # ctx['call_master'] = True
- # intra_extension = call(
- # endpoint="security_router",
- # ctx=ctx,
- # method='route',
- # args={}
- # )
- # if "intra_extensions" not in intra_extension:
- # LOG.error("Error reading intra_extension from router")
- # LOG.error("intra_extension: {}".format(intra_extension))
- # raise IntraExtensionUnknown
- # component_id = list(intra_extension["intra_extensions"].keys())[0]
- LOG.info("Starting MQ server with topic: {}".format(self.TOPIC))
+ self.TOPIC = "authz-workers"
+ transport = oslo_messaging.get_notification_transport(cfg.CONF)
+ targets = [
+ oslo_messaging.Target(topic=self.TOPIC),
+ ]
self.endpoints = [
APIList((Status, Logs)),
Status(),
Logs(),
Authorization(component_id)
]
- self.server = oslo_messaging.get_rpc_server(self.transport, self.target, self.endpoints,
- executor='threading',
- access_policy=oslo_messaging.DefaultRPCAccessPolicy)
+ pool = "authz-workers"
+ self.server = oslo_messaging.get_notification_listener(transport, targets,
+ self.endpoints, executor='threading',
+ pool=pool)
+ LOG.info("Starting MQ notification server with topic: {}".format(self.TOPIC))
def run(self):
try:
self.server.start()
while True:
- time.sleep(1)
+ time.sleep(0.1)
except KeyboardInterrupt:
print("Stopping server by crtl+c")
except SystemExit:
print("Stopping server")
self.server.stop()
- self.server.wait()
+