diff options
author | Thomas Duval <thomas.duval@orange.com> | 2020-06-03 10:06:52 +0200 |
---|---|---|
committer | Thomas Duval <thomas.duval@orange.com> | 2020-06-03 10:06:52 +0200 |
commit | 7bb53c64da2dcf88894bfd31503accdd81498f3d (patch) | |
tree | 4310e12366818af27947b5e2c80cb162da93a4b5 /old/moon_manager/moon_manager | |
parent | cbea4e360e9bfaa9698cf7c61c83c96a1ba89b8c (diff) |
Update to new version 5.4HEADstable/jermamaster
Signed-off-by: Thomas Duval <thomas.duval@orange.com>
Change-Id: Idcd868133d75928a1ffd74d749ce98503e0555ea
Diffstat (limited to 'old/moon_manager/moon_manager')
20 files changed, 3694 insertions, 0 deletions
diff --git a/old/moon_manager/moon_manager/__init__.py b/old/moon_manager/moon_manager/__init__.py new file mode 100644 index 00000000..f0887748 --- /dev/null +++ b/old/moon_manager/moon_manager/__init__.py @@ -0,0 +1,6 @@ +# 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'. + +__version__ = "4.6.0" diff --git a/old/moon_manager/moon_manager/__main__.py b/old/moon_manager/moon_manager/__main__.py new file mode 100644 index 00000000..4fed8d10 --- /dev/null +++ b/old/moon_manager/moon_manager/__main__.py @@ -0,0 +1,4 @@ +from moon_manager.server import create_server + +server = create_server() +server.run() diff --git a/old/moon_manager/moon_manager/api/__init__.py b/old/moon_manager/moon_manager/api/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/old/moon_manager/moon_manager/api/__init__.py diff --git a/old/moon_manager/moon_manager/api/assignments.py b/old/moon_manager/moon_manager/api/assignments.py new file mode 100644 index 00000000..9bc54b2d --- /dev/null +++ b/old/moon_manager/moon_manager/api/assignments.py @@ -0,0 +1,391 @@ +# 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 + +""" +import flask +from flask import request +from flask_restful import Resource +import logging +import requests +from python_moonutilities.security_functions import check_auth +from python_moondb.core import PolicyManager +from python_moonutilities.security_functions import validate_input + +__version__ = "4.3.2" + +logger = logging.getLogger("moon.manager.api." + __name__) + + +def invalidate_data_in_slaves( + policy_id, + perimeter_id, + category_id, + data_id): + slaves = requests.get("http://{}/slaves".format(request.host)).json().get("slaves") + for slave in slaves: + if not slave.get("configured", False): + continue + try: + update = requests.put("http://{}:{}/update".format( + slave.get("wrapper_name"), slave.get("internal_port")), + data={ + "policy_id": policy_id, + "perimeter_id": perimeter_id, + "category_id": category_id, + "data_id": data_id + }, + timeout=1 + ) + logger.info("result {} {}:{} = {}".format( + update.status_code, + slave.get("wrapper_name"), + slave.get("internal_port"), + update.text)) + except requests.exceptions.ConnectionError: + logger.warning("Cannot reach {}:{}".format(slave.get("wrapper_name"), slave.get("port"))) + + +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>", + ) + + @validate_input("get", kwargs_state=[True, False, False, False, False]) + @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 (not used here) + :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 + """ + + data = PolicyManager.get_subject_assignments( + user_id=user_id, policy_id=uuid, + subject_id=perimeter_id, category_id=category_id) + + return {"subject_assignments": data} + + @validate_input("post", kwargs_state=[True, False, False, False, False], + body_state={"id": True, "category_id": True, "data_id": True}) + @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 (mandatory)", + "category_id": "UUID of the category (mandatory)" + "data_id": "UUID of the scope (mandatory)" + } + :return: { + "subject_data_id": { + "policy_id": "ID of the policy", + "subject_id": "ID of the subject (mandatory)", + "category_id": "ID of the category (mandatory)", + "assignments": "Assignments list (list of data_id)", + } + } + :internal_api: update_subject_assignment + """ + data_id = request.json.get("data_id") + category_id = request.json.get("category_id") + perimeter_id = request.json.get("id") + data = PolicyManager.add_subject_assignment( + user_id=user_id, policy_id=uuid, + subject_id=perimeter_id, category_id=category_id, + data_id=data_id) + invalidate_data_in_slaves( + policy_id=uuid, + perimeter_id=perimeter_id, + category_id=category_id, + data_id=data_id) + + return {"subject_assignments": data} + + @validate_input("delete", kwargs_state=[True, True, True, True, False]) + @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 + """ + + data = PolicyManager.delete_subject_assignment( + user_id=user_id, policy_id=uuid, + subject_id=perimeter_id, category_id=category_id, + data_id=data_id) + invalidate_data_in_slaves( + policy_id=uuid, + perimeter_id=perimeter_id, + category_id=category_id, + data_id=data_id) + + return {"result": True} + + +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>", + ) + + @validate_input("get", kwargs_state=[True, False, False, False, False]) + @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 (not used here) + :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 + """ + + data = PolicyManager.get_object_assignments( + user_id=user_id, policy_id=uuid, + object_id=perimeter_id, category_id=category_id) + + return {"object_assignments": data} + + @validate_input("post", kwargs_state=[True, False, False, False, False], + body_state={"id": True, "category_id": True, "data_id": True}) + @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 (mandatory)", + "category_id": "UUID of the category (mandatory)", + "data_id": "UUID of the scope (mandatory)" + } + :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 + """ + + data_id = request.json.get("data_id") + category_id = request.json.get("category_id") + perimeter_id = request.json.get("id") + data = PolicyManager.add_object_assignment( + user_id=user_id, policy_id=uuid, + object_id=perimeter_id, category_id=category_id, + data_id=data_id) + invalidate_data_in_slaves( + policy_id=uuid, + perimeter_id=perimeter_id, + category_id=category_id, + data_id=data_id) + + return {"object_assignments": data} + + @validate_input("delete", kwargs_state=[True, True, True, True, False]) + @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 + """ + data = PolicyManager.delete_object_assignment( + user_id=user_id, policy_id=uuid, + object_id=perimeter_id, category_id=category_id, + data_id=data_id) + invalidate_data_in_slaves( + policy_id=uuid, + perimeter_id=perimeter_id, + category_id=category_id, + data_id=data_id) + + return {"result": True} + + +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>", + ) + + @validate_input("get", kwargs_state=[True, False, False, False, False]) + @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 + """ + data = PolicyManager.get_action_assignments( + user_id=user_id, policy_id=uuid, + action_id=perimeter_id, category_id=category_id) + + return {"action_assignments": data} + + @validate_input("post", kwargs_state=[True, False, False, False, False], + body_state={"id": True, "category_id": True, "data_id": True}) + @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 (mandatory)", + "category_id": "UUID of the category (mandatory)", + "data_id": "UUID of the scope (mandatory)" + } + :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 + """ + + data_id = request.json.get("data_id") + category_id = request.json.get("category_id") + perimeter_id = request.json.get("id") + data = PolicyManager.add_action_assignment( + user_id=user_id, policy_id=uuid, + action_id=perimeter_id, category_id=category_id, + data_id=data_id) + invalidate_data_in_slaves( + policy_id=uuid, + perimeter_id=perimeter_id, + category_id=category_id, + data_id=data_id) + + return {"action_assignments": data} + + @validate_input("delete", kwargs_state=[True, True, True, True, False]) + @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 + """ + + data = PolicyManager.delete_action_assignment( + user_id=user_id, policy_id=uuid, + action_id=perimeter_id, category_id=category_id, + data_id=data_id) + invalidate_data_in_slaves( + policy_id=uuid, + perimeter_id=perimeter_id, + category_id=category_id, + data_id=data_id) + + return {"result": True} diff --git a/old/moon_manager/moon_manager/api/base_exception.py b/old/moon_manager/moon_manager/api/base_exception.py new file mode 100644 index 00000000..0a414a59 --- /dev/null +++ b/old/moon_manager/moon_manager/api/base_exception.py @@ -0,0 +1,17 @@ +class BaseException(Exception): + def __init__(self, message): + self._code = 500 + self._message = message + # Call the base class constructor with the parameters it needs + super(BaseException, self).__init__(message) + + @property + def code(self): + return self._code + + @property + def message(self): + return self._message + + def __str__(self): + return "Error " + str(self._code) + " " + self.__class__.__name__ + ': ' + self.message diff --git a/old/moon_manager/moon_manager/api/data.py b/old/moon_manager/moon_manager/api/data.py new file mode 100644 index 00000000..92d7b2c6 --- /dev/null +++ b/old/moon_manager/moon_manager/api/data.py @@ -0,0 +1,311 @@ +# 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 +import logging +from python_moonutilities.security_functions import check_auth +from python_moondb.core import PolicyManager +from python_moonutilities.security_functions import validate_input + +__version__ = "4.3.2" + +logger = logging.getLogger("moon.manager.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>", + ) + + @validate_input("get", kwargs_state=[True, False, False, False]) + @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 data_id 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 (optional)" + } + } + }] + :internal_api: get_subject_data + """ + logger.info("api.get {} {} {}".format(uuid, category_id, data_id)) + data = PolicyManager.get_subject_data(user_id=user_id, + policy_id=uuid, + category_id=category_id, + data_id=data_id) + logger.info("api.get data = {}".format(data)) + + return {"subject_data": data} + + @validate_input("post", kwargs_state=[True, True, False, False], body_state={"name": True}) + @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 (not used here) + :param user_id: user ID who do the request + :request body: { + "name": "name of the data (mandatory)", + "description": "description of the data (optional)" + } + :return: { + "policy_id": "policy_id1", + "category_id": "category_id1", + "data": { + "subject_data_id": { + "name": "name of the data (mandatory)", + "description": "description of the data (optional)" + } + } + } + :internal_api: add_subject_data + """ + data = PolicyManager.set_subject_data(user_id=user_id, + policy_id=uuid, + category_id=category_id, + value=request.json) + + return {"subject_data": data} + + @validate_input("delete", kwargs_state=[True, False, False, False]) + @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 (optional)" + }] + :internal_api: delete_subject_data + """ + logger.info("api.delete {} {}".format(uuid, data_id)) + data = PolicyManager.delete_subject_data(user_id=user_id, + policy_id=uuid, + category_id=category_id, + data_id=data_id) + + return {"result": True} + + +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>", + ) + + @validate_input("get", kwargs_state=[True, False, False, False]) + @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 (optional)" + } + } + }] + :internal_api: get_object_data + """ + data = PolicyManager.get_object_data(user_id=user_id, + policy_id=uuid, + category_id=category_id, + data_id=data_id) + + return {"object_data": data} + + @validate_input("post", kwargs_state=[True, True, False, False], body_state={"name": True}) + @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 (not used here) + :param user_id: user ID who do the request + :request body: { + "name": "name of the data (mandatory)", + "description": "description of the data (optional)" + } + :return: { + "policy_id": "policy_id1", + "category_id": "category_id1", + "data": { + "object_data_id": { + "name": "name of the data", + "description": "description of the data (optional)" + } + } + } + :internal_api: add_object_data + """ + data = PolicyManager.add_object_data(user_id=user_id, + policy_id=uuid, + category_id=category_id, + value=request.json) + + return {"object_data": data} + + @validate_input("delete", kwargs_state=[True, False, False, False]) + @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 (optional)" + } + :internal_api: delete_object_data + """ + data = PolicyManager.delete_object_data(user_id=user_id, + policy_id=uuid, + category_id=category_id, + data_id=data_id) + + return {"result": True} + + +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>", + ) + + @validate_input("get", kwargs_state=[True, False, False, False]) + @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 (optional)" + } + } + }] + :internal_api: get_action_data + """ + data = PolicyManager.get_action_data(user_id=user_id, + policy_id=uuid, + category_id=category_id, + data_id=data_id) + + return {"action_data": data} + + @validate_input("post", kwargs_state=[True, True, False, False], body_state={"name": True}) + @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 (mandatory)", + "description": "description of the data (optional)" + } + :return: { + "policy_id": "policy_id1", + "category_id": "category_id1", + "data": { + "action_data_id": { + "name": "name of the data", + "description": "description of the data (optional)" + } + } + } + :internal_api: add_action_data + """ + data = PolicyManager.add_action_data(user_id=user_id, + policy_id=uuid, + category_id=category_id, + value=request.json) + return {"action_data": data} + + @validate_input("delete", kwargs_state=[True, False, False, False]) + @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 (optional)" + } + :internal_api: delete_action_data + """ + data = PolicyManager.delete_action_data(user_id=user_id, + policy_id=uuid, + category_id=category_id, + data_id=data_id) + + return {"result": True} diff --git a/old/moon_manager/moon_manager/api/generic.py b/old/moon_manager/moon_manager/api/generic.py new file mode 100644 index 00000000..721f6213 --- /dev/null +++ b/old/moon_manager/moon_manager/api/generic.py @@ -0,0 +1,144 @@ +# 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 +import logging +import moon_manager.api +from python_moonutilities.security_functions import check_auth + +__version__ = "4.3.2" + +logger = logging.getLogger("moon.manager.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" + } + } + """ + raise NotImplemented + + +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 + + raise NotImplemented + + +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_manager.api)) + api_desc = dict() + for api_name in api_list: + api_desc[api_name] = {} + group_api_obj = eval("moon_manager.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_manager.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_manager.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: + logger.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 diff --git a/old/moon_manager/moon_manager/api/json_export.py b/old/moon_manager/moon_manager/api/json_export.py new file mode 100644 index 00000000..069e5884 --- /dev/null +++ b/old/moon_manager/moon_manager/api/json_export.py @@ -0,0 +1,279 @@ +# Copyright 2018 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 +from flask_restful import Resource +from python_moonutilities.security_functions import check_auth +from python_moondb.core import PDPManager +from python_moondb.core import PolicyManager +from python_moondb.core import ModelManager +from moon_manager.api.json_utils import JsonUtils, BaseException + +__version__ = "4.5.0" + +logger = logging.getLogger("moon.manager.api." + __name__) + + +class JsonExport(Resource): + __urls__ = ( + "/export", + "/export/", + ) + + def _export_rules(self, json_content): + policies = PolicyManager.get_policies(self._user_id) + rules_array = [] + + for policy_key in policies: + rules = PolicyManager.get_rules(self._user_id, policy_key) + rules = rules["rules"] + # logger.info(rules) + for rule in rules: + rule_dict = dict() + JsonUtils.copy_field_if_exists(rule, rule_dict, "instructions", dict) + JsonUtils.copy_field_if_exists(rule, rule_dict, "enabled", True) + JsonUtils.convert_id_to_name(rule["meta_rule_id"], rule_dict, "meta_rule", + "meta_rule", ModelManager, self._user_id) + JsonUtils.convert_id_to_name(policy_key, rule_dict, "policy", "policy", + PolicyManager, self._user_id) + ids = rule["rule"] + rule_description = dict() + meta_rule = ModelManager.get_meta_rules(self._user_id, rule["meta_rule_id"]) + meta_rule = [v for v in meta_rule.values()] + meta_rule = meta_rule[0] + index_subject_data = len(meta_rule["subject_categories"]) - 1 + index_object_data = len(meta_rule["subject_categories"]) + len( + meta_rule["object_categories"]) - 1 + index_action_data = len(meta_rule["subject_categories"]) + len( + meta_rule["object_categories"]) + len(meta_rule["action_categories"]) - 1 + ids_subject_data = [ids[0]] if len(meta_rule["subject_categories"]) == 1 else ids[ + 0:index_subject_data] + ids_object_data = [ids[index_object_data]] if len( + meta_rule["object_categories"]) == 1 else ids[ + index_subject_data + 1:index_object_data] + ids_action_date = [ids[index_action_data]] if len( + meta_rule["action_categories"]) == 1 else ids[ + index_object_data + 1:index_action_data] + JsonUtils.convert_ids_to_names(ids_subject_data, rule_description, "subject_data", + "subject_data", PolicyManager, self._user_id, + policy_key) + JsonUtils.convert_ids_to_names(ids_object_data, rule_description, "object_data", + "object_data", PolicyManager, self._user_id, + policy_key) + JsonUtils.convert_ids_to_names(ids_action_date, rule_description, "action_data", + "action_data", PolicyManager, self._user_id, + policy_key) + rule_dict["rule"] = rule_description + rules_array.append(rule_dict) + + if len(rules_array) > 0: + json_content['rules'] = rules_array + + def _export_meta_rules(self, json_content): + meta_rules = ModelManager.get_meta_rules(self._user_id) + meta_rules_array = [] + # logger.info(meta_rules) + for meta_rule_key in meta_rules: + # logger.info(meta_rules[meta_rule_key]) + meta_rule_dict = dict() + JsonUtils.copy_field_if_exists(meta_rules[meta_rule_key], meta_rule_dict, "name", str) + JsonUtils.copy_field_if_exists(meta_rules[meta_rule_key], meta_rule_dict, "description", + str) + JsonUtils.convert_ids_to_names(meta_rules[meta_rule_key]["subject_categories"], + meta_rule_dict, "subject_categories", "subject_category", + ModelManager, self._user_id) + JsonUtils.convert_ids_to_names(meta_rules[meta_rule_key]["object_categories"], + meta_rule_dict, "object_categories", "object_category", + ModelManager, self._user_id) + JsonUtils.convert_ids_to_names(meta_rules[meta_rule_key]["action_categories"], + meta_rule_dict, "action_categories", "action_category", + ModelManager, self._user_id) + logger.info("Exporting meta rule {}".format(meta_rule_dict)) + meta_rules_array.append(meta_rule_dict) + if len(meta_rules_array) > 0: + json_content['meta_rules'] = meta_rules_array + + def _export_subject_object_action_assignments(self, type_element, json_content): + export_method_data = getattr(PolicyManager, 'get_' + type_element + '_assignments') + policies = PolicyManager.get_policies(self._user_id) + element_assignments_array = [] + for policy_key in policies: + assignments = export_method_data(self._user_id, policy_key) + # logger.info(assignments) + for assignment_key in assignments: + assignment_dict = dict() + JsonUtils.convert_id_to_name(assignments[assignment_key][type_element + "_id"], + assignment_dict, type_element, type_element, + PolicyManager, self._user_id, policy_key) + JsonUtils.convert_id_to_name(assignments[assignment_key]["category_id"], + assignment_dict, "category", + type_element + "_category", ModelManager, + self._user_id, policy_key) + JsonUtils.convert_ids_to_names(assignments[assignment_key]["assignments"], + assignment_dict, "assignments", + type_element + "_data", PolicyManager, self._user_id, + policy_key) + element_assignments_array.append(assignment_dict) + logger.info("Exporting {}Â assignment {}".format(type_element, assignment_dict)) + if len(element_assignments_array) > 0: + json_content[type_element + '_assignments'] = element_assignments_array + + def _export_subject_object_action_datas(self, type_element, json_content): + export_method_data = getattr(PolicyManager, 'get_' + type_element + '_data') + policies = PolicyManager.get_policies(self._user_id) + element_datas_array = [] + for policy_key in policies: + datas = export_method_data(self._user_id, policy_key) + # logger.info("data found : {}".format(datas)) + for data_group in datas: + policy_id = data_group["policy_id"] + category_id = data_group["category_id"] + # logger.info(data_group["data"]) + for data_key in data_group["data"]: + data_dict = dict() + if type_element == 'subject': + JsonUtils.copy_field_if_exists(data_group["data"][data_key], data_dict, + "name", str) + JsonUtils.copy_field_if_exists(data_group["data"][data_key], data_dict, + "description", str) + else: + JsonUtils.copy_field_if_exists(data_group["data"][data_key], data_dict, + "name", str) + JsonUtils.copy_field_if_exists(data_group["data"][data_key], data_dict, + "description", str) + + JsonUtils.convert_id_to_name(policy_id, data_dict, "policy", "policy", + PolicyManager, self._user_id) + JsonUtils.convert_id_to_name(category_id, data_dict, "category", + type_element + "_category", ModelManager, + self._user_id, policy_key) + logger.info("Exporting {}Â data {}".format(type_element, data_dict)) + element_datas_array.append(data_dict) + + if len(element_datas_array) > 0: + json_content[type_element + '_data'] = element_datas_array + + def _export_subject_object_action_categories(self, type_element, json_content): + export_method = getattr(ModelManager, 'get_' + type_element + '_categories') + element_categories = export_method(self._user_id) + element_categories_array = [] + for element_category_key in element_categories: + element_category = dict() + JsonUtils.copy_field_if_exists(element_categories[element_category_key], + element_category, "name", str) + JsonUtils.copy_field_if_exists(element_categories[element_category_key], + element_category, "description", str) + element_categories_array.append(element_category) + logger.info("Exporting {}Â category {}".format(type_element, element_category)) + if len(element_categories_array) > 0: + json_content[type_element + '_categories'] = element_categories_array + + def _export_subject_object_action(self, type_element, json_content): + export_method = getattr(PolicyManager, 'get_' + type_element + 's') + policies = PolicyManager.get_policies(self._user_id) + element_dict = dict() + elements_array = [] + for policy_key in policies: + elements = export_method(self._user_id, policy_key) + for element_key in elements: + # logger.info("Exporting {}".format(elements[element_key])) + element = dict() + JsonUtils.copy_field_if_exists(elements[element_key], element, "name", str) + JsonUtils.copy_field_if_exists(elements[element_key], element, "description", str) + JsonUtils.copy_field_if_exists(elements[element_key], element, "extra", dict) + if element["name"] not in element_dict: + element["policies"] = [] + element_dict[element["name"]] = element + current_element = element_dict[element["name"]] + current_element["policies"].append({"name": JsonUtils.convert_id_to_name_string( + policy_key, "policy", PolicyManager, self._user_id)}) + + for key in element_dict: + logger.info("Exporting {}Â {}".format(type_element, element_dict[key])) + elements_array.append(element_dict[key]) + + if len(elements_array) > 0: + json_content[type_element + 's'] = elements_array + + def _export_policies(self, json_content): + policies = PolicyManager.get_policies(self._user_id) + policies_array = [] + for policy_key in policies: + policy = dict() + JsonUtils.copy_field_if_exists(policies[policy_key], policy, "name", str) + JsonUtils.copy_field_if_exists(policies[policy_key], policy, "genre", str) + JsonUtils.copy_field_if_exists(policies[policy_key], policy, "description", str) + JsonUtils.convert_id_to_name(policies[policy_key]["model_id"], policy, "model", "model", + ModelManager, self._user_id) + logger.info("Exporting policy {}".format(policy)) + policies_array.append(policy) + if len(policies_array) > 0: + json_content["policies"] = policies_array + + def _export_models(self, json_content): + models = ModelManager.get_models(self._user_id) + models_array = [] + for model_key in models: + model = dict() + JsonUtils.copy_field_if_exists(models[model_key], model, "name", str) + JsonUtils.copy_field_if_exists(models[model_key], model, "description", str) + # logger.info(models[model_key]["meta_rules"]) + JsonUtils.convert_ids_to_names(models[model_key]["meta_rules"], model, "meta_rules", + "meta_rule", ModelManager, self._user_id) + logger.info("Exporting model {}".format(model)) + models_array.append(model) + if len(models_array) > 0: + json_content["models"] = models_array + + def _export_pdps(self, json_content): + pdps = PDPManager.get_pdp(self._user_id) + pdps_array = [] + for pdp_key in pdps: + logger.info("Exporting pdp {}".format(pdps[pdp_key])) + pdps_array.append(pdps[pdp_key]) + if len(pdps_array) > 0: + json_content["pdps"] = pdps_array + + def _export_json(self, user_id): + self._user_id = user_id + json_content = dict() + + logger.info("Exporting pdps...") + self._export_pdps(json_content) + logger.info("Exporting policies...") + self._export_policies(json_content) + logger.info("Exporting models...") + self._export_models(json_content) + # export subjects, subject_data, subject_categories, subject_assignements idem for object and action + list_element = [{"key": "subject"}, {"key": "object"}, {"key": "action"}] + for elt in list_element: + logger.info("Exporting {}s...".format(elt["key"])) + self._export_subject_object_action(elt["key"], json_content) + logger.info("Exporting {} categories...".format(elt["key"])) + self._export_subject_object_action_categories(elt["key"], json_content) + logger.info("Exporting {} data...".format(elt["key"])) + self._export_subject_object_action_datas(elt["key"], json_content) + logger.info("Exporting {} assignments...".format(elt["key"])) + self._export_subject_object_action_assignments(elt["key"], json_content) + logger.info("Exporting meta rules...") + self._export_meta_rules(json_content) + logger.info("Exporting rules...") + self._export_rules(json_content) + + return json_content + + @check_auth + def get(self, user_id=None): + """Import file. + + :param user_id: user ID who do the request + :return: { + + } + :internal_api: + """ + json_file = self._export_json(user_id) + logger.info(json_file) + return {"content": json_file} diff --git a/old/moon_manager/moon_manager/api/json_import.py b/old/moon_manager/moon_manager/api/json_import.py new file mode 100644 index 00000000..05f4a0c0 --- /dev/null +++ b/old/moon_manager/moon_manager/api/json_import.py @@ -0,0 +1,584 @@ +# 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 request +from flask_restful import Resource +import flask_restful +from flask import abort + +from python_moonutilities.security_functions import check_auth +from python_moonutilities import exceptions +import logging +import json + +from moon_manager.api.base_exception import BaseException +from moon_manager.api.json_utils import JsonUtils, UnknownName +from python_moondb.core import PDPManager +from python_moondb.core import PolicyManager +from python_moondb.core import ModelManager + +__version__ = "4.5.0" + +logger = logging.getLogger("moon.manager.api." + __name__) + +INST_CALLBACK = 0 +DATA_CALLBACK = 1 +ASSIGNMENT_CALLBACK = 2 +CATEGORIES_CALLBACK = 3 + + +class ForbiddenOverride(BaseException): + def __init__(self, message): + # Call the base class constructor with the parameters it needs + super(ForbiddenOverride, self).__init__(message) + + +class UnknownPolicy(BaseException): + def __init__(self, message): + # Call the base class constructor with the parameters it needs + super(UnknownPolicy, self).__init__(message) + + +class UnknownModel(BaseException): + def __init__(self, message): + # Call the base class constructor with the parameters it needs + super(UnknownModel, self).__init__(message) + + +class UnknownData(BaseException): + def __init__(self, message): + # Call the base class constructor with the parameters it needs + super(UnknownData, self).__init__(message) + + +class MissingPolicy(BaseException): + def __init__(self, message): + # Call the base class constructor with the parameters it needs + super(MissingPolicy, self).__init__(message) + + +class InvalidJson(BaseException): + def __init__(self, message): + # Call the base class constructor with the parameters it needs + super(InvalidJson, self).__init__(message) + + +class JsonImport(Resource): + __urls__ = ( + "/import", + "/import/", + ) + + def _reorder_rules_ids(self, rule, ordered_perimeter_categories_ids, json_data_ids, policy_id, + get_function): + ordered_json_ids = [None] * len(ordered_perimeter_categories_ids) + for json_id in json_data_ids: + data = get_function(self._user_id, policy_id, data_id=json_id) + data = data[0] + if data["category_id"] not in ordered_perimeter_categories_ids: + raise InvalidJson( + "The category id {} of the rule {} does not match the meta rule".format( + data["category_id"], rule)) + if ordered_json_ids[ + ordered_perimeter_categories_ids.index(data["category_id"])] is not None: + raise InvalidJson( + "The category id {} of the rule {} shall not be used twice in the same rule".format( + data["category_id"], rule)) + ordered_json_ids[ordered_perimeter_categories_ids.index(data["category_id"])] = json_id + logger.info(ordered_json_ids) + return ordered_json_ids + + def _import_rules(self, json_rules): + if not isinstance(json_rules, list): + raise InvalidJson("rules shall be a list!") + + for json_rule in json_rules: + json_to_use = dict() + JsonUtils.copy_field_if_exists(json_rule, json_to_use, "instructions", str) + JsonUtils.copy_field_if_exists(json_rule, json_to_use, "enabled", bool, + default_value=True) + + json_ids = dict() + JsonUtils.convert_name_to_id(json_rule, json_ids, "policy", "policy_id", "policy", + PolicyManager, self._user_id) + JsonUtils.convert_name_to_id(json_rule, json_to_use, "meta_rule", "meta_rule_id", + "meta_rule", ModelManager, self._user_id) + json_subject_ids = dict() + json_object_ids = dict() + json_action_ids = dict() + JsonUtils.convert_names_to_ids(json_rule["rule"], json_subject_ids, "subject_data", + "subject", "subject_data", PolicyManager, self._user_id, + json_ids["policy_id"]) + JsonUtils.convert_names_to_ids(json_rule["rule"], json_object_ids, "object_data", + "object", "object_data", PolicyManager, self._user_id, + json_ids["policy_id"]) + JsonUtils.convert_names_to_ids(json_rule["rule"], json_action_ids, "action_data", + "action", "action_data", PolicyManager, self._user_id, + json_ids["policy_id"]) + + meta_rule = ModelManager.get_meta_rules(self._user_id, json_to_use["meta_rule_id"]) + meta_rule = [v for v in meta_rule.values()] + meta_rule = meta_rule[0] + + json_to_use_rule = self._reorder_rules_ids(json_rule, meta_rule["subject_categories"], + json_subject_ids["subject"], + json_ids["policy_id"], + PolicyManager.get_subject_data) + json_to_use_rule = json_to_use_rule + self._reorder_rules_ids(json_rule, meta_rule[ + "object_categories"], json_object_ids["object"], json_ids["policy_id"], + PolicyManager.get_object_data) + json_to_use_rule = json_to_use_rule + self._reorder_rules_ids(json_rule, meta_rule[ + "action_categories"], json_action_ids["action"], json_ids["policy_id"], + PolicyManager.get_action_data) + json_to_use["rule"] = json_to_use_rule + try: + logger.debug("Adding / updating a rule from json {}".format(json_to_use)) + PolicyManager.add_rule(self._user_id, json_ids["policy_id"], + json_to_use["meta_rule_id"], json_to_use) + except exceptions.RuleExisting: + pass + except exceptions.PolicyUnknown: + raise UnknownPolicy("Unknown policy with id {}".format(json_ids["policy_id"])) + + def _import_meta_rules(self, json_meta_rules): + logger.info("Input meta rules : {}".format(json_meta_rules)) + for json_meta_rule in json_meta_rules: + json_to_use = dict() + JsonUtils.copy_field_if_exists(json_meta_rule, json_to_use, "name", str) + JsonUtils.copy_field_if_exists(json_meta_rule, json_to_use, "description", str) + JsonUtils.convert_names_to_ids(json_meta_rule, json_to_use, "subject_categories", + "subject_categories", "subject_category", ModelManager, + self._user_id) + JsonUtils.convert_names_to_ids(json_meta_rule, json_to_use, "object_categories", + "object_categories", "object_category", ModelManager, + self._user_id) + JsonUtils.convert_names_to_ids(json_meta_rule, json_to_use, "action_categories", + "action_categories", "action_category", ModelManager, + self._user_id) + logger.debug("Adding / updating a metarule from json {}".format(json_meta_rule)) + meta_rule = ModelManager.add_meta_rule(self._user_id, meta_rule_id=None, + value=json_to_use) + logger.debug("Added / updated meta rule : {}".format(meta_rule)) + + def _import_subject_object_action_assignments(self, json_item_assignments, type_element): + import_method = getattr(PolicyManager, 'add_' + type_element + '_assignment') + get_method = getattr(PolicyManager, 'get_' + type_element + '_data') + + if not isinstance(json_item_assignments, list): + raise InvalidJson(type_element + " assignments shall be a list!") + + # get the policy id related to the user + policies = PolicyManager.get_policies(self._user_id) + + for json_item_assignment in json_item_assignments: + item_override = JsonUtils.get_override(json_item_assignment) + if item_override is True: + raise ForbiddenOverride( + "{} assignments do not support override flag !".format(type_element)) + + json_assignment = dict() + JsonUtils.convert_name_to_id(json_item_assignment, json_assignment, "category", + "category_id", type_element + "_category", ModelManager, + self._user_id) + + has_found_data = False + # loop over policies + for policy_id in policies: + json_data = dict() + try: + JsonUtils.convert_name_to_id(json_item_assignment, json_assignment, + type_element, "id", type_element, PolicyManager, + self._user_id, policy_id) + JsonUtils.convert_names_to_ids(json_item_assignment, json_data, "assignments", + "data_id", type_element + "_data", PolicyManager, + self._user_id, policy_id, + json_assignment["category_id"]) + has_found_data = True + except UnknownName: + # the category or data has not been found in this policy : we look into the next one + continue + for data_id in json_data["data_id"]: + # find the policy related to the current data + data = get_method(self._user_id, policy_id, data_id, + json_assignment["category_id"]) + if data is not None and len(data) == 1: + logger.debug( + "Adding / updating a {} assignment from json {}".format(type_element, + json_assignment)) + import_method(self._user_id, policy_id, json_assignment["id"], + json_assignment["category_id"], + data_id) + else: + raise UnknownData("Unknown data with id {}".format(data_id)) + + # case the data has not been found in any policies + if has_found_data is False: + raise InvalidJson("The json contains unknown {} data or category : {}".format( + type_element, + json_item_assignment)) + + def _import_subject_object_action_datas(self, json_items_data, mandatory_policy_ids, + type_element): + if type_element == "subject": + import_method = getattr(PolicyManager, 'set_' + type_element + '_data') + else: + import_method = getattr(PolicyManager, 'add_' + type_element + '_data') + # get_method = getattr(PolicyManager, 'get_' + type_element + '_data') + + if not isinstance(json_items_data, list): + raise InvalidJson(type_element + " data shall be a list!") + + for json_item_data in json_items_data: + item_override = JsonUtils.get_override(json_items_data) + if item_override is True: + raise ForbiddenOverride( + "{} datas do not support override flag !".format(type_element)) + json_to_use = dict() + JsonUtils.copy_field_if_exists(json_item_data, json_to_use, "name", str) + JsonUtils.copy_field_if_exists(json_item_data, json_to_use, "description", str) + json_policy = dict() + # field_mandatory : not mandatory if there is some mandatory policies + JsonUtils.convert_names_to_ids(json_item_data, json_policy, "policies", "policy_id", + "policy", + PolicyManager, self._user_id, + field_mandatory=len(mandatory_policy_ids) == 0) + json_category = dict() + JsonUtils.convert_name_to_id(json_item_data, json_category, "category", "category_id", + type_element + "_category", + ModelManager, self._user_id) + policy_ids = [] + if "policy_id" in json_policy: + policy_ids = json_policy["policy_id"] + + for policy_id in policy_ids: + if policy_id is not None and policy_id not in mandatory_policy_ids: + mandatory_policy_ids.append(policy_id) + + if len(mandatory_policy_ids) == 0: + raise InvalidJson("Invalid data, the policy shall be set when importing {}".format( + json_item_data)) + category_id = None + if "category_id" in json_category: + category_id = json_category["category_id"] + if category_id is None: + raise InvalidJson( + "Invalid data, the category shall be set when importing {}".format( + json_item_data)) + + for policy_id in mandatory_policy_ids: + try: + data = import_method(self._user_id, policy_id, category_id=category_id, + value=json_to_use) + except exceptions.PolicyUnknown: + raise UnknownPolicy("Unknown policy with id {}".format(policy_id)) + except Exception as e: + logger.exception(str(e)) + raise e + + def _import_subject_object_action_categories(self, json_item_categories, type_element): + import_method = getattr(ModelManager, 'add_' + type_element + '_category') + get_method = getattr(ModelManager, 'get_' + type_element + '_categories') + + categories = get_method(self._user_id) + + if not isinstance(json_item_categories, list): + raise InvalidJson(type_element + " categories shall be a list!") + + for json_item_category in json_item_categories: + json_to_use = dict() + JsonUtils.copy_field_if_exists(json_item_category, json_to_use, "name", str) + + # check if category with the same name exists : do this in moondb ? + existing_id = None + for category_key in categories: + if categories[category_key]["name"] == json_to_use["name"]: + existing_id = category_key + + JsonUtils.copy_field_if_exists(json_item_category, json_to_use, "description", str) + item_override = JsonUtils.get_override(json_item_category) + if item_override is True: + raise ForbiddenOverride( + "{} categories do not support override flag !".format(type_element)) + + try: + category = import_method(self._user_id, existing_id, json_to_use) + except (exceptions.SubjectCategoryExisting, exceptions.ObjectCategoryExisting, + exceptions.ActionCategoryExisting): + # it already exists: do nothing + logger.warning("Ignored {} category with name {} is already in the database".format( + type_element, json_to_use["name"])) + except Exception as e: + logger.warning("Error while importing the category : {}".format(str(e))) + logger.exception(str(e)) + raise e + + def _import_subject_object_action(self, json_items, mandatory_policy_ids, type_element): + import_method = getattr(PolicyManager, 'add_' + type_element) + get_method = getattr(PolicyManager, 'get_' + type_element + 's') + + if not isinstance(json_items, list): + raise InvalidJson(type_element + " items shall be a list!") + + for json_item in json_items: + json_without_policy_name = dict() + JsonUtils.copy_field_if_exists(json_item, json_without_policy_name, "name", str) + JsonUtils.copy_field_if_exists(json_item, json_without_policy_name, "description", str) + JsonUtils.copy_field_if_exists(json_item, json_without_policy_name, "extra", dict) + JsonUtils.convert_names_to_ids(json_item, json_without_policy_name, "policies", + "policy_list", "policy", PolicyManager, self._user_id, + field_mandatory=False) + policy_ids = json_without_policy_name["policy_list"] + for mandatory_policy_id in mandatory_policy_ids: + if mandatory_policy_id not in policy_ids: + policy_ids.append(mandatory_policy_id) + # policy_ids and json_without_policy_name are references to the same array... + # json_without_policy_name["policy_list"].append(mandatory_policy_id) + + item_override = JsonUtils.get_override(json_item) + if item_override is True: + raise ForbiddenOverride("{} does not support override flag !".format(type_element)) + + if len(policy_ids) == 0: + raise MissingPolicy( + "a {} needs at least one policy to be created or updated : {}".format( + type_element, json.dumps(json_item))) + + for policy_id in policy_ids: + try: + items_in_db = get_method(self._user_id, policy_id) + key = None + for key_in_db in items_in_db: + if items_in_db[key_in_db]["name"] == json_without_policy_name["name"]: + key = key_in_db + break + element = import_method(self._user_id, policy_id, perimeter_id=key, + value=json_without_policy_name) + logger.debug("Added / updated {} : {}".format(type_element, element)) + + except exceptions.PolicyUnknown: + raise UnknownPolicy("Unknown policy when adding a {}!".format(type_element)) + except Exception as e: + logger.exception(str(e)) + raise BaseException(str(e)) + + def _import_policies(self, json_policies): + policy_mandatory_ids = [] + + if not isinstance(json_policies, list): + raise InvalidJson("policies shall be a list!") + + for json_policy in json_policies: + # TODO put this in moondb + # policy_in_db = PolicyManager.get_policies_by_name(json_without_model_name["name"]) + policies = PolicyManager.get_policies(self._user_id) + policy_in_db = None + policy_id = None + for policy_key in policies: + if policies[policy_key]["name"] == json_policy["name"]: + policy_in_db = policies[policy_key] + policy_id = policy_key + # end TODO + if policy_in_db is None: + policy_does_exist = False + else: + policy_does_exist = True + + policy_override = JsonUtils.get_override(json_policy) + policy_mandatory = JsonUtils.get_mandatory(json_policy) + + if policy_override is False and policy_does_exist: + if policy_id: + policy_mandatory_ids.append(policy_id) + logger.warning( + "Existing policy not updated because of the override option is not set !") + continue + + json_without_model_name = dict() + JsonUtils.copy_field_if_exists(json_policy, json_without_model_name, "name", str) + JsonUtils.copy_field_if_exists(json_policy, json_without_model_name, "description", str) + JsonUtils.copy_field_if_exists(json_policy, json_without_model_name, "genre", str) + JsonUtils.convert_name_to_id(json_policy, json_without_model_name, "model", "model_id", + "model", ModelManager, self._user_id, + field_mandatory=False) + + if not policy_does_exist: + logger.debug("Creating policy {} ".format(json_without_model_name)) + added_policy = PolicyManager.add_policy(self._user_id, None, + json_without_model_name) + if policy_mandatory is True: + keys = list(added_policy.keys()) + policy_mandatory_ids.append(keys[0]) + elif policy_override is True: + logger.debug("Updating policy {} ".format(json_without_model_name)) + updated_policy = PolicyManager.update_policy(self._user_id, policy_id, + json_without_model_name) + if policy_mandatory is True: + policy_mandatory_ids.append(policy_id) + return policy_mandatory_ids + + def _import_models_with_new_meta_rules(self, json_models): + if not isinstance(json_models, list): + raise InvalidJson("models shall be a list!") + + for json_model in json_models: + logger.debug("json_model {}".format(json_model)) + models = ModelManager.get_models(self._user_id) + model_in_db = None + model_id = None + for model_key in models: + if ("id" in json_model and model_key == json_model["id"]) or ( + "name" in json_model and models[model_key]["name"] == json_model["name"]): + model_in_db = models[model_key] + model_id = model_key + + # this should not occur as the model has been put in db previously in _import_models_without_new_meta_rules + if model_in_db is None: + raise UnknownModel("Unknown model ") + + json_key = dict() + JsonUtils.convert_names_to_ids(json_model, json_key, "meta_rules", "meta_rule_id", + "meta_rule", ModelManager, self._user_id) + for meta_rule_id in json_key["meta_rule_id"]: + if meta_rule_id not in model_in_db["meta_rules"]: + model_in_db["meta_rules"].append(meta_rule_id) + + ModelManager.update_model(self._user_id, model_id, model_in_db) + + def _import_models_without_new_meta_rules(self, json_models): + if not isinstance(json_models, list): + raise InvalidJson("models shall be a list!") + + for json_model in json_models: + json_without_new_metarules = dict() + JsonUtils.copy_field_if_exists(json_model, json_without_new_metarules, "name", str) + + # TODO put this in moondb + # model_in_db = ModelManager.get_models_by_name(json_without_new_metarules["name"]) + models = ModelManager.get_models(self._user_id) + model_in_db = None + for model_key in models: + if models[model_key]["name"] == json_without_new_metarules["name"]: + model_in_db = models[model_key] + model_id = model_key + # end TODO + + JsonUtils.copy_field_if_exists(json_model, json_without_new_metarules, "description", + str) + if model_in_db is None: + model_does_exist = False + else: + json_without_new_metarules["meta_rules"] = model_in_db["meta_rules"] + model_does_exist = True + model_override = JsonUtils.get_override(json_model) + if not model_does_exist: + logger.debug("Creating model {} ".format(json_without_new_metarules)) + ModelManager.add_model(self._user_id, None, json_without_new_metarules) + elif model_override is True: + logger.debug( + "Updating model with id {} : {} ".format(model_id, json_without_new_metarules)) + ModelManager.update_model(self._user_id, model_id, json_without_new_metarules) + + def _import_pdps(self, json_pdps): + if not isinstance(json_pdps, list): + raise InvalidJson("pdps shall be a list!") + + for json_pdp in json_pdps: + json_to_use = dict() + JsonUtils.copy_field_if_exists(json_pdp, json_to_use, "name", str) + JsonUtils.copy_field_if_exists(json_pdp, json_to_use, "keystone_project_id", str) + JsonUtils.copy_field_if_exists(json_pdp, json_to_use, "security_pipeline", list) + JsonUtils.copy_field_if_exists(json_pdp, json_to_use, "description", str) + + pdps = PDPManager.get_pdp(self._user_id) + exists = False + for pdp_key in pdps: + if pdps[pdp_key]["name"] == json_to_use["name"]: + PDPManager.update_pdp(self._user_id, pdp_id=pdp_key, value=json_to_use) + exists = True + if exists is False: + PDPManager.add_pdp(self._user_id, value=json_to_use) + + def _import_json(self, user_id): + self._user_id = user_id + if 'file' in request.files: + file = request.files['file'] + logger.debug("Importing {} file...".format(file)) + json_content = json.load(file) + else: + json_content = request.json + logger.debug("Importing content: {} ...".format(json_content)) + + # first import the models without the meta rules as they are not yet defined + if "models" in json_content: + logger.info("Importing models...") + self._import_models_without_new_meta_rules(json_content["models"]) + + # import the policies that depends on the models + mandatory_policy_ids = [] + if "policies" in json_content: + logger.info("Importing policies...") + mandatory_policy_ids = self._import_policies(json_content["policies"]) + + # import subjects, subject_data, subject_categories, idem for object and action + list_element = [{"key": "subject"}, {"key": "object"}, {"key": "action"}] + for elt in list_element: + in_key = elt["key"] + key = in_key + "s" + if key in json_content: + logger.info("Importing {}...".format(key)) + self._import_subject_object_action(json_content[key], mandatory_policy_ids, in_key) + key = in_key + "_categories" + if key in json_content: + logger.info("Importing {}...".format(key)) + self._import_subject_object_action_categories(json_content[key], in_key) + + # import meta rules + if "meta_rules" in json_content: + logger.info("Importing meta rules...") + self._import_meta_rules(json_content["meta_rules"]) + + # add the metarule to model + if "models" in json_content: + logger.info("Updating models with meta rules...") + self._import_models_with_new_meta_rules(json_content["models"]) + + for elt in list_element: + in_key = elt["key"] + key = in_key + "_data" + if key in json_content: + logger.info("Importing {}...".format(key)) + self._import_subject_object_action_datas(json_content[key], mandatory_policy_ids, + in_key) + + # import subjects assignments, idem for object and action + for elt in list_element: + in_key = elt["key"] + key = in_key + "_assignments" + if key in json_content: + logger.info("Importing {}...".format(key)) + self._import_subject_object_action_assignments(json_content[key], in_key) + + # import rules + if "rules" in json_content: + logger.info("Importing rules...") + self._import_rules(json_content["rules"]) + + # import pdps + if "pdps" in json_content: + logger.info("Importing pdps...") + self._import_pdps(json_content["pdps"]) + + @check_auth + def post(self, user_id=None): + """Import file. + + :param user_id: user ID who do the request + :return: { + + } + :internal_api: + """ + self._import_json(user_id) + return "Import ok !" diff --git a/old/moon_manager/moon_manager/api/json_utils.py b/old/moon_manager/moon_manager/api/json_utils.py new file mode 100644 index 00000000..6a5830f1 --- /dev/null +++ b/old/moon_manager/moon_manager/api/json_utils.py @@ -0,0 +1,282 @@ +import logging +from moon_manager.api.base_exception import BaseException + +logger = logging.getLogger("moon.manager.api." + __name__) + + +class UnknownName(BaseException): + def __init__(self, message): + # Call the base class constructor with the parameters it needs + super(UnknownName, self).__init__(message) + + +class UnknownId(BaseException): + def __init__(self, message): + # Call the base class constructor with the parameters it needs + super(UnknownId, self).__init__(message) + + +class MissingIdOrName(BaseException): + def __init__(self, message): + # Call the base class constructor with the parameters it needs + super(MissingIdOrName, self).__init__(message) + + +class UnknownField(BaseException): + def __init__(self, message): + # Call the base class constructor with the parameters it needs + super(UnknownField, self).__init__(message) + + +class JsonUtils: + @staticmethod + def get_override(json_content): + if "override" in json_content: + return json_content["override"] + return False + + @staticmethod + def get_mandatory(json_content): + if "mandatory" in json_content: + return json_content["mandatory"] + return False + + @staticmethod + def copy_field_if_exists(json_in, json_out, field_name, type_field, default_value=None): + if field_name in json_in: + json_out[field_name] = json_in[field_name] + else: + if type_field is bool: + if default_value is None: + default_value = False + json_out[field_name] = default_value + if type_field is str: + if default_value is None: + default_value = "" + json_out[field_name] = default_value + if type_field is dict: + json_out[field_name] = dict() + if type_field is list: + json_out[field_name] = [] + + @staticmethod + def _get_element_in_db_from_id(element_type, element_id, user_id, policy_id, category_id, + meta_rule_id, manager): + # the item is supposed to be in the db, we check it exists! + if element_type == "model": + data_db = manager.get_models(user_id, model_id=element_id) + elif element_type == "policy": + data_db = manager.get_policies(user_id, policy_id=element_id) + elif element_type == "subject": + data_db = manager.get_subjects(user_id, policy_id, perimeter_id=element_id) + elif element_type == "object": + data_db = manager.get_objects(user_id, policy_id, perimeter_id=element_id) + elif element_type == "action": + data_db = manager.get_actions(user_id, policy_id, perimeter_id=element_id) + elif element_type == "subject_category": + data_db = manager.get_subject_categories(user_id, category_id=element_id) + elif element_type == "object_category": + data_db = manager.get_object_categories(user_id, category_id=element_id) + elif element_type == "action_category": + data_db = manager.get_action_categories(user_id, category_id=element_id) + elif element_type == "meta_rule": + data_db = manager.get_meta_rules(user_id, meta_rule_id=element_id) + elif element_type == "subject_data": + data_db = manager.get_subject_data(user_id, policy_id, data_id=element_id, + category_id=category_id) + elif element_type == "object_data": + data_db = manager.get_object_data(user_id, policy_id, data_id=element_id, + category_id=category_id) + elif element_type == "action_data": + data_db = manager.get_action_data(user_id, policy_id, data_id=element_id, + category_id=category_id) + elif element_type == "meta_rule": + data_db = manager.get_meta_rules(user_id, meta_rule_id=meta_rule_id) + else: + raise Exception("Conversion of {} not implemented yet!".format(element_type)) + + # logger.info(data_db) + + # do some post processing ... the result should be {key : { .... .... } } + if element_type == "subject_data" or element_type == "object_data" or element_type == "action_data": + if data_db is not None and isinstance(data_db, list): + # TODO remove comments after fixing the bug on moondb when adding metarule : we can have several identical entries ! + # if len(data_db) > 1: + # raise Exception("Several {} with the same id : {}".format(element_type, data_db)) + data_db = data_db[0] + + if data_db is not None and data_db["data"] is not None and isinstance(data_db["data"], + dict): + # TODO remove comments after fixing the bug on moondb when adding metarule : we can have several identical entries ! + # if len(data_db["data"].values()) != 1: + # raise Exception("Several {} with the same id : {}".format(element_type, data_db)) + # data_db = data_db["data"] + # TODO remove these two lines after fixing the bug on moondb when adding metarule : we can have several identical entries ! + list_values = list(data_db["data"].values()) + data_db = list_values[0] + # logger.info("subject data after postprocessing {}".format(data_db)) + return data_db + + @staticmethod + def _get_element_id_in_db_from_name(element_type, element_name, user_id, policy_id, category_id, + meta_rule_id, manager): + if element_type == "model": + data_db = manager.get_models(user_id) + elif element_type == "policy": + data_db = manager.get_policies(user_id) + elif element_type == "subject": + data_db = manager.get_subjects(user_id, policy_id) + elif element_type == "object": + data_db = manager.get_objects(user_id, policy_id) + elif element_type == "action": + data_db = manager.get_actions(user_id, policy_id) + elif element_type == "subject_category": + data_db = manager.get_subject_categories(user_id) + elif element_type == "object_category": + data_db = manager.get_object_categories(user_id) + elif element_type == "action_category": + data_db = manager.get_action_categories(user_id) + elif element_type == "meta_rule": + data_db = manager.get_meta_rules(user_id) + elif element_type == "subject_data": + data_db = manager.get_subject_data(user_id, policy_id, category_id=category_id) + elif element_type == "object_data": + data_db = manager.get_object_data(user_id, policy_id, category_id=category_id) + elif element_type == "action_data": + data_db = manager.get_action_data(user_id, policy_id, category_id=category_id) + elif element_type == "meta_rule": + data_db = manager.get_meta_rules(user_id) + elif element_type == "rule": + data_db = manager.get_rules(user_id, policy_id) + else: + raise BaseException("Conversion of {} not implemented yet!".format(element_type)) + + if isinstance(data_db, dict): + for key_id in data_db: + if isinstance(data_db[key_id], dict) and "name" in data_db[key_id]: + if data_db[key_id]["name"] == element_name: + return key_id + else: + for elt in data_db: + if isinstance(elt, + dict) and "data" in elt: # we handle here subject_data, object_data and action_data... + for data_key in elt["data"]: + # logger.info("data from the db {} ".format(elt["data"][data_key])) + data = elt["data"][data_key] + if "name" in data and data["name"] == element_name: + return data_key + if "value" in data and data["value"]["name"] == element_name: + return data_key + return None + + @staticmethod + def convert_name_to_id(json_in, json_out, field_name_in, field_name_out, element_type, manager, + user_id, policy_id=None, category_id=None, meta_rule_id=None, + field_mandatory=True): + if field_name_in not in json_in: + raise UnknownField("The field {} is not in the input json".format(field_name_in)) + + if "id" in json_in[field_name_in]: + data_db = JsonUtils._get_element_in_db_from_id(element_type, + json_in[field_name_in]["id"], user_id, + policy_id, category_id, meta_rule_id, + manager) + if data_db is None: + raise UnknownId("No {} with id {} found in database".format(element_type, + json_in[field_name_in]["id"])) + json_out[field_name_out] = json_in[field_name_in]["id"] + + elif "name" in json_in[field_name_in]: + id_in_db = JsonUtils._get_element_id_in_db_from_name(element_type, + json_in[field_name_in]["name"], + user_id, policy_id, category_id, + meta_rule_id, manager) + if id_in_db is None: + raise UnknownName( + "No {} with name {} found in database".format(element_type, + json_in[field_name_in]["name"])) + json_out[field_name_out] = id_in_db + elif field_mandatory is True: + raise MissingIdOrName("No id or name found in the input json {}".format(json_in)) + + @staticmethod + def convert_id_to_name(id_, json_out, field_name_out, element_type, manager, user_id, + policy_id=None, category_id=None, meta_rule_id=None): + json_out[field_name_out] = { + "name": JsonUtils.convert_id_to_name_string(id_, element_type, manager, user_id, + policy_id, category_id, meta_rule_id)} + + @staticmethod + def __convert_results_to_element(element): + if isinstance(element, dict) and "name" not in element and "value" not in element: + list_values = [v for v in element.values()] + elif isinstance(element, list): + list_values = element + else: + list_values = [] + list_values.append(element) + return list_values[0] + + @staticmethod + def convert_id_to_name_string(id_, element_type, manager, user_id, + policy_id=None, category_id=None, meta_rule_id=None): + + element = JsonUtils._get_element_in_db_from_id(element_type, id_, user_id, policy_id, + category_id, meta_rule_id, manager) + # logger.info(element) + if element is None: + raise UnknownId("No {} with id {} found in database".format(element_type, id_)) + res = JsonUtils.__convert_results_to_element(element) + # logger.info(res) + if "name" in res: + return res["name"] + if "value" in res and "name" in res["value"]: + return res["value"]["name"] + return None + + @staticmethod + def convert_names_to_ids(json_in, json_out, field_name_in, field_name_out, element_type, + manager, user_id, policy_id=None, category_id=None, meta_rule_id=None, + field_mandatory=True): + ids = [] + if field_name_in not in json_in: + raise UnknownField("The field {} is not in the input json".format(field_name_in)) + + for elt in json_in[field_name_in]: + if "id" in elt: + data_db = JsonUtils._get_element_in_db_from_id(element_type, elt["id"], user_id, + policy_id, category_id, + meta_rule_id, manager) + if data_db is None: + raise UnknownId( + "No {} with id {} found in database".format(element_type, elt["id"])) + ids.append(elt["id"]) + elif "name" in elt: + id_in_db = JsonUtils._get_element_id_in_db_from_name(element_type, elt["name"], + user_id, policy_id, + category_id, meta_rule_id, + manager) + if id_in_db is None: + raise UnknownName( + "No {} with name {} found in database".format(element_type, elt["name"])) + ids.append(id_in_db) + elif field_mandatory is True: + raise MissingIdOrName("No id or name found in the input json {}".format(elt)) + json_out[field_name_out] = ids + + @staticmethod + def convert_ids_to_names(ids, json_out, field_name_out, element_type, manager, user_id, + policy_id=None, category_id=None, meta_rule_id=None): + res_array = [] + for id_ in ids: + element = JsonUtils._get_element_in_db_from_id(element_type, id_, user_id, policy_id, + category_id, meta_rule_id, manager) + if element is None: + raise UnknownId("No {} with id {} found in database".format(element_type, id_)) + res = JsonUtils.__convert_results_to_element(element) + # logger.info(res) + if "name" in res: + res_array.append({"name": res["name"]}) + if "value" in res and "name" in res["value"]: + res_array.append({"name": res["value"]["name"]}) + json_out[field_name_out] = res_array diff --git a/old/moon_manager/moon_manager/api/meta_data.py b/old/moon_manager/moon_manager/api/meta_data.py new file mode 100644 index 00000000..b0b86d10 --- /dev/null +++ b/old/moon_manager/moon_manager/api/meta_data.py @@ -0,0 +1,246 @@ +# 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 +import logging +from python_moonutilities.security_functions import check_auth +from python_moondb.core import ModelManager +from python_moonutilities.security_functions import validate_input + +__version__ = "4.3.2" + +logger = logging.getLogger("moon.manager.api." + __name__) + + +class SubjectCategories(Resource): + """ + Endpoint for subject categories requests + """ + + __urls__ = ( + "/subject_categories", + "/subject_categories/", + "/subject_categories/<string:category_id>", + ) + + @validate_input("get", kwargs_state=[False, False]) + @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 (optional)" + } + } + :internal_api: get_subject_categories + """ + data = ModelManager.get_subject_categories( + user_id=user_id, category_id=category_id) + + return {"subject_categories": data} + + @validate_input("post", body_state={"name": True}) + @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 (mandatory)", + "description": "description of the category (optional)" + } + :return: { + "subject_category_id": { + "name": "name of the category", + "description": "description of the category (optional)" + } + } + :internal_api: add_subject_category + """ + data = ModelManager.add_subject_category( + user_id=user_id, value=request.json) + + return {"subject_categories": data} + + @validate_input("delete", kwargs_state=[True, False]) + @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 (optional)" + } + :internal_api: delete_subject_category + """ + + data = ModelManager.delete_subject_category( + user_id=user_id, category_id=category_id) + + return {"result": True} + + +class ObjectCategories(Resource): + """ + Endpoint for object categories requests + """ + + __urls__ = ( + "/object_categories", + "/object_categories/", + "/object_categories/<string:category_id>", + ) + + @validate_input("get", kwargs_state=[False, False]) + @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 (optional)" + } + } + :internal_api: get_object_categories + """ + data = ModelManager.get_object_categories( + user_id=user_id, category_id=category_id) + + return {"object_categories": data} + + @validate_input("post", body_state={"name": True}) + @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 (mandatory)", + "description": "description of the category (optional)" + } + :return: { + "object_category_id": { + "name": "name of the category", + "description": "description of the category (optional)" + } + } + :internal_api: add_object_category + """ + + data = ModelManager.add_object_category( + user_id=user_id, value=request.json) + + return {"object_categories": data} + + @validate_input("delete", kwargs_state=[True, False]) + @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 (optional)" + } + :internal_api: delete_object_category + """ + + data = ModelManager.delete_object_category( + user_id=user_id, category_id=category_id) + + return {"result": True} + + +class ActionCategories(Resource): + """ + Endpoint for action categories requests + """ + + __urls__ = ( + "/action_categories", + "/action_categories/", + "/action_categories/<string:category_id>", + ) + + @validate_input("get", kwargs_state=[False, False]) + @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 (optional)" + } + } + :internal_api: get_action_categories + """ + + data = ModelManager.get_action_categories( + user_id=user_id, category_id=category_id) + + return {"action_categories": data} + + @validate_input("post", body_state={"name": True}) + @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 (mandatory)", + "description": "description of the category (optional)" + } + :return: { + "action_category_id": { + "name": "name of the category", + "description": "description of the category (optional)" + } + } + :internal_api: add_action_category + """ + + data = ModelManager.add_action_category( + user_id=user_id, value=request.json) + + return {"action_categories": data} + + @validate_input("delete", kwargs_state=[True, False]) + @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 (optional)" + } + :internal_api: delete_action_category + """ + data = ModelManager.delete_action_category( + user_id=user_id, category_id=category_id) + + return {"result": True} diff --git a/old/moon_manager/moon_manager/api/meta_rules.py b/old/moon_manager/moon_manager/api/meta_rules.py new file mode 100644 index 00000000..738aad71 --- /dev/null +++ b/old/moon_manager/moon_manager/api/meta_rules.py @@ -0,0 +1,152 @@ +# 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 +import logging +from python_moonutilities.security_functions import check_auth +from python_moondb.core import ModelManager +from python_moonutilities.security_functions import validate_input + +__version__ = "4.3.2" + +logger = logging.getLogger("moon.manager.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>/" + ) + + @validate_input("get", kwargs_state=[False, False]) + @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", + "subject_categories": ["subject_category_id1", + "subject_category_id2"], + "object_categories": ["object_category_id1"], + "action_categories": ["action_category_id1"] + }, + } + } + :internal_api: get_meta_rules + """ + + data = ModelManager.get_meta_rules( + user_id=user_id, meta_rule_id=meta_rule_id) + + return {"meta_rules": data} + + @validate_input("post", body_state={"name": True, "subject_categories": False, + "object_categories": False, "action_categories": False}) + @check_auth + def post(self, meta_rule_id=None, user_id=None): + """Add a meta rule + + :param meta_rule_id: Meta rule ID (not used here) + :param user_id: user ID who do the request + :request body: post = { + "name": "name of the meta rule (mandatory)", + "subject_categories": ["subject_category_id1 (mandatory)", + "subject_category_id2"], + "object_categories": ["object_category_id1 (mandatory)"], + "action_categories": ["action_category_id1 (mandatory)"] + } + :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 + """ + + data = ModelManager.add_meta_rule( + user_id=user_id, meta_rule_id=None, value=request.json) + + return {"meta_rules": data} + + @validate_input("patch", kwargs_state=[True, False], + body_state={"name": True, "subject_categories": False, + "object_categories": False, "action_categories": False}) + @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 + """ + data = ModelManager.update_meta_rule( + user_id=user_id, meta_rule_id=meta_rule_id, value=request.json) + + return {"meta_rules": data} + + @validate_input("delete", kwargs_state=[True, False]) + @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 + :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 + """ + + data = ModelManager.delete_meta_rule( + user_id=user_id, meta_rule_id=meta_rule_id) + + return {"result": True} diff --git a/old/moon_manager/moon_manager/api/models.py b/old/moon_manager/moon_manager/api/models.py new file mode 100644 index 00000000..c72396cf --- /dev/null +++ b/old/moon_manager/moon_manager/api/models.py @@ -0,0 +1,117 @@ +# 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 +import logging +from python_moonutilities.security_functions import check_auth +from python_moondb.core import ModelManager +from python_moonutilities.security_functions import validate_input + +__version__ = "4.3.2" + +logger = logging.getLogger("moon.manager.api." + __name__) + + +class Models(Resource): + """ + Endpoint for model requests + """ + + __urls__ = ( + "/models", + "/models/", + "/models/<string:uuid>", + "/models/<string:uuid>/", + ) + + @validate_input("get", kwargs_state=[False, False]) + @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": "... (optional)", + "meta_rules": ["meta_rule_id1", ] + } + } + :internal_api: get_models + """ + data = ModelManager.get_models(user_id=user_id, model_id=uuid) + + return {"models": data} + + @validate_input("post", body_state={"name": True, "meta_rules": False}) + @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": "name of the model (mandatory)", + "description": "description of the model (optional)", + "meta_rules": ["meta_rule_id1", ] + } + :return: { + "model_id1": { + "name": "name of the model", + "description": "description of the model (optional)", + "meta_rules": ["meta_rule_id1", ] + } + } + :internal_api: add_model + """ + data = ModelManager.add_model( + user_id=user_id, model_id=uuid, value=request.json) + + return {"models": data} + + @validate_input("delete", kwargs_state=[True, False]) + @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 (optional)" + } + :internal_api: delete_model + """ + + data = ModelManager.delete_model(user_id=user_id, model_id=uuid) + + return {"result": True} + + @validate_input("patch", kwargs_state=[True, False], + body_state={"name": True, "meta_rules": False}) + @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": "name of the model", + "description": "... (optional)", + "meta_rules": ["meta_rule_id1", ] + } + } + :internal_api: update_model + """ + data = ModelManager.update_model( + user_id=user_id, model_id=uuid, value=request.json) + + return {"models": data} diff --git a/old/moon_manager/moon_manager/api/pdp.py b/old/moon_manager/moon_manager/api/pdp.py new file mode 100644 index 00000000..65a6a5f1 --- /dev/null +++ b/old/moon_manager/moon_manager/api/pdp.py @@ -0,0 +1,214 @@ +# 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 +import logging +import requests +import time +from python_moonutilities.security_functions import check_auth +from python_moondb.core import PDPManager +from python_moondb.core import PolicyManager +from python_moondb.core import ModelManager +from python_moonutilities import configuration, exceptions +from python_moonutilities.security_functions import validate_input + +__version__ = "4.3.2" + +logger = logging.getLogger("moon.manager.api." + __name__) + + +def delete_pod(uuid): + conf = configuration.get_configuration("components/orchestrator") + hostname = conf["components/orchestrator"].get("hostname", "orchestrator") + port = conf["components/orchestrator"].get("port", 80) + proto = conf["components/orchestrator"].get("protocol", "http") + # while True: + # try: + url = "{}://{}:{}/pods".format(proto, hostname, port) + req = requests.get(url) + # except requests.exceptions.ConnectionError: + # logger.warning("Orchestrator is not ready, standby... {}".format(url)) + # time.sleep(1) + # else: + # break + for pod_key, pod_list in req.json().get("pods", {}).items(): + for pod_value in pod_list: + if "pdp_id" in pod_value: + if pod_value["pdp_id"] == uuid: + req = requests.delete( + "{}://{}:{}/pods/{}".format(proto, hostname, port, pod_key)) + if req.status_code != 200: + logger.warning( + "Cannot delete pod {} - {}".format(pod_key, pod_value['name'])) + logger.debug(req.content) + # Note (Asteroide): no need to go further if one match + break + + +def add_pod(uuid, data): + if not data.get("keystone_project_id"): + return + logger.info("Add a new pod {}".format(data)) + if "pdp_id" not in data: + data["pdp_id"] = uuid + data['policies'] = PolicyManager.get_policies(user_id="admin") + data['models'] = ModelManager.get_models(user_id="admin") + conf = configuration.get_configuration("components/orchestrator") + hostname = conf["components/orchestrator"].get("hostname", "orchestrator") + port = conf["components/orchestrator"].get("port", 80) + proto = conf["components/orchestrator"].get("protocol", "http") + while True: + try: + req = requests.post( + "{}://{}:{}/pods".format(proto, hostname, port), + json=data, + headers={"content-type": "application/json"}) + except requests.exceptions.ConnectionError as e: + logger.warning("add_pod: Orchestrator is not ready, standby...") + logger.exception(e) + time.sleep(1) + else: + break + logger.info("Pod add request answer : {}".format(req.text)) + + +def check_keystone_pid(k_pid): + data = PDPManager.get_pdp(user_id="admin") + for pdp_key, pdp_value in data.items(): + logger.info("pdp={}".format(pdp_value)) + if pdp_value["keystone_project_id"] == k_pid: + return True + + +class PDP(Resource): + """ + Endpoint for pdp requests + """ + + __urls__ = ( + "/pdp", + "/pdp/", + "/pdp/<string:uuid>", + "/pdp/<string:uuid>/", + ) + + @validate_input("get", kwargs_state=[False, False]) + @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": "... (optional)", + } + } + :internal_api: get_pdp + """ + + data = PDPManager.get_pdp(user_id=user_id, pdp_id=uuid) + + return {"pdps": data} + + @validate_input("post", body_state={"name": True, "security_pipeline": True, + "keystone_project_id": True}) + @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": "name of the PDP (mandatory)", + "security_pipeline": ["may be empty"], + "keystone_project_id": "keystone_project_id1 (may be empty)", + "description": "description of the PDP (optional)", + } + :return: { + "pdp_id1": { + "name": "...", + "security_pipeline": [...], + "keystone_project_id": "keystone_project_id1", + "description": "... (optional)", + } + } + :internal_api: add_pdp + """ + + data = dict(request.json) + if not data.get("keystone_project_id"): + data["keystone_project_id"] = None + else: + if check_keystone_pid(data.get("keystone_project_id")): + raise exceptions.PdpKeystoneMappingConflict + data = PDPManager.add_pdp( + user_id=user_id, pdp_id=None, value=request.json) + uuid = list(data.keys())[0] + logger.debug("data={}".format(data)) + logger.debug("uuid={}".format(uuid)) + add_pod(uuid=uuid, data=data[uuid]) + + return {"pdps": data} + + @validate_input("delete", kwargs_state=[True, False]) + @check_auth + def delete(self, uuid, 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 (optional)" + } + :internal_api: delete_pdp + """ + data = PDPManager.delete_pdp(user_id=user_id, pdp_id=uuid) + delete_pod(uuid) + + return {"result": True} + + @validate_input("patch", kwargs_state=[True, False], + body_state={"name": True, "security_pipeline": True, + "keystone_project_id": True}) + @check_auth + def patch(self, uuid, 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": "name of the PDP", + "security_pipeline": ["may be empty"], + "keystone_project_id": "keystone_project_id1 (may be empty)", + "description": "description of the PDP (optional)", + } + } + :internal_api: update_pdp + """ + + _data = dict(request.json) + if not _data.get("keystone_project_id"): + _data["keystone_project_id"] = None + else: + if check_keystone_pid(_data.get("keystone_project_id")): + raise exceptions.PdpKeystoneMappingConflict + data = PDPManager.update_pdp( + user_id=user_id, pdp_id=uuid, value=_data) + logger.debug("data={}".format(data)) + logger.debug("uuid={}".format(uuid)) + add_pod(uuid=uuid, data=data[uuid]) + + return {"pdps": data} diff --git a/old/moon_manager/moon_manager/api/perimeter.py b/old/moon_manager/moon_manager/api/perimeter.py new file mode 100644 index 00000000..a0fda4ad --- /dev/null +++ b/old/moon_manager/moon_manager/api/perimeter.py @@ -0,0 +1,375 @@ +# 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 +import logging +from python_moonutilities.security_functions import check_auth +from python_moondb.core import PolicyManager +from python_moonutilities.security_functions import validate_input + +__version__ = "4.3.2" + +logger = logging.getLogger("moon.manager.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>", + ) + + @validate_input("get", kwargs_state=[False, False, False]) + @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 (optional)" + } + } + :internal_api: get_subjects + """ + + data = PolicyManager.get_subjects( + user_id=user_id, + policy_id=uuid, + perimeter_id=perimeter_id + ) + + return {"subjects": data} + + @validate_input("post", body_state={"name": True}) + @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 (mandatory)", + "description": "description of the subject (optional)", + "password": "password for the subject (optional)", + "email": "email address of the subject (optional)" + } + :return: { + "subject_id": { + "name": "name of the subject", + "keystone_id": "keystone id of the subject", + "description": "description of the subject (optional)", + "password": "password for the subject (optional)", + "email": "email address of the subject (optional)" + } + } + :internal_api: set_subject + """ + + data = PolicyManager.add_subject( + user_id=user_id, policy_id=uuid, + perimeter_id=perimeter_id, value=request.json) + + return {"subjects": data} + + @validate_input("patch", kwargs_state=[False, True, False]) + @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 (optional)", + "password": "password for the subject (optional)", + "email": "email address of the subject (optional)" + } + :return: { + "subject_id": { + "name": "name of the subject", + "keystone_id": "keystone id of the subject", + "description": "description of the subject (optional)", + "password": "password for the subject (optional)", + "email": "email address of the subject (optional)" + } + } + :internal_api: set_subject + """ + data = PolicyManager.update_subject(user_id=user_id, perimeter_id=perimeter_id, + value=request.json) + return {"subjects": data} + + @validate_input("delete", kwargs_state=[False, True, False]) + @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 (mandatory if perimeter_id is not set) + :param perimeter_id: uuid of the subject (mandatory if uuid is not set) + :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 (optional)", + "password": "password for the subject (optional)", + "email": "email address of the subject (optional)" + } + } + :internal_api: delete_subject + """ + + data = PolicyManager.delete_subject( + user_id=user_id, policy_id=uuid, perimeter_id=perimeter_id) + + return {"result": True} + + +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>", + ) + + @validate_input("get", kwargs_state=[False, False, False]) + @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 (optional)" + } + } + :internal_api: get_objects + """ + + data = PolicyManager.get_objects( + user_id=user_id, + policy_id=uuid, + perimeter_id=perimeter_id + ) + + return {"objects": data} + + @validate_input("post", body_state={"name": True}) + @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 (mandatory)", + "object_description": "description of the object (optional)" + } + :return: { + "object_id": { + "name": "name of the object", + "description": "description of the object (optional)" + } + } + :internal_api: set_object + """ + data = PolicyManager.add_object( + user_id=user_id, policy_id=uuid, + perimeter_id=perimeter_id, value=request.json) + + return {"objects": data} + + @validate_input("patch", kwargs_state=[False, True, False]) + @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 (optional)" + } + :return: { + "object_id": { + "name": "name of the object", + "description": "description of the object (optional)" + } + } + :internal_api: set_object + """ + data = PolicyManager.update_object(user_id=user_id, perimeter_id=perimeter_id, + value=request.json) + + return {"objects": data} + + @validate_input("delete", kwargs_state=[False, True, False]) + @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 (mandatory if perimeter_id is not set) + :param perimeter_id: uuid of the object (mandatory if uuid is not set) + :param user_id: user ID who do the request + :return: { + "object_id": { + "name": "name of the object", + "description": "description of the object (optional)" + } + } + :internal_api: delete_object + """ + + data = PolicyManager.delete_object( + user_id=user_id, policy_id=uuid, perimeter_id=perimeter_id) + + return {"result": True} + + +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>", + ) + + @validate_input("get", kwargs_state=[False, False, False]) + @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 (optional)" + } + } + :internal_api: get_actions + """ + + data = PolicyManager.get_actions( + user_id=user_id, policy_id=uuid, perimeter_id=perimeter_id) + + return {"actions": data} + + @validate_input("post", body_state={"name": True}) + @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 (mandatory)", + "description": "description of the action (optional)" + } + :return: { + "action_id": { + "name": "name of the action", + "description": "description of the action (optional)" + } + } + :internal_api: set_action + """ + data = PolicyManager.add_action( + user_id=user_id, policy_id=uuid, + perimeter_id=perimeter_id, value=request.json) + + return {"actions": data} + + @validate_input("patch", kwargs_state=[False, True, False]) + @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 (optional)" + } + :return: { + "action_id": { + "name": "name of the action", + "description": "description of the action (optional)" + } + } + :internal_api: set_action + """ + data = PolicyManager.update_action(user_id=user_id, perimeter_id=perimeter_id, + value=request.json) + + return {"actions": data} + + @validate_input("delete", kwargs_state=[False, True, False]) + @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 (mandatory if perimeter_id is not set) + :param perimeter_id: uuid of the action (mandatory if uuid is not set) + :param user_id: user ID who do the request + :return: { + "action_id": { + "name": "name of the action", + "description": "description of the action (optional)" + } + } + :internal_api: delete_action + """ + + data = PolicyManager.delete_action( + user_id=user_id, policy_id=uuid, perimeter_id=perimeter_id) + + return {"result": True} diff --git a/old/moon_manager/moon_manager/api/policies.py b/old/moon_manager/moon_manager/api/policies.py new file mode 100644 index 00000000..3264e8e0 --- /dev/null +++ b/old/moon_manager/moon_manager/api/policies.py @@ -0,0 +1,125 @@ +# 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 +import logging +from python_moonutilities.security_functions import check_auth +from python_moondb.core import PolicyManager +from python_moonutilities.security_functions import validate_input + +__version__ = "4.3.2" + +logger = logging.getLogger("moon.manager.api." + __name__) + + +class Policies(Resource): + """ + Endpoint for policy requests + """ + + __urls__ = ( + "/policies", + "/policies/", + "/policies/<string:uuid>", + "/policies/<string:uuid>/", + ) + + @validate_input("get", kwargs_state=[False, False]) + @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": "name of the policy (mandatory)", + "model_id": "ID of the model linked to this policy", + "genre": "authz of admin (optional, default to authz)", + "description": "description of the policy (optional)", + } + } + :internal_api: get_policies + """ + + data = PolicyManager.get_policies(user_id=user_id, policy_id=uuid) + + return {"policies": data} + + @validate_input("post", body_state={"name": True, "model_id": False}) + @check_auth + def post(self, uuid=None, user_id=None): + """Create policy. + + :param uuid: uuid of the policy (not used here if a new policy is created) + :param user_id: user ID who do the request + :request body: { + "name": "name of the policy (mandatory)", + "model_id": "ID of the model linked to this policy", + "genre": "authz of admin (optional, default to authz)", + "description": "description of the policy (optional)", + } + :return: { + "policy_id1": { + "name": "name of the policy (mandatory)", + "model_id": "ID of the model linked to this policy", + "genre": "authz of admin (optional, default to authz)", + "description": "description of the policy (optional)", + } + } + :internal_api: add_policy + """ + + data = PolicyManager.add_policy( + user_id=user_id, policy_id=uuid, value=request.json) + + return {"policies": data} + + @validate_input("delete", kwargs_state=[True, False]) + @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 (optional)" + } + :internal_api: delete_policy + """ + + data = PolicyManager.delete_policy(user_id=user_id, policy_id=uuid) + + return {"result": True} + + @validate_input("patch", kwargs_state=[True, False], + body_state={"name": True, "model_id": False}) + @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": "name of the policy (mandatory)", + "model_id": "ID of the model linked to this policy", + "genre": "authz of admin (optional, default to authz)", + "description": "description of the policy (optional)", + } + } + :internal_api: update_policy + """ + + data = PolicyManager.update_policy( + user_id=user_id, policy_id=uuid, value=request.json) + + return {"policies": data} diff --git a/old/moon_manager/moon_manager/api/rules.py b/old/moon_manager/moon_manager/api/rules.py new file mode 100644 index 00000000..cbd39969 --- /dev/null +++ b/old/moon_manager/moon_manager/api/rules.py @@ -0,0 +1,135 @@ +# 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 +import logging +from python_moonutilities.security_functions import check_auth +from python_moondb.core import PolicyManager +from python_moonutilities.security_functions import validate_input + +__version__ = "4.3.2" + +logger = logging.getLogger("moon.manager.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>/", + ) + + @validate_input("get", kwargs_state=[False, False, False]) + @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", "subject_data_id2", "object_data_id1", "action_data_id1"], + "rule_id2": + ["subject_data_id3", "subject_data_id4", "object_data_id2", "action_data_id2"], + ] + } + :internal_api: get_rules + """ + + data = PolicyManager.get_rules(user_id=user_id, + policy_id=uuid, + rule_id=rule_id) + + return {"rules": data} + + @validate_input("post", kwargs_state=[True, False, False], + body_state={"meta_rule_id": True, "rule": True, "instructions": True}) + @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 (not used here) + :param user_id: user ID who do the request + :request body: post = { + "meta_rule_id": "meta_rule_id1", # mandatory + "rule": ["subject_data_id2", "object_data_id2", "action_data_id2"], # mandatory + "instructions": ( # mandatory + {"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 + """ + args = request.json + + data = PolicyManager.add_rule(user_id=user_id, + policy_id=uuid, + meta_rule_id=args['meta_rule_id'], + value=args) + + return {"rules": data} + + @validate_input("delete", kwargs_state=[True, True, False]) + @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 + """ + + data = PolicyManager.delete_rule( + user_id=user_id, policy_id=uuid, rule_id=rule_id) + + return {"result": True} diff --git a/old/moon_manager/moon_manager/api/slaves.py b/old/moon_manager/moon_manager/api/slaves.py new file mode 100644 index 00000000..e2928de0 --- /dev/null +++ b/old/moon_manager/moon_manager/api/slaves.py @@ -0,0 +1,111 @@ +# 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 +import logging +import requests +from python_moonutilities.security_functions import check_auth + +from python_moonutilities import configuration +from python_moonutilities.security_functions import validate_input + +__version__ = "4.3.0" + +logger = logging.getLogger("moon.manager.api." + __name__) + + +class Slaves(Resource): + """ + Endpoint for pdp requests + """ + + __urls__ = ( + "/slaves", + "/slaves/", + "/slaves/<string:uuid>", + "/slaves/<string:uuid>/", + ) + + def __init__(self, **kwargs): + conf = configuration.get_configuration("components/orchestrator") + self.orchestrator_hostname = conf["components/orchestrator"].get("hostname", + "orchestrator") + self.orchestrator_port = conf["components/orchestrator"].get("port", + 80) + + @validate_input("get", kwargs_state=[False, False]) + @check_auth + def get(self, uuid=None, user_id=None): + """Retrieve all slaves + + :param uuid: uuid of the slave + :param user_id: user ID who do the request + :return: { + "slaves": { + "XXX": { + "name": "...", + "installed": True + }, + "YYY": { + "name": "...", + "installed": False + } + } + } + """ + req = requests.get("http://{}:{}/slaves".format( + self.orchestrator_hostname, self.orchestrator_port + )) + return {"slaves": req.json().get("slaves", dict())} + + @validate_input("patch", kwargs_state=[False, False], + body_state={"op": True, "variable": True, "value": True}) + @check_auth + def patch(self, uuid=None, user_id=None): + """Update a slave + + :param uuid: uuid of the slave to update + :param user_id: user ID who do the request + :request body: { + "op": "replace", + "variable": "configured", + "value": True, + } + :return: 204 + :internal_api: add_pdp + """ + logger.info("Will made a request for {}".format(uuid)) + if request.json.get("op") == "replace" \ + and request.json.get("variable") == "configured" \ + and request.json.get("value"): + req = requests.post("http://{}:{}/pods".format( + self.orchestrator_hostname, self.orchestrator_port, + ), + json={"slave_name": uuid} + ) + if req.status_code != 200: + logger.warning("Get error from Orchestrator {} {}".format( + req.reason, req.status_code + )) + return "Orchestrator: " + str(req.reason), req.status_code + elif request.json.get("op") == "replace" \ + and request.json.get("variable") == "configured" \ + and not request.json.get("value"): + req = requests.delete("http://{}:{}/pods/{}".format( + self.orchestrator_hostname, self.orchestrator_port, uuid + )) + if req.status_code != 200: + logger.warning("Get error from Orchestrator {} {}".format( + req.reason, req.status_code + )) + return "Orchestrator: " + str(req.reason), req.status_code + else: + return "Malformed request", 400 + return {"slaves": req.json()} diff --git a/old/moon_manager/moon_manager/http_server.py b/old/moon_manager/moon_manager/http_server.py new file mode 100644 index 00000000..53879529 --- /dev/null +++ b/old/moon_manager/moon_manager/http_server.py @@ -0,0 +1,162 @@ +# 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, jsonify, Response, make_response +from flask_cors import CORS, cross_origin +from json import dumps +from flask_restful import Resource, Api +import logging +import sqlalchemy.exc +import time +from moon_manager import __version__ +from moon_manager.api.generic import Status, Logs, API +from moon_manager.api.models import Models +from moon_manager.api.policies import Policies +from moon_manager.api.pdp import PDP +from moon_manager.api.slaves import Slaves +from moon_manager.api.meta_rules import MetaRules +from moon_manager.api.meta_data import SubjectCategories, ObjectCategories, ActionCategories +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.json_import import JsonImport +from moon_manager.api.json_export import JsonExport +from python_moonutilities import configuration +from python_moondb.core import PDPManager + +logger = logging.getLogger("moon.manager.http_server") + +__API__ = ( + Status, Logs, API, + MetaRules, SubjectCategories, ObjectCategories, ActionCategories, + Subjects, Objects, Actions, Rules, + SubjectAssignments, ObjectAssignments, ActionAssignments, + SubjectData, ObjectData, ActionData, + Models, Policies, PDP, Slaves, JsonImport, JsonExport +) + + +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() + + +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() if item.__doc__ else "" + return { + "version": __version__, + "tree": tree + } + + +class CustomApi(Api): + + @staticmethod + def handle_error(e): + try: + error_message = dumps( + {"result": False, 'message': str(e), "code": getattr(e, "code", 500)}) + logger.error(e, exc_info=True) + logger.error(error_message) + return make_response(error_message, getattr(e, "code", 500)) + except Exception as e2: # unhandled exception in the api... + logger.exception(str(e2)) + return make_response(error_message, 500) + + +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.app.config['TRAP_HTTP_EXCEPTIONS'] = True + 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 = CustomApi(self.app, catch_all_404s=True) + self.__set_route() + + def __set_route(self): + self.api.add_resource(Root, '/') + + for _api in __API__: + self.api.add_resource(_api, *_api.__urls__) + + @staticmethod + def __check_if_db_is_up(): + first = True + while True: + try: + PDPManager.get_pdp(user_id="admin", pdp_id=None) + except (sqlalchemy.exc.ProgrammingError, sqlalchemy.exc.InternalError): + time.sleep(1) + if first: + logger.warning("Waiting for the database...") + first = False + else: + logger.warning("Database is up, resuming operations...") + break + + def run(self): + self.__check_if_db_is_up() + self.app.run(host=self._host, port=self._port, threaded=True) # nosec diff --git a/old/moon_manager/moon_manager/server.py b/old/moon_manager/moon_manager/server.py new file mode 100644 index 00000000..70ddaee0 --- /dev/null +++ b/old/moon_manager/moon_manager/server.py @@ -0,0 +1,39 @@ +# 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 +from python_moonutilities import configuration, exceptions +from moon_manager.http_server import HTTPServer + +logger = logging.getLogger("moon.manager.server") + + +def create_server(): + configuration.init_logging() + try: + conf = configuration.get_configuration("components/manager") + hostname = conf["components/manager"].get("hostname", "manager") + port = conf["components/manager"].get("port", 80) + bind = conf["components/manager"].get("bind", "127.0.0.1") + except exceptions.ConsulComponentNotFound: + hostname = "manager" + bind = "127.0.0.1" + port = 80 + configuration.add_component(uuid="manager", + name=hostname, + port=port, + bind=bind) + logger.info("Starting server with IP {} on port {} bind to {}".format( + hostname, port, bind)) + return HTTPServer(host=bind, port=port) + + +def run(): + server = create_server() + server.run() + + +if __name__ == '__main__': + run() |