Update code to the latest working version: version 4.2 85/44185/1
authorasteroide <thomas.duval@orange.com>
Wed, 4 Oct 2017 07:04:38 +0000 (09:04 +0200)
committerasteroide <thomas.duval@orange.com>
Wed, 4 Oct 2017 07:04:38 +0000 (09:04 +0200)
Change-Id: I25d222ce9c8f4af8755886b79852d99b6870d515

39 files changed:
moonv4/bin/bootstrap.py
moonv4/moon_authz/Dockerfile
moonv4/moon_authz/moon_authz/api/authorization.py
moonv4/moon_authz/moon_authz/http_server.py [new file with mode: 0644]
moonv4/moon_authz/moon_authz/messenger.py [deleted file]
moonv4/moon_authz/moon_authz/server.py
moonv4/moon_authz/requirements.txt
moonv4/moon_interface/moon_interface/api/assignments.py [deleted file]
moonv4/moon_interface/moon_interface/api/authz.py
moonv4/moon_interface/moon_interface/api/data.py [deleted file]
moonv4/moon_interface/moon_interface/api/meta_data.py [deleted file]
moonv4/moon_interface/moon_interface/api/meta_rules.py [deleted file]
moonv4/moon_interface/moon_interface/api/models.py [deleted file]
moonv4/moon_interface/moon_interface/api/pdp.py [deleted file]
moonv4/moon_interface/moon_interface/api/perimeter.py [deleted file]
moonv4/moon_interface/moon_interface/api/policies.py [deleted file]
moonv4/moon_interface/moon_interface/api/rules.py [deleted file]
moonv4/moon_interface/moon_interface/api/wrapper.py [new file with mode: 0644]
moonv4/moon_interface/moon_interface/authz_requests.py [new file with mode: 0644]
moonv4/moon_interface/moon_interface/containers.py [new file with mode: 0644]
moonv4/moon_interface/moon_interface/http_server.py
moonv4/moon_interface/moon_interface/server.py
moonv4/moon_manager/moon_manager/api/containers.py [new file with mode: 0644]
moonv4/moon_manager/moon_manager/http_server.py
moonv4/moon_manager/requirements.txt
moonv4/moon_utilities/Changelog
moonv4/moon_utilities/build.sh [new file with mode: 0644]
moonv4/moon_utilities/moon_utilities/__init__.py
moonv4/moon_utilities/moon_utilities/cache.py [new file with mode: 0644]
moonv4/moon_utilities/moon_utilities/configuration.py
moonv4/moon_utilities/moon_utilities/get_os_apis.py
moonv4/moon_utilities/moon_utilities/security_functions.py
moonv4/moon_wrapper/moon_wrapper/api/__init__.py [new file with mode: 0644]
moonv4/moon_wrapper/moon_wrapper/api/generic.py [new file with mode: 0644]
moonv4/moon_wrapper/moon_wrapper/api/wrapper.py [new file with mode: 0644]
moonv4/moon_wrapper/moon_wrapper/http_server.py
moonv4/moon_wrapper/requirements.txt
moonv4/tests/populate_default_values.py
moonv4/tests/send_authz.py

index 98b8f9a..6f2a5e0 100644 (file)
@@ -213,6 +213,7 @@ def start_moon(data_config):
         output = subprocess.run(cmd,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
+        time.sleep(3)
         if output.returncode != 0:
             log.info(" ".join(cmd))
             log.info(output.returncode)
index 6ecc8f2..579ddd1 100644 (file)
@@ -3,11 +3,12 @@ FROM ubuntu:latest
 ENV UUID=null
 
 RUN apt update && apt install python3.5 python3-pip -y
-RUN pip3 install moon_utilities moon_db pip --upgrade
+RUN pip3 install pip --upgrade
 
 ADD . /root
 WORKDIR /root/
-RUN pip3 install -r requirements.txt
+RUN pip3 install -r requirements.txt --upgrade
+RUN pip3 install dist/moon_utilities-1.3.0-py3-none-any.whl --upgrade
 RUN pip3 install .
 
 CMD ["python3", "-m", "moon_authz"]
\ No newline at end of file
index 94f1e13..caa4108 100644 (file)
@@ -3,17 +3,15 @@
 # license which can be found in the file 'LICENSE' in this package distribution
 # or at 'http://www.apache.org/licenses/LICENSE-2.0'.
 
-import hashlib
+import binascii
 import itertools
-from oslo_log import log as logging
-from oslo_config import cfg
-import oslo_messaging
-from moon_utilities.security_functions import call, Context, notify
-from moon_utilities.misc import get_uuid_from_name
+import pickle
+from uuid import uuid4
+import logging
 from moon_utilities import exceptions
-from moon_db.core import PDPManager
-from moon_db.core import ModelManager
-from moon_db.core import PolicyManager
+import flask
+from flask import request
+from flask_restful import Resource
 
 # TODO (asteroide):
 # - end the dev of the context
@@ -21,43 +19,85 @@ from moon_db.core import PolicyManager
 # - call the next security function
 # - call the master if an element is absent
 
-LOG = logging.getLogger(__name__)
-CONF = cfg.CONF
+LOG = logging.getLogger("moon.api." + __name__)
 
 
-class Authorization(object):
+class Authz(Resource):
     """
-    Retrieve the current status of all components.
+    Endpoint for authz requests
     """
 
+    __urls__ = (
+        "/authz",
+        "/authz/",
+        "/authz/<string:uuid>/<string:subject_name>/<string:object_name>/<string:action_name>",
+    )
     __version__ = "0.1.0"
     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': "\w+_"+hashlib.sha224(component_desc.encode("utf-8")).hexdigest()}
-        )
+    def __init__(self, **kwargs):
+        component_data = kwargs.get("component_data", {})
+        self.component_id = component_data['component_id']
+        self.pdp_id = component_data['pdp_id']
+        self.meta_rule_id = component_data['meta_rule_id']
+        self.keystone_project_id = component_data['keystone_project_id']
+        self.cache = kwargs.get("cache")
+        self.context = None
 
-        for _id_value in component_desc.split("_"):
-            _type, _id = _id_value.split(":")
-            if _type == "pdp":
-                self.pdp_id = _id
-            elif _type == "metarule":
-                self.meta_rule_id = _id
-            elif _type == "project":
-                self.keystone_project_id = _id
+    def post(self, uuid=None, subject_name=None, object_name=None, action_name=None):
+        """Get a response on an authorization request
 
-    def __check_rules(self, context):
+        :param uuid: uuid of a tenant or an intra_extension
+        :param subject_name: name of the subject or the request
+        :param object_name: name of the object
+        :param action_name: name of the action
+        :return: {
+            "args": {},
+            "ctx": {
+                "action_name": "4567",
+                "id": "123456",
+                "method": "authz",
+                "object_name": "234567",
+                "subject_name": "123456",
+                "user_id": "admin"
+            },
+            "error": {
+                "code": 500,
+                "description": "",
+                "title": "Moon Error"
+            },
+            "intra_extension_id": "123456",
+            "result": false
+        }
+        :internal_api: authz
+        """
+        self.context = pickle.loads(request.data)
+        self.context.set_cache(self.cache)
+        self.context.increment_index()
+        self.run()
+        self.context.delete_cache()
+        response = flask.make_response(pickle.dumps(self.context))
+        response.headers['content-type'] = 'application/octet-stream'
+        return response
+
+    def run(self):
+        LOG.info("self.context.pdp_set={}".format(self.context.pdp_set))
+        result, message = self.__check_rules()
+        if result:
+            return self.__exec_instructions(result)
+        else:
+            self.context.current_state = "deny"
+        # self.__exec_next_state(result)
+        return
+
+    def __check_rules(self):
         scopes_list = list()
-        current_header_id = context['headers'][context['index']]
-        Context.update_target(context)
-        current_pdp = context['pdp_set'][current_header_id]
+        current_header_id = self.context.headers[self.context.index]
+        Context.update_target(context)
+        current_pdp = self.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"])
@@ -65,13 +105,12 @@ class Authorization(object):
         for category in category_list:
             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)
+        # policy_id = self.cache.get_policy_from_meta_rules("admin", current_header_id)
+
         for item in itertools.product(*scopes_list):
             req = list(item)
-            for rule in rules['rules']:
+            for rule in self.cache.rules[self.context.current_policy_id]["rules"]:
+                LOG.info("rule={}".format(rule))
                 if req == rule['rule']:
                     return rule['instructions'], ""
         LOG.warning("No rule match the request...")
@@ -84,13 +123,12 @@ class Authorization(object):
         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)
+        # pdp_set = self.payload["authz_context"]['pdp_set']
+        for meta_rule_id in self.context.pdp_set:
             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 self.context.pdp_set[meta_rule_id]["meta_rules"]["name"] == policy_name:
+                for category_id, category_value in self.cache.subject_categories.items():
                     if category_value["name"] == "role":
                         subject_category_id = category_id
                         break
@@ -131,95 +169,96 @@ class Authorization(object):
                 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():
+        context = self.payload["authz_context"]
+        for meta_rule_id, meta_rule_value in self.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)
+                self.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!")
+    # def __exec_next_state(self, rule_found):
+    #     index = self.context.index
+    #     current_meta_rule = self.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.context.headers[index + 1]
+    #     except IndexError:
+    #         next_meta_rule = None
+    #     if current_container_genre == "authz":
+    #         if rule_found:
+    #             return True
+    #         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
 
-            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 __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()
+                        self.context.current_state = "grant"
+                        LOG.info("__exec_instructions True {}".format(
+                            self.context.current_state))
+                        return True
                     else:
-                        self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = instruction["decision"]
+                        self.context.current_state = instruction["decision"].lower()
                 elif key == "chain":
                     result = self.__update_headers(**instruction["chain"])
                     if not result:
-                        self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = "deny"
+                        self.context.current_state = "deny"
                     else:
-                        self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = "passed"
+                        self.context.current_state = "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"
+                        self.context.current_state = "deny"
                     else:
-                        self.payload["authz_context"]['pdp_set'][current_header_id]["effect"] = "passed"
-        # LOG.info("__exec_instructions {}".format(self.payload["authz_context"]))
+                        self.context.current_state = "passed"
+        LOG.info("__exec_instructions False {}".format(self.context.current_state))
 
     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]
+        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
@@ -233,11 +272,11 @@ class Authorization(object):
                     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"])
+                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:
@@ -251,72 +290,65 @@ class Authorization(object):
             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']
+            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"
-        
-        :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("calling authz {} {}".format(ctxt, payload))
-        self.keystone_project_id = payload["id"]
-        self.payload = payload
+    def get_authz(self):
+        # self.keystone_project_id = payload["id"]
+        # LOG.info("get_authz {}".format(payload))
+        # self.payload = payload
         try:
-            if "authz_context" not in payload:
-                try:
-                    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()
-                except exceptions.SubjectUnknown:
-                    ctx = {
-                        "subject_name": self.payload["subject_name"],
-                        "object_name": self.payload["object_name"],
-                        "action_name": self.payload["action_name"],
-                    }
-                    call("moon_manager", method="update_from_master", ctx=ctx, args={})
-                    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()
-                except exceptions.ObjectUnknown:
-                    ctx = {
-                        "subject_name": self.payload["subject_name"],
-                        "object_name": self.payload["object_name"],
-                        "action_name": self.payload["action_name"],
-                    }
-                    call("moon_manager", method="update_from_master", ctx=ctx, args={})
-                    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()
-                except exceptions.ActionUnknown:
-                    ctx = {
-                        "subject_name": self.payload["subject_name"],
-                        "object_name": self.payload["object_name"],
-                        "action_name": self.payload["action_name"],
-                    }
-                    call("moon_manager", method="update_from_master", ctx=ctx, args={})
-                    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:
-                self.payload["authz_context"]["index"] += 1
-                self.__update_current_request()
+            if "authz_context" not in payload:
+                try:
+                    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()
+                except exceptions.SubjectUnknown:
+                    ctx = {
+                        "subject_name": self.payload["subject_name"],
+                        "object_name": self.payload["object_name"],
+                        "action_name": self.payload["action_name"],
+                    }
+                    call("moon_manager", method="update_from_master", ctx=ctx, args={})
+                    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()
+                except exceptions.ObjectUnknown:
+                    ctx = {
+                        "subject_name": self.payload["subject_name"],
+                        "object_name": self.payload["object_name"],
+                        "action_name": self.payload["action_name"],
+                    }
+                    call("moon_manager", method="update_from_master", ctx=ctx, args={})
+                    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()
+                except exceptions.ActionUnknown:
+                    ctx = {
+                        "subject_name": self.payload["subject_name"],
+                        "object_name": self.payload["object_name"],
+                        "action_name": self.payload["action_name"],
+                    }
+                    call("moon_manager", method="update_from_master", ctx=ctx, args={})
+                    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:
+                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:
@@ -327,7 +359,7 @@ class Authorization(object):
             return {"authz": result,
                     "error": message,
                     "pdp_id": self.pdp_id,
-                    "ctx": ctxt, "args": self.payload}
+                    "args": self.payload}
         except Exception as e:
             try:
                 LOG.error(self.payload["authz_context"])
@@ -337,5 +369,8 @@ class Authorization(object):
             return {"authz": False,
                     "error": str(e),
                     "pdp_id": self.pdp_id,
-                    "ctx": ctxt, "args": self.payload}
+                    "args": self.payload}
 
+    def head(self, uuid=None, subject_name=None, object_name=None, action_name=None):
+        LOG.info("HEAD request")
+        return "", 200
\ No newline at end of file
diff --git a/moonv4/moon_authz/moon_authz/http_server.py b/moonv4/moon_authz/moon_authz/http_server.py
new file mode 100644 (file)
index 0000000..b6818a9
--- /dev/null
@@ -0,0 +1,140 @@
+# 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'.
+
+from flask import Flask, request
+# from flask_cors import CORS, cross_origin
+from flask_restful import Resource, Api, reqparse
+import logging
+from moon_utilities import exceptions
+from moon_authz import __version__
+from moon_authz.api.authorization import Authz
+from moon_utilities.cache import Cache
+
+logger = logging.getLogger("moon." + __name__)
+
+CACHE = Cache()
+CACHE.update()
+
+
+class Server:
+    """Base class for HTTP server"""
+
+    def __init__(self, host="localhost", port=80, api=None, **kwargs):
+        """Run a server
+
+        :param host: hostname of the server
+        :param port: port for the running server
+        :param kwargs: optional parameters
+        :return: a running server
+        """
+        self._host = host
+        self._port = port
+        self._api = api
+        self._extra = kwargs
+
+    @property
+    def host(self):
+        return self._host
+
+    @host.setter
+    def host(self, name):
+        self._host = name
+
+    @host.deleter
+    def host(self):
+        self._host = ""
+
+    @property
+    def port(self):
+        return self._port
+
+    @port.setter
+    def port(self, number):
+        self._port = number
+
+    @port.deleter
+    def port(self):
+        self._port = 80
+
+    def run(self):
+        raise NotImplementedError()
+
+__API__ = (
+    Authz,
+ )
+
+
+class Root(Resource):
+    """
+    The root of the web service
+    """
+    __urls__ = ("/", )
+    __methods = ("get", "post", "put", "delete", "options")
+
+    def get(self):
+        tree = {"/": {"methods": ("get",), "description": "List all methods for that service."}}
+        for item in __API__:
+            tree[item.__name__] = {"urls": item.__urls__}
+            _methods = []
+            for _method in self.__methods:
+                if _method in dir(item):
+                    _methods.append(_method)
+            tree[item.__name__]["methods"] = _methods
+            tree[item.__name__]["description"] = item.__doc__.strip()
+        return {
+            "version": __version__,
+            "tree": tree
+        }
+
+    def head(self):
+        return "", 201
+
+
+class HTTPServer(Server):
+
+    def __init__(self, host="0.0.0.0", port=38001, **kwargs):
+        super(HTTPServer, self).__init__(host=host, port=port, **kwargs)
+        self.component_data = kwargs.get("component_data", {})
+        logger.info("HTTPServer port={} {}".format(port, kwargs))
+        self.app = Flask(__name__)
+        self._port = port
+        self._host = host
+        # Todo : specify only few urls instead of *
+        # CORS(self.app)
+        self.component_id = kwargs.get("component_id")
+        self.keystone_project_id = kwargs.get("keystone_project_id")
+        self.container_chaining = kwargs.get("container_chaining")
+        self.api = Api(self.app)
+        self.__set_route()
+        # self.__hook_errors()
+
+        @self.app.errorhandler(exceptions.AuthException)
+        def _auth_exception(error):
+            return {"error": "Unauthorized"}, 401
+
+    def __hook_errors(self):
+        # FIXME (dthom): it doesn't work
+        def get_404_json(e):
+            return {"error": "Error", "code": 404, "description": e}
+        self.app.register_error_handler(404, get_404_json)
+
+        def get_400_json(e):
+            return {"error": "Error", "code": 400, "description": e}
+        self.app.register_error_handler(400, lambda e: get_400_json)
+        self.app.register_error_handler(403, exceptions.AuthException)
+
+    def __set_route(self):
+        self.api.add_resource(Root, '/')
+
+        for api in __API__:
+            self.api.add_resource(api, *api.__urls__,
+                                  resource_class_kwargs={
+                                      "component_data": self.component_data,
+                                      "cache": CACHE
+                                  }
+                                  )
+
+    def run(self):
+        self.app.run(host=self._host, port=self._port)  # nosec
diff --git a/moonv4/moon_authz/moon_authz/messenger.py b/moonv4/moon_authz/moon_authz/messenger.py
deleted file mode 100644 (file)
index 6fa3477..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-# 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'.
-
-from oslo_config import cfg
-import oslo_messaging
-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.api import APIList
-
-LOG = logging.getLogger(__name__)
-CONF = cfg.CONF
-
-
-class Server:
-
-    def __init__(self, component_id, keystone_project_id):
-        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)
-        ]
-        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(0.1)
-        except KeyboardInterrupt:
-            print("Stopping server by crtl+c")
-        except SystemExit:
-            print("Stopping server")
-
-        self.server.stop()
-
-
index 0c2a36f..5ca96e6 100644 (file)
@@ -4,31 +4,43 @@
 # or at 'http://www.apache.org/licenses/LICENSE-2.0'.
 
 import os
-from oslo_config import cfg
 from oslo_log import log as logging
-# cfg.CONF.register_cli_opt(cfg.StrOpt('function_type', positional=True,
-#                                      help="The type of function managed by this component (example 'authz')."))
-cfg.CONF.register_cli_opt(cfg.StrOpt('uuid', positional=True,
-                                     help="The ID of the component managed here."))
-cfg.CONF.register_cli_opt(cfg.StrOpt('keystone_project_id', positional=True,
-                                     help="The ID of the component managed here."))
-from moon_utilities import options  # noqa
-from moon_authz.messenger import Server
-
-LOG = logging.getLogger(__name__)
-CONF = cfg.CONF
+from moon_authz.http_server import HTTPServer as Server
+from moon_utilities import configuration
+
+LOG = logging.getLogger("moon.server")
 DOMAIN = "moon_authz"
 
 __CWD__ = os.path.dirname(os.path.abspath(__file__))
 
 
 def main():
-    component_id = CONF.uuid
-    keystone_project_id = CONF.keystone_project_id
-    # function_type = CONF.intra_extension_id.replace(component_id, "").strip('_')
-    LOG.info("Starting server with IP {} on component {}".format(
-        CONF.security_router.host, component_id))
-    server = Server(component_id=component_id, keystone_project_id=keystone_project_id)
+    component_id = os.getenv("UUID")
+    component_type = os.getenv("TYPE")
+    tcp_port = os.getenv("PORT")
+    pdp_id = os.getenv("PDP_ID")
+    meta_rule_id = os.getenv("META_RULE_ID")
+    keystone_project_id = os.getenv("KEYSTONE_PROJECT_ID")
+    configuration.init_logging()
+    LOG.info("component_type={}".format(component_type))
+    conf = configuration.get_configuration("plugins/{}".format(component_type))
+    conf["plugins/{}".format(component_type)]['id'] = component_id
+    hostname = conf["plugins/{}".format(component_type)].get('hostname', component_id)
+    port = conf["plugins/{}".format(component_type)].get('port', tcp_port)
+    bind = conf["plugins/{}".format(component_type)].get('bind', "0.0.0.0")
+
+    LOG.info("Starting server with IP {} on port {} bind to {}".format(hostname, port, bind))
+    server = Server(
+        host=bind,
+        port=int(port),
+        component_data={
+            'component_id': component_id,
+            'component_type': component_type,
+            'pdp_id': pdp_id,
+            'meta_rule_id': meta_rule_id,
+            'keystone_project_id': keystone_project_id,
+        }
+    )
     server.run()
 
 
index 8faf943..344bec5 100644 (file)
@@ -1 +1,8 @@
-kombu !=4.0.1,!=4.0.0
\ No newline at end of file
+kombu !=4.0.1,!=4.0.0
+oslo.log
+flask
+oslo.config
+flask_restful
+flask_cors
+moon_db
+moon_utilities
diff --git a/moonv4/moon_interface/moon_interface/api/assignments.py b/moonv4/moon_interface/moon_interface/api/assignments.py
deleted file mode 100644 (file)
index 855a904..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-# 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'.
-"""
-Assignments allow to connect data with elements of perimeter
-
-"""
-
-from flask import request
-from flask_restful import Resource
-from oslo_log import log as logging
-from moon_utilities.security_functions import call
-from moon_utilities.security_functions import check_auth
-
-__version__ = "0.2.0"
-
-LOG = logging.getLogger("moon.interface.api." + __name__)
-
-
-class SubjectAssignments(Resource):
-    """
-    Endpoint for subject assignment requests
-    """
-
-    __urls__ = (
-        "/policies/<string:uuid>/subject_assignments",
-        "/policies/<string:uuid>/subject_assignments/",
-        "/policies/<string:uuid>/subject_assignments/<string:perimeter_id>",
-        "/policies/<string:uuid>/subject_assignments/<string:perimeter_id>/<string:category_id>",
-        "/policies/<string:uuid>/subject_assignments/<string:perimeter_id>/<string:category_id>/<string:data_id>",
-    )
-
-    @check_auth
-    def get(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
-        """Retrieve all subject assignments or a specific one for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the subject
-        :param category_id: uuid of the subject category
-        :param data_id: uuid of the subject scope
-        :param user_id: user ID who do the request
-        :return: {
-            "subject_data_id": {
-                "policy_id": "ID of the policy",
-                "subject_id": "ID of the subject",
-                "category_id": "ID of the category",
-                "assignments": "Assignments list (list of data_id)",
-            }
-        }
-        :internal_api: get_subject_assignments
-        """
-        return call(ctx={"id": uuid, "method": "get_subject_assignments", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-    @check_auth
-    def post(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
-        """Create a subject assignment.
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the subject (not used here)
-        :param category_id: uuid of the subject category (not used here)
-        :param data_id: uuid of the subject scope (not used here)
-        :param user_id: user ID who do the request
-        :request body: {
-            "id": "UUID of the subject",
-            "category_id": "UUID of the category"
-            "data_id": "UUID of the scope"
-        }
-        :return: {
-            "subject_data_id": {
-                "policy_id": "ID of the policy",
-                "subject_id": "ID of the subject",
-                "category_id": "ID of the category",
-                "assignments": "Assignments list (list of data_id)",
-            }
-        }
-        :internal_api: update_subject_assignment
-        """
-        return call("security_router",
-                    ctx={"id": uuid, "method": "update_subject_assignment", "user_id": user_id}, args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
-        """Delete a subject assignment for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the subject
-        :param category_id: uuid of the subject category
-        :param data_id: uuid of the subject scope
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_subject_assignment
-        """
-        return call("security_router",
-                    ctx={"id": uuid, "method": "delete_subject_assignment", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-
-class ObjectAssignments(Resource):
-    """
-    Endpoint for object assignment requests
-    """
-
-    __urls__ = (
-        "/policies/<string:uuid>/object_assignments",
-        "/policies/<string:uuid>/object_assignments/",
-        "/policies/<string:uuid>/object_assignments/<string:perimeter_id>",
-        "/policies/<string:uuid>/object_assignments/<string:perimeter_id>/<string:category_id>",
-        "/policies/<string:uuid>/object_assignments/<string:perimeter_id>/<string:category_id>/<string:data_id>",
-    )
-
-    @check_auth
-    def get(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
-        """Retrieve all object assignment or a specific one for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the object
-        :param category_id: uuid of the object category
-        :param data_id: uuid of the object scope
-        :param user_id: user ID who do the request
-        :return: {
-            "object_data_id": {
-                "policy_id": "ID of the policy",
-                "object_id": "ID of the object",
-                "category_id": "ID of the category",
-                "assignments": "Assignments list (list of data_id)",
-            }
-        }
-        :internal_api: get_object_assignments
-        """
-        return call("security_router",
-                    ctx={"id": uuid, "method": "get_object_assignments", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-    @check_auth
-    def post(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
-        """Create an object assignment.
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the object (not used here)
-        :param category_id: uuid of the object category (not used here)
-        :param data_id: uuid of the object scope (not used here)
-        :param user_id: user ID who do the request
-        :request body: {
-            "id": "UUID of the action",
-            "category_id": "UUID of the category"
-            "data_id": "UUID of the scope"
-        }
-        :return: {
-            "object_data_id": {
-                "policy_id": "ID of the policy",
-                "object_id": "ID of the object",
-                "category_id": "ID of the category",
-                "assignments": "Assignments list (list of data_id)",
-            }
-        }
-        :internal_api: update_object_assignment
-        """
-        return call("security_router",
-                    ctx={"id": uuid, "method": "update_object_assignment", "user_id": user_id}, args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
-        """Delete a object assignment for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the object
-        :param category_id: uuid of the object category
-        :param data_id: uuid of the object scope
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_object_assignment
-        """
-        return call("security_router",
-                    ctx={"id": uuid, "method": "delete_object_assignment", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-
-class ActionAssignments(Resource):
-    """
-    Endpoint for action assignment requests
-    """
-
-    __urls__ = (
-        "/policies/<string:uuid>/action_assignments",
-        "/policies/<string:uuid>/action_assignments/",
-        "/policies/<string:uuid>/action_assignments/<string:perimeter_id>",
-        "/policies/<string:uuid>/action_assignments/<string:perimeter_id>/<string:category_id>",
-        "/policies/<string:uuid>/action_assignments/<string:perimeter_id>/<string:category_id>/<string:data_id>",
-    )
-
-    @check_auth
-    def get(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
-        """Retrieve all action assignment or a specific one for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the action
-        :param category_id: uuid of the action category
-        :param data_id: uuid of the action scope
-        :param user_id: user ID who do the request
-        :return: {
-            "action_data_id": {
-                "policy_id": "ID of the policy",
-                "object_id": "ID of the action",
-                "category_id": "ID of the category",
-                "assignments": "Assignments list (list of data_id)",
-            }
-        }
-        :internal_api: get_action_assignments
-        """
-        return call("security_router", ctx={"id": uuid, "method": "get_action_assignments", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-    @check_auth
-    def post(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
-        """Create an action assignment.
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the action (not used here)
-        :param category_id: uuid of the action category (not used here)
-        :param data_id: uuid of the action scope (not used here)
-        :param user_id: user ID who do the request
-        :request body: {
-            "id": "UUID of the action",
-            "category_id": "UUID of the category",
-            "data_id": "UUID of the scope"
-        }
-        :return: {
-            "action_data_id": {
-                "policy_id": "ID of the policy",
-                "object_id": "ID of the action",
-                "category_id": "ID of the category",
-                "assignments": "Assignments list (list of data_id)",
-            }
-        }
-        :internal_api: update_action_assignment
-        """
-        return call("security_router", ctx={"id": uuid, "method": "update_action_assignment", "user_id": user_id},
-                    args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
-        """Delete a action assignment for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the action
-        :param category_id: uuid of the action category
-        :param data_id: uuid of the action scope
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_action_assignment
-        """
-        return call("security_router", ctx={"id": uuid, "method": "delete_action_assignment", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
index 69de0f8..3847cc7 100644 (file)
 Authz is the endpoint to get authorization response
 """
 
-from uuid import uuid4
-import time
+from flask import request
 from flask_restful import Resource
-from oslo_log import log as logging
-from moon_utilities.security_functions import call
+import logging
+import pickle
+import requests
+import time
+from uuid import uuid4
+
+from moon_interface.containers import DockerManager
+from moon_interface.authz_requests import AuthzRequest
+from moon_utilities import configuration
 
 __version__ = "0.1.0"
 
 LOG = logging.getLogger("moon.interface.api." + __name__)
 
 
+def pdp_in_cache(cache, uuid):
+    """Check if a PDP exist with this Keystone Project ID in the cache of this component
+
+    :param cache: Cache to use
+    :param uuid: Keystone Project ID
+    :return: True or False
+    """
+    for item_uuid, item_value in cache.pdp.items():
+        if uuid == item_value['keystone_project_id']:
+            return item_uuid, item_value
+    return None, None
+
+
+def pdp_in_manager(cache, uuid):
+    """Check if a PDP exist with this Keystone Project ID in the Manager component
+
+    :param cache: Cache to use
+    :param uuid: Keystone Project ID
+    :return: True or False
+    """
+    cache.update()
+    return pdp_in_cache(cache, uuid)
+
+
+def container_exist(cache, uuid):
+    """Check if a PDP exist with this Keystone Project ID in the Manager component
+
+    :param cache: Cache to use
+    :param uuid: Keystone Project ID
+    :return: True or False
+    """
+    for key, value in cache.containers.items():
+        if "keystone_project_id" not in value:
+            continue
+        if value["keystone_project_id"] == uuid:
+            try:
+                req = requests.head("http://{}:{}/".format(
+                    value.get("hostname"),
+                    value.get("port")[0].get("PublicPort")))
+                LOG.info("container_exist {}".format(req.status_code))
+                if req.status_code in (200, 201):
+                    return value
+                return
+            except requests.exceptions.ConnectionError:
+                pass
+            # maybe hostname is not working so trying with IP address
+            try:
+                req = requests.head("http://{}:{}/".format(
+                    value.get("ip"),
+                    value.get("port")[0].get("PublicPort")))
+                if req.status_code in (200, 201):
+                    return value
+                return
+            except requests.exceptions.ConnectionError:
+                return
+
+
+def build_container(cache, manager_url, uuid, meta_rule_id, plugin_name="authz"):
+    """Create the container and update the cache with the given perimeter elements
+
+    :param cache: Cache to use
+    :param manager_url: URL of the manager
+    :param uuid: Keystone Project ID
+    :param meta_rule_id: UUID of the meta_rule
+    :param plugin_name: name of the plugin to use
+    :return: True or False
+    """
+    LOG.info("Building a new container for {}".format(plugin_name))
+    manager = DockerManager()
+    tcp_port = configuration.increment_port()
+    container_name = configuration.get_plugins()[plugin_name]['container']
+    name = "{}_{}".format(plugin_name, uuid4().hex)
+    policy_id = cache.get_policy_from_meta_rules(meta_rule_id)
+    container_data = {
+        "name": name,
+        "hostname": name,
+        "port": {
+            "PrivatePort": tcp_port,
+            "Type": "tcp",
+            "IP": "0.0.0.0",
+            "PublicPort": tcp_port
+        },
+        "keystone_project_id": uuid,
+        "pdp_id": cache.get_pdp_from_keystone_project(uuid),
+        "meta_rule_id": meta_rule_id,
+        "policy_id": policy_id,
+        "container_name": container_name,
+        "plugin_name": plugin_name
+    }
+    container = manager.create_container(container_data)
+    container_data['container_id'] = container.id
+    container_data['port']["IP"] = container.ip
+    container_data['start_time'] = time.time()
+    req = requests.post("{}/containers".format(manager_url),
+                        json=container_data)
+    if req.status_code == 200:
+        cache.add_container(container_data)
+        return True
+
+
+def create_containers(cache, manager_url, uuid, plugin_name="authz"):
+    """Create the container and update the cache with the given perimeter elements
+
+    :param cache: Cache to use
+    :param manager_url: URL of the manager
+    :param uuid: Keystone Project ID
+    :param plugin_name: name of the plugin to use
+    :return: True or False
+    """
+    LOG.info("Need to create some containers for {}".format(uuid))
+    for pdp_id, pdp_value in cache.pdp.items():
+        LOG.info("pdp {}".format(pdp_value))
+        if uuid == pdp_value.get("keystone_project_id", ""):
+            LOG.info("uuid {}".format(uuid))
+            for policy_id in pdp_value.get("security_pipeline", []):
+                LOG.info("policy {}".format(policy_id))
+                model_id = cache.policies[policy_id]["model_id"]
+                model_value = cache.models[model_id]
+                for meta_rule_id in model_value["meta_rules"]:
+                    LOG.info("meta_rule {}".format(meta_rule_id))
+                    build_container(
+                        cache=cache,
+                        uuid=uuid,
+                        manager_url=manager_url,
+                        meta_rule_id=meta_rule_id,
+                        plugin_name=plugin_name)
+            return
+
+
+def create_authz_request(cache, interface_name, manager_url, uuid, subject_name, object_name, action_name):
+    """Create the authorization request and make the first call to the Authz function
+
+    :param cache: Cache to use
+    :param interface_name: hostname of the interface
+    :param manager_url: URL of the manager
+    :param uuid: Keystone Project ID
+    :param subject_name: name of the subject
+    :param object_name: name of the object
+    :param action_name: name of the action
+    :return: Authorisation request
+    """
+    req_id = uuid4().hex
+    ctx = {
+        "project_id": uuid,
+        "subject_name": subject_name,
+        "object_name": object_name,
+        "action_name": action_name,
+        "request_id": req_id,
+        "interface_name": interface_name,
+        "manager_url": manager_url,
+        "cookie": uuid4().hex
+    }
+    cache.authz_requests[req_id] = AuthzRequest(ctx)
+    return cache.authz_requests[req_id]
+
+
 class Authz(Resource):
     """
     Endpoint for authz requests
     """
 
-    __urls__ = ("/authz/<string:uuid>/<string:subject_name>/<string:object_name>/<string:action_name>", )
+    __urls__ = (
+        "/authz/<string:uuid>",
+        "/authz/<string:uuid>/<string:subject_name>/<string:object_name>/<string:action_name>",
+    )
+
+    def __init__(self, **kwargs):
+        self.CACHE = kwargs.get("cache")
+        self.INTERFACE_NAME = kwargs.get("interface_name", "interface")
+        self.MANAGER_URL = kwargs.get("manager_url", "http://manager:8080")
+        self.TIMEOUT = 5
 
     def get(self, uuid=None, subject_name=None, object_name=None, action_name=None):
         """Get a response on an authorization request
@@ -51,17 +222,52 @@ class Authz(Resource):
         }
         :internal_api: authz
         """
-        # Note (asteroide): user_id default to admin to be able to read the database
-        # it would be better to have a read-only user.
-        start_time = time.time()
-        result = call("security_router", ctx={"id": uuid,
-                         "call_master": False,
-                         "method": "authz",
-                         "subject_name": subject_name,
-                         "object_name": object_name,
-                         "action_name": action_name,
-                         "user_id": "admin",
-                         "request_id": uuid4().hex}, args={})
-        end_time = time.time()
-        result['time'] = {"start": start_time, "end": end_time}
-        return result
+        pdp_id, pdp_value = pdp_in_cache(self.CACHE, uuid)
+        if not pdp_id:
+            pdp_id, pdp_value = pdp_in_manager(self.CACHE, uuid)
+            if not pdp_id:
+                return {
+                           "result": False,
+                           "message": "Unknown Project ID or "
+                                      "Project ID is not bind to a PDP."}, 403
+        if not container_exist(self.CACHE, uuid):
+            create_containers(
+                cache=self.CACHE,
+                uuid=uuid,
+                manager_url=self.MANAGER_URL,
+                plugin_name="authz")
+        authz_request = create_authz_request(
+            cache=self.CACHE,
+            uuid=uuid,
+            interface_name=self.INTERFACE_NAME,
+            manager_url=self.MANAGER_URL,
+            subject_name=subject_name,
+            object_name=object_name,
+            action_name=action_name)
+        cpt = 0
+        while True:
+            if cpt > self.TIMEOUT*10:
+                return {"result": False,
+                        "message": "Authz request had timed out."}, 500
+            if authz_request.is_authz():
+                if authz_request.final_result == "Grant":
+                    return {"result": True, "message": ""}, 200
+                return {"result": False, "message": ""}, 401
+            cpt += 1
+            time.sleep(0.1)
+
+    def patch(self, uuid=None, subject_name=None, object_name=None, action_name=None):
+        """Get a response on an authorization request
+
+        :param uuid: uuid of the authorization request
+        :param subject_name: not used
+        :param object_name: not used
+        :param action_name: not used
+        :request body: a Context object
+        :return: {}
+        :internal_api: authz
+        """
+        if uuid in self.CACHE.authz_requests:
+            self.CACHE.authz_requests[uuid].set_result(pickle.loads(request.data))
+            return "", 201
+        return {"result": False, "message": "The request ID is unknown"}, 500
diff --git a/moonv4/moon_interface/moon_interface/api/data.py b/moonv4/moon_interface/moon_interface/api/data.py
deleted file mode 100644 (file)
index 6d95909..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-# 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'.
-"""
-Data are elements used to create rules
-
-"""
-
-from flask import request
-from flask_restful import Resource
-from oslo_log import log as logging
-from moon_utilities.security_functions import call
-from moon_utilities.security_functions import check_auth
-
-__version__ = "0.2.0"
-
-LOG = logging.getLogger("moon.interface.api." + __name__)
-
-
-class SubjectData(Resource):
-    """
-    Endpoint for subject data requests
-    """
-
-    __urls__ = (
-        "/policies/<string:uuid>/subject_data",
-        "/policies/<string:uuid>/subject_data/",
-        "/policies/<string:uuid>/subject_data/<string:category_id>",
-        "/policies/<string:uuid>/subject_data/<string:category_id>/<string:data_id>",
-    )
-
-    @check_auth
-    def get(self, uuid=None, category_id=None, data_id=None, user_id=None):
-        """Retrieve all subject categories or a specific one if sid is given for a given policy
-
-        :param uuid: uuid of the policy
-        :param category_id: uuid of the subject category
-        :param data_id: uuid of the subject data
-        :param user_id: user ID who do the request
-        :return: [{
-            "policy_id": "policy_id1",
-            "category_id": "category_id1",
-            "data": {
-                "subject_data_id": {
-                    "name": "name of the data",
-                    "description": "description of the data"
-                }
-            }
-        }]
-        :internal_api: get_subject_data
-        """
-        return call("security_router", ctx={"id": uuid, "method": "get_subject_data", "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-    @check_auth
-    def post(self, uuid=None, category_id=None, data_id=None, user_id=None):
-        """Create or update a subject.
-
-        :param uuid: uuid of the policy
-        :param category_id: uuid of the subject category
-        :param data_id: uuid of the subject data
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "name of the data",
-            "description": "description of the data"
-        }
-        :return: {
-            "policy_id": "policy_id1",
-            "category_id": "category_id1",
-            "data": {
-                "subject_data_id": {
-                    "name": "name of the data",
-                    "description": "description of the data"
-                }
-            }
-        }
-        :internal_api: add_subject_data
-        """
-        return call("security_router", ctx={"id": uuid, "method": "add_subject_data", "category_id": category_id, "user_id": user_id},
-                    args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, category_id=None, data_id=None, user_id=None):
-        """Delete a subject for a given policy
-
-        :param uuid: uuid of the policy
-        :param category_id: uuid of the subject category
-        :param data_id: uuid of the subject data
-        :param user_id: user ID who do the request
-        :return: [{
-            "result": "True or False",
-            "message": "optional message"
-        }]
-        :internal_api: delete_subject_data
-        """
-        return call("security_router", ctx={"id": uuid, "method": "delete_subject_data", "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-
-class ObjectData(Resource):
-    """
-    Endpoint for object data requests
-    """
-
-    __urls__ = (
-        "/policies/<string:uuid>/object_data",
-        "/policies/<string:uuid>/object_data/",
-        "/policies/<string:uuid>/object_data/<string:category_id>",
-        "/policies/<string:uuid>/object_data/<string:category_id>/<string:data_id>",
-    )
-
-    @check_auth
-    def get(self, uuid=None, category_id=None, data_id=None, user_id=None):
-        """Retrieve all object categories or a specific one if sid is given for a given policy
-
-        :param uuid: uuid of the policy
-        :param category_id: uuid of the object category
-        :param data_id: uuid of the object data
-        :param user_id: user ID who do the request
-        :return: [{
-            "policy_id": "policy_id1",
-            "category_id": "category_id1",
-            "data": {
-                "object_data_id": {
-                    "name": "name of the data",
-                    "description": "description of the data"
-                }
-            }
-        }]
-        :internal_api: get_object_data
-        """
-        return call("security_router", ctx={"id": uuid, "method": "get_object_data", "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-    @check_auth
-    def post(self, uuid=None, category_id=None, data_id=None, user_id=None):
-        """Create or update a object.
-
-        :param uuid: uuid of the policy
-        :param category_id: uuid of the object category
-        :param data_id: uuid of the object data
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "name of the data",
-            "description": "description of the data"
-        }
-        :return: {
-            "policy_id": "policy_id1",
-            "category_id": "category_id1",
-            "data": {
-                "object_data_id": {
-                    "name": "name of the data",
-                    "description": "description of the data"
-                }
-            }
-        }
-        :internal_api: add_object_data
-        """
-        return call("security_router", ctx={"id": uuid, "method": "add_object_data", "category_id": category_id, "user_id": user_id}, args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, category_id=None, data_id=None, user_id=None):
-        """Delete a object for a given policy
-
-        :param uuid: uuid of the policy
-        :param category_id: uuid of the object category
-        :param data_id: uuid of the object data
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_object_data
-        """
-        return call("security_router", ctx={"id": uuid, "method": "delete_object_data", "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-
-class ActionData(Resource):
-    """
-    Endpoint for action data requests
-    """
-
-    __urls__ = (
-        "/policies/<string:uuid>/action_data",
-        "/policies/<string:uuid>/action_data/",
-        "/policies/<string:uuid>/action_data/<string:category_id>",
-        "/policies/<string:uuid>/action_data/<string:category_id>/<string:data_id>",
-    )
-
-    @check_auth
-    def get(self, uuid=None, category_id=None, data_id=None, user_id=None):
-        """Retrieve all action categories or a specific one if sid is given for a given policy
-
-        :param uuid: uuid of the policy
-        :param category_id: uuid of the action category
-        :param data_id: uuid of the action data
-        :param user_id: user ID who do the request
-        :return: [{
-            "policy_id": "policy_id1",
-            "category_id": "category_id1",
-            "data": {
-                "action_data_id": {
-                    "name": "name of the data",
-                    "description": "description of the data"
-                }
-            }
-        }]
-        :internal_api: get_action_data
-        """
-        return call("security_router", ctx={"id": uuid, "method": "get_action_data", "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-    @check_auth
-    def post(self, uuid=None, category_id=None, data_id=None, user_id=None):
-        """Create or update a action.
-
-        :param uuid: uuid of the policy
-        :param category_id: uuid of the action category
-        :param data_id: uuid of the action data
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "name of the data",
-            "description": "description of the data"
-        }
-        :return: {
-            "policy_id": "policy_id1",
-            "category_id": "category_id1",
-            "data": {
-                "action_data_id": {
-                    "name": "name of the data",
-                    "description": "description of the data"
-                }
-            }
-        }
-        :internal_api: add_action_data
-        """
-        return call("security_router", ctx={"id": uuid, "method": "add_action_data", "category_id": category_id, "user_id": user_id},
-                    args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, category_id=None, data_id=None, user_id=None):
-        """Delete a action for a given policy
-
-        :param uuid: uuid of the policy
-        :param category_id: uuid of the action category
-        :param data_id: uuid of the action data
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_action_data
-        """
-        return call("security_router", ctx={"id": uuid, "method": "delete_action_data", "category_id": category_id, "user_id": user_id},
-                    args={"data_id": data_id})
-
-
diff --git a/moonv4/moon_interface/moon_interface/api/meta_data.py b/moonv4/moon_interface/moon_interface/api/meta_data.py
deleted file mode 100644 (file)
index 3c93375..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-# 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'.
-"""
-Meta Data are elements used to create Meta data (skeleton of security policies)
-
-"""
-
-from flask import request
-from flask_restful import Resource
-from oslo_log import log as logging
-from moon_utilities.security_functions import call
-from moon_utilities.security_functions import check_auth
-
-__version__ = "0.2.0"
-
-LOG = logging.getLogger("moon.interface.api." + __name__)
-
-
-class SubjectCategories(Resource):
-    """
-    Endpoint for subject categories requests
-    """
-
-    __urls__ = (
-        "/subject_categories",
-        "/subject_categories/",
-        "/subject_categories/<string:category_id>",
-    )
-
-    @check_auth
-    def get(self, category_id=None, user_id=None):
-        """Retrieve all subject categories or a specific one
-
-        :param category_id: uuid of the subject category
-        :param user_id: user ID who do the request
-        :return: {
-            "subject_category_id": {
-                "name": "name of the category",
-                "description": "description of the category"
-            }
-        }
-        :internal_api: get_subject_categories
-        """
-        return call("security_router", ctx={"method": "get_subject_categories", "user_id": user_id}, args={"category_id": category_id})
-
-    @check_auth
-    def post(self, category_id=None, user_id=None):
-        """Create or update a subject category.
-
-        :param category_id: must not be used here
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "name of the category",
-            "description": "description of the category"
-        }
-        :return: {
-            "subject_category_id": {
-                "name": "name of the category",
-                "description": "description of the category"
-            }
-        }
-        :internal_api: add_subject_category
-        """
-        return call("security_router", ctx={"method": "set_subject_category", "user_id": user_id}, args=request.json)
-
-    @check_auth
-    def delete(self, category_id=None, user_id=None):
-        """Delete a subject category
-
-        :param category_id: uuid of the subject category to delete
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_subject_category
-        """
-        return call("security_router", ctx={"method": "delete_subject_category", "user_id": user_id}, args={"category_id": category_id})
-
-
-class ObjectCategories(Resource):
-    """
-    Endpoint for object categories requests
-    """
-
-    __urls__ = (
-        "/object_categories",
-        "/object_categories/",
-        "/object_categories/<string:category_id>",
-    )
-
-    @check_auth
-    def get(self, category_id=None, user_id=None):
-        """Retrieve all object categories or a specific one
-
-        :param category_id: uuid of the object category
-        :param user_id: user ID who do the request
-        :return: {
-            "object_category_id": {
-                "name": "name of the category",
-                "description": "description of the category"
-            }
-        }
-        :internal_api: get_object_categories
-        """
-        return call("security_router", ctx={"method": "get_object_categories", "user_id": user_id}, args={"category_id": category_id})
-
-    @check_auth
-    def post(self, category_id=None, user_id=None):
-        """Create or update a object category.
-
-        :param category_id: must not be used here
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "name of the category",
-            "description": "description of the category"
-        }
-        :return: {
-            "object_category_id": {
-                "name": "name of the category",
-                "description": "description of the category"
-            }
-        }
-        :internal_api: add_object_category
-        """
-        return call("security_router", ctx={"method": "set_object_category", "user_id": user_id}, args=request.json)
-
-    @check_auth
-    def delete(self, category_id=None, user_id=None):
-        """Delete an object category
-
-        :param category_id: uuid of the object category to delete
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_object_category
-        """
-        return call("security_router", ctx={"method": "delete_object_category", "user_id": user_id}, args={"category_id": category_id})
-
-
-class ActionCategories(Resource):
-    """
-    Endpoint for action categories requests
-    """
-
-    __urls__ = (
-        "/action_categories",
-        "/action_categories/",
-        "/action_categories/<string:category_id>",
-    )
-
-    @check_auth
-    def get(self, category_id=None, user_id=None):
-        """Retrieve all action categories or a specific one
-
-        :param category_id: uuid of the action category
-        :param user_id: user ID who do the request
-        :return: {
-            "action_category_id": {
-                "name": "name of the category",
-                "description": "description of the category"
-            }
-        }
-        :internal_api: get_action_categories
-        """
-        return call("security_router", ctx={"method": "get_action_categories", "user_id": user_id}, args={"category_id": category_id})
-
-    @check_auth
-    def post(self, category_id=None, user_id=None):
-        """Create or update an action category.
-
-        :param category_id: must not be used here
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "name of the category",
-            "description": "description of the category"
-        }
-        :return: {
-            "action_category_id": {
-                "name": "name of the category",
-                "description": "description of the category"
-            }
-        }
-        :internal_api: add_action_category
-        """
-        return call("security_router", ctx={"method": "set_action_category", "user_id": user_id}, args=request.json)
-
-    @check_auth
-    def delete(self, category_id=None, user_id=None):
-        """Delete an action
-
-        :param category_id: uuid of the action category to delete
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_action_category
-        """
-        return call("security_router", ctx={"method": "delete_action_category", "user_id": user_id}, args={"category_id": category_id})
diff --git a/moonv4/moon_interface/moon_interface/api/meta_rules.py b/moonv4/moon_interface/moon_interface/api/meta_rules.py
deleted file mode 100644 (file)
index 8507224..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-# 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'.
-"""
-Meta rules are skeleton for security policies
-
-"""
-
-from flask import request
-from flask_restful import Resource
-from oslo_log import log as logging
-from moon_utilities.security_functions import call
-from moon_utilities.security_functions import check_auth
-
-__version__ = "0.1.0"
-
-LOG = logging.getLogger("moon.interface.api." + __name__)
-
-
-class MetaRules(Resource):
-    """
-    Endpoint for meta rules requests
-    """
-
-    __urls__ = ("/meta_rules",
-                "/meta_rules/",
-                "/meta_rules/<string:meta_rule_id>",
-                "/meta_rules/<string:meta_rule_id>/")
-
-    @check_auth
-    def get(self, meta_rule_id=None, user_id=None):
-        """Retrieve all sub meta rules
-
-        :param meta_rule_id: Meta rule algorithm ID
-        :param user_id: user ID who do the request
-        :return: {
-            "meta_rules": {
-                "meta_rule_id1": {
-                    "name": "name of the meta rule",
-                    "algorithm": "name of the meta rule algorithm",
-                    "subject_categories": ["subject_category_id1", "subject_category_id2"],
-                    "object_categories": ["object_category_id1"],
-                    "action_categories": ["action_category_id1"]
-                },
-            }
-        }
-        :internal_api: get_meta_rules
-        """
-        return call("security_router", ctx={"method": "get_meta_rules",
-                         "user_id": user_id,
-                         "meta_rule_id": meta_rule_id}, args={})
-
-    @check_auth
-    def post(self, meta_rule_id=None, user_id=None):
-        """Add a meta rule
-
-        :param meta_rule_id: Meta rule ID
-        :param user_id: user ID who do the request
-        :request body: post = {
-            "name": "name of the meta rule",
-            "subject_categories": ["subject_category_id1", "subject_category_id2"],
-            "object_categories": ["object_category_id1"],
-            "action_categories": ["action_category_id1"]
-        }
-        :return: {
-            "meta_rules": {
-                "meta_rule_id1": {
-                    "name": "name of the meta rule",
-                    "subject_categories": ["subject_category_id1", "subject_category_id2"],
-                    "object_categories": ["object_category_id1"],
-                    "action_categories": ["action_category_id1"]
-                },
-            }
-        }
-        :internal_api: add_meta_rules
-        """
-        return call("security_router", ctx={"method": "add_meta_rules",
-                         "user_id": user_id,
-                         "meta_rule_id": meta_rule_id}, args=request.json)
-
-    @check_auth
-    def patch(self, meta_rule_id=None, user_id=None):
-        """Update a meta rule
-
-        :param meta_rule_id: Meta rule ID
-        :param user_id: user ID who do the request
-        :request body: patch = {
-            "name": "name of the meta rule",
-            "subject_categories": ["subject_category_id1", "subject_category_id2"],
-            "object_categories": ["object_category_id1"],
-            "action_categories": ["action_category_id1"]
-        }
-        :return: {
-            "meta_rules": {
-                "meta_rule_id1": {
-                    "name": "name of the meta rule",
-                    "subject_categories": ["subject_category_id1", "subject_category_id2"],
-                    "object_categories": ["object_category_id1"],
-                    "action_categories": ["action_category_id1"]
-                },
-            }
-        }
-        :internal_api: set_meta_rules
-        """
-        return call("security_router", ctx={"method": "set_meta_rules",
-                         "user_id": user_id,
-                         "meta_rule_id": meta_rule_id}, args=request.json)
-
-    @check_auth
-    def delete(self, meta_rule_id=None, user_id=None):
-        """Delete a meta rule
-
-        :param meta_rule_id: Meta rule ID
-        :param user_id: user ID who do the request
-        :request body: delete = {
-            "name": "name of the meta rule",
-            "subject_categories": ["subject_category_id1", "subject_category_id2"],
-            "object_categories": ["object_category_id1"],
-            "action_categories": ["action_category_id1"]
-        }
-        :return: {
-            "meta_rules": {
-                "meta_rule_id1": {
-                    "name": "name of the meta rule",
-                    "subject_categories": ["subject_category_id1", "subject_category_id2"],
-                    "object_categories": ["object_category_id1"],
-                    "action_categories": ["action_category_id1"]
-                },
-            }
-        }
-        :internal_api: delete_meta_rules
-        """
-        return call("security_router", ctx={"method": "delete_meta_rules",
-                         "user_id": user_id,
-                         "meta_rule_id": meta_rule_id}, args=request.json)
-
-
diff --git a/moonv4/moon_interface/moon_interface/api/models.py b/moonv4/moon_interface/moon_interface/api/models.py
deleted file mode 100644 (file)
index f905db6..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-# 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'.
-"""
-Models aggregate multiple meta rules
-"""
-
-from flask import request
-from flask_restful import Resource
-from oslo_log import log as logging
-from moon_utilities.security_functions import call
-from moon_utilities.security_functions import check_auth
-
-__version__ = "0.1.0"
-
-LOG = logging.getLogger("moon.interface.api." + __name__)
-
-
-class Models(Resource):
-    """
-    Endpoint for model requests
-    """
-
-    __urls__ = (
-        "/models",
-        "/models/",
-        "/models/<string:uuid>",
-        "/models/<string:uuid>/",
-    )
-
-    @check_auth
-    def get(self, uuid=None, user_id=None):
-        """Retrieve all models
-
-        :param uuid: uuid of the model
-        :param user_id: user ID who do the request
-        :return: {
-            "model_id1": {
-                "name": "...",
-                "description": "...",
-                "meta_rules": ["meta_rule_id1", ]
-            }
-        }
-        :internal_api: get_models
-        """
-        return call("security_router", ctx={"id": uuid, "method": "get_models", "user_id": user_id}, args={})
-
-    @check_auth
-    def post(self, uuid=None, user_id=None):
-        """Create model.
-
-        :param uuid: uuid of the model (not used here)
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "...",
-            "description": "...",
-            "meta_rules": ["meta_rule_id1", ]
-        }
-        :return: {
-            "model_id1": {
-                "name": "...",
-                "description": "...",
-                "meta_rules": ["meta_rule_id1", ]
-            }
-        }
-        :internal_api: add_model
-        """
-        return call("security_router", ctx={"id": uuid, "method": "add_model", "user_id": user_id}, args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, user_id=None):
-        """Delete a model
-
-        :param uuid: uuid of the model to delete
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_model
-        """
-        return call("security_router", ctx={"id": uuid, "method": "delete_model", "user_id": user_id}, args={})
-
-    @check_auth
-    def patch(self, uuid=None, user_id=None):
-        """Update a model
-
-        :param uuid: uuid of the model to update
-        :param user_id: user ID who do the request
-        :return: {
-            "model_id1": {
-                "name": "...",
-                "description": "...",
-                "meta_rules": ["meta_rule_id1", ]
-            }
-        }
-        :internal_api: update_model
-        """
-        return call("security_router", ctx={"id": uuid, "method": "update_model", "user_id": user_id}, args=request.json)
-
diff --git a/moonv4/moon_interface/moon_interface/api/pdp.py b/moonv4/moon_interface/moon_interface/api/pdp.py
deleted file mode 100644 (file)
index 5316227..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-# 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'.
-"""
-PDP are Policy Decision Point.
-
-"""
-
-from flask import request
-from flask_restful import Resource
-from oslo_log import log as logging
-from moon_utilities.security_functions import call
-from moon_utilities.security_functions import check_auth
-
-__version__ = "0.1.0"
-
-LOG = logging.getLogger("moon.interface.api." + __name__)
-
-
-class PDP(Resource):
-    """
-    Endpoint for pdp requests
-    """
-
-    __urls__ = (
-        "/pdp",
-        "/pdp/",
-        "/pdp/<string:uuid>",
-        "/pdp/<string:uuid>/",
-    )
-
-    @check_auth
-    def get(self, uuid=None, user_id=None):
-        """Retrieve all pdp
-
-        :param uuid: uuid of the pdp
-        :param user_id: user ID who do the request
-        :return: {
-            "pdp_id1": {
-                "name": "...",
-                "security_pipeline": [...],
-                "keystone_project_id": "keystone_project_id1",
-                "description": "...",
-            }
-        }
-        :internal_api: get_pdp
-        """
-        return call("security_router", ctx={"id": uuid, "method": "get_pdp", "user_id": user_id}, args={})
-
-    @check_auth
-    def post(self, uuid=None, user_id=None):
-        """Create pdp.
-
-        :param uuid: uuid of the pdp (not used here)
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "...",
-            "security_pipeline": [...],
-            "keystone_project_id": "keystone_project_id1",
-            "description": "...",
-        }
-        :return: {
-            "pdp_id1": {
-                "name": "...",
-                "security_pipeline": [...],
-                "keystone_project_id": "keystone_project_id1",
-                "description": "...",
-            }
-        }
-        :internal_api: add_pdp
-        """
-        return call("security_router", ctx={"id": uuid, "method": "add_pdp", "user_id": user_id}, args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, user_id=None):
-        """Delete a pdp
-
-        :param uuid: uuid of the pdp to delete
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_pdp
-        """
-        return call("security_router", ctx={"id": uuid, "method": "delete_pdp", "user_id": user_id}, args={})
-
-    @check_auth
-    def patch(self, uuid=None, user_id=None):
-        """Update a pdp
-
-        :param uuid: uuid of the pdp to update
-        :param user_id: user ID who do the request
-        :return: {
-            "pdp_id1": {
-                "name": "...",
-                "security_pipeline": [...],
-                "keystone_project_id": "keystone_project_id1",
-                "description": "...",
-            }
-        }
-        :internal_api: update_pdp
-        """
-        return call("security_router", ctx={"id": uuid, "method": "update_pdp", "user_id": user_id}, args=request.json)
-
diff --git a/moonv4/moon_interface/moon_interface/api/perimeter.py b/moonv4/moon_interface/moon_interface/api/perimeter.py
deleted file mode 100644 (file)
index 177161f..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-# 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'.
-"""
-* Subjects are the source of an action on an object (examples : users, virtual machines)
-* Objects are the destination of an action (examples virtual machines, virtual Routers)
-* Actions are what subject wants to do on an object
-"""
-
-from flask import request
-from flask_restful import Resource
-from oslo_log import log as logging
-from moon_utilities.security_functions import call
-from moon_utilities.security_functions import check_auth
-
-__version__ = "0.2.0"
-
-LOG = logging.getLogger("moon.interface.api." + __name__)
-
-
-class Subjects(Resource):
-    """
-    Endpoint for subjects requests
-    """
-
-    __urls__ = (
-        "/subjects",
-        "/subjects/",
-        "/subjects/<string:perimeter_id>",
-        "/policies/<string:uuid>/subjects",
-        "/policies/<string:uuid>/subjects/",
-        "/policies/<string:uuid>/subjects/<string:perimeter_id>",
-    )
-
-    @check_auth
-    def get(self, uuid=None, perimeter_id=None, user_id=None):
-        """Retrieve all subjects or a specific one if perimeter_id is given for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the subject
-        :param user_id: user ID who do the request
-        :return: {
-                "subject_id": {
-                    "name": "name of the subject",
-                    "keystone_id": "keystone id of the subject",
-                    "description": "a description"
-            }
-        }
-        :internal_api: get_subjects
-        """
-        return call("security_router", ctx={"id": uuid, "method": "get_subjects", "user_id": user_id}, args={"perimeter_id": perimeter_id})
-
-    @check_auth
-    def post(self, uuid=None, perimeter_id=None, user_id=None):
-        """Create or update a subject.
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: must not be used here
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "name of the subject",
-            "description": "description of the subject",
-            "password": "password for the subject",
-            "email": "email address of the subject"
-        }
-        :return: {
-                "subject_id": {
-                    "name": "name of the subject",
-                    "keystone_id": "keystone id of the subject",
-                    "description": "description of the subject",
-                    "password": "password for the subject",
-                    "email": "email address of the subject"
-            }
-        }
-        :internal_api: set_subject
-        """
-        return call("security_router", ctx={"id": uuid, "method": "set_subject", "user_id": user_id, "perimeter_id": None},
-                    args=request.json)
-
-    @check_auth
-    def patch(self, uuid=None, perimeter_id=None, user_id=None):
-        """Create or update a subject.
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: must not be used here
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "name of the subject",
-            "description": "description of the subject",
-            "password": "password for the subject",
-            "email": "email address of the subject"
-        }
-        :return: {
-                "subject_id": {
-                    "name": "name of the subject",
-                    "keystone_id": "keystone id of the subject",
-                    "description": "description of the subject",
-                    "password": "password for the subject",
-                    "email": "email address of the subject"
-            }
-        }
-        :internal_api: set_subject
-        """
-        return call("security_router", ctx={"id": uuid, "method": "set_subject", "user_id": user_id, "perimeter_id": perimeter_id},
-                    args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, perimeter_id=None, user_id=None):
-        """Delete a subject for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the subject
-        :param user_id: user ID who do the request
-        :return: {
-                "subject_id": {
-                    "name": "name of the subject",
-                    "keystone_id": "keystone id of the subject",
-                    "description": "description of the subject",
-                    "password": "password for the subject",
-                    "email": "email address of the subject"
-            }
-        }
-        :internal_api: delete_subject
-        """
-        return call("security_router", ctx={"id": uuid, "method": "delete_subject", "user_id": user_id}, args={"perimeter_id": perimeter_id})
-
-
-class Objects(Resource):
-    """
-    Endpoint for objects requests
-    """
-
-    __urls__ = (
-        "/objects",
-        "/objects/",
-        "/objects/<string:perimeter_id>",
-        "/policies/<string:uuid>/objects",
-        "/policies/<string:uuid>/objects/",
-        "/policies/<string:uuid>/objects/<string:perimeter_id>",
-    )
-
-    @check_auth
-    def get(self, uuid=None, perimeter_id=None, user_id=None):
-        """Retrieve all objects or a specific one if perimeter_id is given for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the object
-        :param user_id: user ID who do the request
-        :return: {
-                "object_id": {
-                    "name": "name of the object",
-                    "description": "description of the object"
-            }
-        }
-        :internal_api: get_objects
-        """
-        return call("security_router", ctx={"id": uuid, "method": "get_objects", "user_id": user_id}, args={"perimeter_id": perimeter_id})
-
-    @check_auth
-    def post(self, uuid=None, perimeter_id=None, user_id=None):
-        """Create or update a object.
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: must not be used here
-        :param user_id: user ID who do the request
-        :request body: {
-            "object_name": "name of the object",
-            "object_description": "description of the object"
-        }
-        :return: {
-                "object_id": {
-                    "name": "name of the object",
-                    "description": "description of the object"
-            }
-        }
-        :internal_api: set_object
-        """
-        return call("security_router", ctx={"id": uuid, "method": "set_object", "user_id": user_id, "perimeter_id": None},
-                    args=request.json)
-
-    @check_auth
-    def patch(self, uuid=None, perimeter_id=None, user_id=None):
-        """Create or update a object.
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: must not be used here
-        :param user_id: user ID who do the request
-        :request body: {
-            "object_name": "name of the object",
-            "object_description": "description of the object"
-        }
-        :return: {
-                "object_id": {
-                    "name": "name of the object",
-                    "description": "description of the object"
-            }
-        }
-        :internal_api: set_object
-        """
-        return call("security_router", ctx={"id": uuid, "method": "set_object", "user_id": user_id, "perimeter_id": perimeter_id},
-                    args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, perimeter_id=None, user_id=None):
-        """Delete a object for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the object
-        :param user_id: user ID who do the request
-        :return: {
-                "object_id": {
-                    "name": "name of the object",
-                    "description": "description of the object"
-            }
-        }
-        :internal_api: delete_object
-        """
-        return call("security_router", ctx={"id": uuid, "method": "delete_object", "user_id": user_id}, args={"perimeter_id": perimeter_id})
-
-
-class Actions(Resource):
-    """
-    Endpoint for actions requests
-    """
-
-    __urls__ = (
-        "/actions",
-        "/actions/",
-        "/actions/<string:perimeter_id>",
-        "/policies/<string:uuid>/actions",
-        "/policies/<string:uuid>/actions/",
-        "/policies/<string:uuid>/actions/<string:perimeter_id>",
-    )
-
-    @check_auth
-    def get(self, uuid=None, perimeter_id=None, user_id=None):
-        """Retrieve all actions or a specific one if perimeter_id is given for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the action
-        :param user_id: user ID who do the request
-        :return: {
-                "action_id": {
-                    "name": "name of the action",
-                    "description": "description of the action"
-            }
-        }
-        :internal_api: get_actions
-        """
-        return call("security_router", ctx={"id": uuid, "method": "get_actions", "user_id": user_id}, args={"perimeter_id": perimeter_id})
-
-    @check_auth
-    def post(self, uuid=None, perimeter_id=None, user_id=None):
-        """Create or update a action.
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: must not be used here
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "name of the action",
-            "description": "description of the action"
-        }
-        :return: {
-                "action_id": {
-                    "name": "name of the action",
-                    "description": "description of the action"
-            }
-        }
-        :internal_api: set_action
-        """
-        return call("security_router", ctx={"id": uuid, "method": "set_action", "user_id": user_id, "perimeter_id": None},
-                    args=request.json)
-
-    @check_auth
-    def patch(self, uuid=None, perimeter_id=None, user_id=None):
-        """Create or update a action.
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: must not be used here
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "name of the action",
-            "description": "description of the action"
-        }
-        :return: {
-                "action_id": {
-                    "name": "name of the action",
-                    "description": "description of the action"
-            }
-        }
-        :internal_api: set_action
-        """
-        return call("security_router", ctx={"id": uuid, "method": "set_action", "user_id": user_id, "perimeter_id": perimeter_id},
-                    args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, perimeter_id=None, user_id=None):
-        """Delete a action for a given policy
-
-        :param uuid: uuid of the policy
-        :param perimeter_id: uuid of the action
-        :param user_id: user ID who do the request
-        :return: {
-                "action_id": {
-                    "name": "name of the action",
-                    "description": "description of the action"
-            }
-        }
-        :internal_api: delete_action
-        """
-        return call("security_router", ctx={"id": uuid, "method": "delete_action", "user_id": user_id}, args={"perimeter_id": perimeter_id})
diff --git a/moonv4/moon_interface/moon_interface/api/policies.py b/moonv4/moon_interface/moon_interface/api/policies.py
deleted file mode 100644 (file)
index 5a84b61..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-# 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'.
-"""
-Policies are instances of security models and implement security policies
-
-"""
-
-from flask import request
-from flask_restful import Resource
-from oslo_log import log as logging
-from moon_utilities.security_functions import call
-from moon_utilities.security_functions import check_auth
-
-__version__ = "0.1.0"
-
-LOG = logging.getLogger("moon.interface.api." + __name__)
-
-
-class Policies(Resource):
-    """
-    Endpoint for policy requests
-    """
-
-    __urls__ = (
-        "/policies",
-        "/policies/",
-        "/policies/<string:uuid>",
-        "/policies/<string:uuid>/",
-    )
-
-    @check_auth
-    def get(self, uuid=None, user_id=None):
-        """Retrieve all policies
-
-        :param uuid: uuid of the policy
-        :param user_id: user ID who do the request
-        :return: {
-            "policy_id1": {
-                "name": "...",
-                "model_id": "...",
-                "genre": "...",
-                "description": "...",
-            }
-        }
-        :internal_api: get_policies
-        """
-        return call("security_router", ctx={"id": uuid, "method": "get_policies", "user_id": user_id}, args={})
-
-    @check_auth
-    def post(self, uuid=None, user_id=None):
-        """Create policy.
-
-        :param uuid: uuid of the policy (not used here)
-        :param user_id: user ID who do the request
-        :request body: {
-            "name": "...",
-            "model_id": "...",
-            "genre": "...",
-            "description": "...",
-        }
-        :return: {
-            "policy_id1": {
-                "name": "...",
-                "model_id": "...",
-                "genre": "...",
-                "description": "...",
-            }
-        }
-        :internal_api: add_policy
-        """
-        return call("security_router", ctx={"id": uuid, "method": "add_policy", "user_id": user_id}, args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, user_id=None):
-        """Delete a policy
-
-        :param uuid: uuid of the policy to delete
-        :param user_id: user ID who do the request
-        :return: {
-            "result": "True or False",
-            "message": "optional message"
-        }
-        :internal_api: delete_policy
-        """
-        return call("security_router", ctx={"id": uuid, "method": "delete_policy", "user_id": user_id}, args={})
-
-    @check_auth
-    def patch(self, uuid=None, user_id=None):
-        """Update a policy
-
-        :param uuid: uuid of the policy to update
-        :param user_id: user ID who do the request
-        :return: {
-            "policy_id1": {
-                "name": "...",
-                "model_id": "...",
-                "genre": "...",
-                "description": "...",
-            }
-        }
-        :internal_api: update_policy
-        """
-        return call("security_router", ctx={"id": uuid, "method": "update_policy", "user_id": user_id}, args=request.json)
-
diff --git a/moonv4/moon_interface/moon_interface/api/rules.py b/moonv4/moon_interface/moon_interface/api/rules.py
deleted file mode 100644 (file)
index 1111729..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-# 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'.
-"""
-Rules (TODO)
-"""
-
-from flask import request
-from flask_restful import Resource
-from oslo_log import log as logging
-from moon_utilities.security_functions import call
-from moon_utilities.security_functions import check_auth
-
-__version__ = "0.1.0"
-
-LOG = logging.getLogger("moon.interface.api." + __name__)
-
-
-class Rules(Resource):
-    """
-    Endpoint for rules requests
-    """
-
-    __urls__ = ("/policies/<string:uuid>/rules",
-                "/policies/<string:uuid>/rules/",
-                "/policies/<string:uuid>/rules/<string:rule_id>",
-                "/policies/<string:uuid>/rules/<string:rule_id>/",
-                )
-
-    @check_auth
-    def get(self, uuid=None, rule_id=None, user_id=None):
-        """Retrieve all rules or a specific one
-
-        :param uuid: policy ID
-        :param rule_id: rule ID
-        :param user_id: user ID who do the request
-        :return: {
-            "rules": [
-                "policy_id": "policy_id1",
-                "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"],
-            ]
-        }
-        :internal_api: get_rules
-        """
-        return call("security_router", ctx={"id": uuid,
-                         "method": "get_rules",
-                         "user_id": user_id,
-                         "rule_id": rule_id}, args={})
-
-    @check_auth
-    def post(self, uuid=None, rule_id=None, user_id=None):
-        """Add a rule to a meta rule
-
-        :param uuid: policy ID
-        :param rule_id: rule ID
-        :param user_id: user ID who do the request
-        :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": {
-                    "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
-        """
-        return call("security_router", ctx={"id": uuid,
-                         "method": "add_rule",
-                         "user_id": user_id,
-                         "rule_id": rule_id}, args=request.json)
-
-    @check_auth
-    def delete(self, uuid=None, rule_id=None, user_id=None):
-        """Delete one rule linked to a specific sub meta rule
-
-        :param uuid: policy ID
-        :param rule_id: rule ID
-        :param user_id: user ID who do the request
-        :return: { "result": true }
-        :internal_api: delete_rule
-        """
-        return call("security_router", ctx={"id": uuid,
-                         "method": "delete_rule",
-                         "user_id": user_id,
-                         "rule_id": rule_id}, args={})
-
diff --git a/moonv4/moon_interface/moon_interface/api/wrapper.py b/moonv4/moon_interface/moon_interface/api/wrapper.py
new file mode 100644 (file)
index 0000000..5ba5779
--- /dev/null
@@ -0,0 +1,120 @@
+# 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'.
+"""
+Authz is the endpoint to get authorization response
+"""
+
+import flask
+from flask import request
+from flask_restful import Resource
+import logging
+import json
+import requests
+import time
+from uuid import uuid4
+
+from moon_interface.api.authz import pdp_in_cache, pdp_in_manager, container_exist, \
+    create_containers, create_authz_request
+from moon_interface.authz_requests import AuthzRequest
+from moon_utilities import configuration
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger("moon.interface.api." + __name__)
+
+
+class Wrapper(Resource):
+    """
+    Endpoint for authz requests
+    """
+
+    __urls__ = (
+        "/authz/wrapper",
+        "/authz/wrapper/",
+    )
+
+    def __init__(self, **kwargs):
+        self.port = kwargs.get("port")
+        self.CACHE = kwargs.get("cache", {})
+        self.INTERFACE_NAME = kwargs.get("interface_name", "interface")
+        self.MANAGER_URL = kwargs.get("manager_url", "http://manager:8080")
+        self.TIMEOUT = 5
+
+    def get(self):
+        LOG.info("GET")
+        return self.manage_data()
+
+    def post(self):
+        LOG.info("POST {}".format(request.form))
+        response = flask.make_response("False")
+        if self.manage_data():
+            response = flask.make_response("True")
+        response.headers['content-type'] = 'application/octet-stream'
+        return response
+
+    @staticmethod
+    def __get_subject(target, credentials):
+        _subject = target.get("user_id", "")
+        if not _subject:
+            _subject = credentials.get("user_id", "none")
+        return _subject
+
+    @staticmethod
+    def __get_object(target, credentials):
+        try:
+            # note: case of Glance
+            return target['target']['name']
+        except KeyError:
+            pass
+
+        # note: default case
+        return target.get("project_id", "none")
+
+    @staticmethod
+    def __get_project_id(target, credentials):
+        return target.get("project_id", "none")
+
+    def manage_data(self):
+        target = json.loads(request.form.get('target', {}))
+        credentials = json.loads(request.form.get('credentials', {}))
+        rule = request.form.get('rule', "")
+        _subject = self.__get_subject(target, credentials)
+        _object = self.__get_object(target, credentials)
+        _project_id = self.__get_project_id(target, credentials)
+        LOG.info("GET with args project={} / "
+                 "subject={} - object={} - action={}".format(
+                 _project_id, _subject, _object, rule))
+        pdp_id, pdp_value = pdp_in_cache(self.CACHE, _project_id)
+        if not pdp_id:
+            pdp_id, pdp_value = pdp_in_manager(self.CACHE, _project_id)
+            if not pdp_id:
+                LOG.error("Unknown Project ID or "
+                          "Project ID is not bind to a PDP.")
+                return False
+        if not container_exist(self.CACHE, _project_id):
+            create_containers(self.CACHE, _project_id, self.MANAGER_URL,
+                              plugin_name="authz")
+        authz_request = create_authz_request(
+            cache=self.CACHE,
+            uuid=_project_id,
+            interface_name=self.INTERFACE_NAME,
+            manager_url=self.MANAGER_URL,
+            subject_name=_subject,
+            object_name=_object,
+            action_name=rule)
+        cpt = 0
+        while True:
+            LOG.info("Wait")
+            if cpt > self.TIMEOUT*10:
+                LOG.error("Authz request had timed out.")
+                return False
+            if authz_request.is_authz():
+                if authz_request.final_result == "Grant":
+                    LOG.info("Grant")
+                    return True
+                LOG.info("Deny")
+                return False
+            cpt += 1
+            time.sleep(0.1)
diff --git a/moonv4/moon_interface/moon_interface/authz_requests.py b/moonv4/moon_interface/moon_interface/authz_requests.py
new file mode 100644 (file)
index 0000000..2eb5fd1
--- /dev/null
@@ -0,0 +1,159 @@
+# 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 logging
+import itertools
+import pickle
+import requests
+from moon_utilities import configuration, exceptions
+from moon_utilities.security_functions import Context
+from moon_utilities.cache import Cache
+
+LOG = logging.getLogger("moon.interface.authz_requests")
+
+
+CACHE = Cache()
+CACHE.update()
+
+
+class AuthzRequest:
+
+    result = None
+    final_result = "Deny"
+    req_max_delay = 2
+
+    def __init__(self, ctx, args=None):
+        self.context = Context(ctx, CACHE)
+        self.args = args
+        self.request_id = ctx["request_id"]
+        if ctx['project_id'] not in CACHE.container_chaining:
+            raise exceptions.KeystoneProjectError("Unknown Project ID {}".format(ctx['project_id']))
+        self.container_chaining = CACHE.container_chaining[ctx['project_id']]
+        if len(self.container_chaining) == 0:
+            raise exceptions.MoonError('Void container chaining')
+        self.pdp_container = self.container_chaining[0]["container_id"]
+        self.run()
+
+    def run(self):
+        self.context.delete_cache()
+        try:
+            req = requests.post("http://{}:{}/authz".format(
+                self.container_chaining[0]["hostname"],
+                self.container_chaining[0]["port"],
+            ), data=pickle.dumps(self.context))
+            if req.status_code != 200:
+                # LOG.error("Cannot connect to {}".format(
+                #     "http://{}:{}/authz".format(
+                #         self.container_chaining[0]["hostname"],
+                #         self.container_chaining[0]["port"]
+                #     )))
+                raise exceptions.AuthzException(
+                    "Receive bad response from Authz function "
+                    "(with hostname - {})".format(
+                        req.status_code
+                    ))
+        except requests.exceptions.ConnectionError:
+            try:
+                req = requests.post("http://{}:{}/authz".format(
+                    self.container_chaining[0]["hostip"],
+                    self.container_chaining[0]["port"],
+                ), data=pickle.dumps(self.context))
+                if req.status_code != 200:
+                    # LOG.error("req={}".format(req))
+                    raise exceptions.AuthzException(
+                        "Receive bad response from Authz function "
+                        "(with IP address - {})".format(
+                            req.status_code
+                        ))
+            except requests.exceptions.ConnectionError:
+                LOG.error("Cannot connect to {}".format(
+                    "http://{}:{}/authz".format(
+                        self.container_chaining[0]["hostip"],
+                        self.container_chaining[0]["port"]
+                    )))
+                raise exceptions.AuthzException(
+                    "Cannot connect to Authz function with IP address")
+        self.context.set_cache(CACHE)
+        if len(self.container_chaining) == 1:
+            # req.raw.decode_content = True
+            self.result = pickle.loads(req.content)
+
+    def __exec_next_state(self, rule_found):
+        index = self.context.index
+        current_meta_rule = self.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.context.headers[index + 1]
+        except IndexError:
+            next_meta_rule = None
+        if current_container_genre == "authz":
+            if rule_found:
+                return True
+            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 set_result(self, result):
+        self.result = result
+
+    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":
+                    # 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"
+        if self.result:
+            if self.result.pdp_set["effect"] == "grant":
+                self.final_result = "Grant"
+                return True
+        self.final_result = "Deny"
+        return True
+
+    # def notify(self, request_id, container_id, payload):
+    #     LOG.info("notify {} {} {}".format(request_id, container_id, payload))
+    #     # TODO: send the notification and wait for the result
+    #     # req = requests.get()
diff --git a/moonv4/moon_interface/moon_interface/containers.py b/moonv4/moon_interface/moon_interface/containers.py
new file mode 100644 (file)
index 0000000..1ca76a2
--- /dev/null
@@ -0,0 +1,102 @@
+# Copyright 2017 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 docker
+import logging
+import re
+import requests
+import time
+from moon_utilities import configuration, exceptions
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger("moon.interface.container")
+
+
+class DockerManager:
+
+    def __init__(self):
+        docker_conf = configuration.get_configuration("docker")['docker']
+        self.docker = docker.DockerClient(base_url=docker_conf['url'])
+
+    def create_container(self, data):
+        """Create the container through the docker client
+
+        :param data: {
+            "name": "authz",
+            "hostname": "authz123456789",
+            "port": {
+                "PrivatePort": 8090,
+                "Type": "tcp",
+                "IP": "0.0.0.0",
+                "PublicPort": 8090
+            },
+            "keystone_project_id": "keystone_project_id1",
+            "pdp_id": "123456789",
+            "container_name": "wukongsun/moon_authz:v4.1"
+        }
+        :return: container output
+        """
+        output = self.docker.containers.run(
+            image=data.get("container_name"),
+            hostname=data.get("hostname", data.get("name"))[:63],
+            name=data.get("name"),
+            network='moon',
+            ports={'{}/{}'.format(
+                data.get("port").get("PrivatePort"),
+                data.get("port").get("Type")
+            ): int(data.get("port").get("PrivatePort"))},
+            environment={
+                "UUID": data.get("hostname"),
+                "BIND": data.get("port").get("IP"),
+                "TYPE": data.get("plugin_name"),
+                "PORT": data.get("port").get("PrivatePort"),
+                "PDP_ID": data.get("pdp_id"),
+                "META_RULE_ID": data.get("meta_rule_id"),
+                "KEYSTONE_PROJECT_ID": data.get("keystone_project_id"),
+            },
+            detach=True
+        )
+        try:
+            req = requests.head("http://{}:{}/".format(data.get("hostname"), data.get("port").get("PublicPort")))
+        except requests.exceptions.ConnectionError:
+            pass
+        else:
+            if req.status_code != 200:
+                raise exceptions.DockerError("Container {} is not running!".format(data.get("hostname")))
+            output.ip = "0.0.0.0"
+            return output
+
+        # Note: host is not reachable through hostname so trying to find th IP address
+        res = output.exec_run("ip addr")
+        find = re.findall("inet (\d+\.\d+\.\d+\.\d+)", res.decode("utf-8"))
+        ip = "127.0.0.1"
+        for ip in find:
+            if ip.startswith("127"):
+                continue
+            break
+        cpt = 0
+        while True:
+            try:
+                req = requests.head("http://{}:{}/".format(ip, data.get("port").get("PublicPort")))
+            except requests.exceptions.ConnectionError:
+                pass
+            else:
+                if req.status_code not in (200, 201):
+                    LOG.error("url={}".format("http://{}:{}/".format(ip, data.get("port").get("PublicPort"))))
+                    LOG.error("req={}".format(req))
+                    raise exceptions.DockerError("Container {} is not running!".format(data.get("hostname")))
+                output.ip = ip
+                return output
+            finally:
+                cpt += 1
+                time.sleep(0.1)
+                if cpt > 20:
+                    break
+        output.ip = ip
+        return output
+
+    def delete_container(self, uuid):
+        raise NotImplementedError
index 046337a..d7f8469 100644 (file)
@@ -3,23 +3,16 @@
 # license which can be found in the file 'LICENSE' in this package distribution
 # or at 'http://www.apache.org/licenses/LICENSE-2.0'.
 
-from flask import Flask
+from flask import Flask, jsonify
 from flask_cors import CORS, cross_origin
 from flask_restful import Resource, Api
 import logging
 from moon_interface import __version__
 from moon_interface.api.generic import Status, Logs, API
-from moon_interface.api.models import Models
-from moon_interface.api.policies import Policies
-from moon_interface.api.pdp import PDP
-from moon_interface.api.meta_rules import MetaRules
-from moon_interface.api.meta_data import SubjectCategories, ObjectCategories, ActionCategories
-from moon_interface.api.perimeter import Subjects, Objects, Actions
-from moon_interface.api.data import SubjectData, ObjectData, ActionData
-from moon_interface.api.assignments import SubjectAssignments, ObjectAssignments, ActionAssignments
-from moon_interface.api.rules import Rules
 from moon_interface.api.authz import Authz
-from moon_utilities import exceptions
+from moon_interface.api.wrapper import Wrapper
+from moon_interface.authz_requests import CACHE
+from moon_utilities import configuration, exceptions
 
 logger = logging.getLogger("moon.interface.http")
 
@@ -68,13 +61,7 @@ class Server:
         raise NotImplementedError()
 
 __API__ = (
-    Status, Logs, API,
-    MetaRules, SubjectCategories, ObjectCategories, ActionCategories,
-    Subjects, Objects, Actions,
-    SubjectAssignments, ObjectAssignments, ActionAssignments,
-    SubjectData, ObjectData, ActionData,
-    Rules, Authz,
-    Models, Policies, PDP
+    Status, Logs, API
  )
 
 
@@ -106,24 +93,28 @@ class HTTPServer(Server):
     def __init__(self, host="localhost", port=80, **kwargs):
         super(HTTPServer, self).__init__(host=host, port=port, **kwargs)
         self.app = Flask(__name__)
+        self.port = port
+        conf = configuration.get_configuration("components/manager")
+        self.manager_hostname = conf["components/manager"].get("hostname", "manager")
+        self.manager_port = conf["components/manager"].get("port", 80)
         #Todo : specify only few urls instead of *
         CORS(self.app)
         self.api = Api(self.app)
         self.__set_route()
-        self.__hook_errors()
+        self.__hook_errors()
 
-        @self.app.errorhandler(exceptions.AuthException)
-        def _auth_exception(error):
-            return {"error": "Unauthorized"}, 401
+        @self.app.errorhandler(exceptions.AuthException)
+        def _auth_exception(error):
+            return {"error": "Unauthorized"}, 401
 
     def __hook_errors(self):
-        # FIXME (dthom): it doesn't work
+
         def get_404_json(e):
-            return {"error": "Error", "code": 404, "description": e}
+            return jsonify({"result": False, "code": 404, "description": str(e)}), 404
         self.app.register_error_handler(404, get_404_json)
 
         def get_400_json(e):
-            return {"error": "Error", "code": 400, "description": e}
+            return jsonify({"result": False, "code": 400, "description": str(e)}), 400
         self.app.register_error_handler(400, lambda e: get_400_json)
         self.app.register_error_handler(403, exceptions.AuthException)
 
@@ -132,7 +123,23 @@ class HTTPServer(Server):
 
         for api in __API__:
             self.api.add_resource(api, *api.__urls__)
+        self.api.add_resource(Wrapper, *Wrapper.__urls__,
+                              resource_class_kwargs={
+                                  "port": self.port,
+                                  "cache": CACHE,
+                                  "interface_name": self.host,
+                                  "manager_url": "http://{}:{}".format(self.manager_hostname, self.manager_port),
+                              }
+                              )
+        self.api.add_resource(Authz, *Authz.__urls__,
+                              resource_class_kwargs={
+                                  "cache": CACHE,
+                                  "interface_name": self.host,
+                                  "manager_url": "http://{}:{}".format(self.manager_hostname, self.manager_port),
+                              }
+                              )
 
     def run(self):
-        self.app.run(debug=True, host=self._host, port=self._port)  # nosec
+        self.app.run(host=self._host, port=self._port)  # nosec
+        # self.app.run(debug=True, host=self._host, port=self._port)  # nosec
 
index 711aa00..86274ec 100644 (file)
@@ -14,7 +14,6 @@ def main():
     configuration.init_logging()
     try:
         conf = configuration.get_configuration("components/interface")
-        LOG.debug("interface.conf={}".format(conf))
         hostname = conf["components/interface"].get("hostname", "interface")
         port = conf["components/interface"].get("port", 80)
         bind = conf["components/interface"].get("bind", "127.0.0.1")
@@ -25,6 +24,8 @@ def main():
         configuration.add_component(uuid="interface", name=hostname, port=port, bind=bind)
     LOG.info("Starting server with IP {} on port {} bind to {}".format(hostname, port, bind))
     server = HTTPServer(host=bind, port=port)
+    # LOG.info("Starting server")
+    # server = HTTPServer(host="0.0.0.0", port=8081)
     server.run()
 
 
diff --git a/moonv4/moon_manager/moon_manager/api/containers.py b/moonv4/moon_manager/moon_manager/api/containers.py
new file mode 100644 (file)
index 0000000..44e7baa
--- /dev/null
@@ -0,0 +1,179 @@
+# 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'.
+"""
+PDP are Policy Decision Point.
+
+"""
+
+import copy
+from docker import Client
+from flask import request
+from flask_restful import Resource
+from oslo_log import log as logging
+from moon_utilities.security_functions import check_auth
+from moon_db.core import PDPManager
+from moon_utilities import configuration, exceptions
+
+docker_conf = configuration.get_configuration("docker")['docker']
+docker = Client(base_url=docker_conf['url'])
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger("moon.manager.api." + __name__)
+
+
+class Container(Resource):
+    """
+    Endpoint for container requests
+    """
+
+    __urls__ = (
+        "/containers",
+        "/containers/",
+        "/containers/<string:uuid>",
+        "/containers/<string:uuid>/",
+    )
+
+    def __init__(self):
+        self.containers = {}
+        self.update()
+
+    def update(self):
+        for _container in docker.containers():
+            if _container['Id'] not in self.containers:
+                self.containers[_container['Id']] = {
+                    "name": _container["Names"],
+                    "port": _container["Ports"],
+                }
+
+    @check_auth
+    def get(self, uuid=None, user_id=None):
+        """Retrieve all containers
+
+        :param uuid: uuid of the container
+        :param user_id: user ID who do the request
+        :return: {
+            "containers": {
+                "da0fd80fc1dc146e1b...a2e07d240cde09f0a": {
+                    "name": [
+                        "/wrapper"
+                    ],
+                    "port": [
+                        {
+                            "PrivatePort": 8080,
+                            "Type": "tcp",
+                            "IP": "0.0.0.0",
+                            "PublicPort": 8080
+                        }
+                    ]
+                },
+            }
+        }
+        :internal_api: get_containers
+        """
+        # try:
+        #     data = [{"name": item["Names"], "port": item["Ports"], } for item in docker.containers()]
+        # except Exception as e:
+        #     LOG.error(e, exc_info=True)
+        #     return {"result": False,
+        #             "error": str(e)}
+        return {"containers": self.containers}
+
+    @check_auth
+    def post(self, uuid=None, user_id=None):
+        """Add a new container.
+
+        :param uuid: uuid of the pdp (not used here)
+        :param user_id: user ID who do the request
+        :request body: {
+            "id": "id of the new container",
+            "name": "name of the new container",
+            "hostname": "hostname of the new container",
+            "port": {
+                "PrivatePort": 8080,
+                "Type": "tcp",
+                "IP": "0.0.0.0",
+                "PublicPort": 8080
+            },
+            "keystone_project_id": "keystone_project_id1",
+            "pdp_id": "PDP UUID",
+            "container_name": "wukongsun/moon_authz:v4.1"
+        }
+        :return: {
+            "containers": {
+                "da0fd80fc1dc146e1b...a2e07d240cde09f0a": {
+                    "name": [
+                        "/wrapper"
+                    ],
+                    "port": [
+                        {
+                            "PrivatePort": 8080,
+                            "Type": "tcp",
+                            "IP": "0.0.0.0",
+                            "PublicPort": 8080
+                        }
+                    ]
+                },
+            }
+        }
+        :internal_api: add_container
+        """
+        try:
+            self.update()
+            self.containers[request.json.get('id')] = copy.deepcopy(request.json)
+            LOG.info("Added a new container {}".format(request.json.get('name')))
+        except Exception as e:
+            LOG.error(e, exc_info=True)
+            return {"result": False,
+                    "error": str(e)}, 500
+        return {"containers": self.containers}
+
+    @check_auth
+    def delete(self, uuid=None, user_id=None):
+        """Delete a pdp
+
+        :param uuid: uuid of the pdp to delete
+        :param user_id: user ID who do the request
+        :return: {
+            "result": "True or False",
+            "message": "optional message"
+        }
+        :internal_api: delete_pdp
+        """
+        # try:
+        #     data = PDPManager.delete_pdp(user_id=user_id, pdp_id=uuid)
+        # except Exception as e:
+        #     LOG.error(e, exc_info=True)
+        #     return {"result": False,
+        #             "error": str(e)}
+        # return {"result": True}
+        raise NotImplementedError
+
+    @check_auth
+    def patch(self, uuid=None, user_id=None):
+        """Update a pdp
+
+        :param uuid: uuid of the pdp to update
+        :param user_id: user ID who do the request
+        :return: {
+            "pdp_id1": {
+                "name": "...",
+                "security_pipeline": [...],
+                "keystone_project_id": "keystone_project_id1",
+                "description": "...",
+            }
+        }
+        :internal_api: update_pdp
+        """
+        # try:
+        #     data = PDPManager.update_pdp(user_id=user_id, pdp_id=uuid, value=request.json)
+        #     add_container(uuid=uuid, pipeline=data[uuid]['security_pipeline'])
+        # except Exception as e:
+        #     LOG.error(e, exc_info=True)
+        #     return {"result": False,
+        #             "error": str(e)}
+        # return {"pdps": data}
+        raise NotImplementedError
+
index bdd429e..a59921f 100644 (file)
@@ -18,6 +18,7 @@ from moon_manager.api.perimeter import Subjects, Objects, Actions
 from moon_manager.api.data import SubjectData, ObjectData, ActionData
 from moon_manager.api.assignments import SubjectAssignments, ObjectAssignments, ActionAssignments
 from moon_manager.api.rules import Rules
+from moon_manager.api.containers import Container
 from moon_utilities import configuration, exceptions
 
 logger = logging.getLogger("moon.manager.http")
@@ -72,7 +73,7 @@ __API__ = (
     Subjects, Objects, Actions,
     SubjectAssignments, ObjectAssignments, ActionAssignments,
     SubjectData, ObjectData, ActionData,
-    Rules,
+    Rules, Container,
     Models, Policies, PDP
  )
 
index e7be3d0..6b2af70 100644 (file)
@@ -2,4 +2,5 @@ flask
 flask_restful
 flask_cors
 moon_utilities
-moon_db
\ No newline at end of file
+moon_db
+docker-py
index e39a8b5..51a007c 100644 (file)
@@ -35,3 +35,7 @@ CHANGES
 -----
 - Add authentication features for interface
 
+1.3.0
+-----
+- Add cache functionality
+
diff --git a/moonv4/moon_utilities/build.sh b/moonv4/moon_utilities/build.sh
new file mode 100644 (file)
index 0000000..4c7db18
--- /dev/null
@@ -0,0 +1,21 @@
+
+
+VERSION=moon_utilities-1.2.0
+
+python3 setup.py sdist bdist_wheel
+
+rm dist/*.asc
+
+gpg --detach-sign -u "A0A96E75" -a dist/${VERSION}-py3-none-any.whl
+gpg --detach-sign -u "A0A96E75" -a dist/${VERSION}.linux-x86_64.tar.gz
+
+if [ "$1" = "upload" ]; then
+    twine upload dist/${VERSION}-py3-none-any.whl dist/${VERSION}-py3-none-any.whl.asc
+    twine upload dist/${VERSION}.linux-x86_64.tar.gz dist/${VERSION}.linux-x86_64.tar.gz.asc
+fi
+
+cp dist/${VERSION}-py3-none-any.whl ../moon_orchestrator/dist/
+cp dist/${VERSION}-py3-none-any.whl ../moon_router/dist/
+cp dist/${VERSION}-py3-none-any.whl ../moon_interface/dist/
+cp dist/${VERSION}-py3-none-any.whl ../moon_manager/dist/
+cp dist/${VERSION}-py3-none-any.whl ../moon_authz/dist/
index 2c7f8f5..6e5782c 100644 (file)
@@ -3,4 +3,4 @@
 # license which can be found in the file 'LICENSE' in this package distribution
 # or at 'http://www.apache.org/licenses/LICENSE-2.0'.
 
-__version__ = "1.2.0"
+__version__ = "1.3.0"
diff --git a/moonv4/moon_utilities/moon_utilities/cache.py b/moonv4/moon_utilities/moon_utilities/cache.py
new file mode 100644 (file)
index 0000000..7c938b3
--- /dev/null
@@ -0,0 +1,520 @@
+import logging
+import time
+import requests
+from uuid import uuid4
+from moon_utilities import configuration, exceptions
+
+LOG = logging.getLogger("moon.utilities.cache")
+
+
+class Cache(object):
+    # TODO (asteroide): set cache integer in CONF file
+    __UPDATE_INTERVAL = 10
+
+    __CONTAINERS = {}
+    __CONTAINERS_UPDATE = 0
+
+    __CONTAINER_CHAINING_UPDATE = 0
+    __CONTAINER_CHAINING = {}
+
+    __PDP = {}
+    __PDP_UPDATE = 0
+
+    __POLICIES = {}
+    __POLICIES_UPDATE = 0
+
+    __MODELS = {}
+    __MODELS_UPDATE = 0
+
+    __SUBJECTS = {}
+    __OBJECTS = {}
+    __ACTIONS = {}
+
+    __SUBJECT_ASSIGNMENTS = {}
+    __OBJECT_ASSIGNMENTS = {}
+    __ACTION_ASSIGNMENTS = {}
+
+    __SUBJECT_CATEGORIES = {}
+    __SUBJECT_CATEGORIES_UPDATE = 0
+    __OBJECT_CATEGORIES = {}
+    __OBJECT_CATEGORIES_UPDATE = 0
+    __ACTION_CATEGORIES = {}
+    __ACTION_CATEGORIES_UPDATE = 0
+
+    __META_RULES = {}
+    __META_RULES_UPDATE = 0
+
+    __RULES = {}
+    __RULES_UPDATE = 0
+
+    __AUTHZ_REQUESTS = {}
+
+
+    def __init__(self):
+        self.manager_url = "{}://{}:{}".format(
+            configuration.get_components()['manager'].get('protocol', 'http'),
+            configuration.get_components()['manager']['hostname'],
+            configuration.get_components()['manager']['port']
+        )
+        self.orchestrator_url = "{}://{}:{}".format(
+            configuration.get_components()['orchestrator'].get('protocol', 'http'),
+            configuration.get_components()['orchestrator']['hostname'],
+            configuration.get_components()['orchestrator']['port']
+        )
+
+    def update(self):
+        self.__update_container()
+        self.__update_pdp()
+        self.__update_policies()
+        self.__update_models()
+        for key, value in self.__PDP.items():
+            # LOG.info("Updating container_chaining with {}".format(value["keystone_project_id"]))
+            self.__update_container_chaining(value["keystone_project_id"])
+
+    @property
+    def authz_requests(self):
+        return self.__AUTHZ_REQUESTS
+
+    # perimeter functions
+
+    @property
+    def subjects(self):
+        return self.__SUBJECTS
+
+    def update_subjects(self, policy_id=None):
+        req = requests.get("{}/policies/{}/subjects".format(self.manager_url, policy_id))
+        self.__SUBJECTS[policy_id] = req.json()['subjects']
+
+    def get_subject(self, policy_id, name):
+        try:
+            for _subject_id, _subject_dict in self.__SUBJECTS[policy_id].items():
+                if _subject_dict["name"] == name:
+                    return _subject_id
+        except KeyError:
+            pass
+        self.update_subjects(policy_id)
+        for _subject_id, _subject_dict in self.__SUBJECTS[policy_id].items():
+            if _subject_dict["name"] == name:
+                return _subject_id
+        raise exceptions.SubjectUnknown("Cannot find subject {}".format(name))
+
+    @property
+    def objects(self):
+        return self.__OBJECTS
+
+    def update_objects(self, policy_id=None):
+        req = requests.get("{}/policies/{}/objects".format(self.manager_url, policy_id))
+        self.__OBJECTS[policy_id] = req.json()['objects']
+
+    def get_object(self, policy_id, name):
+        try:
+            for _object_id, _object_dict in self.__OBJECTS[policy_id].items():
+                if _object_dict["name"] == name:
+                    return _object_id
+        except KeyError:
+            pass
+        self.update_objects(policy_id)
+        for _object_id, _object_dict in self.__OBJECTS[policy_id].items():
+            if _object_dict["name"] == name:
+                return _object_id
+        raise exceptions.SubjectUnknown("Cannot find object {}".format(name))
+
+    @property
+    def actions(self):
+        return self.__ACTIONS
+
+    def update_actions(self, policy_id=None):
+        req = requests.get("{}/policies/{}/actions".format(self.manager_url, policy_id))
+        self.__ACTIONS[policy_id] = req.json()['actions']
+
+    def get_action(self, policy_id, name):
+        try:
+            for _action_id, _action_dict in self.__ACTIONS[policy_id].items():
+                if _action_dict["name"] == name:
+                    return _action_id
+        except KeyError:
+            pass
+        self.update_actions(policy_id)
+        for _action_id, _action_dict in self.__ACTIONS[policy_id].items():
+            if _action_dict["name"] == name:
+                return _action_id
+        raise exceptions.SubjectUnknown("Cannot find action {}".format(name))
+
+    # meta_rule functions
+
+    @property
+    def meta_rules(self):
+        current_time = time.time()
+        if self.__META_RULES_UPDATE + self.__UPDATE_INTERVAL < current_time:
+            self.__update_meta_rules()
+        self.__META_RULES_UPDATE = current_time
+        return self.__META_RULES
+
+    def __update_meta_rules(self):
+        req = requests.get("{}/meta_rules".format(self.manager_url))
+        self.__META_RULES = req.json()['meta_rules']
+
+    # rule functions
+
+    @property
+    def rules(self):
+        current_time = time.time()
+        if self.__RULES_UPDATE + self.__UPDATE_INTERVAL < current_time:
+            self.__update_rules()
+        self.__RULES_UPDATE = current_time
+        return self.__RULES
+
+    def __update_rules(self):
+        for policy_id in self.__POLICIES:
+            LOG.info("Get {}".format("{}/policies/{}/rules".format(
+                self.manager_url, policy_id)))
+            req = requests.get("{}/policies/{}/rules".format(
+                self.manager_url, policy_id))
+            self.__RULES[policy_id] = req.json()['rules']
+        LOG.info("UPDATE RULES {}".format(self.__RULES))
+
+    # assignment functions
+
+    @property
+    def subject_assignments(self):
+        return self.__SUBJECT_ASSIGNMENTS
+
+    def update_subject_assignments(self, policy_id=None, perimeter_id=None):
+        if perimeter_id:
+            req = requests.get("{}/policies/{}/subject_assignments/{}".format(
+                self.manager_url, policy_id, perimeter_id))
+        else:
+            req = requests.get("{}/policies/{}/subject_assignments".format(self.manager_url, policy_id))
+        if policy_id not in self.__SUBJECT_ASSIGNMENTS:
+            self.__SUBJECT_ASSIGNMENTS[policy_id] = {}
+        self.__SUBJECT_ASSIGNMENTS[policy_id].update(req.json()['subject_assignments'])
+
+    def get_subject_assignments(self, policy_id, perimeter_id, category_id):
+        if policy_id not in self.subject_assignments:
+            self.update_subject_assignments(policy_id, perimeter_id)
+        if policy_id not in self.subject_assignments:
+            raise Exception("Cannot found the policy {}".format(policy_id))
+        for key, value in self.subject_assignments[policy_id].items():
+            if perimeter_id == value['subject_id'] and category_id == value['category_id']:
+                return value['assignments']
+        return []
+
+    @property
+    def object_assignments(self):
+        return self.__OBJECT_ASSIGNMENTS
+
+    def update_object_assignments(self, policy_id=None, perimeter_id=None):
+        if perimeter_id:
+            req = requests.get("{}/policies/{}/object_assignments/{}".format(
+                self.manager_url, policy_id, perimeter_id))
+        else:
+            req = requests.get("{}/policies/{}/object_assignments".format(self.manager_url, policy_id))
+        if policy_id not in self.__OBJECT_ASSIGNMENTS:
+            self.__OBJECT_ASSIGNMENTS[policy_id] = {}
+        self.__OBJECT_ASSIGNMENTS[policy_id].update(req.json()['object_assignments'])
+
+    def get_object_assignments(self, policy_id, perimeter_id, category_id):
+        if policy_id not in self.object_assignments:
+            self.update_object_assignments(policy_id, perimeter_id)
+        if policy_id not in self.object_assignments:
+            raise Exception("Cannot found the policy {}".format(policy_id))
+        for key, value in self.object_assignments[policy_id].items():
+            if perimeter_id == value['object_id'] and category_id == value['category_id']:
+                return value['assignments']
+        return []
+
+    @property
+    def action_assignments(self):
+        return self.__ACTION_ASSIGNMENTS
+
+    def update_action_assignments(self, policy_id=None, perimeter_id=None):
+        if perimeter_id:
+            req = requests.get("{}/policies/{}/action_assignments/{}".format(
+                self.manager_url, policy_id, perimeter_id))
+        else:
+            req = requests.get("{}/policies/{}/action_assignments".format(self.manager_url, policy_id))
+        if policy_id not in self.__ACTION_ASSIGNMENTS:
+            self.__ACTION_ASSIGNMENTS[policy_id] = {}
+        self.__ACTION_ASSIGNMENTS[policy_id].update(req.json()['action_assignments'])
+
+    def get_action_assignments(self, policy_id, perimeter_id, category_id):
+        if policy_id not in self.action_assignments:
+            self.update_action_assignments(policy_id, perimeter_id)
+        if policy_id not in self.action_assignments:
+            raise Exception("Cannot found the policy {}".format(policy_id))
+        for key, value in self.action_assignments[policy_id].items():
+            if perimeter_id == value['action_id'] and category_id == value['category_id']:
+                return value['assignments']
+        return []
+
+    # category functions
+
+    @property
+    def subject_categories(self):
+        current_time = time.time()
+        if self.__SUBJECT_CATEGORIES_UPDATE + self.__UPDATE_INTERVAL < current_time:
+            self.__update_subject_categories()
+        self.__SUBJECT_CATEGORIES_UPDATE = current_time
+        return self.__SUBJECT_CATEGORIES
+
+    def __update_subject_categories(self):
+        req = requests.get("{}/policies/subject_categories".format(
+            self.manager_url))
+        self.__SUBJECT_CATEGORIES.update(req.json()['subject_categories'])
+
+    @property
+    def object_categories(self):
+        current_time = time.time()
+        if self.__OBJECT_CATEGORIES_UPDATE + self.__UPDATE_INTERVAL < current_time:
+            self.__update_object_categories()
+        self.__OBJECT_CATEGORIES_UPDATE = current_time
+        return self.__OBJECT_CATEGORIES
+
+    def __update_object_categories(self):
+        req = requests.get("{}/policies/object_categories".format(
+            self.manager_url))
+        self.__OBJECT_CATEGORIES.update(req.json()['object_categories'])
+
+    @property
+    def action_categories(self):
+        current_time = time.time()
+        if self.__ACTION_CATEGORIES_UPDATE + self.__UPDATE_INTERVAL < current_time:
+            self.__update_action_categories()
+        self.__ACTION_CATEGORIES_UPDATE = current_time
+        return self.__ACTION_CATEGORIES
+
+    def __update_action_categories(self):
+        req = requests.get("{}/policies/action_categories".format(
+            self.manager_url))
+        self.__ACTION_CATEGORIES.update(req.json()['action_categories'])
+
+    # PDP functions
+
+    def __update_pdp(self):
+        req = requests.get("{}/pdp".format(self.manager_url))
+        pdp = req.json()
+        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):
+        """Policy Decision Point
+        Example of content:
+        {
+            "pdp_id": {
+                "keystone_project_id": "keystone_project_id",
+                "name": "pdp1",
+                "description": "test",
+                "security_pipeline": [
+                    "policy_id"
+                ]
+            }
+        }
+
+        :return:
+        """
+        current_time = time.time()
+        if self.__PDP_UPDATE + self.__UPDATE_INTERVAL < current_time:
+            self.__update_pdp()
+        self.__PDP_UPDATE = current_time
+        return self.__PDP
+
+    # policy functions
+    def __update_policies(self):
+        req = requests.get("{}/policies".format(self.manager_url))
+        policies = req.json()
+        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
+
+    # model functions
+
+    def __update_models(self):
+        req = requests.get("{}/models".format(self.manager_url))
+        models = req.json()
+        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
+
+    # helper functions
+
+    def get_policy_from_meta_rules(self, meta_rule_id):
+        for pdp_key, pdp_value in self.pdp.items():
+            for policy_id in pdp_value["security_pipeline"]:
+                model_id = self.policies[policy_id]["model_id"]
+                if meta_rule_id in self.models[model_id]["meta_rules"]:
+                    return policy_id
+
+    def get_pdp_from_keystone_project(self, keystone_project_id):
+        for pdp_key, pdp_value in self.pdp.items():
+            if keystone_project_id == pdp_value["keystone_project_id"]:
+                return pdp_key
+
+    def get_keystone_project_id_from_policy_id(self, policy_id):
+        for pdp_key, pdp_value in self.pdp.items():
+            if policy_id in pdp_value["security_pipeline"]:
+                return pdp_value["keystone_project_id"]
+            # for policy_id in pdp_value["security_pipeline"]:
+            #     model_id = self.policies[policy_id]["model_id"]
+            #     if meta_rule_id in self.models[model_id]["meta_rules"]:
+            #         return pdp_value["keystone_project_id"]
+
+    def get_containers_from_keystone_project_id(self, keystone_project_id, meta_rule_id=None):
+        for container_id, container_value in self.containers.items():
+            if 'keystone_project_id' not in container_value:
+                continue
+            if container_value['keystone_project_id'] == keystone_project_id:
+                if not meta_rule_id:
+                    yield container_id, container_value
+                elif container_value['meta_rule_id'] == meta_rule_id:
+                    yield container_id, container_value
+                    break
+
+    # containers functions
+
+    def __update_container(self):
+        req = requests.get("{}/containers".format(self.manager_url))
+        containers = req.json()
+        for key, value in containers["containers"].items():
+            if key not in self.__CONTAINERS:
+                self.__CONTAINERS[key] = value
+            else:
+                self.__CONTAINERS[key].update(value)
+
+    def add_container(self, container_data):
+        """Add a new container in the cache
+
+        :param container_data: dictionary with information for the container
+        Example:
+        {
+            "name": name,
+            "hostname": name,
+            "port": {
+                "PrivatePort": tcp_port,
+                "Type": "tcp",
+                "IP": "0.0.0.0",
+                "PublicPort": tcp_port
+            },
+            "keystone_project_id": uuid,
+            "pdp_id": self.CACHE.get_pdp_from_keystone_project(uuid),
+            "meta_rule_id": meta_rule_id,
+            "container_name": container_name,
+            "plugin_name": plugin_name
+            "container_id": "container_id"
+        }
+
+        :return:
+        """
+        self.__CONTAINERS[uuid4().hex] = {
+            "keystone_project_id": container_data['keystone_project_id'],
+            "name": container_data['name'],
+            "container_id": container_data['container_id'],
+            "hostname": container_data['name'],
+            "policy_id": container_data['policy_id'],
+            "meta_rule_id": container_data['meta_rule_id'],
+            "port": [
+                {
+                    "PublicPort": container_data['port']["PublicPort"],
+                    "Type": container_data['port']["Type"],
+                    "IP": container_data['port']["IP"],
+                    "PrivatePort": container_data['port']["PrivatePort"]
+                }
+            ],
+            "genre": container_data['plugin_name']
+        }
+        self.__update_container_chaining(self.get_keystone_project_id_from_policy_id(container_data['policy_id']))
+
+    @property
+    def containers(self):
+        """Containers cache
+        example of content :
+        {
+            "policy_uuid1": "component_hostname1",
+            "policy_uuid2": "component_hostname2",
+        }
+        :return:
+        """
+        current_time = time.time()
+        if self.__CONTAINERS_UPDATE + self.__UPDATE_INTERVAL < current_time:
+            self.__update_container()
+        self.__CONTAINERS_UPDATE = current_time
+        return self.__CONTAINERS
+
+    @property
+    def container_chaining(self):
+        """Cache for mapping Keystone Project ID with meta_rule ID and container ID
+        Example of content:
+        {
+            "keystone_project_id": [
+                {
+                    "container_id": "container_id",
+                    "genre": "genre",
+                    "policy_id": "policy_id",
+                    "meta_rule_id": "meta_rule_id",
+                }
+            ]
+        }
+
+        :return:
+        """
+        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
+        LOG.info(self.__CONTAINER_CHAINING_UPDATE)
+        return self.__CONTAINER_CHAINING
+
+    def __update_container_chaining(self, keystone_project_id):
+        container_ids = []
+        for pdp_id, pdp_value, in self.__PDP.items():
+            # LOG.info("pdp_id, pdp_value = {}, {}".format(pdp_id, pdp_value))
+            # LOG.info("__POLICIES = {}".format(self.__POLICIES))
+            if pdp_value:
+                if pdp_value["keystone_project_id"] == keystone_project_id:
+                    for policy_id in pdp_value["security_pipeline"]:
+                        model_id = self.__POLICIES[policy_id]['model_id']
+                        # LOG.info("model_id = {}".format(model_id))
+                        # LOG.info("CACHE = {}".format(self.__MODELS[model_id]))
+                        # LOG.info("CACHE.containers = {}".format(self.__CONTAINERS))
+                        # LOG.info("CACHE.models = {}".format(self.__MODELS))
+                        for meta_rule_id in self.__MODELS[model_id]["meta_rules"]:
+                            # LOG.info("meta_rule = {}".format(self.__MODELS[model_id]["meta_rules"]))
+                            for container_id, container_value in self.get_containers_from_keystone_project_id(
+                                keystone_project_id,
+                                meta_rule_id
+                            ):
+                                # LOG.info("CONTAINER: {} {}".format(container_id, container_value))
+                                container_ids.append(
+                                    {
+                                        "container_id": self.__CONTAINERS[container_id]["container_id"],
+                                        "genre": self.__CONTAINERS[container_id]["genre"],
+                                        "policy_id": policy_id,
+                                        "meta_rule_id": meta_rule_id,
+                                        "hostname": self.__CONTAINERS[container_id]["hostname"],
+                                        "hostip": self.__CONTAINERS[container_id]["port"][0]["IP"],
+                                        "port": self.__CONTAINERS[container_id]["port"][0]["PublicPort"],
+                                    }
+                                )
+        # LOG.info("__update_container_chaining={}".format(container_ids))
+        self.__CONTAINER_CHAINING[keystone_project_id] = container_ids
+
index 32eeff1..d1c5545 100644 (file)
@@ -53,8 +53,8 @@ def get_configuration(key):
     url = "http://{}:{}/v1/kv/{}".format(CONSUL_HOST, CONSUL_PORT, key)
     req = requests.get(url)
     if req.status_code != 200:
-        LOG.info("url={}".format(url))
-        raise exceptions.ConsulComponentNotFound
+        LOG.error("url={}".format(url))
+        raise exceptions.ConsulComponentNotFound("error={}: {}".format(req.status_code, req.text))
     data = req.json()
     if len(data) == 1:
         data = data[0]
index dea2a87..d019c1c 100644 (file)
@@ -1,4 +1,5 @@
 import json
+import yaml
 import logging
 import requests
 import argparse
@@ -26,6 +27,7 @@ def init():
     parser.add_argument("--debug", "-d", action='store_true', help="debug mode")
     parser.add_argument("--format", "-f", help="Output format (txt, json)", default="json")
     parser.add_argument("--output", "-o", help="Output filename")
+    parser.add_argument("--from-policies", "-p", help="Get API from policy.{json,yaml}", target="policies")
     parser.add_argument("--credentials", "-c", help="Github credential filename (inside format user:pass)")
     args = parser.parse_args()
 
@@ -98,6 +100,13 @@ def to_str(results):
     return output
 
 
+def get_data_from_policies(policies):
+    for filename in policies.split(","):
+        try:
+            obj = json.loads(open(filename.strip()).read())
+
+
+
 def save(results, args):
     if args.output:
         if args.format == 'json':
@@ -114,8 +123,11 @@ def save(results, args):
 def main():
     args = init()
     results = {}
-    for key in URLS:
-        results[key] = get_content(key, args)
+    if not args.policies:
+        for key in URLS:
+            results[key] = get_content(key, args)
+    else:
+        get_data_from_policies(args.policies)
     save(results, args)
 
 if __name__ == "__main__":
index ad1a44f..9893599 100644 (file)
@@ -209,59 +209,90 @@ def call(endpoint="security_router", ctx=None, method="route", **kwargs):
 
 class Context:
 
-    def __init__(self, _keystone_project_id, _subject, _object, _action, _request_id):
-        from moon_db.core import PDPManager, ModelManager, PolicyManager
-        self.PolicyManager = PolicyManager
-        self.ModelManager = ModelManager
-        self.PDPManager = PDPManager
-        self.__keystone_project_id = _keystone_project_id
+    def __init__(self, init_context, cache):
+        self.cache = cache
+        self.__keystone_project_id = init_context.get("project_id")
         self.__pdp_id = None
         self.__pdp_value = None
-        for _pdp_key, _pdp_value in PDPManager.get_pdp("admin").items():
-            if _pdp_value["keystone_project_id"] == _keystone_project_id:
+        for _pdp_key, _pdp_value in self.cache.pdp.items():
+            if _pdp_value["keystone_project_id"] == self.__keystone_project_id:
                 self.__pdp_id = _pdp_key
                 self.__pdp_value = copy.deepcopy(_pdp_value)
                 break
-        self.__subject = _subject
-        self.__object = _object
-        self.__action = _action
+        if not self.__pdp_value:
+            raise exceptions.AuthzException(
+                "Cannot create context for authz "
+                "with Keystone project ID {}".format(
+                    self.__keystone_project_id
+            ))
+        self.__subject = init_context.get("subject_name")
+        self.__object = init_context.get("object_name")
+        self.__action = init_context.get("action_name")
         self.__current_request = None
-        self.__request_id = _request_id
-        self.__index = 0
-        self.__init_initial_request()
+        self.__request_id = init_context.get("req_id")
+        self.__cookie = init_context.get("cookie")
+        self.__manager_url = init_context.get("manager_url")
+        self.__interface_name = init_context.get("interface_name")
+        self.__index = -1
+        # self.__init_initial_request()
         self.__headers = []
-        policies = PolicyManager.get_policies("admin")
-        models = ModelManager.get_models("admin")
+        policies = self.cache.policies
+        models = self.cache.models
         for policy_id in self.__pdp_value["security_pipeline"]:
             model_id = policies[policy_id]["model_id"]
             for meta_rule in models[model_id]["meta_rules"]:
                 self.__headers.append(meta_rule)
-        self.__meta_rules = ModelManager.get_meta_rules("admin")
+        self.__meta_rules = self.cache.meta_rules
         self.__pdp_set = {}
+        # self.__init_pdp_set()
+
+    def delete_cache(self):
+        self.cache = {}
+
+    def set_cache(self, cache):
+        self.cache = cache
+
+    def increment_index(self):
+        self.__index += 1
+        self.__init_current_request()
         self.__init_pdp_set()
 
-    def __init_initial_request(self):
-        subjects = self.PolicyManager.get_subjects("admin", policy_id=None)
-        for _subject_id, _subject_dict in subjects.items():
-            if _subject_dict["name"] == self.__subject:
-                self.__subject = _subject_id
-                break
-        else:
-            raise exceptions.SubjectUnknown("Cannot find subject {}".format(self.__subject))
-        objects = self.PolicyManager.get_objects("admin", policy_id=None)
-        for _object_id, _object_dict in objects.items():
-            if _object_dict["name"] == self.__object:
-                self.__object = _object_id
-                break
-        else:
-            raise exceptions.ObjectUnknown("Cannot find object {}".format(self.__object))
-        actions = self.PolicyManager.get_actions("admin", policy_id=None)
-        for _action_id, _action_dict in actions.items():
-            if _action_dict["name"] == self.__action:
-                self.__action = _action_id
-                break
-        else:
-            raise exceptions.ActionUnknown("Cannot find action {}".format(self.__action))
+    @property
+    def current_state(self):
+        return self.__pdp_set[self.__headers[self.__index]]['effect']
+
+    @current_state.setter
+    def current_state(self, state):
+        if state not in ("grant", "deny", "passed"):
+            state = "passed"
+        self.__pdp_set[self.__headers[self.__index]]['effect'] = state
+
+    @current_state.deleter
+    def current_state(self):
+        self.__pdp_set[self.__headers[self.__index]]['effect'] = "unset"
+
+    @property
+    def current_policy_id(self):
+        return self.__pdp_value["security_pipeline"][self.__index]
+
+    @current_policy_id.setter
+    def current_policy_id(self, value):
+        pass
+
+    @current_policy_id.deleter
+    def current_policy_id(self):
+        pass
+
+    def __init_current_request(self):
+        self.__subject = self.cache.get_subject(
+            self.__pdp_value["security_pipeline"][self.__index],
+            self.__subject)
+        self.__object = self.cache.get_object(
+            self.__pdp_value["security_pipeline"][self.__index],
+            self.__object)
+        self.__action = self.cache.get_action(
+            self.__pdp_value["security_pipeline"][self.__index],
+            self.__action)
         self.__current_request = dict(self.initial_request)
 
     def __init_pdp_set(self):
@@ -269,67 +300,64 @@ class Context:
             self.__pdp_set[header] = dict()
             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]["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 update_target(self, context):
+    #     # 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 = self.cache.get_policy_from_meta_rules(meta_rule_id)
+    #     meta_rules = self.cache.meta_rules()
+    #     # 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 self.cache.get_subject_assignments(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 self.cache.get_object_assignments(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 self.cache.get_action_assignments(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")
-        policy_id = self.PolicyManager.get_policy_from_meta_rules("admin", meta_rule_id)
+        meta_rules = self.cache.meta_rules
+        policy_id = self.cache.get_policy_from_meta_rules(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"])
+            result[sub_cat].extend(
+                self.cache.get_subject_assignments(policy_id, _subject, sub_cat))
         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"])
+            result[obj_cat].extend(
+                self.cache.get_object_assignments(policy_id, _object, obj_cat))
         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"])
+            result[act_cat].extend(
+                self.cache.get_action_assignments(policy_id, _action, act_cat))
         return result
 
     def __repr__(self):
@@ -356,6 +384,8 @@ pdp_set: {pdp_set}
             "index": copy.deepcopy(self.__index),
             "pdp_set": copy.deepcopy(self.__pdp_set),
             "request_id": copy.deepcopy(self.__request_id),
+            "manager_url": copy.deepcopy(self.__manager_url),
+            "interface_name": copy.deepcopy(self.__interface_name),
         }
 
     @property
@@ -370,6 +400,42 @@ pdp_set: {pdp_set}
     def request_id(self):
         raise Exception("You cannot update the request_id")
 
+    @property
+    def manager_url(self):
+        return self.__manager_url
+
+    @manager_url.setter
+    def manager_url(self, value):
+        raise Exception("You cannot update the manager_url")
+
+    @manager_url.deleter
+    def manager_url(self):
+        raise Exception("You cannot update the manager_url")
+
+    @property
+    def interface_name(self):
+        return self.__interface_name
+
+    @interface_name.setter
+    def interface_name(self, value):
+        raise Exception("You cannot update the interface_name")
+
+    @interface_name.deleter
+    def interface_name(self):
+        raise Exception("You cannot update the interface_name")
+
+    @property
+    def cookie(self):
+        return self.__cookie
+
+    @cookie.setter
+    def cookie(self, value):
+        raise Exception("You cannot update the cookie")
+
+    @cookie.deleter
+    def cookie(self):
+        raise Exception("You cannot delete the cookie")
+
     @property
     def initial_request(self):
         return {
@@ -425,7 +491,7 @@ pdp_set: {pdp_set}
 
     @index.deleter
     def index(self):
-        self.__index = 0
+        self.__index = -1
 
     @property
     def pdp_set(self):
diff --git a/moonv4/moon_wrapper/moon_wrapper/api/__init__.py b/moonv4/moon_wrapper/moon_wrapper/api/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/moonv4/moon_wrapper/moon_wrapper/api/generic.py b/moonv4/moon_wrapper/moon_wrapper/api/generic.py
new file mode 100644 (file)
index 0000000..80e8abf
--- /dev/null
@@ -0,0 +1,151 @@
+# 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'.
+"""
+Those API are helping API used to manage the Moon platform.
+"""
+
+from flask_restful import Resource, request
+from oslo_log import log as logging
+from moon_utilities.security_functions import call
+import moon_interface.api
+from moon_utilities.security_functions import check_auth
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger("moon.interface.api." + __name__)
+
+
+class Status(Resource):
+    """
+    Endpoint for status requests
+    """
+
+    __urls__ = ("/status", "/status/", "/status/<string:component_id>")
+
+    def get(self, component_id=None):
+        """Retrieve status of all components
+
+        :return: {
+          "orchestrator": {
+            "status": "Running"
+          },
+          "security_router": {
+            "status": "Running"
+          }
+        }
+        """
+        return call("security_router", method="get_status", ctx={"component_id": component_id})
+
+
+class Logs(Resource):
+    """
+    Endpoint for logs requests
+    """
+
+    __urls__ = ("/logs", "/logs/", "/logs/<string:component_id>")
+
+    def get(self, component_id=None):
+        """Get logs from the Moon platform
+
+        :param component_id: the ID of the component your are looking for (optional)
+        :return: [
+            "2015-04-15-13:45:20
+            "2015-04-15-13:45:21
+            "2015-04-15-13:45:22
+            "2015-04-15-13:45:23
+        ]
+        """
+        filter_str = request.args.get('filter', '')
+        from_str = request.args.get('from', '')
+        to_str = request.args.get('to', '')
+        event_number = request.args.get('event_number', '')
+        try:
+            event_number = int(event_number)
+        except ValueError:
+            event_number = None
+        args = dict()
+        args["filter"] = filter_str
+        args["from"] = from_str
+        args["to"] = to_str
+        args["event_number"] = event_number
+
+        return call("security_router", method="get_logs", ctx={"component_id": component_id}, args=args)
+
+
+class API(Resource):
+    """
+    Endpoint for API requests
+    """
+
+    __urls__ = (
+        "/api",
+        "/api/",
+        "/api/<string:group_id>",
+        "/api/<string:group_id>/",
+        "/api/<string:group_id>/<string:endpoint_id>")
+
+    @check_auth
+    def get(self, group_id="", endpoint_id="", user_id=""):
+        """Retrieve all API endpoints or a specific endpoint if endpoint_id is given
+
+        :param group_id: the name of one existing group (ie generic, ...)
+        :param endpoint_id: the name of one existing component (ie Logs, Status, ...)
+        :return: {
+            "group_name": {
+                "endpoint_name": {
+                    "description": "a description",
+                    "methods": {
+                        "get": "description of the HTTP method"
+                    },
+                    "urls": ('/api', '/api/', '/api/<string:endpoint_id>')
+                }
+        }
+        """
+        __methods = ("get", "post", "put", "delete", "options", "patch")
+        api_list = filter(lambda x: "__" not in x, dir(moon_interface.api))
+        api_desc = dict()
+        for api_name in api_list:
+            api_desc[api_name] = {}
+            group_api_obj = eval("moon_interface.api.{}".format(api_name))
+            api_desc[api_name]["description"] = group_api_obj.__doc__
+            if "__version__" in dir(group_api_obj):
+                api_desc[api_name]["version"] = group_api_obj.__version__
+            object_list = list(filter(lambda x: "__" not in x, dir(group_api_obj)))
+            for obj in map(lambda x: eval("moon_interface.api.{}.{}".format(api_name, x)), object_list):
+                if "__urls__" in dir(obj):
+                    api_desc[api_name][obj.__name__] = dict()
+                    api_desc[api_name][obj.__name__]["urls"] = obj.__urls__
+                    api_desc[api_name][obj.__name__]["methods"] = dict()
+                    for _method in filter(lambda x: x in __methods, dir(obj)):
+                        docstring = eval("moon_interface.api.{}.{}.{}.__doc__".format(api_name, obj.__name__, _method))
+                        api_desc[api_name][obj.__name__]["methods"][_method] = docstring
+                    api_desc[api_name][obj.__name__]["description"] = str(obj.__doc__)
+        if group_id in api_desc:
+            if endpoint_id in api_desc[group_id]:
+                return {group_id: {endpoint_id: api_desc[group_id][endpoint_id]}}
+            elif len(endpoint_id) > 0:
+                LOG.error("Unknown endpoint_id {}".format(endpoint_id))
+                return {"error": "Unknown endpoint_id {}".format(endpoint_id)}
+            return {group_id: api_desc[group_id]}
+        return api_desc
+
+
+class InternalAPI(Resource):
+    """
+    Endpoint for status requests
+    """
+
+    __urls__ = ("/internal_api", "/internal_api/", "/internal_api/<string:component_id>")
+
+    def get(self, component_id=None, user_id=""):
+        api_list = ("orchestrator", "security_router")
+        if not component_id:
+            return {"api": api_list}
+        if component_id in api_list:
+            api_desc = dict()
+            api_desc["name"] = component_id
+            api_desc["endpoints"] = call("security_router", component_id, {}, "list_api")
+            return api_desc
+
diff --git a/moonv4/moon_wrapper/moon_wrapper/api/wrapper.py b/moonv4/moon_wrapper/moon_wrapper/api/wrapper.py
new file mode 100644 (file)
index 0000000..832909c
--- /dev/null
@@ -0,0 +1,101 @@
+# 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'.
+"""
+Authz is the endpoint to get authorization response
+"""
+
+import flask
+from flask import request
+from flask_restful import Resource
+import logging
+import json
+import requests
+import time
+from uuid import uuid4
+
+from moon_interface.api.authz import pdp_in_cache, pdp_in_manager, container_exist, \
+    create_containers, create_authz_request
+from moon_interface.authz_requests import AuthzRequest
+from moon_utilities import configuration
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger("moon.wrapper.api." + __name__)
+
+
+class Wrapper(Resource):
+    """
+    Endpoint for authz requests
+    """
+
+    __urls__ = (
+        "/",
+    )
+
+    def __init__(self, **kwargs):
+        self.port = kwargs.get("port")
+        self.CACHE = kwargs.get("cache", {})
+        self.TIMEOUT = 5
+
+    # def get(self):
+    #     LOG.info("GET")
+    #     return self.manage_data()
+
+    def post(self):
+        LOG.info("POST {}".format(request.form))
+        response = flask.make_response("False")
+        if self.manage_data():
+            response = flask.make_response("True")
+        response.headers['content-type'] = 'application/octet-stream'
+        return response
+
+    @staticmethod
+    def __get_subject(target, credentials):
+        _subject = target.get("user_id", "")
+        if not _subject:
+            _subject = credentials.get("user_id", "none")
+        return _subject
+
+    @staticmethod
+    def __get_object(target, credentials):
+        try:
+            # note: case of Glance
+            return target['target']['name']
+        except KeyError:
+            pass
+
+        # note: default case
+        return target.get("project_id", "none")
+
+    @staticmethod
+    def __get_project_id(target, credentials):
+        return target.get("project_id", "none")
+
+    def get_interface_url(self, project_id):
+        for container in self.CACHE.containers.values():
+            if container.get("keystone_project_id") == project_id:
+                return "http://{}:{}".format(container['hostname'],
+                                             container['port'][0]["PublicPort"])
+
+    def manage_data(self):
+        target = json.loads(request.form.get('target', {}))
+        credentials = json.loads(request.form.get('credentials', {}))
+        rule = request.form.get('rule', "")
+        _subject = self.__get_subject(target, credentials)
+        _object = self.__get_object(target, credentials)
+        _project_id = self.__get_project_id(target, credentials)
+        LOG.info("POST with args project={} / "
+                 "subject={} - object={} - action={}".format(
+                    _project_id, _subject, _object, rule))
+        interface_url = self.get_interface_url(_project_id)
+        req = requests.get("{}/{}/{}/{}".format(
+            interface_url,
+            _subject,
+            _object,
+            rule
+        ))
+        if req.status_code == 200:
+            if req.json().get("result", False):
+                return True
index f50213c..d93d696 100644 (file)
 # license which can be found in the file 'LICENSE' in this package distribution
 # or at 'http://www.apache.org/licenses/LICENSE-2.0'.
 
-import requests
-import json
-from flask import Flask, request
+from flask import Flask, jsonify
+from flask_cors import CORS, cross_origin
+from flask_restful import Resource, Api
 import logging
-from moon_utilities import configuration
+from moon_wrapper import __version__
+from moon_wrapper.api.generic import Status, Logs, API
+from moon_wrapper.api.wrapper import Wrapper
+from moon_utilities.cache import Cache
+from moon_utilities import configuration, exceptions
 
 logger = logging.getLogger("moon.wrapper.http")
 
 
-def __get_subject(target, credentials):
-    _subject = target.get("user_id", "")
-    if not _subject:
-        _subject = credentials.get("user_id", "")
-    return _subject
-
-
-def __get_object(target, credentials):
-    try:
-        # note: case of Glance
-        return target['target']['name']
-    except KeyError:
-        pass
-
-    # note: default case
-    return target.get("project_id", "")
-
-
-def __get_project_id(target, credentials):
-    return target.get("project_id", "")
-
-
-def HTTPServer(host, port):
-    app = Flask(__name__)
-    conf = configuration.get_configuration("components/wrapper")
-    timeout = conf["components/wrapper"].get("timeout", 5)
-    conf = configuration.get_configuration("components/interface")
-    interface_hostname = conf["components/interface"].get("hostname", "interface")
-    interface_port = conf["components/interface"].get("port", 80)
-    conf = configuration.get_configuration("logging")
-    try:
-        debug = conf["logging"]["loggers"]['moon']['level'] == "DEBUG"
-    except KeyError:
-        debug = False
-
-    @app.route("/", methods=['POST', 'GET'])
-    def wrapper():
-        try:
-            target = json.loads(request.form.get('target', {}))
-            credentials = json.loads(request.form.get('credentials', {}))
-            rule = request.form.get('rule', "")
-            _subject = __get_subject(target, credentials)
-            _object = __get_object(target, credentials)
-            _project_id = __get_project_id(target, credentials)
-            logger.info("GET with args {} / {} - {} - {}".format(_project_id, _subject, _object, rule))
-            _url = "http://{}:{}/authz/{}/{}/{}/{}".format(
-                interface_hostname,
-                interface_port,
-                _project_id,
-                _subject,
-                _object,
-                rule
-            )
-            req = requests.get(url=_url, timeout=timeout)
-            logger.info("req txt={}".format(req.text))
-            if req.json()["result"] == True:
-                return "True"
-        except Exception as e:
-            logger.exception("An exception occurred: {}".format(e))
-        return "False"
-
-    app.run(debug=debug, host=host, port=port)
+CACHE = Cache()
+
+
+class Server:
+    """Base class for HTTP server"""
+
+    def __init__(self, host="localhost", port=80, api=None, **kwargs):
+        """Run a server
+
+        :param host: hostname of the server
+        :param port: port for the running server
+        :param kwargs: optional parameters
+        :return: a running server
+        """
+        self._host = host
+        self._port = port
+        self._api = api
+        self._extra = kwargs
+
+    @property
+    def host(self):
+        return self._host
+
+    @host.setter
+    def host(self, name):
+        self._host = name
+
+    @host.deleter
+    def host(self):
+        self._host = ""
+
+    @property
+    def port(self):
+        return self._port
+
+    @port.setter
+    def port(self, number):
+        self._port = number
+
+    @port.deleter
+    def port(self):
+        self._port = 80
+
+    def run(self):
+        raise NotImplementedError()
+
+__API__ = (
+    Status, Logs, API
+ )
+
+
+class Root(Resource):
+    """
+    The root of the web service
+    """
+    __urls__ = ("/", )
+    __methods = ("get", "post", "put", "delete", "options")
+
+    def get(self):
+        tree = {"/": {"methods": ("get",),
+                      "description": "List all methods for that service."}}
+        for item in __API__:
+            tree[item.__name__] = {"urls": item.__urls__}
+            _methods = []
+            for _method in self.__methods:
+                if _method in dir(item):
+                    _methods.append(_method)
+            tree[item.__name__]["methods"] = _methods
+            tree[item.__name__]["description"] = item.__doc__.strip()
+        return {
+            "version": __version__,
+            "tree": tree
+        }
+
+
+class HTTPServer(Server):
+
+    def __init__(self, host="localhost", port=80, **kwargs):
+        super(HTTPServer, self).__init__(host=host, port=port, **kwargs)
+        self.app = Flask(__name__)
+        self.port = port
+        conf = configuration.get_configuration("components/orchestrator")
+        _hostname = conf["components/orchestrator"].get("hostname",
+                                                        "orchestrator")
+        _port = conf["components/manager"].get("port", 80)
+        _protocol = conf["components/manager"].get("protocol", "http")
+        self.orchestrator_url = "{}://{}:{}".format(
+            _protocol, _hostname, _port)
+        # Todo : specify only few urls instead of *
+        # CORS(self.app)
+        self.api = Api(self.app)
+        self.__set_route()
+        self.__hook_errors()
+
+    def __hook_errors(self):
+
+        def get_404_json(e):
+            return jsonify({"result": False, "code": 404,
+                            "description": str(e)}), 404
+        self.app.register_error_handler(404, get_404_json)
+
+        def get_400_json(e):
+            return jsonify({"result": False, "code": 400,
+                            "description": str(e)}), 400
+        self.app.register_error_handler(400, lambda e: get_400_json)
+        self.app.register_error_handler(403, exceptions.AuthException)
+
+    def __set_route(self):
+        self.api.add_resource(Root, '/')
+
+        for api in __API__:
+            self.api.add_resource(api, *api.__urls__)
+        self.api.add_resource(Wrapper, *Wrapper.__urls__,
+                              resource_class_kwargs={
+                                  "orchestrator_url": self.orchestrator_url,
+                                  "cache": CACHE,
+                              }
+                              )
+
+    def run(self):
+        self.app.run(host=self._host, port=self._port)  # nosec
+        # self.app.run(debug=True, host=self._host, port=self._port)  # nosec
+
index 51b5727..399ee15 100644 (file)
@@ -1,4 +1,3 @@
 flask
 flask_restful
-babel
 moon_utilities
\ No newline at end of file
index 740ad8e..cd06ab1 100644 (file)
@@ -7,8 +7,11 @@ from utils.policies import *
 
 parser = argparse.ArgumentParser()
 parser.add_argument('filename', help='scenario filename', nargs=1)
-parser.add_argument("--verbose", "-v", action='store_true', help="verbose mode")
+parser.add_argument("--verbose", "-v", action='store_true',
+                    help="verbose mode")
 parser.add_argument("--debug", "-d", action='store_true', help="debug mode")
+parser.add_argument("--keystone-pid", "-k", dest="keystone_pid", default="",
+                    help="Force a particular Keystone Project ID")
 args = parser.parse_args()
 
 FORMAT = '%(asctime)-15s %(levelname)s %(message)s'
@@ -202,11 +205,12 @@ def create_policy(model_id, meta_rule_list):
 def create_pdp(policy_id=None):
     logger.info("Creating PDP {}".format(scenario.pdp_name))
     projects = get_keystone_projects()
-    admin_project_id = None
-    for _project in projects['projects']:
-        if _project['name'] == "admin":
-            admin_project_id = _project['id']
-    assert admin_project_id
+    project_id = args.keystone_pid
+    if not project_id:
+        for _project in projects['projects']:
+            if _project['name'] == "admin":
+                project_id = _project['id']
+    assert project_id
     pdps = check_pdp()["pdps"]
     for pdp_id, pdp_value in pdps.items():
         if scenario.pdp_name == pdp_value["name"]:
@@ -214,7 +218,7 @@ def create_pdp(policy_id=None):
             logger.debug("Found existing PDP named {} (will add policy {})".format(scenario.pdp_name, policy_id))
             return pdp_id
     _pdp_id = add_pdp(name=scenario.pdp_name, policy_id=policy_id)
-    map_to_keystone(pdp_id=_pdp_id, keystone_project_id=admin_project_id)
+    map_to_keystone(pdp_id=_pdp_id, keystone_project_id=project_id)
     return _pdp_id
 
 if __name__ == "__main__":
index a6ad733..c21c8bc 100644 (file)
@@ -136,7 +136,9 @@ def _send(url, stress_test=False):
         return {}
     if not stress_test:
         if res.status_code == 200:
-            logger.info("\033[1m{}\033[m {}".format(url, res.status_code))
+            logger.warning("\033[1m{}\033[m \033[32mGrant\033[m".format(url))
+        elif res.status_code == 401:
+            logger.warning("\033[1m{}\033[m \033[31mDeny\033[m".format(url))
         else:
             logger.error("\033[1m{}\033[m {} {}".format(url, res.status_code, res.text))
         try:
@@ -146,11 +148,11 @@ def _send(url, stress_test=False):
             logger.error(res.text)
         else:
             if j.get("result"):
-                logger.warning("{} \033[32m{}\033[m".format(url, j.get("result")))
+                logger.warning("{} \033[32m{}\033[m".format(url, j.get("result")))
                 logger.debug("{}".format(j.get("error", "")))
                 current_request['result'] = "Grant"
             else:
-                logger.warning("{} \033[31m{}\033[m".format(url, "Deny"))
+                logger.warning("{} \033[31m{}\033[m".format(url, "Deny"))
                 logger.debug("{}".format(j))
                 current_request['result'] = "Deny"
     return current_request