Add moon_bouchon component. 97/48797/1
authorThomas Duval <thomas.duval@orange.com>
Wed, 13 Dec 2017 10:04:09 +0000 (11:04 +0100)
committerThomas Duval <thomas.duval@orange.com>
Wed, 13 Dec 2017 10:04:09 +0000 (11:04 +0100)
Change-Id: I6b5e88ca9349923c15c252f7f338b790a6714320

moonv4/moon_bouchon/Dockerfile [new file with mode: 0644]
moonv4/moon_bouchon/README.md [new file with mode: 0644]
moonv4/moon_bouchon/moon_bouchon/__init__.py [new file with mode: 0644]
moonv4/moon_bouchon/moon_bouchon/__main__.py [new file with mode: 0644]
moonv4/moon_bouchon/moon_bouchon/server.py [new file with mode: 0644]
moonv4/moon_bouchon/requirements.txt [new file with mode: 0644]
moonv4/moon_bouchon/setup.cfg [new file with mode: 0644]
moonv4/moon_bouchon/setup.py [new file with mode: 0644]
moonv4/moon_bouchon/tests/test_interface.py [new file with mode: 0644]
moonv4/moon_bouchon/tests/test_wrapper.py [new file with mode: 0644]

diff --git a/moonv4/moon_bouchon/Dockerfile b/moonv4/moon_bouchon/Dockerfile
new file mode 100644 (file)
index 0000000..ed01393
--- /dev/null
@@ -0,0 +1,8 @@
+FROM python:3
+
+ADD . /root
+RUN pip install -r /root/requirements.txt --upgrade
+WORKDIR /root
+RUN pip install .
+
+CMD ["python", "-m", "moon_bouchon"]
\ No newline at end of file
diff --git a/moonv4/moon_bouchon/README.md b/moonv4/moon_bouchon/README.md
new file mode 100644 (file)
index 0000000..11733ce
--- /dev/null
@@ -0,0 +1,42 @@
+#Moon Bouchon
+
+Moon_bouchon is a fake interface to the Moon platform.
+Moon platform can be requested through 2 interfaces:
+
+- ''wrapper'', interface for the OpenStack platform
+- ''interface'', interface for other components
+
+## Usage:
+
+### server
+
+To start the server:
+
+    docker run -ti -p 31002:31002 wukongsun/moon_bouchon:v1.0
+    # or docker run -dti -p 31002:31002 wukongsun/moon_bouchon:v1.0
+
+### wrapper
+
+Here are the URL, you can request:
+    
+    POST /wrapper/authz/grant to request the wrapper component with always a "True" response 
+    POST /wrapper/authz/deny to request the wrapper component with always a "False" response
+    POST /wrapper/authz to request the wrapper component with always a "True" or "False" response
+
+In each request you must pass the following data (or similar):
+
+    {'rule': 'start', 'target': '{"target": {"name": "vm0"}, "user_id": "user0"}', 'credentials': 'null'}
+
+You have examples in the moon_bouchon/tests directory.
+
+### interface
+
+Here are the URL, you can request:
+    
+    GET /interface/authz/grant/<string:project_id>/<string:subject_name>/<string:object_name>/<string:action_name> to request the interface component with always a "True" response 
+    GET /interface/authz/deny/<string:project_id>/<string:subject_name>/<string:object_name>/<string:action_name> to request the interface component with always a "False" response
+    GET /interface/authz/<string:project_id>/<string:subject_name>/<string:object_name>/<string:action_name> to request the interface component with always a "True" or "False" response
+
+You have examples in the moon_bouchon/tests directory.
+
+
diff --git a/moonv4/moon_bouchon/moon_bouchon/__init__.py b/moonv4/moon_bouchon/moon_bouchon/__init__.py
new file mode 100644 (file)
index 0000000..8811d91
--- /dev/null
@@ -0,0 +1,7 @@
+# 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__ = "1.1"
diff --git a/moonv4/moon_bouchon/moon_bouchon/__main__.py b/moonv4/moon_bouchon/moon_bouchon/__main__.py
new file mode 100644 (file)
index 0000000..4499a96
--- /dev/null
@@ -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'.
+
+
+import moon_bouchon.server
+
+moon_bouchon.server.main()
diff --git a/moonv4/moon_bouchon/moon_bouchon/server.py b/moonv4/moon_bouchon/moon_bouchon/server.py
new file mode 100644 (file)
index 0000000..29e9101
--- /dev/null
@@ -0,0 +1,138 @@
+# 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 sys
+import flask
+from flask import Flask
+from flask import request
+import json
+import logging
+import random
+
+logger = logging.getLogger(__name__)
+app = Flask(__name__)
+
+
+@app.route("/interface/authz/grant/<string:project_id>/<string:subject_name>/"
+           "<string:object_name>/<string:action_name>",
+           methods=["GET"])
+def interface_grant(project_id, subject_name, object_name, action_name):
+    logger.info("Requesting interface authz on {} {} {} {}".format(
+        project_id, subject_name, object_name, action_name))
+    return json.dumps({
+        "result": True,
+        "context": {
+            "project_id": project_id,
+            "subject_name": subject_name,
+            "object_name": object_name,
+            "action_name": action_name
+        }
+    })
+
+
+@app.route("/interface/authz/deny/<string:project_id>/<string:subject_name>/"
+           "<string:object_name>/<string:action_name>",
+           methods=["GET"])
+def interface_deny(project_id, subject_name, object_name, action_name):
+    logger.info("Requesting interface authz on {} {} {} {}".format(
+        project_id, subject_name, object_name, action_name))
+    return json.dumps({
+        "result": False,
+        "context": {
+            "project_id": project_id,
+            "subject_name": subject_name,
+            "object_name": object_name,
+            "action_name": action_name
+        }
+    })
+
+
+@app.route("/interface/authz/<string:project_id>/<string:subject_name>/"
+           "<string:object_name>/<string:action_name>",
+           methods=["GET"])
+def interface_authz(project_id, subject_name, object_name, action_name):
+    logger.info("Requesting interface authz on {} {} {} {}".format(
+        project_id, subject_name, object_name, action_name))
+    return json.dumps({
+        "result": random.choice((True, False)),
+        "context": {
+            "project_id": project_id,
+            "subject_name": subject_name,
+            "object_name": object_name,
+            "action_name": action_name
+        }
+    })
+
+
+def test_data():
+    data = request.form
+    if not dict(request.form):
+        data = json.loads(request.data.decode("utf-8"))
+    try:
+        target = json.loads(data.get('target', {}))
+    except Exception:
+        raise Exception("Error reading target")
+    try:
+        credentials = json.loads(data.get('credentials', {}))
+    except Exception:
+        raise Exception("Error reading credentials")
+    try:
+        rule = data.get('rule', "")
+    except Exception:
+        raise Exception("Error reading rule")
+
+
+@app.route("/wrapper/authz/grant", methods=["POST"])
+def wrapper_grant():
+    logger.info("Requesting wrapper authz")
+    try:
+        test_data()
+    except Exception as e:
+        logger.exception(e)
+        return str(e), 400
+    response = flask.make_response("True")
+    response.headers['content-type'] = 'application/octet-stream'
+    return response
+
+
+@app.route("/wrapper/authz/deny", methods=["POST"])
+def wrapper_deny():
+    logger.info("Requesting wrapper authz")
+    try:
+        test_data()
+    except Exception as e:
+        logger.exception(e)
+        return str(e), 400
+    response = flask.make_response("False")
+    response.headers['content-type'] = 'application/octet-stream'
+    return response
+
+
+@app.route("/wrapper/authz", methods=["POST"])
+def wrapper_authz():
+    logger.info("Requesting wrapper authz")
+    try:
+        test_data()
+    except Exception as e:
+        logger.exception(e)
+        return str(e), 400
+    response = flask.make_response(random.choice(("True", "False")))
+    response.headers['content-type'] = 'application/octet-stream'
+    return response
+
+
+def main():
+    port = 31002
+    if len(sys.argv) > 1:
+        try:
+            port = int(sys.argv[1])
+        except ValueError:
+            logger.error("Argument for Port in command line is not an integer")
+            sys.exit(1)
+    app.run(host="0.0.0.0", port=port)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/moonv4/moon_bouchon/requirements.txt b/moonv4/moon_bouchon/requirements.txt
new file mode 100644 (file)
index 0000000..8ab6294
--- /dev/null
@@ -0,0 +1 @@
+flask
\ No newline at end of file
diff --git a/moonv4/moon_bouchon/setup.cfg b/moonv4/moon_bouchon/setup.cfg
new file mode 100644 (file)
index 0000000..7c2b287
--- /dev/null
@@ -0,0 +1,2 @@
+[bdist_wheel]
+universal = 1
\ No newline at end of file
diff --git a/moonv4/moon_bouchon/setup.py b/moonv4/moon_bouchon/setup.py
new file mode 100644 (file)
index 0000000..a875be4
--- /dev/null
@@ -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_bouchon
+
+
+setup(
+
+    name='moon_bouchon',
+
+    version=moon_bouchon.__version__,
+
+    packages=find_packages(),
+
+    author="Thomas Duval",
+
+    author_email="thomas.duval@orange.com",
+
+    description="",
+
+    long_description=open('README.md').read(),
+
+    install_requires=["flask"],
+
+    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_bouchon = moon_bouchon.server:main',
+        ],
+    }
+
+)
diff --git a/moonv4/moon_bouchon/tests/test_interface.py b/moonv4/moon_bouchon/tests/test_interface.py
new file mode 100644 (file)
index 0000000..425ba2e
--- /dev/null
@@ -0,0 +1,61 @@
+import requests
+from uuid import uuid4
+import pytest
+
+
+@pytest.fixture
+def args():
+    return {
+        "project_id": uuid4().hex,
+        "subject_id": uuid4().hex,
+        "object_id": uuid4().hex,
+        "action_id": uuid4().hex
+    }
+
+
+def test_false(args):
+    url = "http://127.0.0.1:31002/interface/authz/deny/{project_id}" \
+          "/{subject_id}/{object_id}/{action_id}".format(**args)
+    data = {'rule': 'start',
+            'target': '{"target": {"name": "vm0"}, "user_id": "user0"}',
+            'credentials': 'null'}
+    req = requests.get(
+        url, json=data,
+        headers={'content-type': "application/x-www-form-urlencode"}
+    )
+    assert req.status_code == 200
+    assert "result" in req.json()
+    assert req.json()["result"] == False
+
+
+def test_true(args):
+    url = "http://127.0.0.1:31002/interface/authz/grant/{project_id}" \
+          "/{subject_id}/{object_id}/{action_id}".format(**args)
+
+    data = {'rule': 'start',
+            'target': '{"target": {"name": "vm0"}, "user_id": "user0"}',
+            'credentials': 'null'}
+    req = requests.get(
+        url, json=data,
+        headers={'content-type': "application/x-www-form-urlencode"}
+    )
+    assert req.status_code == 200
+    assert "result" in req.json()
+    assert req.json()["result"] == True
+
+
+def test_random(args):
+    url = "http://127.0.0.1:31002/interface/authz/{project_id}" \
+          "/{subject_id}/{object_id}/{action_id}".format(**args)
+
+    data = {'rule': 'start',
+            'target': '{"target": {"name": "vm0"}, "user_id": "user0"}',
+            'credentials': 'null'}
+    req = requests.get(
+        url, json=data,
+        headers={'content-type': "application/x-www-form-urlencode"}
+    )
+    assert req.status_code == 200
+    assert "result" in req.json()
+    assert req.json()["result"] in (False, True)
+
diff --git a/moonv4/moon_bouchon/tests/test_wrapper.py b/moonv4/moon_bouchon/tests/test_wrapper.py
new file mode 100644 (file)
index 0000000..3d5e150
--- /dev/null
@@ -0,0 +1,38 @@
+import requests
+
+
+def test_false():
+    url = "http://127.0.0.1:31002/wrapper/authz/deny"
+
+    data = {'rule': 'start', 'target': '{"target": {"name": "vm0"}, "user_id": "user0"}', 'credentials': 'null'}
+    req = requests.post(
+        url, json=data,
+        headers={'content-type': "application/x-www-form-urlencode"}
+    )
+    assert req.status_code == 200
+    assert req.text == "False"
+
+
+def test_true():
+    url = "http://127.0.0.1:31002/wrapper/authz/grant"
+
+    data = {'rule': 'start', 'target': '{"target": {"name": "vm0"}, "user_id": "user0"}', 'credentials': 'null'}
+    req = requests.post(
+        url, json=data,
+        headers={'content-type': "application/x-www-form-urlencode"}
+    )
+    assert req.status_code == 200
+    assert req.text == "True"
+
+
+def test_random():
+    url = "http://127.0.0.1:31002/wrapper/authz"
+
+    data = {'rule': 'start', 'target': '{"target": {"name": "vm0"}, "user_id": "user0"}', 'credentials': 'null'}
+    req = requests.post(
+        url, json=data,
+        headers={'content-type': "application/x-www-form-urlencode"}
+    )
+    assert req.status_code == 200
+    assert req.text in ("False", "True")
+