diff options
author | WuKong <rebirthmonkey@gmail.com> | 2017-12-23 21:49:35 +0100 |
---|---|---|
committer | WuKong <rebirthmonkey@gmail.com> | 2017-12-23 21:49:58 +0100 |
commit | 1100c66ce03a059ebe7ece9734e799b49b3a5a9e (patch) | |
tree | a057e7e7511f6675a9327b79e6919f07c5f89f07 /moon_wrapper | |
parent | 7a4dfdde6314476ae2a1a1c881ff1e3c430f790e (diff) |
moonv4 cleanup
Change-Id: Icef927f3236d985ac13ff7376f6ce6314b2b39b0
Signed-off-by: WuKong <rebirthmonkey@gmail.com>
Diffstat (limited to 'moon_wrapper')
-rw-r--r-- | moon_wrapper/Dockerfile | 12 | ||||
-rw-r--r-- | moon_wrapper/LICENSE | 202 | ||||
-rw-r--r-- | moon_wrapper/MANIFEST.in | 9 | ||||
-rw-r--r-- | moon_wrapper/README.md | 9 | ||||
-rw-r--r-- | moon_wrapper/moon_wrapper/__init__.py | 6 | ||||
-rw-r--r-- | moon_wrapper/moon_wrapper/__main__.py | 4 | ||||
-rw-r--r-- | moon_wrapper/moon_wrapper/api/__init__.py | 0 | ||||
-rw-r--r-- | moon_wrapper/moon_wrapper/api/generic.py | 131 | ||||
-rw-r--r-- | moon_wrapper/moon_wrapper/api/wrapper.py | 120 | ||||
-rw-r--r-- | moon_wrapper/moon_wrapper/http_server.py | 140 | ||||
-rw-r--r-- | moon_wrapper/moon_wrapper/server.py | 33 | ||||
-rw-r--r-- | moon_wrapper/requirements.txt | 5 | ||||
-rw-r--r-- | moon_wrapper/setup.py | 47 | ||||
-rw-r--r-- | moon_wrapper/tests/README.md | 35 | ||||
-rw-r--r-- | moon_wrapper/tests/unit_python/api/__init__.py | 0 | ||||
-rw-r--r-- | moon_wrapper/tests/unit_python/api/test_wrapper.py | 28 | ||||
-rw-r--r-- | moon_wrapper/tests/unit_python/conftest.py | 687 | ||||
-rw-r--r-- | moon_wrapper/tests/unit_python/requirements.txt | 5 |
18 files changed, 1473 insertions, 0 deletions
diff --git a/moon_wrapper/Dockerfile b/moon_wrapper/Dockerfile new file mode 100644 index 00000000..55e7208d --- /dev/null +++ b/moon_wrapper/Dockerfile @@ -0,0 +1,12 @@ +FROM ubuntu:latest + +RUN apt update && apt install python3.5 python3-pip -y +RUN pip3 install pip --upgrade + +ADD . /root +WORKDIR /root/ +RUN pip3 install -r requirements.txt --upgrade +RUN pip3 install /root/dist/* --upgrade +RUN pip3 install . + +CMD ["python3", "-m", "moon_wrapper"] diff --git a/moon_wrapper/LICENSE b/moon_wrapper/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/moon_wrapper/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/moon_wrapper/MANIFEST.in b/moon_wrapper/MANIFEST.in new file mode 100644 index 00000000..cf4d2e4e --- /dev/null +++ b/moon_wrapper/MANIFEST.in @@ -0,0 +1,9 @@ +# 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'. + +include README.md +include LICENSE +include setup.py +include requirements.txt diff --git a/moon_wrapper/README.md b/moon_wrapper/README.md new file mode 100644 index 00000000..4e8fd05c --- /dev/null +++ b/moon_wrapper/README.md @@ -0,0 +1,9 @@ +Wrapper module for the Moon project +=================================== + +This package contains the core module for the Moon project +It is designed to provide authorization features to all OpenStack components. + +For any other information, refer to the parent project: + + https://git.opnfv.org/moon diff --git a/moon_wrapper/moon_wrapper/__init__.py b/moon_wrapper/moon_wrapper/__init__.py new file mode 100644 index 00000000..903c6518 --- /dev/null +++ b/moon_wrapper/moon_wrapper/__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__ = "0.1.0" diff --git a/moon_wrapper/moon_wrapper/__main__.py b/moon_wrapper/moon_wrapper/__main__.py new file mode 100644 index 00000000..46cafa76 --- /dev/null +++ b/moon_wrapper/moon_wrapper/__main__.py @@ -0,0 +1,4 @@ +from moon_wrapper.server import main + +server = main() +server.run() diff --git a/moon_wrapper/moon_wrapper/api/__init__.py b/moon_wrapper/moon_wrapper/api/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/moon_wrapper/moon_wrapper/api/__init__.py diff --git a/moon_wrapper/moon_wrapper/api/generic.py b/moon_wrapper/moon_wrapper/api/generic.py new file mode 100644 index 00000000..7dd44fb4 --- /dev/null +++ b/moon_wrapper/moon_wrapper/api/generic.py @@ -0,0 +1,131 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. +""" +Those API are helping API used to manage the Moon platform. +""" + +from flask_restful import Resource, request +from oslo_log import log as logging +import moon_wrapper.api +from python_moonutilities.security_functions import check_auth + +__version__ = "0.1.0" + +LOG = 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_wrapper.api)) + api_desc = dict() + for api_name in api_list: + api_desc[api_name] = {} + group_api_obj = eval("moon_interface.api.{}".format(api_name)) + api_desc[api_name]["description"] = group_api_obj.__doc__ + if "__version__" in dir(group_api_obj): + api_desc[api_name]["version"] = group_api_obj.__version__ + object_list = list(filter(lambda x: "__" not in x, dir(group_api_obj))) + for obj in map(lambda x: eval("moon_interface.api.{}.{}".format(api_name, x)), object_list): + if "__urls__" in dir(obj): + api_desc[api_name][obj.__name__] = dict() + api_desc[api_name][obj.__name__]["urls"] = obj.__urls__ + api_desc[api_name][obj.__name__]["methods"] = dict() + for _method in filter(lambda x: x in __methods, dir(obj)): + docstring = eval("moon_interface.api.{}.{}.{}.__doc__".format(api_name, obj.__name__, _method)) + api_desc[api_name][obj.__name__]["methods"][_method] = docstring + api_desc[api_name][obj.__name__]["description"] = str(obj.__doc__) + if group_id in api_desc: + if endpoint_id in api_desc[group_id]: + return {group_id: {endpoint_id: api_desc[group_id][endpoint_id]}} + elif len(endpoint_id) > 0: + LOG.error("Unknown endpoint_id {}".format(endpoint_id)) + return {"error": "Unknown endpoint_id {}".format(endpoint_id)} + return {group_id: api_desc[group_id]} + return api_desc diff --git a/moon_wrapper/moon_wrapper/api/wrapper.py b/moon_wrapper/moon_wrapper/api/wrapper.py new file mode 100644 index 00000000..e1ce783a --- /dev/null +++ b/moon_wrapper/moon_wrapper/api/wrapper.py @@ -0,0 +1,120 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. +""" +Authz is the endpoint to get authorization response +""" + +import flask +from flask import request +from flask_restful import Resource +import logging +import json +import requests +from python_moonutilities import exceptions + +__version__ = "0.1.0" + +LOG = logging.getLogger("moon.wrapper.api." + __name__) + + +class Wrapper(Resource): + """ + Endpoint for authz requests + """ + + __urls__ = ( + "/authz", + "/authz/", + ) + + def __init__(self, **kwargs): + self.port = kwargs.get("port") + self.CACHE = kwargs.get("cache", {}) + self.TIMEOUT = 5 + + # def get(self): + # LOG.info("GET") + # return self.manage_data() + + def post(self): + LOG.debug("POST {}".format(request.form)) + response = flask.make_response("False") + if self.manage_data(): + response = flask.make_response("True") + response.headers['content-type'] = 'application/octet-stream' + return response + + @staticmethod + def __get_subject(target, credentials): + _subject = target.get("user_id", "") + if not _subject: + _subject = credentials.get("user_id", "none") + return _subject + + @staticmethod + def __get_object(target, credentials): + try: + # note: case of Glance + return target['target']['name'] + except KeyError: + pass + + # note: default case + return target.get("project_id", "none") + + @staticmethod + def __get_project_id(target, credentials): + LOG.info("__get_project_id {}".format(target)) + return target.get("project_id", "none") + + def get_interface_url(self, project_id): + LOG.info("project_id {}".format(project_id)) + for containers in self.CACHE.containers.values(): + LOG.info("containers {}".format(containers)) + for container in containers: + if container.get("keystone_project_id") == project_id: + if "interface" in container['name']: + return "http://{}:{}".format( + container['name'], + container['port']) + self.CACHE.update() + # Note (asteroide): test an other time after the update + for containers in self.CACHE.containers.values(): + for container in containers: + if container.get("keystone_project_id") == project_id: + if "interface" in container['name']: + return "http://{}:{}".format( + container['name'], + container['port']) + raise exceptions.AuthzException("Keystone Project " + "ID ({}) is unknown or not mapped " + "to a PDP.".format(project_id)) + + def manage_data(self): + data = request.form + if not dict(request.form): + data = json.loads(request.data.decode("utf-8")) + target = json.loads(data.get('target', {})) + credentials = json.loads(data.get('credentials', {})) + rule = data.get('rule', "") + _subject = self.__get_subject(target, credentials) + _object = self.__get_object(target, credentials) + _project_id = self.__get_project_id(target, credentials) + LOG.debug("POST with args project={} / " + "subject={} - object={} - action={}".format( + _project_id, _subject, _object, rule)) + interface_url = self.get_interface_url(_project_id) + LOG.debug("interface_url={}".format(interface_url)) + req = requests.get("{}/authz/{}/{}/{}/{}".format( + interface_url, + _project_id, + _subject, + _object, + rule + )) + LOG.debug("Get interface {}".format(req.text)) + if req.status_code == 200: + if req.json().get("result", False): + return True diff --git a/moon_wrapper/moon_wrapper/http_server.py b/moon_wrapper/moon_wrapper/http_server.py new file mode 100644 index 00000000..1b429bc5 --- /dev/null +++ b/moon_wrapper/moon_wrapper/http_server.py @@ -0,0 +1,140 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. + +from flask import Flask, jsonify +from flask_restful import Resource, Api +import logging +from moon_wrapper import __version__ +from moon_wrapper.api.generic import Status, Logs, API +from moon_wrapper.api.wrapper import Wrapper +from python_moonutilities.cache import Cache +from python_moonutilities import configuration, exceptions + +logger = logging.getLogger("moon.wrapper.http") + + +CACHE = Cache() + + +class Server: + """Base class for HTTP server""" + + def __init__(self, host="localhost", port=80, api=None, **kwargs): + """Run a server + + :param host: hostname of the server + :param port: port for the running server + :param kwargs: optional parameters + :return: a running server + """ + self._host = host + self._port = port + self._api = api + self._extra = kwargs + + @property + def host(self): + return self._host + + @host.setter + def host(self, name): + self._host = name + + @host.deleter + def host(self): + self._host = "" + + @property + def port(self): + return self._port + + @port.setter + def port(self, number): + self._port = number + + @port.deleter + def port(self): + self._port = 80 + + def run(self): + raise NotImplementedError() + +__API__ = ( + Status, Logs, API + ) + + +class Root(Resource): + """ + The root of the web service + """ + __urls__ = ("/", ) + __methods = ("get", "post", "put", "delete", "options") + + def get(self): + tree = {"/": {"methods": ("get",), + "description": "List all methods for that service."}} + for item in __API__: + tree[item.__name__] = {"urls": item.__urls__} + _methods = [] + for _method in self.__methods: + if _method in dir(item): + _methods.append(_method) + tree[item.__name__]["methods"] = _methods + tree[item.__name__]["description"] = item.__doc__.strip() + return { + "version": __version__, + "tree": tree + } + + +class HTTPServer(Server): + + def __init__(self, host="localhost", port=80, **kwargs): + super(HTTPServer, self).__init__(host=host, port=port, **kwargs) + self.app = Flask(__name__) + self.port = port + conf = configuration.get_configuration("components/orchestrator") + _hostname = conf["components/orchestrator"].get("hostname", + "orchestrator") + _port = conf["components/orchestrator"].get("port", 80) + _protocol = conf["components/orchestrator"].get("protocol", "http") + self.orchestrator_url = "{}://{}:{}".format( + _protocol, _hostname, _port) + # Todo : specify only few urls instead of * + # CORS(self.app) + self.api = Api(self.app) + self.__set_route() + self.__hook_errors() + + def __hook_errors(self): + + def get_404_json(e): + return jsonify({"result": False, "code": 404, + "description": str(e)}), 404 + self.app.register_error_handler(404, get_404_json) + + def get_400_json(e): + return jsonify({"result": False, "code": 400, + "description": str(e)}), 400 + self.app.register_error_handler(400, lambda e: get_400_json) + self.app.register_error_handler(403, exceptions.AuthException) + + def __set_route(self): + self.api.add_resource(Root, '/') + + for api in __API__: + self.api.add_resource(api, *api.__urls__) + self.api.add_resource(Wrapper, *Wrapper.__urls__, + resource_class_kwargs={ + "orchestrator_url": self.orchestrator_url, + "cache": CACHE, + } + ) + + def run(self): + self.app.run(host=self._host, port=self._port) # nosec + # self.app.run(debug=True, host=self._host, port=self._port) # nosec + diff --git a/moon_wrapper/moon_wrapper/server.py b/moon_wrapper/moon_wrapper/server.py new file mode 100644 index 00000000..2f236c4f --- /dev/null +++ b/moon_wrapper/moon_wrapper/server.py @@ -0,0 +1,33 @@ +# 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_wrapper.http_server import HTTPServer + +LOG = logging.getLogger("moon.wrapper") + + +def main(): + configuration.init_logging() + try: + conf = configuration.get_configuration("components/wrapper") + LOG.debug("wrapper.conf={}".format(conf)) + hostname = conf["components/wrapper"].get("hostname", "wrapper") + port = conf["components/wrapper"].get("port", 80) + bind = conf["components/wrapper"].get("bind", "127.0.0.1") + except exceptions.ConsulComponentNotFound: + hostname = "wrapper" + bind = "127.0.0.1" + port = 80 + configuration.add_component(uuid="wrapper", name=hostname, port=port, bind=bind) + LOG.info("Starting server with IP {} on port {} bind to {}".format(hostname, port, bind)) + server = HTTPServer(host=bind, port=port) + return server + + +if __name__ == '__main__': + server = main() + server.run() diff --git a/moon_wrapper/requirements.txt b/moon_wrapper/requirements.txt new file mode 100644 index 00000000..c1bd9a2f --- /dev/null +++ b/moon_wrapper/requirements.txt @@ -0,0 +1,5 @@ +flask +flask_restful +flask_cors +werkzeug +python_moonutilities
\ No newline at end of file diff --git a/moon_wrapper/setup.py b/moon_wrapper/setup.py new file mode 100644 index 00000000..6aaa343f --- /dev/null +++ b/moon_wrapper/setup.py @@ -0,0 +1,47 @@ +# 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 setuptools import setup, find_packages +import moon_wrapper + + +setup( + + name='moon_wrapper', + + version=moon_wrapper.__version__, + + packages=find_packages(), + + author="Thomas Duval", + + author_email="thomas.duval@orange.com", + + description="", + + long_description=open('README.md').read(), + + # install_requires= , + + include_package_data=True, + + url='https://git.opnfv.org/cgit/moon', + + classifiers=[ + "Programming Language :: Python", + "Development Status :: 1 - Planning", + "License :: OSI Approved", + "Natural Language :: French", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + ], + + entry_points={ + 'console_scripts': [ + 'moon_wrapper = moon_wrapper.server:main', + ], + } + +) diff --git a/moon_wrapper/tests/README.md b/moon_wrapper/tests/README.md new file mode 100644 index 00000000..73a9fcd2 --- /dev/null +++ b/moon_wrapper/tests/README.md @@ -0,0 +1,35 @@ +# Tests + +## Python Unit Test for moon_db + +- launch Docker for Python unit tests + + + cd ${MOON_HOME}/moonv4/moon_db/ + docker run -ti --volume ${PWD}:/data asteroide/moon_tests + + +## Build and upload python packages + +- build python packages + + + python setup.py sdist bdist_wheel + + +- upload moon_db to PIP + + + python setup.py upload + + +or + + + gpg --detach-sign -u "${GPG_ID}" -a dist/moon_db-X.Y.Z-py3-none-any.whl + gpg --detach-sign -u "${GPG_ID}" -a dist/moon_db-X.Y.Z.tar.gz + twine upload dist/moon_db-X.Y.Z-py3-none-any.whl dist/moon_db-X.Y.Z-py3-none-any.whl.asc + twine upload dist/moon_db-X.Y.Z.tar.gz dist/moon_db-X.Y.Z.tar.gz.asc + + + diff --git a/moon_wrapper/tests/unit_python/api/__init__.py b/moon_wrapper/tests/unit_python/api/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/moon_wrapper/tests/unit_python/api/__init__.py diff --git a/moon_wrapper/tests/unit_python/api/test_wrapper.py b/moon_wrapper/tests/unit_python/api/test_wrapper.py new file mode 100644 index 00000000..7e9a7421 --- /dev/null +++ b/moon_wrapper/tests/unit_python/api/test_wrapper.py @@ -0,0 +1,28 @@ +import json + + +def get_json(data): + return json.loads(data.decode("utf-8")) + + +def test_authz_true(context): + import moon_wrapper.server + server = moon_wrapper.server.main() + client = server.app.test_client() + _target = { + 'target': { + "name": context.get('object_name'), + }, + "project_id": context.get('project_id'), + "user_id": context.get('subject_name') + } + authz_data = { + 'rule': context.get('action_name'), + 'target': json.dumps(_target), + 'credentials': 'null'} + req = client.post("/authz", data=json.dumps(authz_data)) + assert req.status_code == 200 + assert req.data + assert isinstance(req.data, bytes) + assert req.data == b"True" + diff --git a/moon_wrapper/tests/unit_python/conftest.py b/moon_wrapper/tests/unit_python/conftest.py new file mode 100644 index 00000000..b160ebf6 --- /dev/null +++ b/moon_wrapper/tests/unit_python/conftest.py @@ -0,0 +1,687 @@ +import base64 +import json +import os +import pickle +import pytest +import requests_mock +from uuid import uuid4 +from requests.packages.urllib3.response import HTTPResponse + +CONF = { + "openstack": { + "keystone": { + "url": "http://keystone:5000/v3", + "user": "admin", + "check_token": False, + "password": "p4ssw0rd", + "domain": "default", + "certificate": False, + "project": "admin" + } + }, + "components": { + "wrapper": { + "bind": "0.0.0.0", + "port": 8080, + "container": "wukongsun/moon_wrapper:v4.3", + "timeout": 5, + "hostname": "wrapper" + }, + "manager": { + "bind": "0.0.0.0", + "port": 8082, + "container": "wukongsun/moon_manager:v4.3", + "hostname": "manager" + }, + "port_start": 31001, + "orchestrator": { + "bind": "0.0.0.0", + "port": 8083, + "container": "wukongsun/moon_orchestrator:v4.3", + "hostname": "orchestrator" + }, + "interface": { + "bind": "0.0.0.0", + "port": 8080, + "container": "wukongsun/moon_interface:v4.3", + "hostname": "interface" + } + }, + "plugins": { + "session": { + "port": 8082, + "container": "asteroide/session:latest" + }, + "authz": { + "port": 8081, + "container": "wukongsun/moon_authz:v4.3" + } + }, + "logging": { + "handlers": { + "file": { + "filename": "/tmp/moon.log", + "class": "logging.handlers.RotatingFileHandler", + "level": "DEBUG", + "formatter": "custom", + "backupCount": 3, + "maxBytes": 1048576 + }, + "console": { + "class": "logging.StreamHandler", + "formatter": "brief", + "level": "INFO", + "stream": "ext://sys.stdout" + } + }, + "formatters": { + "brief": { + "format": "%(levelname)s %(name)s %(message)-30s" + }, + "custom": { + "format": "%(asctime)-15s %(levelname)s %(name)s %(message)s" + } + }, + "root": { + "handlers": [ + "console" + ], + "level": "ERROR" + }, + "version": 1, + "loggers": { + "moon": { + "handlers": [ + "console", + "file" + ], + "propagate": False, + "level": "DEBUG" + } + } + }, + "slave": { + "name": None, + "master": { + "url": None, + "login": None, + "password": None + } + }, + "docker": { + "url": "tcp://172.88.88.1:2376", + "network": "moon" + }, + "database": { + "url": "sqlite:///database.db", + # "url": "mysql+pymysql://moon:p4sswOrd1@db/moon", + "driver": "sql" + }, + "messenger": { + "url": "rabbit://moon:p4sswOrd1@messenger:5672/moon" + } +} + +COMPONENTS = ( + "logging", + "openstack/keystone", + "database", + "slave", + "components/manager", + "components/orchestrator", + "components/interface", + "components/wrapper", +) + +CONTEXT = { + "project_id": "a64beb1cc224474fb4badd43173e7101", + "subject_name": "testuser", + "object_name": "vm1", + "action_name": "boot", + "request_id": uuid4().hex, + "interface_name": "interface", + "manager_url": "http://{}:{}".format( + CONF["components"]["manager"]["hostname"], + CONF["components"]["manager"]["port"] + ), + "cookie": uuid4().hex + } + + +def get_b64_conf(component=None): + if component == "components": + return base64.b64encode( + json.dumps(CONF["components"]).encode('utf-8')+b"\n").decode('utf-8') + elif component in CONF: + return base64.b64encode( + json.dumps( + CONF[component]).encode('utf-8')+b"\n").decode('utf-8') + elif not component: + return base64.b64encode( + json.dumps(CONF).encode('utf-8')+b"\n").decode('utf-8') + elif "/" in component: + key1, _, key2 = component.partition("/") + return base64.b64encode( + json.dumps( + CONF[key1][key2]).encode('utf-8')+b"\n").decode('utf-8') + + +MOCK_URLS = [ + ('GET', 'http://consul:8500/v1/kv/components?recurse=true', + {'json': {"Key": key, "Value": get_b64_conf(key)} + for key in COMPONENTS} + ), + ('POST', 'http://keystone:5000/v3/auth/tokens', + {'headers': {'X-Subject-Token': "111111111"}}), + ('DELETE', 'http://keystone:5000/v3/auth/tokens', + {'headers': {'X-Subject-Token': "111111111"}}), + ('POST', 'http://keystone:5000/v3/users?name=testuser&domain_id=default', + {'json': {"users": {}}}), + ('GET', 'http://keystone:5000/v3/users?name=testuser&domain_id=default', + {'json': {"users": {}}}), + ('POST', 'http://keystone:5000/v3/users/', + {'json': {"users": [{ + "id": "1111111111111" + }]}}), +] + + +@pytest.fixture +def db(): + return CONF['database'] + + +@pytest.fixture +def context(): + return CONTEXT + + +def set_env_variables(): + os.environ['UUID'] = "1111111111" + os.environ['TYPE'] = "authz" + os.environ['PORT'] = "8081" + os.environ['PDP_ID'] = "b3d3e18abf3340e8b635fd49e6634ccd" + os.environ['META_RULE_ID'] = "f8f49a779ceb47b3ac810f01ef71b4e0" + os.environ['KEYSTONE_PROJECT_ID'] = CONTEXT['project_id'] + + +def get_pickled_context(): + from python_moonutilities.security_functions import Context + from python_moonutilities.cache import Cache + CACHE = Cache() + CACHE.update() + _context = Context(context(), CACHE) + _context.increment_index() + _context.pdp_set['effect'] = 'grant' + _context.pdp_set[os.environ['META_RULE_ID']]['effect'] = 'grant' + return pickle.dumps(_context) + + +@pytest.fixture(autouse=True) +def set_consul_and_db(monkeypatch): + """ Modify the response from Requests module + """ + set_env_variables() + with requests_mock.Mocker(real_http=True) as m: + for component in COMPONENTS: + m.register_uri( + 'GET', 'http://consul:8500/v1/kv/{}'.format(component), + json=[{'Key': component, 'Value': get_b64_conf(component)}] + ) + # for _data in MOCK_URLS: + # m.register_uri(_data[0], _data[1], **_data[2]) + m.register_uri( + 'GET', 'http://consul:8500/v1/kv/components?recurse=true', + json=[ + {"Key": key, "Value": get_b64_conf(key)} for key in COMPONENTS + ], + ) + m.register_uri( + 'GET', 'http://consul:8500/v1/kv/plugins/authz', + json=[ + { + "LockIndex": 0, + "Key": "plugins/authz", + "Flags": 0, + "Value": "eyJjb250YWluZXIiOiAid3Vrb25nc3VuL21vb25fYXV0aHo6djQuMyIsICJwb3J0IjogODA4MX0=", + "CreateIndex": 14, + "ModifyIndex": 656 + } + ], + ) + m.register_uri( + 'POST', 'http://keystone:5000/v3/auth/tokens', + headers={'X-Subject-Token': "111111111"} + ) + m.register_uri( + 'DELETE', 'http://keystone:5000/v3/auth/tokens', + headers={'X-Subject-Token': "111111111"} + ) + m.register_uri( + 'POST', 'http://keystone:5000/v3/users?name=testuser&domain_id=default', + json={"users": {}} + ) + m.register_uri( + 'GET', 'http://keystone:5000/v3/users?name=testuser&domain_id=default', + json={"users": {}} + ) + m.register_uri( + 'POST', 'http://keystone:5000/v3/users/', + json={"users": [{ + "id": "1111111111111" + }]} + ) + m.register_uri( + 'GET', 'http://orchestrator:8083/pods', + json={ + "pods": { + "721760dd-de5f-11e7-8001-3863bbb766f3": [ + { + "pdp_id": "b3d3e18abf3340e8b635fd49e6634ccd", + "port": 8080, + "genre": "interface", + "name": "interface-paltry", + "keystone_project_id": "a64beb1cc224474fb4badd43173e7101", + "namespace": "moon", + "container": "wukongsun/moon_interface:v4.3" + }, + { + "pdp_id": "b3d3e18abf3340e8b635fd49e6634ccd", + "meta_rule_id": "f8f49a779ceb47b3ac810f01ef71b4e0", + "port": 8081, + "genre": "authz", + "name": "authz-economic", + "policy_id": "f8f49a779ceb47b3ac810f01ef71b4e0", + "keystone_project_id": "a64beb1cc224474fb4badd43173e7101", + "namespace": "moon", + "container": "wukongsun/moon_authz:v4.3" + } + ], + "232399a4-de5f-11e7-8001-3863bbb766f3": [ + { + "port": 8080, + "namespace": "moon", + "name": "wrapper-paltry", + "container": "wukongsun/moon_wrapper:v4.3.1" + } + ] + } + } + ) + m.register_uri( + 'GET', 'http://orchestrator:8083/pods/authz-economic', + json={ + "pods": None + } + ) + m.register_uri( + 'GET', 'http://manager:8082/pdp', + json={ + "pdps": { + "b3d3e18abf3340e8b635fd49e6634ccd": { + "description": "test", + "security_pipeline": [ + "f8f49a779ceb47b3ac810f01ef71b4e0" + ], + "name": "pdp_rbac", + "keystone_project_id": "a64beb1cc224474fb4badd43173e7101" + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies', + json={ + "policies": { + "f8f49a779ceb47b3ac810f01ef71b4e0": { + "name": "RBAC policy example", + "model_id": "cd923d8633ff4978ab0e99938f5153d6", + "description": "test", + "genre": "authz" + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/models', + json={ + "models": { + "cd923d8633ff4978ab0e99938f5153d6": { + "name": "RBAC", + "meta_rules": [ + "f8f49a779ceb47b3ac810f01ef71b4e0" + ], + "description": "test" + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/meta_rules', + json={ + "meta_rules": { + "f8f49a779ceb47b3ac810f01ef71b4e0": { + "subject_categories": [ + "14e6ae0ba34d458b876c791b73aa17bd" + ], + "action_categories": [ + "241a2a791554421a91c9f1bc564aa94d" + ], + "description": "", + "name": "rbac", + "object_categories": [ + "6d48500f639d4c2cab2b1f33ef93a1e8" + ] + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies/f8f49a779ceb47b3ac810f01ef71b4e0/subjects', + json={ + "subjects": { + "89ba91c18dd54abfbfde7a66936c51a6": { + "description": "test", + "policy_list": [ + "f8f49a779ceb47b3ac810f01ef71b4e0", + "636cd473324f4c0bbd9102cb5b62a16d" + ], + "name": "testuser", + "email": "mail", + "id": "89ba91c18dd54abfbfde7a66936c51a6", + "partner_id": "" + }, + "31fd15ad14784a9696fcc887dddbfaf9": { + "description": "test", + "policy_list": [ + "f8f49a779ceb47b3ac810f01ef71b4e0", + "636cd473324f4c0bbd9102cb5b62a16d" + ], + "name": "adminuser", + "email": "mail", + "id": "31fd15ad14784a9696fcc887dddbfaf9", + "partner_id": "" + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies/f8f49a779ceb47b3ac810f01ef71b4e0/objects', + json={ + "objects": { + "67b8008a3f8d4f8e847eb628f0f7ca0e": { + "name": "vm1", + "description": "test", + "id": "67b8008a3f8d4f8e847eb628f0f7ca0e", + "partner_id": "", + "policy_list": [ + "f8f49a779ceb47b3ac810f01ef71b4e0", + "636cd473324f4c0bbd9102cb5b62a16d" + ] + }, + "9089b3d2ce5b4e929ffc7e35b55eba1a": { + "name": "vm0", + "description": "test", + "id": "9089b3d2ce5b4e929ffc7e35b55eba1a", + "partner_id": "", + "policy_list": [ + "f8f49a779ceb47b3ac810f01ef71b4e0", + "636cd473324f4c0bbd9102cb5b62a16d" + ] + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies/f8f49a779ceb47b3ac810f01ef71b4e0/actions', + json={ + "actions": { + "cdb3df220dc05a6ea3334b994827b068": { + "name": "boot", + "description": "test", + "id": "cdb3df220dc04a6ea3334b994827b068", + "partner_id": "", + "policy_list": [ + "f8f49a779ceb47b3ac810f01ef71b4e0", + "636cd473324f4c0bbd9102cb5b62a16d" + ] + }, + "cdb3df220dc04a6ea3334b994827b068": { + "name": "stop", + "description": "test", + "id": "cdb3df220dc04a6ea3334b994827b068", + "partner_id": "", + "policy_list": [ + "f8f49a779ceb47b3ac810f01ef71b4e0", + "636cd473324f4c0bbd9102cb5b62a16d" + ] + }, + "9f5112afe9b34a6c894eb87246ccb7aa": { + "name": "start", + "description": "test", + "id": "9f5112afe9b34a6c894eb87246ccb7aa", + "partner_id": "", + "policy_list": [ + "f8f49a779ceb47b3ac810f01ef71b4e0", + "636cd473324f4c0bbd9102cb5b62a16d" + ] + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies/f8f49a779ceb47b3ac810f01ef71b4e0/subject_assignments', + json={ + "subject_assignments": { + "826c1156d0284fc9b4b2ddb279f63c52": { + "category_id": "14e6ae0ba34d458b876c791b73aa17bd", + "assignments": [ + "24ea95256c5f4c888c1bb30a187788df", + "6b227b77184c48b6a5e2f3ed1de0c02a", + "31928b17ec90438ba5a2e50ae7650e63", + "4e60f554dd3147af87595fb6b37dcb13", + "7a5541b63a024fa88170a6b59f99ccd7", + "dd2af27812f742029d289df9687d6126" + ], + "id": "826c1156d0284fc9b4b2ddb279f63c52", + "subject_id": "89ba91c18dd54abfbfde7a66936c51a6", + "policy_id": "f8f49a779ceb47b3ac810f01ef71b4e0" + }, + "7407ffc1232944279b0cbcb0847c86f7": { + "category_id": "315072d40d774c43a89ff33937ed24eb", + "assignments": [ + "6b227b77184c48b6a5e2f3ed1de0c02a", + "31928b17ec90438ba5a2e50ae7650e63", + "7a5541b63a024fa88170a6b59f99ccd7", + "dd2af27812f742029d289df9687d6126" + ], + "id": "7407ffc1232944279b0cbcb0847c86f7", + "subject_id": "89ba91c18dd54abfbfde7a66936c51a6", + "policy_id": "3e65256389b448cb9897917ea235f0bb" + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies/f8f49a779ceb47b3ac810f01ef71b4e0/object_assignments', + json={ + "object_assignments": { + "201ad05fd3f940948b769ab9214fe295": { + "object_id": "9089b3d2ce5b4e929ffc7e35b55eba1a", + "assignments": [ + "030fbb34002e4236a7b74eeb5fd71e35", + "06bcb8655b9d46a9b90e67ef7c825b50", + "34eb45d7f46d4fb6bc4965349b8e4b83", + "4b7793dbae434c31a77da9d92de9fa8c" + ], + "id": "201ad05fd3f940948b769ab9214fe295", + "category_id": "6d48500f639d4c2cab2b1f33ef93a1e8", + "policy_id": "f8f49a779ceb47b3ac810f01ef71b4e0" + }, + "90c5e86f8be34c0298fbd1973e4fb043": { + "object_id": "67b8008a3f8d4f8e847eb628f0f7ca0e", + "assignments": [ + "a098918e915b4b12bccb89f9a3f3b4e4", + "06bcb8655b9d46a9b90e67ef7c825b50", + "7dc76c6142af47c88b60cc2b0df650ba", + "4b7793dbae434c31a77da9d92de9fa8c" + ], + "id": "90c5e86f8be34c0298fbd1973e4fb043", + "category_id": "33aece52d45b4474a20dc48a76800daf", + "policy_id": "3e65256389b448cb9897917ea235f0bb" + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies/f8f49a779ceb47b3ac810f01ef71b4e0/action_assignments', + json={ + "action_assignments": { + "2128e3ffbd1c4ef5be515d625745c2d4": { + "category_id": "241a2a791554421a91c9f1bc564aa94d", + "action_id": "cdb3df220dc05a6ea3334b994827b068", + "policy_id": "f8f49a779ceb47b3ac810f01ef71b4e0", + "id": "2128e3ffbd1c4ef5be515d625745c2d4", + "assignments": [ + "570c036781e540dc9395b83098c40ba7", + "7fe17d7a2e3542719f8349c3f2273182", + "015ca6f40338422ba3f692260377d638", + "23d44c17bf88480f83e8d57d2aa1ea79" + ] + }, + "cffb98852f3a4110af7a0ddfc4e19201": { + "category_id": "4a2c5abaeaf644fcaf3ca8df64000d53", + "action_id": "cdb3df220dc04a6ea3334b994827b068", + "policy_id": "3e65256389b448cb9897917ea235f0bb", + "id": "cffb98852f3a4110af7a0ddfc4e19201", + "assignments": [ + "570c036781e540dc9395b83098c40ba7", + "7fe17d7a2e3542719f8349c3f2273182", + "015ca6f40338422ba3f692260377d638", + "23d44c17bf88480f83e8d57d2aa1ea79" + ] + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies/f8f49a779ceb47b3ac810f01ef71b4e0/subject_assignments/89ba91c18dd54abfbfde7a66936c51a6', + json={ + "subject_assignments": { + "826c1156d0284fc9b4b2ddb279f63c52": { + "category_id": "14e6ae0ba34d458b876c791b73aa17bd", + "assignments": [ + "24ea95256c5f4c888c1bb30a187788df", + "6b227b77184c48b6a5e2f3ed1de0c02a", + "31928b17ec90438ba5a2e50ae7650e63", + "4e60f554dd3147af87595fb6b37dcb13", + "7a5541b63a024fa88170a6b59f99ccd7", + "dd2af27812f742029d289df9687d6126" + ], + "id": "826c1156d0284fc9b4b2ddb279f63c52", + "subject_id": "89ba91c18dd54abfbfde7a66936c51a6", + "policy_id": "f8f49a779ceb47b3ac810f01ef71b4e0" + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies/f8f49a779ceb47b3ac810f01ef71b4e0/object_assignments/67b8008a3f8d4f8e847eb628f0f7ca0e', + json={ + "object_assignments": { + "201ad05fd3f940948b769ab9214fe295": { + "object_id": "67b8008a3f8d4f8e847eb628f0f7ca0e", + "assignments": [ + "030fbb34002e4236a7b74eeb5fd71e35", + "06bcb8655b9d46a9b90e67ef7c825b50", + "34eb45d7f46d4fb6bc4965349b8e4b83", + "4b7793dbae434c31a77da9d92de9fa8c" + ], + "id": "201ad05fd3f940948b769ab9214fe295", + "category_id": "6d48500f639d4c2cab2b1f33ef93a1e8", + "policy_id": "f8f49a779ceb47b3ac810f01ef71b4e0" + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies/f8f49a779ceb47b3ac810f01ef71b4e0/action_assignments/cdb3df220dc05a6ea3334b994827b068', + json={ + "action_assignments": { + "2128e3ffbd1c4ef5be515d625745c2d4": { + "category_id": "241a2a791554421a91c9f1bc564aa94d", + "action_id": "cdb3df220dc05a6ea3334b994827b068", + "policy_id": "f8f49a779ceb47b3ac810f01ef71b4e0", + "id": "2128e3ffbd1c4ef5be515d625745c2d4", + "assignments": [ + "570c036781e540dc9395b83098c40ba7", + "7fe17d7a2e3542719f8349c3f2273182", + "015ca6f40338422ba3f692260377d638", + "23d44c17bf88480f83e8d57d2aa1ea79" + ] + } + } + } + ) + m.register_uri( + 'GET', 'http://manager:8082/policies/f8f49a779ceb47b3ac810f01ef71b4e0/rules', + json={ + "rules": { + "policy_id": "f8f49a779ceb47b3ac810f01ef71b4e0", + "rules": [ + { + "policy_id": "f8f49a779ceb47b3ac810f01ef71b4e0", + "rule": [ + "24ea95256c5f4c888c1bb30a187788df", + "030fbb34002e4236a7b74eeb5fd71e35", + "570c036781e540dc9395b83098c40ba7" + ], + "enabled": True, + "id": "0201a2bcf56943c1904dbac016289b71", + "instructions": [ + { + "decision": "grant" + } + ], + "meta_rule_id": "f8f49a779ceb47b3ac810f01ef71b4e0" + }, + { + "policy_id": "ecc2451c494e47b5bca7250cd324a360", + "rule": [ + "54f574cd2043468da5d65e4f6ed6e3c9", + "6559686961a3490a978f246ac9f85fbf", + "ac0d1f600bf447e8bd2f37b7cc47f2dc" + ], + "enabled": True, + "id": "a83fed666af8436192dfd8b3c83a6fde", + "instructions": [ + { + "decision": "grant" + } + ], + "meta_rule_id": "f8f49a779ceb47b3ac810f01ef71b4e0" + } + ] + } + } + ) + m.register_uri( + 'POST', 'http://127.0.0.1:8081/authz', + content=get_pickled_context() + ) + m.register_uri( + 'GET', 'http://interface-paltry:8080/authz/{}/{}/{}/{}'.format( + CONTEXT.get("project_id"), + CONTEXT.get("subject_name"), + CONTEXT.get("object_name"), + CONTEXT.get("action_name"), + ), + json={"result": True, "message": "================"} + ) + # from moon_db.db_manager import init_engine, run + # engine = init_engine() + # run("upgrade", logging.getLogger("db_manager"), engine) + yield m + # os.unlink(CONF['database']['url'].replace("sqlite:///", "")) + + diff --git a/moon_wrapper/tests/unit_python/requirements.txt b/moon_wrapper/tests/unit_python/requirements.txt new file mode 100644 index 00000000..21975ce3 --- /dev/null +++ b/moon_wrapper/tests/unit_python/requirements.txt @@ -0,0 +1,5 @@ +flask +flask_cors +flask_restful +python_moondb +python_moonutilities
\ No newline at end of file |