aboutsummaryrefslogtreecommitdiffstats
path: root/moon_manager/moon_manager/api/pdp.py
diff options
context:
space:
mode:
Diffstat (limited to 'moon_manager/moon_manager/api/pdp.py')
-rw-r--r--moon_manager/moon_manager/api/pdp.py468
1 files changed, 326 insertions, 142 deletions
diff --git a/moon_manager/moon_manager/api/pdp.py b/moon_manager/moon_manager/api/pdp.py
index 65a6a5f1..6f0b5214 100644
--- a/moon_manager/moon_manager/api/pdp.py
+++ b/moon_manager/moon_manager/api/pdp.py
@@ -1,214 +1,398 @@
-# 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'.
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
"""
-PDP are Policy Decision Point.
+PDP are Policy Decision Points.
"""
-from flask import request
-from flask_restful import Resource
+import hug
+import json
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))
+from moon_manager.api import ERROR_CODE
+from moon_manager import db_driver
+from moon_utilities.auth_functions import api_key_authentication, connect_from_env
+from moon_manager import orchestration_driver
+from moon_utilities import exceptions
+from moon_utilities.security_functions import validate_input
+from moon_utilities.invalided_functions import invalidate_pdp_in_slaves
+from moon_manager.api import slave as slave_class
+from moon_manager.api import configuration
-
-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
+LOGGER = logging.getLogger("moon.manager.api." + __name__)
-class PDP(Resource):
+class PDP(object):
"""
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):
+ @staticmethod
+ @hug.local()
+ @hug.get("/pdp/", requires=api_key_authentication)
+ @hug.get("/pdp/{uuid}", requires=api_key_authentication)
+ def get(uuid: hug.types.uuid = None, authed_user: hug.directives.user = None):
"""Retrieve all pdp
:param uuid: uuid of the pdp
- :param user_id: user ID who do the request
+ :param authed_user: the name of the authenticated user
:return: {
"pdp_id1": {
"name": "...",
"security_pipeline": [...],
- "keystone_project_id": "keystone_project_id1",
+ "vim_project_id": "vim_project_id1",
"description": "... (optional)",
}
}
:internal_api: get_pdp
"""
-
- data = PDPManager.get_pdp(user_id=user_id, pdp_id=uuid)
+ if uuid:
+ uuid = str(uuid).replace("-", "")
+ data = db_driver.PDPManager.get_pdp(moon_user_id=authed_user, 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):
+ @staticmethod
+ @hug.local()
+ @hug.post("/pdp/", requires=api_key_authentication)
+ def post(body: validate_input("name"), response, authed_user: hug.directives.user = None):
"""Create pdp.
- :param uuid: uuid of the pdp (not used here)
- :param user_id: user ID who do the request
+ :param body: preformed body from Hug
+ :param response: preformed response from Hug
+ :param authed_user: the name of the authenticated user
:request body: {
"name": "name of the PDP (mandatory)",
"security_pipeline": ["may be empty"],
- "keystone_project_id": "keystone_project_id1 (may be empty)",
+ "vim_project_id": "vim_project_id1 (may be empty)",
"description": "description of the PDP (optional)",
}
:return: {
"pdp_id1": {
"name": "...",
"security_pipeline": [...],
- "keystone_project_id": "keystone_project_id1",
+ "vim_project_id": "vim_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)
+ if not body.get("security_pipeline"):
+ body["security_pipeline"] = []
+ if not body.get("vim_project_id"):
+ body["vim_project_id"] = None
+ data = db_driver.PDPManager.add_pdp(
+ moon_user_id="admin", pdp_id=None, value=body)
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}
+ if body["vim_project_id"] and body["security_pipeline"]:
+ orchestration_driver.PipelineManager.add_pipeline(
+ moon_user_id=authed_user, pipeline_id=uuid, data=data[uuid])
+ return {"pdps": db_driver.PDPManager.get_pdp(moon_user_id=authed_user, pdp_id=uuid)}
- @validate_input("delete", kwargs_state=[True, False])
- @check_auth
- def delete(self, uuid, user_id=None):
+ @staticmethod
+ @hug.local()
+ @hug.delete("/pdp/{uuid}", requires=api_key_authentication)
+ def delete(uuid: hug.types.uuid, response=None, authed_user: hug.directives.user = None):
"""Delete a pdp
:param uuid: uuid of the pdp to delete
- :param user_id: user ID who do the request
+ :param response: preformed response from Hug
+ :param authed_user: the name of the authenticated user
: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)
+ uuid = str(uuid).replace("-", "")
+ data = db_driver.PDPManager.delete_pdp(moon_user_id=authed_user, pdp_id=uuid)
+ LOGGER.info(data)
+
+ orchestration_driver.PipelineManager.delete_pipeline(moon_user_id=authed_user, pipeline_id=uuid)
+ slaves = slave_class.Slaves.get().get("slaves")
+ invalidate_pdp_in_slaves(slaves=slaves, pdp_id=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):
+ @staticmethod
+ @hug.local()
+ @hug.patch("/pdp/{uuid}", requires=api_key_authentication)
+ def patch(uuid: hug.types.uuid, body: validate_input("name"), response,
+ authed_user: hug.directives.user = None):
"""Update a pdp
- :param uuid: uuid of the pdp to update
- :param user_id: user ID who do the request
+ :param uuid: uuid of the pdp to delete
+ :param body: preformed body from Hug
+ :param response: preformed response from Hug
+ :param authed_user: the name of the authenticated user
:return: {
"pdp_id1": {
"name": "name of the PDP",
"security_pipeline": ["may be empty"],
- "keystone_project_id": "keystone_project_id1 (may be empty)",
+ "vim_project_id": "vim_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
+ uuid = str(uuid).replace("-", "")
+ prev_data = db_driver.PDPManager.get_pdp(moon_user_id=authed_user, pdp_id=uuid)
+ if not prev_data:
+ response.status = ERROR_CODE[400]
+ return {"message": "The PDP is unknown."}
+
+ data = db_driver.PDPManager.update_pdp(moon_user_id=authed_user, pdp_id=uuid, value=body).get(uuid)
+
+ orchestration_driver.PipelineManager.update_pipeline(moon_user_id=authed_user, pipeline_id=uuid, data=data)
+ slaves = slave_class.Slaves.get().get("slaves")
+ invalidate_pdp_in_slaves(slaves=slaves, pdp_id=uuid, is_delete=False, data=data)
+
+ return {"pdps": db_driver.PDPManager.get_pdp(moon_user_id=authed_user, pdp_id=uuid)}
+
+
+PDPAPI = hug.API(name='pdps', doc=PDP.__doc__)
+
+
+@hug.object(name='pdps', version='1.0.0', api=PDPAPI)
+class PDPCLI(object):
+ """An example of command like calls via an Object"""
+
+ @staticmethod
+ @hug.object.cli
+ def list(name_or_id="", human: bool = False):
+ db_conf = configuration.get_configuration(key='management')
+ manager_api_key = connect_from_env()
+ _pdps = requests.get("{}/pdp".format(db_conf.get("url")),
+ headers={"x-api-key": manager_api_key}
+ )
+ if _pdps.status_code == 200:
+ if name_or_id:
+ _pdp = None
+ if name_or_id in _pdps.json().get("pdps"):
+ _pdp = _pdps.json().get("pdps").get(name_or_id)
+ else:
+ for _pdp_key in _pdps.json().get("pdps"):
+ if _pdps.json().get("pdps").get(_pdp_key).get("name") == name_or_id:
+ _pdp = _pdps.json().get("pdps").get(_pdp_key)
+ name_or_id = _pdp_key
+ break
+ if not _pdp:
+ raise Exception("Cannot find PDP with name or ID {}".format(name_or_id))
+ else:
+ if human:
+ result = {"pdps": {name_or_id: _pdp}}
+ else:
+ result = {"pdps": [{name_or_id: _pdp}]}
+ else:
+ result = _pdps.json()
+
+ if human:
+ return PDPCLI.human_display(result)
+ else:
+ return result
+ LOGGER.error('Cannot list PDP {}'.format(_pdps.status_code))
+
+ @staticmethod
+ @hug.object.cli
+ def add(name, description="", security_pipeline="", vim_project_id="", human: bool = False):
+ """
+ Add pdp in the database
+ :return: JSON status output
+ """
+ db_conf = configuration.get_configuration(key='management')
+ manager_api_key = connect_from_env()
+ security_pipeline = security_pipeline.split(",")
+ _pdps = requests.post(
+ "{}/pdp".format(db_conf.get("url")),
+ json={
+ "name": name,
+ "security_pipeline": security_pipeline,
+ "vim_project_id": vim_project_id,
+ "description": description,
+ },
+ headers={
+ "x-api-key": manager_api_key,
+ "Content-Type": "application/json"
+ }
+ )
+ if _pdps.status_code == 200:
+ LOGGER.warning('Create {}'.format(_pdps.content))
+ if human:
+ return PDPCLI.human_display(_pdps.json())
+ else:
+ return _pdps.json()
+ LOGGER.error('Cannot create {}'.format(name, _pdps.content[:40]))
+
+ @staticmethod
+ @hug.object.cli
+ def delete(name='default'):
+ db_conf = configuration.get_configuration(key='management')
+ manager_api_key = connect_from_env()
+ _pdps = PDPCLI.list()
+ for _slave_id, _slave_value in _pdps.get("pdps").items():
+ if _slave_value.get("name") == name:
+ req = requests.delete(
+ "{}/pdp/{}".format(db_conf.get("url"), _slave_id),
+ headers={"x-api-key": manager_api_key}
+ )
+ break
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])
+ LOGGER.error("Cannot find PDP with name {}".format(name))
+ return False
+ if req.status_code == 200:
+ LOGGER.warning('Deleted {}'.format(name))
+ return True
+ LOGGER.error("Cannot delete PDP with name {}".format(name))
+ return False
- return {"pdps": data}
+ @staticmethod
+ @hug.object.cli
+ def update(name, description=None, security_pipeline=None, vim_project_id=None):
+ db_conf = configuration.get_configuration(key='management')
+ manager_api_key = connect_from_env()
+ _pdps = PDPCLI.list()
+
+ for _slave_id, _slave_value in _pdps.get("pdps").items():
+ if _slave_value.get("name") == name:
+ description_updated = _slave_value.get("description")
+ security_pipeline_updated = _slave_value.get("security_pipeline")
+ vim_project_id_updated = _slave_value.get("vim_project_id")
+
+ if description is not None:
+ description_updated = description
+ if security_pipeline is not None:
+ if security_pipeline == "":
+ LOGGER.error(f"Policy given to update the PDP {name} is unknown")
+ return
+ else:
+ security_pipeline_updated = security_pipeline.split(",")
+ if vim_project_id is not None:
+ vim_project_id_updated = vim_project_id
+
+ req = requests.patch(
+ "{}/pdp/{}".format(db_conf.get("url"), _slave_id),
+ json={
+ "name": name,
+ "security_pipeline": security_pipeline_updated,
+ "vim_project_id": vim_project_id_updated,
+ "description": description_updated,
+ },
+ headers={
+ "x-api-key": manager_api_key,
+ "Content-Type": "application/json"
+ }
+ )
+
+ if req.status_code == 200:
+ LOGGER.warning('Updated {}'.format(name))
+ return True
+ LOGGER.error('Cannot update PDP {}'.format(req.status_code))
+ return False
+
+ @staticmethod
+ def human_display(pdps_json):
+ human_result = "PDPs"
+ for pdp in pdps_json.get("pdps"):
+ human_result += "\n" + pdps_json.get("pdps").get(pdp).get("name") + " : \n"
+ human_result += "\tname : " + pdps_json.get("pdps").get(pdp).get("name") + "\n"
+ human_result += "\tid : " + pdp + "\n"
+ human_result += "\tdescription : " + pdps_json.get("pdps").get(pdp).get("description") + "\n"
+ human_result += "\tvim_project_id : " + pdps_json.get("pdps").get(pdp).get("vim_project_id") + "\n"
+ human_result += "\tsecurity_pipeline : \n"
+ for security_pipeline in pdps_json.get("pdps").get(pdp).get("security_pipeline"):
+ human_result += "\t\t" + security_pipeline + "\n"
+ return human_result
+
+ # FIXME: not tested
+ # @staticmethod
+ # @hug.object.cli
+ # def set_project(pdp_name, project_id):
+ # db_conf = configuration.get_configuration(key='management')
+ # manager_api_key = configuration.get_api_key_for_user("admin")
+ # _pdp = PDPCLI.get(pdp_name)
+ # _pdp_id = list(_pdp.get("pdps")[0].keys())[0]
+ # _pdp_name = _pdp.get("pdps")[0].get(_pdp_id).get("name")
+ # _pdps = requests.patch(
+ # "{}/pdp/{}".format(db_conf.get("url"), _pdp_id),
+ # json={
+ # "name": _pdp_name,
+ # "vim_project_id": project_id,
+ # },
+ # headers={
+ # "x-api-key": manager_api_key,
+ # "Content-Type": "application/json"
+ # }
+ # )
+ # if _pdps.status_code == 200:
+ # LOGGER.warning('Set project {}'.format(_pdps.content))
+ # return _pdps.json()
+ # LOGGER.error('Cannot set project {} (error: {})'.format(project_id, _pdps.status_code))
+ # return 'Cannot set project {} (error: {})'.format(project_id, _pdps.status_code)
+ #
+ # @staticmethod
+ # @hug.object.cli
+ # def add_pipeline(pdp_name, pipeline_id):
+ # db_conf = configuration.get_configuration(key='management')
+ # manager_api_key = configuration.get_api_key_for_user("admin")
+ # _pdp = PDPCLI.get(pdp_name)
+ # _pdp_id = list(_pdp.get("pdps")[0].keys())[0]
+ # _pdp_name = _pdp.get("pdps")[0].get(_pdp_id).get("name")
+ # _pdp_pipelines = _pdp.get("pdps")[0].get(_pdp_id).get("security_pipeline", [])
+ # # TODO check if pipeline exists
+ # _pdp_pipelines.append(pipeline_id)
+ # _pdps = requests.patch(
+ # "{}/pdp/{}".format(db_conf.get("url"), _pdp_id),
+ # json={
+ # "name": _pdp_name,
+ # "security_pipeline": _pdp_pipelines,
+ # },
+ # headers={
+ # "x-api-key": manager_api_key,
+ # "Content-Type": "application/json"
+ # }
+ # )
+ # if _pdps.status_code == 200:
+ # LOGGER.warning('Set project {}'.format(_pdps.content))
+ # return _pdps.json()
+ # LOGGER.error('Cannot add security pipeline {} (error: {})'.format(pipeline_id,
+ # _pdps.status_code))
+ # return 'Cannot add security pipeline {} (error: {})'.format(pipeline_id, _pdps.content)
+ #
+ # @staticmethod
+ # @hug.object.cli
+ # def delete_pipeline(pdp_name, pipeline_id):
+ # db_conf = configuration.get_configuration(key='management')
+ # manager_api_key = configuration.get_api_key_for_user("admin")
+ # _pdp = PDPCLI.get(pdp_name)
+ # _pdp_id = list(_pdp.get("pdps")[0].keys())[0]
+ # _pdp_name = _pdp.get("pdps")[0].get(_pdp_id).get("name")
+ # _pdp_pipelines = _pdp.get("pdps")[0].get(_pdp_id).get("security_pipeline")
+ # # TODO check if pipeline exists
+ # _pdp_pipelines.remove(pipeline_id)
+ # _pdps = requests.patch(
+ # "{}/pdp/{}".format(db_conf.get("url"), _pdp_id),
+ # json={
+ # "name": _pdp_name,
+ # "security_pipeline": _pdp_pipelines,
+ # },
+ # headers={
+ # "x-api-key": manager_api_key,
+ # "Content-Type": "application/json"
+ # }
+ # )
+ # if _pdps.status_code == 200:
+ # LOGGER.warning('Set project {}'.format(_pdps.content))
+ # return _pdps.json()
+ # LOGGER.error('Cannot add security pipeline {} (error: {})'.format(pipeline_id,
+ # _pdps.status_code))
+ # return 'Cannot add security pipeline {} (error: {})'.format(pipeline_id, _pdps.status_code)