Update Moon engine to allow a session policy 67/34767/1
authorasteroide <thomas.duval@orange.com>
Mon, 15 May 2017 12:19:43 +0000 (14:19 +0200)
committerasteroide <thomas.duval@orange.com>
Mon, 15 May 2017 12:19:43 +0000 (14:19 +0200)
Change-Id: I63a80597710f08a6641e159cc2306d3cc68b1240

13 files changed:
moonv4/moon_authz/moon_authz/api/authorization.py
moonv4/moon_db/moon_db/backends/sql.py
moonv4/moon_interface/moon_interface/api/rules.py
moonv4/moon_interface/tests/apitests/populate_default_values.py
moonv4/moon_interface/tests/apitests/scenario/rbac.py
moonv4/moon_interface/tests/apitests/scenario/session.py
moonv4/moon_interface/tests/apitests/set_authz.py
moonv4/moon_interface/tests/apitests/utils/policies.py
moonv4/moon_orchestrator/conf/plugins/session.py [new file with mode: 0644]
moonv4/moon_orchestrator/moon_orchestrator/api/containers.py
moonv4/moon_orchestrator/moon_orchestrator/server.py
moonv4/moon_secrouter/moon_secrouter/api/route.py
moonv4/moon_utilities/moon_utilities/security_functions.py

index 5968178..e4d7ad7 100644 (file)
@@ -25,12 +25,6 @@ LOG = logging.getLogger(__name__)
 CONF = cfg.CONF
 
 
-class PDP:
-
-    def __init__(self, context):
-        self.__context = context
-
-
 class Authorization(object):
     """
     Retrieve the current status of all components.
@@ -40,13 +34,14 @@ class Authorization(object):
     pdp_id = None
     meta_rule_id = None
     keystone_project_id = None
+    payload = None
 
     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()}
+            context={'container_id': "\w+_"+hashlib.sha224(component_desc.encode("utf-8")).hexdigest()}
         )
 
         for _id_value in component_desc.split("_"):
@@ -61,27 +56,205 @@ class Authorization(object):
     def __check_rules(self, context):
         scopes_list = list()
         current_header_id = context['headers'][context['index']]
+        Context.update_target(context)
         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"]["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']))
-            scopes_list.append(current_pdp['target'][category])
+            scope = list(current_pdp['target'][category])
+            scopes_list.append(scope)
         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):
             req = list(item)
-            if req in rules:
-                return True, ""
+            for rule in rules['rules']:
+                if req == rule['rule']:
+                    return rule['instructions'], ""
         LOG.warning("No rule match the request...")
         return False, "No rule match the request..."
 
+    def __update_subject_category_in_policy(self, operation, target):
+        result = False
+        try:
+            policy_name, category_name, data_name = target.split(":")
+        except ValueError:
+            LOG.error("Cannot understand value in instruction ({})".format(target))
+            return False
+        pdp_set = self.payload["authz_context"]['pdp_set']
+        for meta_rule_id in self.payload["authz_context"]['pdp_set']:
+            policy_id = PolicyManager.get_policy_from_meta_rules("admin", meta_rule_id)
+            if meta_rule_id == "effect":
+                continue
+            if pdp_set[meta_rule_id]["meta_rules"]["name"] == policy_name:
+                for category_id, category_value in ModelManager.get_subject_categories("admin").items():
+                    if category_value["name"] == "role":
+                        subject_category_id = category_id
+                        break
+                else:
+                    LOG.error("Cannot understand category in instruction ({})".format(target))
+                    return False
+                subject_data_id = None
+                for data in PolicyManager.get_subject_data("admin", policy_id, category_id=subject_category_id):
+                    for data_id, data_value in data['data'].items():
+                        if data_value["name"] == data_name:
+                            subject_data_id = data_id
+                            break
+                    if subject_data_id:
+                        break
+                else:
+                    LOG.error("Cannot understand data in instruction ({})".format(target))
+                    return False
+                if operation == "add":
+                    self.payload["authz_context"]['pdp_set'][meta_rule_id]['target'][subject_category_id].append(
+                        subject_data_id)
+                elif operation == "delete":
+                    try:
+                        self.payload["authz_context"]['pdp_set'][meta_rule_id]['target'][subject_category_id].remove(
+                            subject_data_id)
+                    except ValueError:
+                        LOG.warning("Cannot remove role {} from target".format(data_name))
+                result = True
+                break
+        return result
+
+    def __update_container_chaining(self):
+        for index in range(len(self.payload["authz_context"]['headers'])):
+            self.payload["container_chaining"][index]["meta_rule_id"] = self.payload["authz_context"]['headers'][index]
+
+    def __get_container_from_meta_rule(self, meta_rule_id):
+        for index in range(len(self.payload["authz_context"]['headers'])):
+            if self.payload["container_chaining"][index]["meta_rule_id"] == meta_rule_id:
+                return self.payload["container_chaining"][index]
+
+    def __update_headers(self, name):
+        context = self.payload["authz_context"]
+        for meta_rule_id, meta_rule_value in context["pdp_set"].items():
+            if meta_rule_id == "effect":
+                continue
+            if meta_rule_value["meta_rules"]["name"] == name:
+                self.payload["authz_context"]['headers'].append(meta_rule_id)
+                return True
+        return False
+
+    def __exec_next_state(self, rule_found):
+        index = self.payload["authz_context"]['index']
+        current_meta_rule = self.payload["authz_context"]['headers'][index]
+        current_container = self.__get_container_from_meta_rule(current_meta_rule)
+        current_container_genre = current_container["genre"]
+        try:
+            next_meta_rule = self.payload["authz_context"]['headers'][index+1]
+        except IndexError:
+            next_meta_rule = None
+        if current_container_genre == "authz":
+            if rule_found:
+                return self.__return_to_router()
+            pass
+            if next_meta_rule:
+                # next will be session if current is deny and session is unset
+                if self.payload["authz_context"]['pdp_set'][next_meta_rule]['effect'] == "unset":
+                    return notify(
+                        request_id=self.payload["authz_context"]["request_id"],
+                        container_id=self.__get_container_from_meta_rule(next_meta_rule)['container_id'],
+                        payload=self.payload)
+                # next will be delegation if current is deny and session is passed or deny and delegation is unset
+                else:
+                    LOG.error("Delegation is not developed!")
+
+            else:
+                # else next will be None and the request is sent to router
+                return self.__return_to_router()
+        elif current_container_genre == "session":
+            pass
+            # next will be next container in headers if current is passed
+            if self.payload["authz_context"]['pdp_set'][current_meta_rule]['effect'] == "passed":
+                return notify(
+                    request_id=self.payload["authz_context"]["request_id"],
+                    container_id=self.__get_container_from_meta_rule(next_meta_rule)['container_id'],
+                    payload=self.payload)
+            # next will be None if current is grant and the request is sent to router
+            else:
+                return self.__return_to_router()
+        elif current_container_genre == "delegation":
+            LOG.error("Delegation is not developed!")
+            # next will be authz if current is deny
+            # next will be None if current is grant and the request is sent to router
+
+    def __return_to_router(self):
+        call(endpoint="security_router",
+             ctx={"id": self.component_id,
+                  "call_master": False,
+                  "method": "return_authz",
+                  "request_id": self.payload["authz_context"]["request_id"]},
+             method="route",
+             args=self.payload["authz_context"])
+
+    def __exec_instructions(self, instructions):
+        current_header_id = self.payload["authz_context"]['headers'][self.payload["authz_context"]['index']]
+        for instruction in instructions:
+            for key in instruction:
+                if key == "decision":
+                    if instruction["decision"] == "grant":
+                        self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = "grant"
+                        self.__return_to_router()
+                    else:
+                        self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = instruction["decision"]
+                elif key == "chain":
+                    result = self.__update_headers(**instruction["chain"])
+                    if not result:
+                        self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = "deny"
+                    else:
+                        self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = "passed"
+                elif key == "update":
+                    result = self.__update_subject_category_in_policy(**instruction["update"])
+                    if not result:
+                        self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = "deny"
+                    else:
+                        self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = "passed"
+        # LOG.info("__exec_instructions {}".format(self.payload["authz_context"]))
+
+    def __update_current_request(self):
+        index = self.payload["authz_context"]["index"]
+        current_header_id = self.payload["authz_context"]['headers'][index]
+        previous_header_id = self.payload["authz_context"]['headers'][index-1]
+        current_policy_id = PolicyManager.get_policy_from_meta_rules("admin", current_header_id)
+        previous_policy_id = PolicyManager.get_policy_from_meta_rules("admin", previous_header_id)
+        # FIXME (asteroide): must change those lines to be ubiquitous against any type of policy
+        if self.payload["authz_context"]['pdp_set'][current_header_id]['meta_rules']['name'] == "session":
+            subject = self.payload["authz_context"]['current_request'].get("subject")
+            subject_category_id = None
+            role_names = []
+            for category_id, category_value in ModelManager.get_subject_categories("admin").items():
+                if category_value["name"] == "role":
+                    subject_category_id = category_id
+                    break
+            for assignment_id, assignment_value in PolicyManager.get_subject_assignments(
+                    "admin", previous_policy_id, subject, subject_category_id).items():
+                    for data_id in assignment_value["assignments"]:
+                        data = PolicyManager.get_subject_data("admin", previous_policy_id, data_id, subject_category_id)
+                        for _data in data:
+                            for key, value in _data["data"].items():
+                                role_names.append(value["name"])
+            new_role_ids = []
+            for perimeter_id, perimeter_value in PolicyManager.get_objects("admin", current_policy_id).items():
+                if perimeter_value["name"] in role_names:
+                    new_role_ids.append(perimeter_id)
+                    break
+            perimeter_id = None
+            for perimeter_id, perimeter_value in PolicyManager.get_actions("admin", current_policy_id).items():
+                if perimeter_value["name"] == "*":
+                    break
+
+            self.payload["authz_context"]['current_request']['object'] = new_role_ids[0]
+            self.payload["authz_context"]['current_request']['action'] = perimeter_id
+        elif self.payload["authz_context"]['pdp_set'][current_header_id]['meta_rules']['name'] == "rbac":
+            self.payload["authz_context"]['current_request']['subject'] = self.payload["authz_context"]['initial_request']['subject']
+            self.payload["authz_context"]['current_request']['object'] = self.payload["authz_context"]['initial_request']['object']
+            self.payload["authz_context"]['current_request']['action'] = self.payload["authz_context"]['initial_request']['action']
+
     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"
@@ -93,50 +266,39 @@ class Authorization(object):
         :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"]
+        LOG.info("calling authz {} {}".format(ctxt, payload))
+        self.keystone_project_id = payload["id"]
+        self.payload = payload
         try:
             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()
+                self.payload["authz_context"] = Context(self.keystone_project_id,
+                                                        self.payload["subject_name"],
+                                                        self.payload["object_name"],
+                                                        self.payload["action_name"],
+                                                        self.payload["request_id"]).to_dict()
+                self.__update_container_chaining()
             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]
+                self.payload["authz_context"]["index"] += 1
+                self.__update_current_request()
+            result, message = self.__check_rules(self.payload["authz_context"])
+            current_header_id = self.payload["authz_context"]['headers'][self.payload["authz_context"]['index']]
             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)
+                self.__exec_instructions(result)
             else:
-                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"]
+                self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = "deny"
+            self.__exec_next_state(result)
             return {"authz": result,
                     "error": message,
                     "pdp_id": self.pdp_id,
-                    "ctx": ctxt, "args": payload}
+                    "ctx": ctxt, "args": self.payload}
         except Exception as e:
             try:
-                LOG.error(payload["authz_context"])
-                # del ctx["authz_context"]
+                LOG.error(self.payload["authz_context"])
             except KeyError:
                 LOG.error("Cannot find \"authz_context\" in context")
             LOG.error(e, exc_info=True)
             return {"authz": False,
                     "error": str(e),
                     "pdp_id": self.pdp_id,
-                    "ctx": ctxt, "args": payload}
+                    "ctx": ctxt, "args": self.payload}
 
index 5ab653a..8cb6bb8 100644 (file)
@@ -328,6 +328,7 @@ class Rule(Base, DictBase):
         return {
             'id': self.id,
             'rule': self.rule["rule"],
+            'instructions': self.rule["instructions"],
             'enabled': self.rule["enabled"],
             'policy_id': self.policy_id,
             'meta_rule_id': self.meta_rule_id
@@ -651,6 +652,7 @@ class PolicyConnector(BaseConnector, PolicyDriver):
                     session.delete(_action)
 
     def get_subject_data(self, policy_id, data_id=None, category_id=None):
+        LOG.info("driver {} {} {}".format(policy_id, data_id, category_id))
         with self.get_session_for_read() as session:
             query = session.query(SubjectData)
             if data_id:
@@ -658,6 +660,7 @@ class PolicyConnector(BaseConnector, PolicyDriver):
             else:
                 query = query.filter_by(policy_id=policy_id, category_id=category_id)
             ref_list = query.all()
+            LOG.info("ref_list={}".format(ref_list))
             return {
                 "policy_id": policy_id,
                 "category_id": category_id,
@@ -979,10 +982,7 @@ class PolicyConnector(BaseConnector, PolicyDriver):
             query = session.query(Rule)
             query = query.filter_by(policy_id=policy_id, meta_rule_id=meta_rule_id)
             ref_list = query.all()
-            LOG.info("add_rule {}".format(ref_list))
-            LOG.info("add_rule {}".format(value))
             rules = list(map(lambda x: x.rule, ref_list))
-            LOG.info("add_rule rules={}".format(rules))
             if not rules or value not in rules:
                 LOG.info("add_rule IN IF")
                 ref = Rule.from_dict(
index 81639a3..7757d27 100644 (file)
@@ -62,13 +62,34 @@ class Rules(Resource):
         :request body: post = {
             "meta_rule_id": "meta_rule_id1",
             "rule": ["subject_data_id2", "object_data_id2", "action_data_id2"],
+            "instructions": (
+                {"decision": "grant"},
+            )
             "enabled": True
         }
         :return: {
             "rules": [
                 "meta_rule_id": "meta_rule_id1",
-                "rule_id1": ["subject_data_id1", "object_data_id1", "action_data_id1"],
-                "rule_id2": ["subject_data_id2", "object_data_id2", "action_data_id2"],
+                "rule_id1": {
+                    "rule": ["subject_data_id1", "object_data_id1", "action_data_id1"],
+                    "instructions": (
+                        {"decision": "grant"},  # "grant" to immediately exit, 
+                                                # "continue" to wait for the result of next policy
+                                                # "deny" to deny the request
+                    )
+                }
+                "rule_id2": {
+                    "rule": ["subject_data_id2", "object_data_id2", "action_data_id2"],
+                    "instructions": (
+                        {
+                            "update": {
+                                "operation": "add",  # operations may be "add" or "delete"
+                                "target": "rbac:role:admin"  # add the role admin to the current user
+                            }
+                        },
+                        {"chain": {"name": "rbac"}}  # chain with the policy named rbac
+                    )
+                }
             ]
         }
         :internal_api: add_rule
index 5ad6098..0e3438d 100644 (file)
@@ -56,7 +56,7 @@ def create_model():
 def create_policy(model_id, meta_rule_list):
     if args.verbose:
         logger.warning("Creating policy {}".format(scenario.policy_name))
-    policy_id = add_policy(name=scenario.policy_name)
+    policy_id = add_policy(name=scenario.policy_name, genre=scenario.policy_genre)
 
     update_policy(policy_id, model_id)
 
@@ -90,23 +90,52 @@ def create_policy(model_id, meta_rule_list):
         scenario.actions[name] = add_action(policy_id, name=name)
 
     for subject_name in scenario.subject_assignments:
-        for subject_category_name in scenario.subject_assignments[subject_name]:
-            subject_id = scenario.subjects[subject_name]
-            subject_cat_id = scenario.subject_categories[subject_category_name]
-            subject_data_id = scenario.subject_data[subject_category_name][scenario.subject_assignments[subject_name][subject_category_name]]
-            add_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id)
+        if type(scenario.subject_assignments[subject_name]) in (list, tuple):
+            for items in scenario.subject_assignments[subject_name]:
+                for subject_category_name in items:
+                    subject_id = scenario.subjects[subject_name]
+                    subject_cat_id = scenario.subject_categories[subject_category_name]
+                    for data in scenario.subject_assignments[subject_name]:
+                        subject_data_id = scenario.subject_data[subject_category_name][data[subject_category_name]]
+                        add_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id)
+        else:
+            for subject_category_name in scenario.subject_assignments[subject_name]:
+                subject_id = scenario.subjects[subject_name]
+                subject_cat_id = scenario.subject_categories[subject_category_name]
+                subject_data_id = scenario.subject_data[subject_category_name][scenario.subject_assignments[subject_name][subject_category_name]]
+                add_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id)
+        
     for object_name in scenario.object_assignments:
-        for object_category_name in scenario.object_assignments[object_name]:
-            object_id = scenario.objects[object_name]
-            object_cat_id = scenario.object_categories[object_category_name]
-            object_data_id = scenario.object_data[object_category_name][scenario.object_assignments[object_name][object_category_name]]
-            add_object_assignments(policy_id, object_id, object_cat_id, object_data_id)
+        if type(scenario.object_assignments[object_name]) in (list, tuple):
+            for items in scenario.object_assignments[object_name]:
+                for object_category_name in items:
+                    object_id = scenario.objects[object_name]
+                    object_cat_id = scenario.object_categories[object_category_name]
+                    for data in scenario.object_assignments[object_name]:
+                        object_data_id = scenario.object_data[object_category_name][data[object_category_name]]
+                        add_object_assignments(policy_id, object_id, object_cat_id, object_data_id)
+        else:
+            for object_category_name in scenario.object_assignments[object_name]:
+                object_id = scenario.objects[object_name]
+                object_cat_id = scenario.object_categories[object_category_name]
+                object_data_id = scenario.object_data[object_category_name][scenario.object_assignments[object_name][object_category_name]]
+                add_object_assignments(policy_id, object_id, object_cat_id, object_data_id)
+
     for action_name in scenario.action_assignments:
-        for action_category_name in scenario.action_assignments[action_name]:
-            action_id = scenario.actions[action_name]
-            action_cat_id = scenario.action_categories[action_category_name]
-            action_data_id = scenario.action_data[action_category_name][scenario.action_assignments[action_name][action_category_name]]
-            add_action_assignments(policy_id, action_id, action_cat_id, action_data_id)
+        if type(scenario.action_assignments[action_name]) in (list, tuple):
+            for items in scenario.action_assignments[action_name]:
+                for action_category_name in items:
+                    action_id = scenario.actions[action_name]
+                    action_cat_id = scenario.action_categories[action_category_name]
+                    for data in scenario.action_assignments[action_name]:
+                        action_data_id = scenario.action_data[action_category_name][data[action_category_name]]
+                        add_action_assignments(policy_id, action_id, action_cat_id, action_data_id)
+        else:
+            for action_category_name in scenario.action_assignments[action_name]:
+                action_id = scenario.actions[action_name]
+                action_cat_id = scenario.action_categories[action_category_name]
+                action_data_id = scenario.action_data[action_category_name][scenario.action_assignments[action_name][action_category_name]]
+                add_action_assignments(policy_id, action_id, action_cat_id, action_data_id)
 
     for meta_rule_name in scenario.rules:
         meta_rule_value = scenario.meta_rule[meta_rule_name]
index a43bd1f..89fd7de 100644 (file)
@@ -2,6 +2,7 @@
 pdp_name = "pdp1"
 policy_name = "RBAC policy example"
 model_name = "RBAC"
+policy_genre = "authz"
 
 subjects = {"user0": "", "user1": "", }
 objects = {"vm0": "", "vm1": "", }
@@ -11,13 +12,13 @@ subject_categories = {"role": "", }
 object_categories = {"id": "", }
 action_categories = {"action-type": "", }
 
-subject_data = {"role": {"admin": "", "employee": ""}}
-object_data = {"id": {"vm0": "", "vm1": ""}}
-action_data = {"action-type": {"vm-action": "", }}
+subject_data = {"role": {"admin": "", "employee": "", "*": ""}}
+object_data = {"id": {"vm0": "", "vm1": "", "*": ""}}
+action_data = {"action-type": {"vm-action": "", "*": ""}}
 
-subject_assignments = {"user0": {"role": "employee"}, "user1": {"role": "employee"}, }
-object_assignments = {"vm0": {"id": "vm0"}, "vm1": {"id": "vm1"}}
-action_assignments = {"start": {"action-type": "vm-action"}, "stop": {"action-type": "vm-action"}}
+subject_assignments = {"user0": ({"role": "employee"}, {"role": "*"}), "user1": ({"role": "employee"}, {"role": "*"}), }
+object_assignments = {"vm0": ({"id": "vm0"}, {"id": "*"}), "vm1": ({"id": "vm1"}, {"id": "*"})}
+action_assignments = {"start": ({"action-type": "vm-action"}, {"action-type": "*"}), "stop": ({"action-type": "vm-action"}, {"action-type": "*"})}
 
 meta_rule = {
     "rbac": {"id": "", "value": ("role", "id", "action-type")},
@@ -28,13 +29,13 @@ rules = {
         {
             "rule": ("admin", "vm0", "vm-action"),
             "instructions": (
-                {"decision": "grant"}  # "grant" to immediately exit, "continue" to wait for the result of next policy
+                {"decision": "grant"},  # "grant" to immediately exit, "continue" to wait for the result of next policy
             )
         },
         {
-            "rule": ("admin", "vm1", "vm-action"),
+            "rule": ("employee", "vm1", "vm-action"),
             "instructions": (
-                {"decision": "grant"}
+                {"decision": "grant"},
             )
         },
     )
index 6b7e0f1..97d7aec 100644 (file)
@@ -2,6 +2,7 @@
 pdp_name = "pdp1"
 policy_name = "Session policy example"
 model_name = "Session"
+policy_genre = "session"
 
 subjects = {"user0": "", "user1": "", }
 objects = {"admin": "", "employee": "", }
@@ -12,12 +13,16 @@ object_categories = {"role": "", }
 action_categories = {"session-action": "", }
 
 subject_data = {"subjectid": {"user0": "", "user1": ""}}
-object_data = {"role": {"admin": "", "employee": ""}}
-action_data = {"session-action": {"activate": "", "deactivate": ""}}
+object_data = {"role": {"admin": "", "employee": "", "*": ""}}
+action_data = {"session-action": {"activate": "", "deactivate": "", "*": ""}}
 
-subject_assignments = {"user0": {"subjectid": "user0"}, "user1": {"subjectid": "user1"}, }
-object_assignments = {"admin": {"role": "admin"}, "employee": {"role": "employee"}}
-action_assignments = {"activate": {"session-action": "activate"}, "deactivate": {"session-action": "deactivate"}}
+subject_assignments = {"user0": ({"subjectid": "user0"}, ), "user1": ({"subjectid": "user1"}, ), }
+object_assignments = {"admin": ({"role": "admin"}, {"role": "*"}),
+                      "employee": ({"role": "employee"}, {"role": "employee"})
+                      }
+action_assignments = {"activate": ({"session-action": "activate"}, {"session-action": "*"}, ),
+                      "deactivate": ({"session-action": "deactivate"}, {"session-action": "*"}, )
+                      }
 
 meta_rule = {
     "session": {"id": "", "value": ("subjectid", "role", "session-action")},
@@ -26,7 +31,7 @@ meta_rule = {
 rules = {
     "session": (
         {
-            "rule": ("user0", "admin", "activate"),
+            "rule": ("user0", "employee", "*"),
             "instructions": (
                 {
                     "update": {
@@ -34,11 +39,11 @@ rules = {
                         "target": "rbac:role:admin"  # add the role admin to the current user
                     }
                 },
-                {"chain": [{"security_pipeline": "rbac"}]}  # chain with the meta_rule named rbac
+                {"chain": {"name": "rbac"}}  # chain with the meta_rule named rbac
             )
         },
         {
-            "rule": ("user1", "employee", "deactivate"),
+            "rule": ("user1", "employee", "*"),
             "instructions": (
                 {
                     "update": {
@@ -46,7 +51,7 @@ rules = {
                         "target": "rbac:role:employee"  # delete the role employee from the current user
                     }
                 },
-                {"chain": [{"security_pipeline": "rbac"}]}  # chain with the meta_rule named rbac
+                {"chain": {"name": "rbac"}}  # chain with the meta_rule named rbac
             )
         },
     )
index 38b6350..f515e4e 100644 (file)
@@ -41,10 +41,13 @@ for rule in rules:
     url = "http://172.18.0.11:38001/authz/{}/{}".format(keystone_project_id, "/".join(rule))
     req = requests.get(url)
     print("\033[1m{}\033[m {}".format(url, req.status_code))
-    j = req.json()
-    # print(j)
-    if j.get("authz"):
-        print("\t\033[32m{}\033[m {}".format(j.get("authz"), j.get("error", "")))
+    try:
+        j = req.json()
+    except Exception as e:
+        print(req.text)
     else:
-        print("\t\033[31m{}\033[m {}".format(j.get("authz"), j.get("error", "")))
+        if j.get("authz"):
+            print("\t\033[32m{}\033[m {}".format(j.get("authz"), j.get("error", "")))
+        else:
+            print("\t\033[31m{}\033[m {}".format(j.get("authz"), j.get("error", "")))
 
index bf75734..969ab70 100644 (file)
@@ -63,8 +63,9 @@ def check_policy(policy_id=None):
         assert policy_template["name"] == result['policies'][policy_id]["name"]
 
 
-def add_policy(name="test_policy"):
+def add_policy(name="test_policy", genre="authz"):
     policy_template["name"] = name
+    policy_template["genre"] = genre
     req = requests.post(URL.format("/policies"), json=policy_template, headers=HEADERS)
     assert req.status_code == 200
     result = req.json()
diff --git a/moonv4/moon_orchestrator/conf/plugins/session.py b/moonv4/moon_orchestrator/conf/plugins/session.py
new file mode 100644 (file)
index 0000000..6fa2cfe
--- /dev/null
@@ -0,0 +1,67 @@
+# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
+# This software is distributed under the terms and conditions of the 'Apache-2.0'
+# license which can be found in the file 'LICENSE' in this package distribution
+# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
+
+import os
+import time
+import hashlib
+from oslo_config import cfg
+from oslo_log import log as logging
+import oslo_messaging
+from moon_orchestrator.dockers import DockerBase
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+DOMAIN = "moon_orchestrator"
+
+__CWD__ = os.path.dirname(os.path.abspath(__file__))
+# TODO (asteroide): select the right template folder
+TEMPLATES_FOLDER = os.path.join(__CWD__, "..", "conf", "dockers")
+# TODO (asteroide): add specific configuration options for that plugin
+
+
+class AuthzFunction(DockerBase):
+
+    id = "moon_session_function"
+    __build = """RUN mkdir -p /etc/moon/
+COPY conf /etc/moon/
+ADD dist/{py_pkg}.tar.gz /root
+WORKDIR /root/{py_pkg}
+RUN pip3 install -r requirements.txt
+RUN pip3 install .
+"""
+
+    def __init__(self, uuid, conf_file="", docker=None, network_config=None):
+        self.id = "session_"+hashlib.sha224(uuid.encode("utf-8")).hexdigest()
+        super(AuthzFunction, self).__init__(
+            name="moon_authz",
+            run_cmd=["python3", "-m", "moon_authz", uuid],
+            conf_file=conf_file,
+            docker=docker,
+            network_config=network_config,
+            build_cmd=self.__build,
+            id=self.id,
+            tag=""
+            # tag=CONF.security_function.container
+        )
+        # note(asteroide): time to let the new docker boot
+        time.sleep(3)
+        # self.get_status()
+
+    def get_status(self):
+        return True
+        # transport = oslo_messaging.get_transport(CONF)
+        # target = oslo_messaging.Target(topic=self.id, version='1.0')
+        # client = oslo_messaging.RPCClient(transport, target)
+        # LOG.info("Calling Status on {}".format(self.id))
+        # ret = client.call({"component_id": self.id}, 'get_status', args=None)
+        # LOG.info(ret)
+        # return ret
+
+
+def run(uuid, conf_file="", docker=None, network_config=None):
+    return AuthzFunction(uuid,
+                         conf_file=conf_file,
+                         docker=docker,
+                         network_config=network_config)
index 3572d61..2ed5b26 100644 (file)
@@ -109,7 +109,7 @@ class Containers(object):
                         "meta_rule_id": meta_rule,
                         "genre": policy_value['genre'],
                         "keystone_project_id": keystone_project_id,
-                        "container_id": "authz_"+hashlib.sha224(pre_container_id.encode("utf-8")).hexdigest()
+                        "container_id": policy_value['genre']+"_"+hashlib.sha224(pre_container_id.encode("utf-8")).hexdigest()
                     })
         return {"containers": self.components[ctx["id"]]}
         # function_components = []
index 4fc9d5f..e6d28c2 100644 (file)
@@ -62,7 +62,7 @@ class DockerManager:
         :param uuid: the uuid of the intra_extension linked to that component
         :return: the created component
         """
-        component_id = "authz_"+hashlib.sha224(uuid.encode("utf-8")).hexdigest()
+        component_id = component+"_"+hashlib.sha224(uuid.encode("utf-8")).hexdigest()
         if component_id not in CONTAINERS:
             plug = load_plugin(component)
             LOG.info("Creating {} with id {}".format(component, uuid))
index ccdff08..7cce135 100644 (file)
@@ -200,7 +200,12 @@ class Cache(object):
                             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"])
+                                        container_ids.append(
+                                            {
+                                                "container_id": container_value["container_id"],
+                                                "genre": container_value["genre"]
+                                            }
+                                        )
                                         break
         self.__CONTAINER_CHAINING[keystone_project_id] = container_ids
 
@@ -227,7 +232,7 @@ CACHE = Cache()
 class AuthzRequest:
 
     result = None
-    req_max_delay = 5
+    req_max_delay = 2
 
     def __init__(self, ctx, args):
         self.ctx = ctx
@@ -235,7 +240,7 @@ class AuthzRequest:
         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.pdp_container = self.container_chaining[0]["container_id"]
         self.run()
 
     def run(self):
@@ -256,8 +261,16 @@ class AuthzRequest:
         for key in self.result["pdp_set"]:
             if "effect" in self.result["pdp_set"][key]:
                 if self.result["pdp_set"][key]["effect"] == "grant":
+                    # the pdp is a authorization PDP and grant the request
+                    authz_results.append(True)
+                elif self.result["pdp_set"][key]["effect"] == "passed":
+                    # the pdp is not a authorization PDP (session or delegation) and had run normally
+                    authz_results.append(True)
+                elif self.result["pdp_set"][key]["effect"] == "unset":
+                    # the pdp is not a authorization PDP (session or delegation) and had not yep run
                     authz_results.append(True)
                 else:
+                    # the pdp is (or not) a authorization PDP and had run badly
                     authz_results.append(False)
         if list(itertools.accumulate(authz_results, lambda x, y: x & y))[-1]:
             self.result["pdp_set"]["effect"] = "grant"
index f7cbdf2..5d66d92 100644 (file)
@@ -168,8 +168,10 @@ def notify(request_id, container_id, payload, event_type="authz"):
         'request_id': request_id,
         'container_id': container_id
     }
-    result = __n_notifier.critical(ctxt, event_type, payload=payload)
-    return result
+    __n_notifier.critical(ctxt, event_type, payload=payload)
+    # FIXME (asteroide): the notification mus be done 2 times otherwise the notification
+    #                    may not be sent (need to search why)
+    __n_notifier.critical(ctxt, event_type, payload=payload)
 
 
 def call(endpoint, ctx=None, method="get_status", **kwargs):
@@ -249,34 +251,66 @@ class Context:
             self.__pdp_set[header]["meta_rules"] = self.__meta_rules[header]
             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"] = "deny"
+            self.__pdp_set[header]["effect"] = "unset"
         self.__pdp_set["effect"] = "deny"
 
+    @staticmethod
+    def update_target(context):
+        from moon_db.core import PDPManager, ModelManager, PolicyManager
+        # result = dict()
+        current_request = context['current_request']
+        _subject = current_request.get("subject")
+        _object = current_request.get("object")
+        _action = current_request.get("action")
+        meta_rule_id = context['headers'][context['index']]
+        policy_id = PolicyManager.get_policy_from_meta_rules("admin", meta_rule_id)
+        meta_rules = ModelManager.get_meta_rules("admin")
+        # for meta_rule_id in meta_rules:
+        for sub_cat in meta_rules[meta_rule_id]['subject_categories']:
+            if sub_cat not in context["pdp_set"][meta_rule_id]["target"]:
+                context["pdp_set"][meta_rule_id]["target"][sub_cat] = []
+            for assign in PolicyManager.get_subject_assignments("admin", policy_id, _subject, sub_cat).values():
+                for assign in assign["assignments"]:
+                    if assign not in context["pdp_set"][meta_rule_id]["target"][sub_cat]:
+                        context["pdp_set"][meta_rule_id]["target"][sub_cat].append(assign)
+        for obj_cat in meta_rules[meta_rule_id]['object_categories']:
+            if obj_cat not in context["pdp_set"][meta_rule_id]["target"]:
+                context["pdp_set"][meta_rule_id]["target"][obj_cat] = []
+            for assign in PolicyManager.get_object_assignments("admin", policy_id, _object, obj_cat).values():
+                for assign in assign["assignments"]:
+                    if assign not in context["pdp_set"][meta_rule_id]["target"][obj_cat]:
+                        context["pdp_set"][meta_rule_id]["target"][obj_cat].append(assign)
+        for act_cat in meta_rules[meta_rule_id]['action_categories']:
+            if act_cat not in context["pdp_set"][meta_rule_id]["target"]:
+                context["pdp_set"][meta_rule_id]["target"][act_cat] = []
+            for assign in PolicyManager.get_action_assignments("admin", policy_id, _action, act_cat).values():
+                for assign in assign["assignments"]:
+                    if assign not in context["pdp_set"][meta_rule_id]["target"][act_cat]:
+                        context["pdp_set"][meta_rule_id]["target"][act_cat].append(assign)
+        # context["pdp_set"][meta_rule_id]["target"].update(result)
+
     def __add_target(self, meta_rule_id):
         result = dict()
         _subject = self.__current_request["subject"]
         _object = self.__current_request["object"]
         _action = self.__current_request["action"]
         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"])
+        policy_id = self.PolicyManager.get_policy_from_meta_rules("admin", meta_rule_id)
+        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):