aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Duval <thomas.duval@orange.com>2017-12-13 11:04:09 +0100
committerThomas Duval <thomas.duval@orange.com>2017-12-13 11:04:09 +0100
commitbf495b93579a71dd01460cfeaf750703b239892d (patch)
tree54bcfd520a3ec14c0b7fd480ce8aa6d11841c7b6
parent4fa851471190f968289e04ae0f803b5b63744f6b (diff)
Add moon_bouchon component.
Change-Id: I6b5e88ca9349923c15c252f7f338b790a6714320
-rw-r--r--moonv4/moon_bouchon/Dockerfile8
-rw-r--r--moonv4/moon_bouchon/README.md42
-rw-r--r--moonv4/moon_bouchon/moon_bouchon/__init__.py7
-rw-r--r--moonv4/moon_bouchon/moon_bouchon/__main__.py9
-rw-r--r--moonv4/moon_bouchon/moon_bouchon/server.py138
-rw-r--r--moonv4/moon_bouchon/requirements.txt1
-rw-r--r--moonv4/moon_bouchon/setup.cfg2
-rw-r--r--moonv4/moon_bouchon/setup.py47
-rw-r--r--moonv4/moon_bouchon/tests/test_interface.py61
-rw-r--r--moonv4/moon_bouchon/tests/test_wrapper.py38
10 files changed, 353 insertions, 0 deletions
diff --git a/moonv4/moon_bouchon/Dockerfile b/moonv4/moon_bouchon/Dockerfile
new file mode 100644
index 00000000..ed013935
--- /dev/null
+++ b/moonv4/moon_bouchon/Dockerfile
@@ -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
index 00000000..11733cef
--- /dev/null
+++ b/moonv4/moon_bouchon/README.md
@@ -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
index 00000000..8811d91d
--- /dev/null
+++ b/moonv4/moon_bouchon/moon_bouchon/__init__.py
@@ -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
index 00000000..4499a96b
--- /dev/null
+++ b/moonv4/moon_bouchon/moon_bouchon/__main__.py
@@ -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
index 00000000..29e9101e
--- /dev/null
+++ b/moonv4/moon_bouchon/moon_bouchon/server.py
@@ -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
index 00000000..8ab6294c
--- /dev/null
+++ b/moonv4/moon_bouchon/requirements.txt
@@ -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
index 00000000..7c2b2874
--- /dev/null
+++ b/moonv4/moon_bouchon/setup.cfg
@@ -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
index 00000000..a875be40
--- /dev/null
+++ b/moonv4/moon_bouchon/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_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
index 00000000..425ba2e5
--- /dev/null
+++ b/moonv4/moon_bouchon/tests/test_interface.py
@@ -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
index 00000000..3d5e150c
--- /dev/null
+++ b/moonv4/moon_bouchon/tests/test_wrapper.py
@@ -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")
+