aboutsummaryrefslogtreecommitdiffstats
path: root/moonv4/moon_interface
diff options
context:
space:
mode:
authorWuKong <rebirthmonkey@gmail.com>2017-04-22 13:25:07 +0200
committerWuKong <rebirthmonkey@gmail.com>2017-04-22 13:25:07 +0200
commitd182202fc6001983541504ed323d68479086317e (patch)
tree11d4c10cdd3e995f519c3e0e324968fdaf175114 /moonv4/moon_interface
parent83c1c966baf73329fab8ddcfad19ad7fe0c41c2a (diff)
add moonv4
Change-Id: I247af788d0b0fb961fbc85416486b241eb1d807c Signed-off-by: WuKong <rebirthmonkey@gmail.com>
Diffstat (limited to 'moonv4/moon_interface')
-rw-r--r--moonv4/moon_interface/.cache/v/cache/lastfailed1
-rw-r--r--moonv4/moon_interface/LICENSE204
-rw-r--r--moonv4/moon_interface/MANIFEST.in9
-rw-r--r--moonv4/moon_interface/Makefile12
-rw-r--r--moonv4/moon_interface/README.rst9
-rw-r--r--moonv4/moon_interface/moon_interface/__init__.py6
-rw-r--r--moonv4/moon_interface/moon_interface/__main__.py3
-rw-r--r--moonv4/moon_interface/moon_interface/api/__init__.py0
-rw-r--r--moonv4/moon_interface/moon_interface/api/assignments.py261
-rw-r--r--moonv4/moon_interface/moon_interface/api/authz.py66
-rw-r--r--moonv4/moon_interface/moon_interface/api/data.py261
-rw-r--r--moonv4/moon_interface/moon_interface/api/generic.py153
-rw-r--r--moonv4/moon_interface/moon_interface/api/meta_data.py206
-rw-r--r--moonv4/moon_interface/moon_interface/api/meta_rules.py140
-rw-r--r--moonv4/moon_interface/moon_interface/api/models.py103
-rw-r--r--moonv4/moon_interface/moon_interface/api/pdp.py108
-rw-r--r--moonv4/moon_interface/moon_interface/api/perimeter.py314
-rw-r--r--moonv4/moon_interface/moon_interface/api/policies.py108
-rw-r--r--moonv4/moon_interface/moon_interface/api/rules.py95
-rw-r--r--moonv4/moon_interface/moon_interface/http_server.py173
-rw-r--r--moonv4/moon_interface/moon_interface/server.py26
-rw-r--r--moonv4/moon_interface/moon_interface/tools.py99
-rw-r--r--moonv4/moon_interface/requirements.txt7
-rw-r--r--moonv4/moon_interface/setup.py47
-rw-r--r--moonv4/moon_interface/tests/apitests/README.md33
-rw-r--r--moonv4/moon_interface/tests/apitests/populate_default_values.py149
-rw-r--r--moonv4/moon_interface/tests/apitests/scenario/mls.py44
-rw-r--r--moonv4/moon_interface/tests/apitests/scenario/rbac.py32
-rw-r--r--moonv4/moon_interface/tests/apitests/scenario/rbac_mls.py50
-rw-r--r--moonv4/moon_interface/tests/apitests/test_models.py37
-rw-r--r--moonv4/moon_interface/tests/apitests/test_pdp.py16
-rw-r--r--moonv4/moon_interface/tests/apitests/test_policies.py154
-rw-r--r--moonv4/moon_interface/tests/apitests/utils/__init__.py0
-rw-r--r--moonv4/moon_interface/tests/apitests/utils/models.py260
-rw-r--r--moonv4/moon_interface/tests/apitests/utils/pdp.py145
-rw-r--r--moonv4/moon_interface/tests/apitests/utils/policies.py581
-rw-r--r--moonv4/moon_interface/tools/api2rst.py145
-rw-r--r--moonv4/moon_interface/tools/get_keystone_token.py72
-rw-r--r--moonv4/moon_interface/tools/run.sh5
39 files changed, 4134 insertions, 0 deletions
diff --git a/moonv4/moon_interface/.cache/v/cache/lastfailed b/moonv4/moon_interface/.cache/v/cache/lastfailed
new file mode 100644
index 00000000..9e26dfee
--- /dev/null
+++ b/moonv4/moon_interface/.cache/v/cache/lastfailed
@@ -0,0 +1 @@
+{} \ No newline at end of file
diff --git a/moonv4/moon_interface/LICENSE b/moonv4/moon_interface/LICENSE
new file mode 100644
index 00000000..4143aac2
--- /dev/null
+++ b/moonv4/moon_interface/LICENSE
@@ -0,0 +1,204 @@
+
+ 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.
+
+--- License for python-keystoneclient versions prior to 2.1 ---
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of this project nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/moonv4/moon_interface/MANIFEST.in b/moonv4/moon_interface/MANIFEST.in
new file mode 100644
index 00000000..1f674d50
--- /dev/null
+++ b/moonv4/moon_interface/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.rst
+include LICENSE
+include setup.py
+include requirements.txt
diff --git a/moonv4/moon_interface/Makefile b/moonv4/moon_interface/Makefile
new file mode 100644
index 00000000..af91b904
--- /dev/null
+++ b/moonv4/moon_interface/Makefile
@@ -0,0 +1,12 @@
+all: built run
+
+built:
+ docker build -t moon_policy:16.04 .
+
+run:
+ docker run -p 8000:8000 moon_policy:16.04
+
+.PHONY: clean
+
+clean:
+ find . -name "*.py" -exec echo rm {}\;
diff --git a/moonv4/moon_interface/README.rst b/moonv4/moon_interface/README.rst
new file mode 100644
index 00000000..ded4e99a
--- /dev/null
+++ b/moonv4/moon_interface/README.rst
@@ -0,0 +1,9 @@
+Core 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/moonv4/moon_interface/moon_interface/__init__.py b/moonv4/moon_interface/moon_interface/__init__.py
new file mode 100644
index 00000000..903c6518
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/__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/moonv4/moon_interface/moon_interface/__main__.py b/moonv4/moon_interface/moon_interface/__main__.py
new file mode 100644
index 00000000..2dac7b1d
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/__main__.py
@@ -0,0 +1,3 @@
+from moon_interface.server import main
+
+main()
diff --git a/moonv4/moon_interface/moon_interface/api/__init__.py b/moonv4/moon_interface/moon_interface/api/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/__init__.py
diff --git a/moonv4/moon_interface/moon_interface/api/assignments.py b/moonv4/moon_interface/moon_interface/api/assignments.py
new file mode 100644
index 00000000..c270440a
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/assignments.py
@@ -0,0 +1,261 @@
+# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
+# This software is distributed under the terms and conditions of the 'Apache-2.0'
+# license which can be found in the file 'LICENSE' in this package distribution
+# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
+"""
+Assignments allow to connect data with elements of perimeter
+
+"""
+
+from flask import request
+from flask_restful import Resource
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+from moon_interface.tools import check_auth
+
+__version__ = "0.2.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+class SubjectAssignments(Resource):
+ """
+ Endpoint for subject assignment requests
+ """
+
+ __urls__ = (
+ "/policies/<string:uuid>/subject_assignments",
+ "/policies/<string:uuid>/subject_assignments/",
+ "/policies/<string:uuid>/subject_assignments/<string:perimeter_id>",
+ "/policies/<string:uuid>/subject_assignments/<string:perimeter_id>/<string:category_id>",
+ "/policies/<string:uuid>/subject_assignments/<string:perimeter_id>/<string:category_id>/<string:data_id>",
+ )
+
+ @check_auth
+ def get(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
+ """Retrieve all subject assignments or a specific one for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the subject
+ :param category_id: uuid of the subject category
+ :param data_id: uuid of the subject scope
+ :param user_id: user ID who do the request
+ :return: {
+ "subject_data_id": {
+ "policy_id": "ID of the policy",
+ "subject_id": "ID of the subject",
+ "category_id": "ID of the category",
+ "assignments": "Assignments list (list of data_id)",
+ }
+ }
+ :internal_api: get_subject_assignments
+ """
+ return call(ctx={"id": uuid, "method": "get_subject_assignments", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+ @check_auth
+ def post(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
+ """Create a subject assignment.
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the subject (not used here)
+ :param category_id: uuid of the subject category (not used here)
+ :param data_id: uuid of the subject scope (not used here)
+ :param user_id: user ID who do the request
+ :request body: {
+ "id": "UUID of the subject",
+ "category_id": "UUID of the category"
+ "data_id": "UUID of the scope"
+ }
+ :return: {
+ "subject_data_id": {
+ "policy_id": "ID of the policy",
+ "subject_id": "ID of the subject",
+ "category_id": "ID of the category",
+ "assignments": "Assignments list (list of data_id)",
+ }
+ }
+ :internal_api: update_subject_assignment
+ """
+ return call(ctx={"id": uuid, "method": "update_subject_assignment", "user_id": user_id}, args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
+ """Delete a subject assignment for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the subject
+ :param category_id: uuid of the subject category
+ :param data_id: uuid of the subject scope
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_subject_assignment
+ """
+ return call(ctx={"id": uuid, "method": "delete_subject_assignment", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+
+class ObjectAssignments(Resource):
+ """
+ Endpoint for object assignment requests
+ """
+
+ __urls__ = (
+ "/policies/<string:uuid>/object_assignments",
+ "/policies/<string:uuid>/object_assignments/",
+ "/policies/<string:uuid>/object_assignments/<string:perimeter_id>",
+ "/policies/<string:uuid>/object_assignments/<string:perimeter_id>/<string:category_id>",
+ "/policies/<string:uuid>/object_assignments/<string:perimeter_id>/<string:category_id>/<string:data_id>",
+ )
+
+ @check_auth
+ def get(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
+ """Retrieve all object assignment or a specific one for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the object
+ :param category_id: uuid of the object category
+ :param data_id: uuid of the object scope
+ :param user_id: user ID who do the request
+ :return: {
+ "object_data_id": {
+ "policy_id": "ID of the policy",
+ "object_id": "ID of the object",
+ "category_id": "ID of the category",
+ "assignments": "Assignments list (list of data_id)",
+ }
+ }
+ :internal_api: get_object_assignments
+ """
+ return call(ctx={"id": uuid, "method": "get_object_assignments", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+ @check_auth
+ def post(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
+ """Create an object assignment.
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the object (not used here)
+ :param category_id: uuid of the object category (not used here)
+ :param data_id: uuid of the object scope (not used here)
+ :param user_id: user ID who do the request
+ :request body: {
+ "id": "UUID of the action",
+ "category_id": "UUID of the category"
+ "data_id": "UUID of the scope"
+ }
+ :return: {
+ "object_data_id": {
+ "policy_id": "ID of the policy",
+ "object_id": "ID of the object",
+ "category_id": "ID of the category",
+ "assignments": "Assignments list (list of data_id)",
+ }
+ }
+ :internal_api: update_object_assignment
+ """
+ return call(ctx={"id": uuid, "method": "update_object_assignment", "user_id": user_id}, args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
+ """Delete a object assignment for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the object
+ :param category_id: uuid of the object category
+ :param data_id: uuid of the object scope
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_object_assignment
+ """
+ return call(ctx={"id": uuid, "method": "delete_object_assignment", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+
+class ActionAssignments(Resource):
+ """
+ Endpoint for action assignment requests
+ """
+
+ __urls__ = (
+ "/policies/<string:uuid>/action_assignments",
+ "/policies/<string:uuid>/action_assignments/",
+ "/policies/<string:uuid>/action_assignments/<string:perimeter_id>",
+ "/policies/<string:uuid>/action_assignments/<string:perimeter_id>/<string:category_id>",
+ "/policies/<string:uuid>/action_assignments/<string:perimeter_id>/<string:category_id>/<string:data_id>",
+ )
+
+ @check_auth
+ def get(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
+ """Retrieve all action assignment or a specific one for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the action
+ :param category_id: uuid of the action category
+ :param data_id: uuid of the action scope
+ :param user_id: user ID who do the request
+ :return: {
+ "action_data_id": {
+ "policy_id": "ID of the policy",
+ "object_id": "ID of the action",
+ "category_id": "ID of the category",
+ "assignments": "Assignments list (list of data_id)",
+ }
+ }
+ :internal_api: get_action_assignments
+ """
+ return call(ctx={"id": uuid, "method": "get_action_assignments", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+ @check_auth
+ def post(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
+ """Create an action assignment.
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the action (not used here)
+ :param category_id: uuid of the action category (not used here)
+ :param data_id: uuid of the action scope (not used here)
+ :param user_id: user ID who do the request
+ :request body: {
+ "id": "UUID of the action",
+ "category_id": "UUID of the category",
+ "data_id": "UUID of the scope"
+ }
+ :return: {
+ "action_data_id": {
+ "policy_id": "ID of the policy",
+ "object_id": "ID of the action",
+ "category_id": "ID of the category",
+ "assignments": "Assignments list (list of data_id)",
+ }
+ }
+ :internal_api: update_action_assignment
+ """
+ return call(ctx={"id": uuid, "method": "update_action_assignment", "user_id": user_id},
+ args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, perimeter_id=None, category_id=None, data_id=None, user_id=None):
+ """Delete a action assignment for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the action
+ :param category_id: uuid of the action category
+ :param data_id: uuid of the action scope
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_action_assignment
+ """
+ return call(ctx={"id": uuid, "method": "delete_action_assignment", "perimeter_id": perimeter_id, "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
diff --git a/moonv4/moon_interface/moon_interface/api/authz.py b/moonv4/moon_interface/moon_interface/api/authz.py
new file mode 100644
index 00000000..d1bf3407
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/authz.py
@@ -0,0 +1,66 @@
+# 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
+"""
+
+from uuid import uuid4
+from flask_restful import Resource
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+from moon_interface.tools import check_auth
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+class Authz(Resource):
+ """
+ Endpoint for authz requests
+ """
+
+ __urls__ = ("/authz/<string:uuid>/<string:subject_name>/<string:object_name>/<string:action_name>", )
+
+ def get(self, uuid=None, subject_name=None, object_name=None, action_name=None):
+ """Get a response on an authorization request
+
+ :param uuid: uuid of a tenant or an intra_extension
+ :param subject_name: name of the subject or the request
+ :param object_name: name of the object
+ :param action_name: name of the action
+ :return: {
+ "args": {},
+ "ctx": {
+ "action_name": "4567",
+ "id": "123456",
+ "method": "authz",
+ "object_name": "234567",
+ "subject_name": "123456",
+ "user_id": "admin"
+ },
+ "error": {
+ "code": 500,
+ "description": "",
+ "title": "Moon Error"
+ },
+ "intra_extension_id": "123456",
+ "result": false
+ }
+ :internal_api: authz
+ """
+ # Note (asteroide): user_id default to admin to be able to read the database
+ # it would be better to have a read-only user.
+ return call(ctx={"id": uuid,
+ "call_master": False,
+ "method": "authz",
+ "subject_name": subject_name,
+ "object_name": object_name,
+ "action_name": action_name,
+ "user_id": "admin",
+ "request_id": uuid4().hex}, args={})
+
diff --git a/moonv4/moon_interface/moon_interface/api/data.py b/moonv4/moon_interface/moon_interface/api/data.py
new file mode 100644
index 00000000..fdd28e9e
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/data.py
@@ -0,0 +1,261 @@
+# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
+# This software is distributed under the terms and conditions of the 'Apache-2.0'
+# license which can be found in the file 'LICENSE' in this package distribution
+# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
+"""
+Data are elements used to create rules
+
+"""
+
+from flask import request
+from flask_restful import Resource
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+from moon_interface.tools import check_auth
+
+__version__ = "0.2.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+class SubjectData(Resource):
+ """
+ Endpoint for subject data requests
+ """
+
+ __urls__ = (
+ "/policies/<string:uuid>/subject_data",
+ "/policies/<string:uuid>/subject_data/",
+ "/policies/<string:uuid>/subject_data/<string:category_id>",
+ "/policies/<string:uuid>/subject_data/<string:category_id>/<string:data_id>",
+ )
+
+ @check_auth
+ def get(self, uuid=None, category_id=None, data_id=None, user_id=None):
+ """Retrieve all subject categories or a specific one if sid is given for a given policy
+
+ :param uuid: uuid of the policy
+ :param category_id: uuid of the subject category
+ :param data_id: uuid of the subject data
+ :param user_id: user ID who do the request
+ :return: [{
+ "policy_id": "policy_id1",
+ "category_id": "category_id1",
+ "data": {
+ "subject_data_id": {
+ "name": "name of the data",
+ "description": "description of the data"
+ }
+ }
+ }]
+ :internal_api: get_subject_data
+ """
+ return call(ctx={"id": uuid, "method": "get_subject_data", "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+ @check_auth
+ def post(self, uuid=None, category_id=None, data_id=None, user_id=None):
+ """Create or update a subject.
+
+ :param uuid: uuid of the policy
+ :param category_id: uuid of the subject category
+ :param data_id: uuid of the subject data
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "name of the data",
+ "description": "description of the data"
+ }
+ :return: {
+ "policy_id": "policy_id1",
+ "category_id": "category_id1",
+ "data": {
+ "subject_data_id": {
+ "name": "name of the data",
+ "description": "description of the data"
+ }
+ }
+ }
+ :internal_api: add_subject_data
+ """
+ return call(ctx={"id": uuid, "method": "add_subject_data", "category_id": category_id, "user_id": user_id},
+ args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, category_id=None, data_id=None, user_id=None):
+ """Delete a subject for a given policy
+
+ :param uuid: uuid of the policy
+ :param category_id: uuid of the subject category
+ :param data_id: uuid of the subject data
+ :param user_id: user ID who do the request
+ :return: [{
+ "result": "True or False",
+ "message": "optional message"
+ }]
+ :internal_api: delete_subject_data
+ """
+ return call(ctx={"id": uuid, "method": "delete_subject_data", "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+
+class ObjectData(Resource):
+ """
+ Endpoint for object data requests
+ """
+
+ __urls__ = (
+ "/policies/<string:uuid>/object_data",
+ "/policies/<string:uuid>/object_data/",
+ "/policies/<string:uuid>/object_data/<string:category_id>",
+ "/policies/<string:uuid>/object_data/<string:category_id>/<string:data_id>",
+ )
+
+ @check_auth
+ def get(self, uuid=None, category_id=None, data_id=None, user_id=None):
+ """Retrieve all object categories or a specific one if sid is given for a given policy
+
+ :param uuid: uuid of the policy
+ :param category_id: uuid of the object category
+ :param data_id: uuid of the object data
+ :param user_id: user ID who do the request
+ :return: [{
+ "policy_id": "policy_id1",
+ "category_id": "category_id1",
+ "data": {
+ "object_data_id": {
+ "name": "name of the data",
+ "description": "description of the data"
+ }
+ }
+ }]
+ :internal_api: get_object_data
+ """
+ return call(ctx={"id": uuid, "method": "get_object_data", "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+ @check_auth
+ def post(self, uuid=None, category_id=None, data_id=None, user_id=None):
+ """Create or update a object.
+
+ :param uuid: uuid of the policy
+ :param category_id: uuid of the object category
+ :param data_id: uuid of the object data
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "name of the data",
+ "description": "description of the data"
+ }
+ :return: {
+ "policy_id": "policy_id1",
+ "category_id": "category_id1",
+ "data": {
+ "object_data_id": {
+ "name": "name of the data",
+ "description": "description of the data"
+ }
+ }
+ }
+ :internal_api: add_object_data
+ """
+ return call(ctx={"id": uuid, "method": "add_object_data", "category_id": category_id, "user_id": user_id}, args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, category_id=None, data_id=None, user_id=None):
+ """Delete a object for a given policy
+
+ :param uuid: uuid of the policy
+ :param category_id: uuid of the object category
+ :param data_id: uuid of the object data
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_object_data
+ """
+ return call(ctx={"id": uuid, "method": "delete_object_data", "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+
+class ActionData(Resource):
+ """
+ Endpoint for action data requests
+ """
+
+ __urls__ = (
+ "/policies/<string:uuid>/action_data",
+ "/policies/<string:uuid>/action_data/",
+ "/policies/<string:uuid>/action_data/<string:category_id>",
+ "/policies/<string:uuid>/action_data/<string:category_id>/<string:data_id>",
+ )
+
+ @check_auth
+ def get(self, uuid=None, category_id=None, data_id=None, user_id=None):
+ """Retrieve all action categories or a specific one if sid is given for a given policy
+
+ :param uuid: uuid of the policy
+ :param category_id: uuid of the action category
+ :param data_id: uuid of the action data
+ :param user_id: user ID who do the request
+ :return: [{
+ "policy_id": "policy_id1",
+ "category_id": "category_id1",
+ "data": {
+ "action_data_id": {
+ "name": "name of the data",
+ "description": "description of the data"
+ }
+ }
+ }]
+ :internal_api: get_action_data
+ """
+ return call(ctx={"id": uuid, "method": "get_action_data", "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+ @check_auth
+ def post(self, uuid=None, category_id=None, data_id=None, user_id=None):
+ """Create or update a action.
+
+ :param uuid: uuid of the policy
+ :param category_id: uuid of the action category
+ :param data_id: uuid of the action data
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "name of the data",
+ "description": "description of the data"
+ }
+ :return: {
+ "policy_id": "policy_id1",
+ "category_id": "category_id1",
+ "data": {
+ "action_data_id": {
+ "name": "name of the data",
+ "description": "description of the data"
+ }
+ }
+ }
+ :internal_api: add_action_data
+ """
+ return call(ctx={"id": uuid, "method": "add_action_data", "category_id": category_id, "user_id": user_id},
+ args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, category_id=None, data_id=None, user_id=None):
+ """Delete a action for a given policy
+
+ :param uuid: uuid of the policy
+ :param category_id: uuid of the action category
+ :param data_id: uuid of the action data
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_action_data
+ """
+ return call(ctx={"id": uuid, "method": "delete_action_data", "category_id": category_id, "user_id": user_id},
+ args={"data_id": data_id})
+
+
diff --git a/moonv4/moon_interface/moon_interface/api/generic.py b/moonv4/moon_interface/moon_interface/api/generic.py
new file mode 100644
index 00000000..6c29039d
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/generic.py
@@ -0,0 +1,153 @@
+# 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_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+import moon_interface.api
+from moon_interface.tools import check_auth
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+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"
+ }
+ }
+ """
+ return call(method="get_status", ctx={"component_id": component_id})
+
+
+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
+
+ return call(method="get_logs", ctx={"component_id": component_id}, args=args)
+
+
+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_interface.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
+
+
+class InternalAPI(Resource):
+ """
+ Endpoint for status requests
+ """
+
+ __urls__ = ("/internal_api", "/internal_api/", "/internal_api/<string:component_id>")
+
+ def get(self, component_id=None, user_id=""):
+ api_list = ("orchestrator", "security_router")
+ if not component_id:
+ return {"api": api_list}
+ if component_id in api_list:
+ api_desc = dict()
+ api_desc["name"] = component_id
+ api_desc["endpoints"] = call(component_id, {}, "list_api")
+ return api_desc
+
diff --git a/moonv4/moon_interface/moon_interface/api/meta_data.py b/moonv4/moon_interface/moon_interface/api/meta_data.py
new file mode 100644
index 00000000..c34faa20
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/meta_data.py
@@ -0,0 +1,206 @@
+# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
+# This software is distributed under the terms and conditions of the 'Apache-2.0'
+# license which can be found in the file 'LICENSE' in this package distribution
+# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
+"""
+Meta Data are elements used to create Meta data (skeleton of security policies)
+
+"""
+
+from flask import request
+from flask_restful import Resource
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+from moon_interface.tools import check_auth
+
+__version__ = "0.2.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+class SubjectCategories(Resource):
+ """
+ Endpoint for subject categories requests
+ """
+
+ __urls__ = (
+ "/subject_categories",
+ "/subject_categories/",
+ "/subject_categories/<string:category_id>",
+ )
+
+ @check_auth
+ def get(self, category_id=None, user_id=None):
+ """Retrieve all subject categories or a specific one
+
+ :param category_id: uuid of the subject category
+ :param user_id: user ID who do the request
+ :return: {
+ "subject_category_id": {
+ "name": "name of the category",
+ "description": "description of the category"
+ }
+ }
+ :internal_api: get_subject_categories
+ """
+ return call(ctx={"method": "get_subject_categories", "user_id": user_id}, args={"category_id": category_id})
+
+ @check_auth
+ def post(self, category_id=None, user_id=None):
+ """Create or update a subject category.
+
+ :param category_id: must not be used here
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "name of the category",
+ "description": "description of the category"
+ }
+ :return: {
+ "subject_category_id": {
+ "name": "name of the category",
+ "description": "description of the category"
+ }
+ }
+ :internal_api: add_subject_category
+ """
+ return call(ctx={"method": "set_subject_category", "user_id": user_id}, args=request.json)
+
+ @check_auth
+ def delete(self, category_id=None, user_id=None):
+ """Delete a subject category
+
+ :param category_id: uuid of the subject category to delete
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_subject_category
+ """
+ return call(ctx={"method": "delete_subject_category", "user_id": user_id}, args={"category_id": category_id})
+
+
+class ObjectCategories(Resource):
+ """
+ Endpoint for object categories requests
+ """
+
+ __urls__ = (
+ "/object_categories",
+ "/object_categories/",
+ "/object_categories/<string:category_id>",
+ )
+
+ @check_auth
+ def get(self, category_id=None, user_id=None):
+ """Retrieve all object categories or a specific one
+
+ :param category_id: uuid of the object category
+ :param user_id: user ID who do the request
+ :return: {
+ "object_category_id": {
+ "name": "name of the category",
+ "description": "description of the category"
+ }
+ }
+ :internal_api: get_object_categories
+ """
+ return call(ctx={"method": "get_object_categories", "user_id": user_id}, args={"category_id": category_id})
+
+ @check_auth
+ def post(self, category_id=None, user_id=None):
+ """Create or update a object category.
+
+ :param category_id: must not be used here
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "name of the category",
+ "description": "description of the category"
+ }
+ :return: {
+ "object_category_id": {
+ "name": "name of the category",
+ "description": "description of the category"
+ }
+ }
+ :internal_api: add_object_category
+ """
+ return call(ctx={"method": "set_object_category", "user_id": user_id}, args=request.json)
+
+ @check_auth
+ def delete(self, category_id=None, user_id=None):
+ """Delete an object category
+
+ :param category_id: uuid of the object category to delete
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_object_category
+ """
+ return call(ctx={"method": "delete_object_category", "user_id": user_id}, args={"category_id": category_id})
+
+
+class ActionCategories(Resource):
+ """
+ Endpoint for action categories requests
+ """
+
+ __urls__ = (
+ "/action_categories",
+ "/action_categories/",
+ "/action_categories/<string:category_id>",
+ )
+
+ @check_auth
+ def get(self, category_id=None, user_id=None):
+ """Retrieve all action categories or a specific one
+
+ :param category_id: uuid of the action category
+ :param user_id: user ID who do the request
+ :return: {
+ "action_category_id": {
+ "name": "name of the category",
+ "description": "description of the category"
+ }
+ }
+ :internal_api: get_action_categories
+ """
+ return call(ctx={"method": "get_action_categories", "user_id": user_id}, args={"category_id": category_id})
+
+ @check_auth
+ def post(self, category_id=None, user_id=None):
+ """Create or update an action category.
+
+ :param category_id: must not be used here
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "name of the category",
+ "description": "description of the category"
+ }
+ :return: {
+ "action_category_id": {
+ "name": "name of the category",
+ "description": "description of the category"
+ }
+ }
+ :internal_api: add_action_category
+ """
+ return call(ctx={"method": "set_action_category", "user_id": user_id}, args=request.json)
+
+ @check_auth
+ def delete(self, category_id=None, user_id=None):
+ """Delete an action
+
+ :param category_id: uuid of the action category to delete
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_action_category
+ """
+ return call(ctx={"method": "delete_action_category", "user_id": user_id}, args={"category_id": category_id})
diff --git a/moonv4/moon_interface/moon_interface/api/meta_rules.py b/moonv4/moon_interface/moon_interface/api/meta_rules.py
new file mode 100644
index 00000000..5e059109
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/meta_rules.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'.
+"""
+Meta rules are skeleton for security policies
+
+"""
+
+from flask import request
+from flask_restful import Resource
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+from moon_interface.tools import check_auth
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+class MetaRules(Resource):
+ """
+ Endpoint for meta rules requests
+ """
+
+ __urls__ = ("/meta_rules",
+ "/meta_rules/",
+ "/meta_rules/<string:meta_rule_id>",
+ "/meta_rules/<string:meta_rule_id>/")
+
+ @check_auth
+ def get(self, meta_rule_id=None, user_id=None):
+ """Retrieve all sub meta rules
+
+ :param meta_rule_id: Meta rule algorithm ID
+ :param user_id: user ID who do the request
+ :return: {
+ "meta_rules": {
+ "meta_rule_id1": {
+ "name": "name of the meta rule",
+ "algorithm": "name of the meta rule algorithm",
+ "subject_categories": ["subject_category_id1", "subject_category_id2"],
+ "object_categories": ["object_category_id1"],
+ "action_categories": ["action_category_id1"]
+ },
+ }
+ }
+ :internal_api: get_meta_rules
+ """
+ return call(ctx={"method": "get_meta_rules",
+ "user_id": user_id,
+ "meta_rule_id": meta_rule_id}, args={})
+
+ @check_auth
+ def post(self, meta_rule_id=None, user_id=None):
+ """Add a meta rule
+
+ :param meta_rule_id: Meta rule ID
+ :param user_id: user ID who do the request
+ :request body: post = {
+ "name": "name of the meta rule",
+ "subject_categories": ["subject_category_id1", "subject_category_id2"],
+ "object_categories": ["object_category_id1"],
+ "action_categories": ["action_category_id1"]
+ }
+ :return: {
+ "meta_rules": {
+ "meta_rule_id1": {
+ "name": "name of the meta rule",
+ "subject_categories": ["subject_category_id1", "subject_category_id2"],
+ "object_categories": ["object_category_id1"],
+ "action_categories": ["action_category_id1"]
+ },
+ }
+ }
+ :internal_api: add_meta_rules
+ """
+ return call(ctx={"method": "add_meta_rules",
+ "user_id": user_id,
+ "meta_rule_id": meta_rule_id}, args=request.json)
+
+ @check_auth
+ def patch(self, meta_rule_id=None, user_id=None):
+ """Update a meta rule
+
+ :param meta_rule_id: Meta rule ID
+ :param user_id: user ID who do the request
+ :request body: patch = {
+ "name": "name of the meta rule",
+ "subject_categories": ["subject_category_id1", "subject_category_id2"],
+ "object_categories": ["object_category_id1"],
+ "action_categories": ["action_category_id1"]
+ }
+ :return: {
+ "meta_rules": {
+ "meta_rule_id1": {
+ "name": "name of the meta rule",
+ "subject_categories": ["subject_category_id1", "subject_category_id2"],
+ "object_categories": ["object_category_id1"],
+ "action_categories": ["action_category_id1"]
+ },
+ }
+ }
+ :internal_api: set_meta_rules
+ """
+ return call(ctx={"method": "set_meta_rules",
+ "user_id": user_id,
+ "meta_rule_id": meta_rule_id}, args=request.json)
+
+ @check_auth
+ def delete(self, meta_rule_id=None, user_id=None):
+ """Delete a meta rule
+
+ :param meta_rule_id: Meta rule ID
+ :param user_id: user ID who do the request
+ :request body: delete = {
+ "name": "name of the meta rule",
+ "subject_categories": ["subject_category_id1", "subject_category_id2"],
+ "object_categories": ["object_category_id1"],
+ "action_categories": ["action_category_id1"]
+ }
+ :return: {
+ "meta_rules": {
+ "meta_rule_id1": {
+ "name": "name of the meta rule",
+ "subject_categories": ["subject_category_id1", "subject_category_id2"],
+ "object_categories": ["object_category_id1"],
+ "action_categories": ["action_category_id1"]
+ },
+ }
+ }
+ :internal_api: delete_meta_rules
+ """
+ return call(ctx={"method": "delete_meta_rules",
+ "user_id": user_id,
+ "meta_rule_id": meta_rule_id}, args=request.json)
+
+
diff --git a/moonv4/moon_interface/moon_interface/api/models.py b/moonv4/moon_interface/moon_interface/api/models.py
new file mode 100644
index 00000000..0226a87e
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/models.py
@@ -0,0 +1,103 @@
+# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
+# This software is distributed under the terms and conditions of the 'Apache-2.0'
+# license which can be found in the file 'LICENSE' in this package distribution
+# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
+"""
+Models aggregate multiple meta rules
+"""
+
+from flask import request
+from flask_restful import Resource
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+from moon_interface.tools import check_auth
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+class Models(Resource):
+ """
+ Endpoint for model requests
+ """
+
+ __urls__ = (
+ "/models",
+ "/models/",
+ "/models/<string:uuid>",
+ "/models/<string:uuid>/",
+ )
+
+ @check_auth
+ def get(self, uuid=None, user_id=None):
+ """Retrieve all models
+
+ :param uuid: uuid of the model
+ :param user_id: user ID who do the request
+ :return: {
+ "model_id1": {
+ "name": "...",
+ "description": "...",
+ "meta_rules": ["meta_rule_id1", ]
+ }
+ }
+ :internal_api: get_models
+ """
+ return call(ctx={"id": uuid, "method": "get_models", "user_id": user_id}, args={})
+
+ @check_auth
+ def post(self, uuid=None, user_id=None):
+ """Create model.
+
+ :param uuid: uuid of the model (not used here)
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "...",
+ "description": "...",
+ "meta_rules": ["meta_rule_id1", ]
+ }
+ :return: {
+ "model_id1": {
+ "name": "...",
+ "description": "...",
+ "meta_rules": ["meta_rule_id1", ]
+ }
+ }
+ :internal_api: add_model
+ """
+ return call(ctx={"id": uuid, "method": "add_model", "user_id": user_id}, args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, user_id=None):
+ """Delete a model
+
+ :param uuid: uuid of the model to delete
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_model
+ """
+ return call(ctx={"id": uuid, "method": "delete_model", "user_id": user_id}, args={})
+
+ @check_auth
+ def patch(self, uuid=None, user_id=None):
+ """Update a model
+
+ :param uuid: uuid of the model to update
+ :param user_id: user ID who do the request
+ :return: {
+ "model_id1": {
+ "name": "...",
+ "description": "...",
+ "meta_rules": ["meta_rule_id1", ]
+ }
+ }
+ :internal_api: update_model
+ """
+ return call(ctx={"id": uuid, "method": "update_model", "user_id": user_id}, args=request.json)
+
diff --git a/moonv4/moon_interface/moon_interface/api/pdp.py b/moonv4/moon_interface/moon_interface/api/pdp.py
new file mode 100644
index 00000000..3a3519c4
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/pdp.py
@@ -0,0 +1,108 @@
+# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
+# This software is distributed under the terms and conditions of the 'Apache-2.0'
+# license which can be found in the file 'LICENSE' in this package distribution
+# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
+"""
+PDP are Policy Decision Point.
+
+"""
+
+from flask import request
+from flask_restful import Resource
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+from moon_interface.tools import check_auth
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+class PDP(Resource):
+ """
+ Endpoint for pdp requests
+ """
+
+ __urls__ = (
+ "/pdp",
+ "/pdp/",
+ "/pdp/<string:uuid>",
+ "/pdp/<string:uuid>/",
+ )
+
+ @check_auth
+ def get(self, uuid=None, user_id=None):
+ """Retrieve all pdp
+
+ :param uuid: uuid of the pdp
+ :param user_id: user ID who do the request
+ :return: {
+ "pdp_id1": {
+ "name": "...",
+ "security_pipeline": [...],
+ "keystone_project_id": "keystone_project_id1",
+ "description": "...",
+ }
+ }
+ :internal_api: get_pdp
+ """
+ return call(ctx={"id": uuid, "method": "get_pdp", "user_id": user_id}, args={})
+
+ @check_auth
+ def post(self, uuid=None, user_id=None):
+ """Create pdp.
+
+ :param uuid: uuid of the pdp (not used here)
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "...",
+ "security_pipeline": [...],
+ "keystone_project_id": "keystone_project_id1",
+ "description": "...",
+ }
+ :return: {
+ "pdp_id1": {
+ "name": "...",
+ "security_pipeline": [...],
+ "keystone_project_id": "keystone_project_id1",
+ "description": "...",
+ }
+ }
+ :internal_api: add_pdp
+ """
+ return call(ctx={"id": uuid, "method": "add_pdp", "user_id": user_id}, args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, user_id=None):
+ """Delete a pdp
+
+ :param uuid: uuid of the pdp to delete
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_pdp
+ """
+ return call(ctx={"id": uuid, "method": "delete_pdp", "user_id": user_id}, args={})
+
+ @check_auth
+ def patch(self, uuid=None, user_id=None):
+ """Update a pdp
+
+ :param uuid: uuid of the pdp to update
+ :param user_id: user ID who do the request
+ :return: {
+ "pdp_id1": {
+ "name": "...",
+ "security_pipeline": [...],
+ "keystone_project_id": "keystone_project_id1",
+ "description": "...",
+ }
+ }
+ :internal_api: update_pdp
+ """
+ return call(ctx={"id": uuid, "method": "update_pdp", "user_id": user_id}, args=request.json)
+
diff --git a/moonv4/moon_interface/moon_interface/api/perimeter.py b/moonv4/moon_interface/moon_interface/api/perimeter.py
new file mode 100644
index 00000000..8907c8f4
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/perimeter.py
@@ -0,0 +1,314 @@
+# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
+# This software is distributed under the terms and conditions of the 'Apache-2.0'
+# license which can be found in the file 'LICENSE' in this package distribution
+# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
+"""
+* Subjects are the source of an action on an object (examples : users, virtual machines)
+* Objects are the destination of an action (examples virtual machines, virtual Routers)
+* Actions are what subject wants to do on an object
+"""
+
+from flask import request
+from flask_restful import Resource
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+from moon_interface.tools import check_auth
+
+__version__ = "0.2.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+class Subjects(Resource):
+ """
+ Endpoint for subjects requests
+ """
+
+ __urls__ = (
+ "/subjects",
+ "/subjects/",
+ "/subjects/<string:perimeter_id>",
+ "/policies/<string:uuid>/subjects",
+ "/policies/<string:uuid>/subjects/",
+ "/policies/<string:uuid>/subjects/<string:perimeter_id>",
+ )
+
+ @check_auth
+ def get(self, uuid=None, perimeter_id=None, user_id=None):
+ """Retrieve all subjects or a specific one if perimeter_id is given for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the subject
+ :param user_id: user ID who do the request
+ :return: {
+ "subject_id": {
+ "name": "name of the subject",
+ "keystone_id": "keystone id of the subject",
+ "description": "a description"
+ }
+ }
+ :internal_api: get_subjects
+ """
+ return call(ctx={"id": uuid, "method": "get_subjects", "user_id": user_id}, args={"perimeter_id": perimeter_id})
+
+ @check_auth
+ def post(self, uuid=None, perimeter_id=None, user_id=None):
+ """Create or update a subject.
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: must not be used here
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "name of the subject",
+ "description": "description of the subject",
+ "password": "password for the subject",
+ "email": "email address of the subject"
+ }
+ :return: {
+ "subject_id": {
+ "name": "name of the subject",
+ "keystone_id": "keystone id of the subject",
+ "description": "description of the subject",
+ "password": "password for the subject",
+ "email": "email address of the subject"
+ }
+ }
+ :internal_api: set_subject
+ """
+ return call(ctx={"id": uuid, "method": "set_subject", "user_id": user_id, "perimeter_id": None},
+ args=request.json)
+
+ @check_auth
+ def patch(self, uuid=None, perimeter_id=None, user_id=None):
+ """Create or update a subject.
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: must not be used here
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "name of the subject",
+ "description": "description of the subject",
+ "password": "password for the subject",
+ "email": "email address of the subject"
+ }
+ :return: {
+ "subject_id": {
+ "name": "name of the subject",
+ "keystone_id": "keystone id of the subject",
+ "description": "description of the subject",
+ "password": "password for the subject",
+ "email": "email address of the subject"
+ }
+ }
+ :internal_api: set_subject
+ """
+ return call(ctx={"id": uuid, "method": "set_subject", "user_id": user_id, "perimeter_id": perimeter_id},
+ args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, perimeter_id=None, user_id=None):
+ """Delete a subject for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the subject
+ :param user_id: user ID who do the request
+ :return: {
+ "subject_id": {
+ "name": "name of the subject",
+ "keystone_id": "keystone id of the subject",
+ "description": "description of the subject",
+ "password": "password for the subject",
+ "email": "email address of the subject"
+ }
+ }
+ :internal_api: delete_subject
+ """
+ return call(ctx={"id": uuid, "method": "delete_subject", "user_id": user_id}, args={"perimeter_id": perimeter_id})
+
+
+class Objects(Resource):
+ """
+ Endpoint for objects requests
+ """
+
+ __urls__ = (
+ "/objects",
+ "/objects/",
+ "/objects/<string:perimeter_id>",
+ "/policies/<string:uuid>/objects",
+ "/policies/<string:uuid>/objects/",
+ "/policies/<string:uuid>/objects/<string:perimeter_id>",
+ )
+
+ @check_auth
+ def get(self, uuid=None, perimeter_id=None, user_id=None):
+ """Retrieve all objects or a specific one if perimeter_id is given for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the object
+ :param user_id: user ID who do the request
+ :return: {
+ "object_id": {
+ "name": "name of the object",
+ "description": "description of the object"
+ }
+ }
+ :internal_api: get_objects
+ """
+ return call(ctx={"id": uuid, "method": "get_objects", "user_id": user_id}, args={"perimeter_id": perimeter_id})
+
+ @check_auth
+ def post(self, uuid=None, perimeter_id=None, user_id=None):
+ """Create or update a object.
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: must not be used here
+ :param user_id: user ID who do the request
+ :request body: {
+ "object_name": "name of the object",
+ "object_description": "description of the object"
+ }
+ :return: {
+ "object_id": {
+ "name": "name of the object",
+ "description": "description of the object"
+ }
+ }
+ :internal_api: set_object
+ """
+ return call(ctx={"id": uuid, "method": "set_object", "user_id": user_id, "perimeter_id": None},
+ args=request.json)
+
+ @check_auth
+ def patch(self, uuid=None, perimeter_id=None, user_id=None):
+ """Create or update a object.
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: must not be used here
+ :param user_id: user ID who do the request
+ :request body: {
+ "object_name": "name of the object",
+ "object_description": "description of the object"
+ }
+ :return: {
+ "object_id": {
+ "name": "name of the object",
+ "description": "description of the object"
+ }
+ }
+ :internal_api: set_object
+ """
+ return call(ctx={"id": uuid, "method": "set_object", "user_id": user_id, "perimeter_id": perimeter_id},
+ args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, perimeter_id=None, user_id=None):
+ """Delete a object for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the object
+ :param user_id: user ID who do the request
+ :return: {
+ "object_id": {
+ "name": "name of the object",
+ "description": "description of the object"
+ }
+ }
+ :internal_api: delete_object
+ """
+ return call(ctx={"id": uuid, "method": "delete_object", "user_id": user_id}, args={"perimeter_id": perimeter_id})
+
+
+class Actions(Resource):
+ """
+ Endpoint for actions requests
+ """
+
+ __urls__ = (
+ "/actions",
+ "/actions/",
+ "/actions/<string:perimeter_id>",
+ "/policies/<string:uuid>/actions",
+ "/policies/<string:uuid>/actions/",
+ "/policies/<string:uuid>/actions/<string:perimeter_id>",
+ )
+
+ @check_auth
+ def get(self, uuid=None, perimeter_id=None, user_id=None):
+ """Retrieve all actions or a specific one if perimeter_id is given for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the action
+ :param user_id: user ID who do the request
+ :return: {
+ "action_id": {
+ "name": "name of the action",
+ "description": "description of the action"
+ }
+ }
+ :internal_api: get_actions
+ """
+ return call(ctx={"id": uuid, "method": "get_actions", "user_id": user_id}, args={"perimeter_id": perimeter_id})
+
+ @check_auth
+ def post(self, uuid=None, perimeter_id=None, user_id=None):
+ """Create or update a action.
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: must not be used here
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "name of the action",
+ "description": "description of the action"
+ }
+ :return: {
+ "action_id": {
+ "name": "name of the action",
+ "description": "description of the action"
+ }
+ }
+ :internal_api: set_action
+ """
+ return call(ctx={"id": uuid, "method": "set_action", "user_id": user_id, "perimeter_id": None},
+ args=request.json)
+
+ @check_auth
+ def patch(self, uuid=None, perimeter_id=None, user_id=None):
+ """Create or update a action.
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: must not be used here
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "name of the action",
+ "description": "description of the action"
+ }
+ :return: {
+ "action_id": {
+ "name": "name of the action",
+ "description": "description of the action"
+ }
+ }
+ :internal_api: set_action
+ """
+ return call(ctx={"id": uuid, "method": "set_action", "user_id": user_id, "perimeter_id": perimeter_id},
+ args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, perimeter_id=None, user_id=None):
+ """Delete a action for a given policy
+
+ :param uuid: uuid of the policy
+ :param perimeter_id: uuid of the action
+ :param user_id: user ID who do the request
+ :return: {
+ "action_id": {
+ "name": "name of the action",
+ "description": "description of the action"
+ }
+ }
+ :internal_api: delete_action
+ """
+ return call(ctx={"id": uuid, "method": "delete_action", "user_id": user_id}, args={"perimeter_id": perimeter_id})
diff --git a/moonv4/moon_interface/moon_interface/api/policies.py b/moonv4/moon_interface/moon_interface/api/policies.py
new file mode 100644
index 00000000..ba2b2e1e
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/policies.py
@@ -0,0 +1,108 @@
+# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
+# This software is distributed under the terms and conditions of the 'Apache-2.0'
+# license which can be found in the file 'LICENSE' in this package distribution
+# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
+"""
+Policies are instances of security models and implement security policies
+
+"""
+
+from flask import request
+from flask_restful import Resource
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+from moon_interface.tools import check_auth
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+class Policies(Resource):
+ """
+ Endpoint for policy requests
+ """
+
+ __urls__ = (
+ "/policies",
+ "/policies/",
+ "/policies/<string:uuid>",
+ "/policies/<string:uuid>/",
+ )
+
+ @check_auth
+ def get(self, uuid=None, user_id=None):
+ """Retrieve all policies
+
+ :param uuid: uuid of the policy
+ :param user_id: user ID who do the request
+ :return: {
+ "policy_id1": {
+ "name": "...",
+ "model_id": "...",
+ "genre": "...",
+ "description": "...",
+ }
+ }
+ :internal_api: get_policies
+ """
+ return call(ctx={"id": uuid, "method": "get_policies", "user_id": user_id}, args={})
+
+ @check_auth
+ def post(self, uuid=None, user_id=None):
+ """Create policy.
+
+ :param uuid: uuid of the policy (not used here)
+ :param user_id: user ID who do the request
+ :request body: {
+ "name": "...",
+ "model_id": "...",
+ "genre": "...",
+ "description": "...",
+ }
+ :return: {
+ "policy_id1": {
+ "name": "...",
+ "model_id": "...",
+ "genre": "...",
+ "description": "...",
+ }
+ }
+ :internal_api: add_policy
+ """
+ return call(ctx={"id": uuid, "method": "add_policy", "user_id": user_id}, args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, user_id=None):
+ """Delete a policy
+
+ :param uuid: uuid of the policy to delete
+ :param user_id: user ID who do the request
+ :return: {
+ "result": "True or False",
+ "message": "optional message"
+ }
+ :internal_api: delete_policy
+ """
+ return call(ctx={"id": uuid, "method": "delete_policy", "user_id": user_id}, args={})
+
+ @check_auth
+ def patch(self, uuid=None, user_id=None):
+ """Update a policy
+
+ :param uuid: uuid of the policy to update
+ :param user_id: user ID who do the request
+ :return: {
+ "policy_id1": {
+ "name": "...",
+ "model_id": "...",
+ "genre": "...",
+ "description": "...",
+ }
+ }
+ :internal_api: update_policy
+ """
+ return call(ctx={"id": uuid, "method": "update_policy", "user_id": user_id}, args=request.json)
+
diff --git a/moonv4/moon_interface/moon_interface/api/rules.py b/moonv4/moon_interface/moon_interface/api/rules.py
new file mode 100644
index 00000000..81639a37
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/api/rules.py
@@ -0,0 +1,95 @@
+# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors
+# This software is distributed under the terms and conditions of the 'Apache-2.0'
+# license which can be found in the file 'LICENSE' in this package distribution
+# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
+"""
+Rules (TODO)
+"""
+
+from flask import request
+from flask_restful import Resource
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_interface.tools import call
+from moon_interface.tools import check_auth
+
+__version__ = "0.1.0"
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+
+class Rules(Resource):
+ """
+ Endpoint for rules requests
+ """
+
+ __urls__ = ("/policies/<string:uuid>/rules",
+ "/policies/<string:uuid>/rules/",
+ "/policies/<string:uuid>/rules/<string:rule_id>",
+ "/policies/<string:uuid>/rules/<string:rule_id>/",
+ )
+
+ @check_auth
+ def get(self, uuid=None, rule_id=None, user_id=None):
+ """Retrieve all rules or a specific one
+
+ :param uuid: policy ID
+ :param rule_id: rule ID
+ :param user_id: user ID who do the request
+ :return: {
+ "rules": [
+ "policy_id": "policy_id1",
+ "meta_rule_id": "meta_rule_id1",
+ "rule_id1": ["subject_data_id1", "object_data_id1", "action_data_id1"],
+ "rule_id2": ["subject_data_id2", "object_data_id2", "action_data_id2"],
+ ]
+ }
+ :internal_api: get_rules
+ """
+ return call(ctx={"id": uuid,
+ "method": "get_rules",
+ "user_id": user_id,
+ "rule_id": rule_id}, args={})
+
+ @check_auth
+ def post(self, uuid=None, rule_id=None, user_id=None):
+ """Add a rule to a meta rule
+
+ :param uuid: policy ID
+ :param rule_id: rule ID
+ :param user_id: user ID who do the request
+ :request body: post = {
+ "meta_rule_id": "meta_rule_id1",
+ "rule": ["subject_data_id2", "object_data_id2", "action_data_id2"],
+ "enabled": True
+ }
+ :return: {
+ "rules": [
+ "meta_rule_id": "meta_rule_id1",
+ "rule_id1": ["subject_data_id1", "object_data_id1", "action_data_id1"],
+ "rule_id2": ["subject_data_id2", "object_data_id2", "action_data_id2"],
+ ]
+ }
+ :internal_api: add_rule
+ """
+ return call(ctx={"id": uuid,
+ "method": "add_rule",
+ "user_id": user_id,
+ "rule_id": rule_id}, args=request.json)
+
+ @check_auth
+ def delete(self, uuid=None, rule_id=None, user_id=None):
+ """Delete one rule linked to a specific sub meta rule
+
+ :param uuid: policy ID
+ :param rule_id: rule ID
+ :param user_id: user ID who do the request
+ :return: { "result": true }
+ :internal_api: delete_rule
+ """
+ return call(ctx={"id": uuid,
+ "method": "delete_rule",
+ "user_id": user_id,
+ "rule_id": rule_id}, args={})
+
diff --git a/moonv4/moon_interface/moon_interface/http_server.py b/moonv4/moon_interface/moon_interface/http_server.py
new file mode 100644
index 00000000..b475e141
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/http_server.py
@@ -0,0 +1,173 @@
+# 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, request
+from flask_cors import CORS, cross_origin
+from flask_restful import Resource, Api, reqparse
+import logging
+from moon_interface import __version__
+from moon_interface.api.generic import Status, Logs, API, InternalAPI
+from moon_interface.api.models import Models
+from moon_interface.api.policies import Policies
+from moon_interface.api.pdp import PDP
+from moon_interface.api.meta_rules import MetaRules
+from moon_interface.api.meta_data import SubjectCategories, ObjectCategories, ActionCategories
+from moon_interface.api.perimeter import Subjects, Objects, Actions
+from moon_interface.api.data import SubjectData, ObjectData, ActionData
+from moon_interface.api.assignments import SubjectAssignments, ObjectAssignments, ActionAssignments
+from moon_interface.api.rules import Rules
+from moon_interface.api.authz import Authz
+from moon_utilities import exceptions
+
+logger = logging.getLogger(__name__)
+
+
+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,
+ MetaRules, SubjectCategories, ObjectCategories, ActionCategories,
+ Subjects, Objects, Actions,
+ SubjectAssignments, ObjectAssignments, ActionAssignments,
+ SubjectData, ObjectData, ActionData,
+ Rules, Authz,
+ Models, Policies, PDP
+ )
+
+
+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__)
+ #Todo : specify only few urls instead of *
+ CORS(self.app)
+ self.api = Api(self.app)
+ self.__set_route()
+ # self.__hook_errors()
+
+ @self.app.errorhandler(exceptions.AuthException)
+ def _auth_exception(error):
+ return {"error": "Unauthorized"}, 401
+
+ def __hook_errors(self):
+ # FIXME (dthom): it doesn't work
+ def get_404_json(e):
+ return {"error": "Error", "code": 404, "description": e}
+ self.app.register_error_handler(404, get_404_json)
+
+ def get_400_json(e):
+ return {"error": "Error", "code": 400, "description": e}
+ 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(Status, *Status.__urls__)
+ # self.api.add_resource(Logs, *Logs.__urls__)
+ # self.api.add_resource(API, *API.__urls__)
+ # self.api.add_resource(InternalAPI, *InternalAPI.__urls__)
+ #
+ # self.api.add_resource(InternalAPI, *InternalAPI.__urls__)
+ #
+ # self.api.add_resource(IntraExtensions, *IntraExtensions.__urls__)
+ # self.api.add_resource(SubMetaRuleAlgorithm, *SubMetaRuleAlgorithm.__urls__)
+ # self.api.add_resource(AggregationAlgorithm, *AggregationAlgorithm.__urls__)
+ #
+ # self.api.add_resource(Templates, *Templates.__urls__)
+ # self.api.add_resource(SubMetaRuleAlgorithms, *SubMetaRuleAlgorithms.__urls__)
+ # self.api.add_resource(AggregationAlgorithms, *AggregationAlgorithms.__urls__)
+ #
+ # self.api.add_resource(Subjects, *Subjects.__urls__)
+ # self.api.add_resource(SubjectCategories, *SubjectCategories.__urls__)
+ # self.api.add_resource(SubjectScopes, *SubjectScopes.__urls__)
+ # self.api.add_resource(SubjectAssignments, *SubjectAssignments.__urls__)
+ #
+ # self.api.add_resource(Objects, *Objects.__urls__)
+ # self.api.add_resource(ObjectCategories, *ObjectCategories.__urls__)
+ # self.api.add_resource(ObjectScopes, *ObjectScopes.__urls__)
+ # self.api.add_resource(ObjectAssignments, *ObjectAssignments.__urls__)
+ #
+ # self.api.add_resource(Actions, *Actions.__urls__)
+ # self.api.add_resource(ActionCategories, *ActionCategories.__urls__)
+ # self.api.add_resource(ActionScopes, *ActionScopes.__urls__)
+ # self.api.add_resource(ActionAssignments, *ActionAssignments.__urls__)
+ #
+ # self.api.add_resource(Rules, *Rules.__urls__)
+ # self.api.add_resource(SubMetaRules, *SubMetaRules.__urls__)
+ #
+ # self.api.add_resource(Mappings, *Mappings.__urls__)
+
+ def run(self):
+ self.app.run(debug=True, host=self._host, port=self._port) # nosec
+
diff --git a/moonv4/moon_interface/moon_interface/server.py b/moonv4/moon_interface/moon_interface/server.py
new file mode 100644
index 00000000..e70cec89
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/server.py
@@ -0,0 +1,26 @@
+# 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 os
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_utilities import options # noqa
+from moon_interface.http_server import HTTPServer
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+DOMAIN = "moon_interface"
+
+__CWD__ = os.path.dirname(os.path.abspath(__file__))
+
+
+def main():
+ LOG.info("Starting server with IP {} on port {}".format(CONF.interface.host, CONF.interface.port))
+ server = HTTPServer(host=CONF.interface.host, port=CONF.interface.port)
+ server.run()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/moonv4/moon_interface/moon_interface/tools.py b/moonv4/moon_interface/moon_interface/tools.py
new file mode 100644
index 00000000..3c0fffa5
--- /dev/null
+++ b/moonv4/moon_interface/moon_interface/tools.py
@@ -0,0 +1,99 @@
+# 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 os
+import requests
+import time
+from functools import wraps
+from flask import request
+from oslo_config import cfg
+from oslo_log import log as logging
+import oslo_messaging
+from moon_utilities import exceptions
+
+
+LOG = logging.getLogger(__name__)
+CONF = cfg.CONF
+
+TOKENS = {}
+
+
+def timeit(function):
+ def wrapper(*args, **kwargs):
+ LOG.info("Calling {} with {} {}...".format(function, args, kwargs))
+ ret = function(*args, **kwargs)
+ LOG.info("End of {}".format(function))
+ return ret
+ return wrapper
+
+
+@timeit
+def call(topic="security_router", ctx=None, method="route", **kwargs):
+ if not ctx:
+ ctx = dict()
+ transport = oslo_messaging.get_transport(CONF)
+ target = oslo_messaging.Target(topic=topic, version='1.0')
+ client = oslo_messaging.RPCClient(transport, target)
+ LOG.info("Calling {} on {}...".format(method, topic))
+ return client.call(ctx, method, **kwargs)
+
+
+def check_token(token, url=None):
+ _verify = False
+ if CONF.keystone.server_crt:
+ _verify = CONF.keystone.server_crt
+ try:
+ os.environ.pop("http_proxy")
+ os.environ.pop("https_proxy")
+ except KeyError:
+ pass
+ if not url:
+ url = CONF.keystone.url
+ headers = {
+ "Content-Type": "application/json",
+ 'X-Subject-Token': token,
+ 'X-Auth-Token': token,
+ }
+ if CONF.keystone.check_token.lower() in ("false", "no", "n"):
+ # TODO (asteroide): must send the admin id
+ return "admin" if not token else token
+ if CONF.keystone.check_token.lower() in ("yes", "y", "true"):
+ if token in TOKENS:
+ delta = time.mktime(TOKENS[token]["expires_at"]) - time.mktime(time.gmtime())
+ if delta > 0:
+ return TOKENS[token]["user"]
+ raise exceptions.KeystoneError
+ else:
+ req = requests.get("{}/auth/tokens".format(url), headers=headers, verify=_verify)
+ if req.status_code in (200, 201):
+ # Note (asteroide): the time stamps is not in ISO 8601, so it is necessary to delete
+ # characters after the dot
+ token_time = req.json().get("token").get("expires_at").split(".")
+ TOKENS[token] = dict()
+ TOKENS[token]["expires_at"] = time.strptime(token_time[0], "%Y-%m-%dT%H:%M:%S")
+ TOKENS[token]["user"] = req.json().get("token").get("user").get("id")
+ return TOKENS[token]["user"]
+ LOG.error("{} - {}".format(req.status_code, req.text))
+ raise exceptions.KeystoneError
+ elif CONF.keystone.check_token.lower() == "strict":
+ req = requests.head("{}/auth/tokens".format(url), headers=headers, verify=_verify)
+ if req.status_code in (200, 201):
+ return token
+ LOG.error("{} - {}".format(req.status_code, req.text))
+ raise exceptions.KeystoneError
+ raise exceptions.KeystoneError
+
+
+def check_auth(function):
+ @wraps(function)
+ def wrapper(*args, **kwargs):
+ token = request.headers.get('X-Auth-Token')
+ token = check_token(token)
+ if not token:
+ raise exceptions.AuthException
+ user_id = kwargs.pop("user_id", token)
+ result = function(*args, **kwargs, user_id=user_id)
+ return result
+ return wrapper
diff --git a/moonv4/moon_interface/requirements.txt b/moonv4/moon_interface/requirements.txt
new file mode 100644
index 00000000..85fc9e04
--- /dev/null
+++ b/moonv4/moon_interface/requirements.txt
@@ -0,0 +1,7 @@
+kombu !=4.0.1,!=4.0.0
+oslo.messaging
+oslo.config
+vine
+flask
+flask_restful
+flask_cors \ No newline at end of file
diff --git a/moonv4/moon_interface/setup.py b/moonv4/moon_interface/setup.py
new file mode 100644
index 00000000..3460c991
--- /dev/null
+++ b/moonv4/moon_interface/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_interface
+
+
+setup(
+
+ name='moon_interface',
+
+ version=moon_interface.__version__,
+
+ packages=find_packages(),
+
+ author="Thomas Duval",
+
+ author_email="thomas.duval@orange.com",
+
+ description="",
+
+ long_description=open('README.rst').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_interface = moon_interface.server:main',
+ ],
+ }
+
+)
diff --git a/moonv4/moon_interface/tests/apitests/README.md b/moonv4/moon_interface/tests/apitests/README.md
new file mode 100644
index 00000000..ef74a1e3
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/README.md
@@ -0,0 +1,33 @@
+Test directory
+==============
+
+API tests
+---------
+To test all interfaces, you can use :
+
+```bash
+$ cd moonv4/moon_interface/tests/apitests
+$ pytest
+============================================================================= test session starts ==============================================================================
+platform linux -- Python 3.5.2, pytest-3.0.7, py-1.4.33, pluggy-0.4.0
+rootdir: /home/vdsq3226/projets/opnfv/moonv4/moon_interface, inifile:
+collected 15 items
+
+test_models.py .....
+test_pdp.py .
+test_policies.py .........
+
+```
+
+Populate default variables for a particular demonstration
+---------------------------------------------------------
+
+```bash
+$ cd moonv4/moon_interface/tests/apitests
+$ python3 populate_default_values.py scenario/rbac.py -v
+Loading: scenario/rbac.py
+2017-03-31 09:57:17,243 WARNING Creating model RBAC
+2017-03-31 09:57:17,507 WARNING Creating policy Multi policy example
+2017-03-31 09:57:18,690 WARNING Creating PDP pdp1
+
+``` \ No newline at end of file
diff --git a/moonv4/moon_interface/tests/apitests/populate_default_values.py b/moonv4/moon_interface/tests/apitests/populate_default_values.py
new file mode 100644
index 00000000..f58a7444
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/populate_default_values.py
@@ -0,0 +1,149 @@
+import argparse
+import logging
+from importlib.machinery import SourceFileLoader
+from utils.pdp import *
+from utils.models import *
+from utils.policies import *
+
+parser = argparse.ArgumentParser()
+parser.add_argument('filename', help='scenario filename', nargs=1)
+parser.add_argument("--verbose", "-v", action='store_true', help="verbose mode")
+args = parser.parse_args()
+
+FORMAT = '%(asctime)-15s %(levelname)s %(message)s'
+logging.basicConfig(
+ format=FORMAT,
+ level=logging.WARNING)
+
+logger = logging.getLogger(__name__)
+
+if args.filename:
+ print("Loading: {}".format(args.filename[0]))
+
+m = SourceFileLoader("scenario", args.filename[0])
+
+scenario = m.load_module()
+
+
+def create_model():
+ if args.verbose:
+ logger.warning("Creating model {}".format(scenario.model_name))
+ _model_id = add_model(name=scenario.model_name)
+ for cat in scenario.subject_categories:
+ scenario.subject_categories[cat] = add_subject_category(name=cat)
+ for cat in scenario.object_categories:
+ scenario.object_categories[cat] = add_object_category(name=cat)
+ for cat in scenario.action_categories:
+ scenario.action_categories[cat] = add_action_category(name=cat)
+ sub_cat = []
+ ob_cat = []
+ act_cat = []
+ meta_rule_list = []
+ for item_name, item_value in scenario.meta_rule.items():
+ for item in item_value["value"]:
+ if item in scenario.subject_categories:
+ sub_cat.append(scenario.subject_categories[item])
+ elif item in scenario.object_categories:
+ ob_cat.append(scenario.object_categories[item])
+ elif item in scenario.action_categories:
+ act_cat.append(scenario.action_categories[item])
+ meta_rule_id = add_meta_rule(item_name, sub_cat, ob_cat, act_cat)
+ item_value["id"] = meta_rule_id
+ meta_rule_list.append(meta_rule_id)
+ return _model_id, meta_rule_list
+
+
+def create_policy(model_id, meta_rule_list):
+ if args.verbose:
+ logger.warning("Creating policy {}".format(scenario.policy_name))
+ policy_id = add_policy(name=scenario.policy_name)
+
+ update_policy(policy_id, model_id)
+
+ for meta_rule_id in meta_rule_list:
+ add_meta_rule_to_model(model_id, meta_rule_id)
+
+ for subject_cat_name in scenario.subject_data:
+ for subject_data_name in scenario.subject_data[subject_cat_name]:
+ data_id = scenario.subject_data[subject_cat_name][subject_data_name] = add_subject_data(
+ policy_id=policy_id,
+ category_id=scenario.subject_categories[subject_cat_name], name=subject_data_name)
+ scenario.subject_data[subject_cat_name][subject_data_name] = data_id
+ for object_cat_name in scenario.object_data:
+ for object_data_name in scenario.object_data[object_cat_name]:
+ data_id = scenario.object_data[object_cat_name][object_data_name] = add_object_data(
+ policy_id=policy_id,
+ category_id=scenario.object_categories[object_cat_name], name=object_data_name)
+ scenario.object_data[object_cat_name][object_data_name] = data_id
+ for action_cat_name in scenario.action_data:
+ for action_data_name in scenario.action_data[action_cat_name]:
+ data_id = scenario.action_data[action_cat_name][action_data_name] = add_action_data(
+ policy_id=policy_id,
+ category_id=scenario.action_categories[action_cat_name], name=action_data_name)
+ scenario.action_data[action_cat_name][action_data_name] = data_id
+
+ for name in scenario.subjects:
+ scenario.subjects[name] = add_subject(policy_id, name=name)
+ for name in scenario.objects:
+ scenario.objects[name] = add_object(policy_id, name=name)
+ for name in scenario.actions:
+ scenario.actions[name] = add_action(policy_id, name=name)
+
+ for subject_name in scenario.subject_assignments:
+ for subject_category_name in scenario.subject_assignments[subject_name]:
+ subject_id = scenario.subjects[subject_name]
+ subject_cat_id = scenario.subject_categories[subject_category_name]
+ subject_data_id = scenario.subject_data[subject_category_name][scenario.subject_assignments[subject_name][subject_category_name]]
+ add_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id)
+ for object_name in scenario.object_assignments:
+ for object_category_name in scenario.object_assignments[object_name]:
+ object_id = scenario.objects[object_name]
+ object_cat_id = scenario.object_categories[object_category_name]
+ object_data_id = scenario.object_data[object_category_name][scenario.object_assignments[object_name][object_category_name]]
+ add_object_assignments(policy_id, object_id, object_cat_id, object_data_id)
+ for action_name in scenario.action_assignments:
+ for action_category_name in scenario.action_assignments[action_name]:
+ action_id = scenario.actions[action_name]
+ action_cat_id = scenario.action_categories[action_category_name]
+ action_data_id = scenario.action_data[action_category_name][scenario.action_assignments[action_name][action_category_name]]
+ add_action_assignments(policy_id, action_id, action_cat_id, action_data_id)
+
+ for meta_rule_name in scenario.rules:
+ data_list = []
+ meta_rule_value = scenario.meta_rule[meta_rule_name]
+ for rule in scenario.rules[meta_rule_name]:
+ _meta_rule = list(meta_rule_value["value"])
+ for data_name in rule:
+ category_name = _meta_rule.pop(0)
+ if category_name in scenario.subject_categories:
+ data_list.append(scenario.subject_data[category_name][data_name])
+ elif category_name in scenario.object_categories:
+ data_list.append(scenario.object_data[category_name][data_name])
+ elif category_name in scenario.action_categories:
+ data_list.append(scenario.action_data[category_name][data_name])
+ add_rule(policy_id, meta_rule_value["id"], data_list)
+ return policy_id
+
+
+def create_pdp(policy_id=None):
+ if args.verbose:
+ logger.warning("Creating PDP {}".format(scenario.pdp_name))
+ projects = get_keystone_projects()
+ admin_project_id = None
+ for _project in projects['projects']:
+ if _project['name'] == "admin":
+ admin_project_id = _project['id']
+ assert admin_project_id
+ pdps = check_pdp()["pdps"]
+ for pdp_id, pdp_value in pdps.items():
+ if scenario.pdp_name == pdp_value["name"]:
+ update_pdp(pdp_id, policy_id=policy_id)
+ return pdp_id
+ _pdp_id = add_pdp(name=scenario.pdp_name, policy_id=policy_id)
+ map_to_keystone(pdp_id=_pdp_id, keystone_project_id=admin_project_id)
+ return _pdp_id
+
+if __name__ == "__main__":
+ model_id, meta_rule_list = create_model()
+ policy_id = create_policy(model_id, meta_rule_list)
+ pdp_id = create_pdp(policy_id)
diff --git a/moonv4/moon_interface/tests/apitests/scenario/mls.py b/moonv4/moon_interface/tests/apitests/scenario/mls.py
new file mode 100644
index 00000000..fab1d528
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/scenario/mls.py
@@ -0,0 +1,44 @@
+
+pdp_name = "pdp1"
+policy_name = "MLS Policy example"
+model_name = "MLS"
+
+subjects = {"user0": "", "user1": "", "user2": "", }
+objects = {"vm0": "", "vm1": "", }
+actions = {"start": "", "stop": ""}
+
+subject_categories = {"subject-security-level": "", }
+object_categories = {"object-security-level": "", }
+action_categories = {"action-type": "", }
+
+subject_data = {
+ "subject-security-level": {"low": "", "medium": "", "high": ""},
+}
+object_data = {
+ "object-security-level": {"low": "", "medium": "", "high": ""},
+}
+action_data = {"action-type": {"vm-action": "", "storage-action": "", }}
+
+subject_assignments = {
+ "user0": {"subject-security-level": "high"},
+ "user1": {"subject-security-level": "medium"},
+}
+object_assignments = {
+ "vm0": {"object-security-level": "medium"},
+ "vm1": {"object-security-level": "low"},
+}
+action_assignments = {
+ "start": {"action-type": "vm-action"},
+ "stop": {"action-type": "vm-action"}
+}
+
+meta_rule = {
+ "mls": {"id": "", "value": ("subject-security-level", "object-security-level", "action-type")},
+}
+
+rules = {
+ "mls": (
+ ("high", "medium", "vm-action"),
+ ("medium", "low", "vm-action"),
+ )
+}
diff --git a/moonv4/moon_interface/tests/apitests/scenario/rbac.py b/moonv4/moon_interface/tests/apitests/scenario/rbac.py
new file mode 100644
index 00000000..073f1d65
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/scenario/rbac.py
@@ -0,0 +1,32 @@
+
+pdp_name = "pdp1"
+policy_name = "RBAC policy example"
+model_name = "RBAC"
+
+subjects = {"user0": "", "user1": "", }
+objects = {"vm0": "", }
+actions = {"start": "", "stop": ""}
+
+subject_categories = {"role": "", }
+object_categories = {"id": "", }
+action_categories = {"action-type": "", }
+
+subject_data = {"role": {"admin": "", "employee": ""}}
+object_data = {"id": {"vm1": "", "vm2": ""}}
+action_data = {"action-type": {"vm-action": "", }}
+
+subject_assignments = {"user0": {"role": "admin"}, "user1": {"role": "employee"}, }
+object_assignments = {"vm0": {"id": "vm1"}}
+action_assignments = {"start": {"action-type": "vm-action"}, "stop": {"action-type": "vm-action"}}
+
+meta_rule = {
+ "rbac": {"id": "", "value": ("role", "id", "action-type")},
+}
+
+rules = {
+ "rbac": (
+ ("admin", "vm1", "vm-action"),
+ )
+}
+
+
diff --git a/moonv4/moon_interface/tests/apitests/scenario/rbac_mls.py b/moonv4/moon_interface/tests/apitests/scenario/rbac_mls.py
new file mode 100644
index 00000000..8a5362ea
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/scenario/rbac_mls.py
@@ -0,0 +1,50 @@
+
+pdp_name = "pdp1"
+policy_name = "Multi policy example"
+model_name = "RBAC"
+
+subjects = {"user0": "", "user1": "", "user2": "", }
+objects = {"vm0": "", "vm1": "", }
+actions = {"start": "", "stop": ""}
+
+subject_categories = {"role": "", "subject-security-level": "", }
+object_categories = {"id": "", "object-security-level": "", }
+action_categories = {"action-type": "", }
+
+subject_data = {
+ "role": {"admin": "", "employee": ""},
+ "subject-security-level": {"low": "", "medium": "", "high": ""},
+}
+object_data = {
+ "id": {"vm1": "", "vm2": ""},
+ "object-security-level": {"low": "", "medium": "", "high": ""},
+}
+action_data = {"action-type": {"vm-action": "", "storage-action": "", }}
+
+subject_assignments = {
+ "user0": {"role": "admin", "subject-security-level": "high"},
+ "user1": {"role": "employee", "subject-security-level": "medium"},
+}
+object_assignments = {
+ "vm0": {"id": "vm1", "object-security-level": "medium"},
+ "vm1": {"id": "vm2", "object-security-level": "low"},
+}
+action_assignments = {
+ "start": {"action-type": "vm-action"},
+ "stop": {"action-type": "vm-action"}
+}
+
+meta_rule = {
+ "rbac": {"id": "", "value": ("role", "id", "action-type")},
+ "mls": {"id": "", "value": ("subject-security-level", "object-security-level", "action-type")},
+}
+
+rules = {
+ "rbac": (
+ ("admin", "vm1", "vm-action"),
+ ),
+ "mls": (
+ ("high", "medium", "vm-action"),
+ ("medium", "low", "vm-action"),
+ )
+}
diff --git a/moonv4/moon_interface/tests/apitests/test_models.py b/moonv4/moon_interface/tests/apitests/test_models.py
new file mode 100644
index 00000000..0da40ce5
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/test_models.py
@@ -0,0 +1,37 @@
+from utils.models import *
+
+
+def test_models():
+ check_model()
+ model_id = add_model()
+ check_model(model_id)
+ delete_model(model_id)
+
+
+def test_meta_data_subject():
+ category_id = add_subject_category()
+ check_subject_category(category_id)
+ # TODO (asteroide): must implement the deletion of linked data
+ # delete_subject_category(category_id)
+
+
+def test_meta_data_object():
+ category_id = add_object_category()
+ check_object_category(category_id)
+ # TODO (asteroide): must implement the deletion of linked data
+ # delete_object_category(category_id)
+
+
+def test_meta_data_action():
+ category_id = add_action_category()
+ check_action_category(category_id)
+ # TODO (asteroide): must implement the deletion of linked data
+ # delete_action_category(category_id)
+
+
+def test_meta_rule():
+ meta_rule_id, scat_id, ocat_id, acat_id = add_categories_and_meta_rule()
+ check_meta_rule(meta_rule_id, scat_id, ocat_id, acat_id)
+ delete_meta_rule(meta_rule_id)
+
+
diff --git a/moonv4/moon_interface/tests/apitests/test_pdp.py b/moonv4/moon_interface/tests/apitests/test_pdp.py
new file mode 100644
index 00000000..6cd5365b
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/test_pdp.py
@@ -0,0 +1,16 @@
+from utils.pdp import *
+
+
+def test_pdp():
+ projects = get_keystone_projects()
+ admin_project_id = None
+ for _project in projects['projects']:
+ if _project['name'] == "admin":
+ admin_project_id = _project['id']
+ assert admin_project_id
+ check_pdp()
+ pdp_id = add_pdp()
+ check_pdp(pdp_id)
+ map_to_keystone(pdp_id=pdp_id, keystone_project_id=admin_project_id)
+ check_pdp(pdp_id=pdp_id, keystone_project_id=admin_project_id)
+ delete_pdp(pdp_id)
diff --git a/moonv4/moon_interface/tests/apitests/test_policies.py b/moonv4/moon_interface/tests/apitests/test_policies.py
new file mode 100644
index 00000000..310aad66
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/test_policies.py
@@ -0,0 +1,154 @@
+from utils.policies import *
+from utils.models import *
+
+
+def test_policies():
+ check_policy()
+ policy_id = add_policy()
+ check_policy(policy_id)
+ delete_policy(policy_id)
+
+
+def test_subjects():
+ policy_id = add_policy()
+ subject_id = add_subject()
+
+ update_subject(subject_id=subject_id, policy_id=policy_id)
+
+ check_subject(subject_id=subject_id, policy_id=policy_id)
+
+ delete_subject(subject_id, policy_id=policy_id)
+ delete_subject(subject_id)
+
+
+def test_objects():
+ policy_id = add_policy()
+ object_id = add_object()
+
+ update_object(object_id=object_id, policy_id=policy_id)
+ check_object(object_id=object_id, policy_id=policy_id)
+
+ delete_object(object_id=object_id, policy_id=policy_id)
+ delete_object(object_id=object_id)
+
+
+def test_actions():
+ policy_id = add_policy()
+ action_id = add_action()
+
+ update_action(action_id=action_id, policy_id=policy_id)
+ check_action(action_id=action_id, policy_id=policy_id)
+
+ delete_action(action_id=action_id, policy_id=policy_id)
+ delete_action(action_id=action_id)
+
+
+def test_subject_data():
+ policy_id = add_policy()
+
+ model_id = add_model()
+
+ update_policy(policy_id, model_id)
+
+ meta_rule_id, subject_cat_id, object_cat_id, action_cat_id = add_categories_and_meta_rule()
+ add_meta_rule_to_model(model_id, meta_rule_id)
+
+ subject_data_id = add_subject_data(policy_id=policy_id, category_id=subject_cat_id)
+ check_subject_data(policy_id=policy_id, data_id=subject_data_id, category_id=subject_cat_id)
+
+
+def test_object_data():
+ policy_id = add_policy()
+
+ model_id = add_model()
+
+ update_policy(policy_id, model_id)
+
+ meta_rule_id, object_cat_id, object_cat_id, action_cat_id = add_categories_and_meta_rule()
+ add_meta_rule_to_model(model_id, meta_rule_id)
+
+ object_data_id = add_object_data(policy_id=policy_id, category_id=object_cat_id)
+ check_object_data(policy_id=policy_id, data_id=object_data_id, category_id=object_cat_id)
+
+
+def test_action_data():
+ policy_id = add_policy()
+
+ model_id = add_model()
+
+ update_policy(policy_id, model_id)
+
+ meta_rule_id, action_cat_id, action_cat_id, action_cat_id = add_categories_and_meta_rule()
+ add_meta_rule_to_model(model_id, meta_rule_id)
+
+ action_data_id = add_action_data(policy_id=policy_id, category_id=action_cat_id)
+ check_action_data(policy_id=policy_id, data_id=action_data_id, category_id=action_cat_id)
+
+
+def test_assignments():
+ policy_id = add_policy()
+
+ model_id = add_model()
+
+ update_policy(policy_id, model_id)
+
+ meta_rule_id, subject_cat_id, object_cat_id, action_cat_id = add_categories_and_meta_rule()
+ add_meta_rule_to_model(model_id, meta_rule_id)
+
+ subject_data_id = add_subject_data(policy_id=policy_id, category_id=subject_cat_id)
+ subject_data_id_bis = add_subject_data(policy_id=policy_id, category_id=subject_cat_id)
+ object_data_id = add_object_data(policy_id=policy_id, category_id=object_cat_id)
+ object_data_id_bis = add_object_data(policy_id=policy_id, category_id=object_cat_id)
+ action_data_id = add_action_data(policy_id=policy_id, category_id=action_cat_id)
+ action_data_id_bis = add_action_data(policy_id=policy_id, category_id=action_cat_id)
+
+ subject_id = add_subject(policy_id)
+ object_id = add_object(policy_id)
+ action_id = add_action(policy_id)
+
+ add_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id)
+ add_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id_bis)
+ add_object_assignments(policy_id, object_id, object_cat_id, object_data_id)
+ add_object_assignments(policy_id, object_id, object_cat_id, object_data_id_bis)
+ add_action_assignments(policy_id, action_id, action_cat_id, action_data_id)
+ add_action_assignments(policy_id, action_id, action_cat_id, action_data_id_bis)
+
+ check_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id)
+ check_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id_bis)
+ check_object_assignments(policy_id, object_id, object_cat_id, object_data_id)
+ check_object_assignments(policy_id, object_id, object_cat_id, object_data_id_bis)
+ check_action_assignments(policy_id, action_id, action_cat_id, action_data_id)
+ check_action_assignments(policy_id, action_id, action_cat_id, action_data_id_bis)
+
+ delete_subject_assignment(policy_id, subject_id, subject_cat_id, subject_data_id)
+ delete_object_assignment(policy_id, object_id, object_cat_id, object_data_id)
+ delete_action_assignment(policy_id, action_id, action_cat_id, action_data_id)
+
+
+def test_rule():
+ policy_id = add_policy()
+
+ model_id = add_model()
+
+ update_policy(policy_id, model_id)
+
+ meta_rule_id, subject_cat_id, object_cat_id, action_cat_id = add_categories_and_meta_rule()
+ add_meta_rule_to_model(model_id, meta_rule_id)
+
+ subject_data_id = add_subject_data(policy_id=policy_id, category_id=subject_cat_id)
+ object_data_id = add_object_data(policy_id=policy_id, category_id=object_cat_id)
+ action_data_id = add_action_data(policy_id=policy_id, category_id=action_cat_id)
+
+ subject_id = add_subject(policy_id)
+ object_id = add_object(policy_id)
+ action_id = add_action(policy_id)
+
+ add_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id)
+ add_object_assignments(policy_id, object_id, object_cat_id, object_data_id)
+ add_action_assignments(policy_id, action_id, action_cat_id, action_data_id)
+
+ rule_id = add_rule(policy_id, meta_rule_id, [subject_data_id, object_data_id, action_data_id])
+ check_rule(policy_id, meta_rule_id, rule_id, [subject_data_id, object_data_id, action_data_id])
+
+ delete_rule(policy_id, rule_id)
+
diff --git a/moonv4/moon_interface/tests/apitests/utils/__init__.py b/moonv4/moon_interface/tests/apitests/utils/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/utils/__init__.py
diff --git a/moonv4/moon_interface/tests/apitests/utils/models.py b/moonv4/moon_interface/tests/apitests/utils/models.py
new file mode 100644
index 00000000..1ba6e440
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/utils/models.py
@@ -0,0 +1,260 @@
+import requests
+import copy
+
+URL = "http://172.18.0.11:38001{}"
+HEADERS = {"content-type": "application/json"}
+
+model_template = {
+ "name": "test_model",
+ "description": "test",
+ "meta_rules": []
+}
+
+category_template = {
+ "name": "name of the category",
+ "description": "description of the category"
+}
+
+meta_rule_template = {
+ "name": "test_meta_rule",
+ "subject_categories": [],
+ "object_categories": [],
+ "action_categories": []
+}
+
+
+def check_model(model_id=None):
+ req = requests.get(URL.format("/models"))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "models" in result
+ if model_id:
+ assert result["models"]
+ assert model_id in result['models']
+ assert "name" in result['models'][model_id]
+ assert model_template["name"] == result['models'][model_id]["name"]
+ return result['models']
+
+
+def add_model(name=None):
+ if name:
+ model_template['name'] = name
+ req = requests.post(URL.format("/models"), json=model_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ model_id = list(result['models'].keys())[0]
+ if "result" in result:
+ assert result["result"]
+ assert "name" in result['models'][model_id]
+ assert model_template["name"] == result['models'][model_id]["name"]
+ return model_id
+
+
+def delete_model(model_id):
+ req = requests.delete(URL.format("/models/{}".format(model_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "result" in result
+ assert result["result"]
+
+
+def add_subject_category(name="subject_cat_1"):
+ category_template["name"] = name
+ req = requests.post(URL.format("/subject_categories"), json=category_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "subject_categories" in result
+ category_id = list(result['subject_categories'].keys())[0]
+ if "result" in result:
+ assert result["result"]
+ assert "name" in result['subject_categories'][category_id]
+ assert category_template["name"] == result['subject_categories'][category_id]["name"]
+ return category_id
+
+
+def check_subject_category(category_id):
+ req = requests.get(URL.format("/subject_categories"))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "subject_categories" in result
+ if "result" in result:
+ assert result["result"]
+ assert category_id in result['subject_categories']
+ assert "name" in result['subject_categories'][category_id]
+ assert category_template["name"] == result['subject_categories'][category_id]["name"]
+
+
+def delete_subject_category(category_id):
+ req = requests.delete(URL.format("/subject_categories/{}".format(category_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ if "result" in result:
+ assert result["result"]
+
+
+def add_object_category(name="object_cat_1"):
+ category_template["name"] = name
+ req = requests.post(URL.format("/object_categories"), json=category_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "object_categories" in result
+ category_id = list(result['object_categories'].keys())[0]
+ if "result" in result:
+ assert result["result"]
+ assert "name" in result['object_categories'][category_id]
+ assert category_template["name"] == result['object_categories'][category_id]["name"]
+ return category_id
+
+
+def check_object_category(category_id):
+ req = requests.get(URL.format("/object_categories"))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "object_categories" in result
+ if "result" in result:
+ assert result["result"]
+ assert category_id in result['object_categories']
+ assert "name" in result['object_categories'][category_id]
+ assert category_template["name"] == result['object_categories'][category_id]["name"]
+
+
+def delete_object_category(category_id):
+ req = requests.delete(URL.format("/object_categories/{}".format(category_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ if "result" in result:
+ assert result["result"]
+
+
+def add_action_category(name="action_cat_1"):
+ category_template["name"] = name
+ req = requests.post(URL.format("/action_categories"), json=category_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "action_categories" in result
+ category_id = list(result['action_categories'].keys())[0]
+ if "result" in result:
+ assert result["result"]
+ assert "name" in result['action_categories'][category_id]
+ assert category_template["name"] == result['action_categories'][category_id]["name"]
+ return category_id
+
+
+def check_action_category(category_id):
+ req = requests.get(URL.format("/action_categories"))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "action_categories" in result
+ if "result" in result:
+ assert result["result"]
+ assert category_id in result['action_categories']
+ assert "name" in result['action_categories'][category_id]
+ assert category_template["name"] == result['action_categories'][category_id]["name"]
+
+
+def delete_action_category(category_id):
+ req = requests.delete(URL.format("/action_categories/{}".format(category_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ if "result" in result:
+ assert result["result"]
+
+
+def add_categories_and_meta_rule(name="test_meta_rule"):
+ scat_id = add_subject_category()
+ ocat_id = add_object_category()
+ acat_id = add_action_category()
+ _meta_rule_template = copy.deepcopy(meta_rule_template)
+ _meta_rule_template["name"] = name
+ _meta_rule_template["subject_categories"].append(scat_id)
+ _meta_rule_template["object_categories"].append(ocat_id)
+ _meta_rule_template["action_categories"].append(acat_id)
+ req = requests.post(URL.format("/meta_rules"), json=_meta_rule_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "meta_rules" in result
+ meta_rule_id = list(result['meta_rules'].keys())[0]
+ if "result" in result:
+ assert result["result"]
+ assert "name" in result['meta_rules'][meta_rule_id]
+ assert _meta_rule_template["name"] == result['meta_rules'][meta_rule_id]["name"]
+ return meta_rule_id, scat_id, ocat_id, acat_id
+
+
+def add_meta_rule(name="test_meta_rule", scat=[], ocat=[], acat=[]):
+ _meta_rule_template = copy.deepcopy(meta_rule_template)
+ _meta_rule_template["name"] = name
+ _meta_rule_template["subject_categories"] = []
+ _meta_rule_template["subject_categories"].extend(scat)
+ _meta_rule_template["object_categories"] = []
+ _meta_rule_template["object_categories"].extend(ocat)
+ _meta_rule_template["action_categories"] = []
+ _meta_rule_template["action_categories"].extend(acat)
+ req = requests.post(URL.format("/meta_rules"), json=_meta_rule_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "meta_rules" in result
+ meta_rule_id = list(result['meta_rules'].keys())[0]
+ if "result" in result:
+ assert result["result"]
+ assert "name" in result['meta_rules'][meta_rule_id]
+ assert _meta_rule_template["name"] == result['meta_rules'][meta_rule_id]["name"]
+ return meta_rule_id
+
+
+def check_meta_rule(meta_rule_id, scat_id=None, ocat_id=None, acat_id=None):
+ req = requests.get(URL.format("/meta_rules"))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "meta_rules" in result
+ if "result" in result:
+ assert result["result"]
+ assert meta_rule_id in result['meta_rules']
+ assert "name" in result['meta_rules'][meta_rule_id]
+ if scat_id:
+ assert scat_id in result['meta_rules'][meta_rule_id]["subject_categories"]
+ if ocat_id:
+ assert ocat_id in result['meta_rules'][meta_rule_id]["object_categories"]
+ if acat_id:
+ assert acat_id in result['meta_rules'][meta_rule_id]["action_categories"]
+
+
+def delete_meta_rule(meta_rule_id):
+ req = requests.delete(URL.format("/meta_rules/{}".format(meta_rule_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ if "result" in result:
+ assert result["result"]
+
+
+def add_meta_rule_to_model(model_id, meta_rule_id):
+ model = check_model(model_id)
+ meta_rule_list = model[model_id]["meta_rules"]
+ meta_rule_list.append(meta_rule_id)
+ req = requests.patch(URL.format("/models/{}".format(model_id)),
+ json={"meta_rules": meta_rule_list},
+ headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ model_id = list(result['models'].keys())[0]
+ if "result" in result:
+ assert result["result"]
+ assert "meta_rules" in result['models'][model_id]
+ assert meta_rule_list == result['models'][model_id]["meta_rules"]
diff --git a/moonv4/moon_interface/tests/apitests/utils/pdp.py b/moonv4/moon_interface/tests/apitests/utils/pdp.py
new file mode 100644
index 00000000..81b50e38
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/utils/pdp.py
@@ -0,0 +1,145 @@
+import requests
+
+URL = "http://172.18.0.11:38001{}"
+HEADERS = {"content-type": "application/json"}
+KEYSTONE_USER = "admin"
+KEYSTONE_PASSWORD = "p4ssw0rd"
+KEYSTONE_PROJECT = "admin"
+
+pdp_template = {
+ "name": "test_pdp",
+ "security_pipeline": [],
+ "keystone_project_id": "",
+ "description": "test",
+}
+
+
+def get_keystone_projects():
+ server = "keystone"
+
+ HEADERS = {
+ "Content-Type": "application/json"
+ }
+
+ data_auth = {
+ "auth": {
+ "identity": {
+ "methods": [
+ "password"
+ ],
+ "password": {
+ "user": {
+ "domain": {
+ "id": "Default"
+ },
+ "name": KEYSTONE_USER,
+ "password": KEYSTONE_PASSWORD
+ }
+ }
+ },
+ "scope": {
+ "project": {
+ "domain": {
+ "id": "Default"
+ },
+ "name": KEYSTONE_PROJECT
+ }
+ }
+ }
+ }
+
+ req = requests.post("http://{}:5000/v3/auth/tokens".format(server), json=data_auth, headers=HEADERS)
+
+ assert req.status_code in (200, 201)
+ TOKEN = req.headers['X-Subject-Token']
+ HEADERS['X-Auth-Token'] = TOKEN
+ req = requests.get("http://{}:5000/v3/projects".format(server), headers=HEADERS)
+ assert req.status_code in (200, 201)
+ return req.json()
+
+
+def check_pdp(pdp_id=None, keystone_project_id=None):
+ req = requests.get(URL.format("/pdp"))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "pdps" in result
+ if pdp_id:
+ assert result["pdps"]
+ assert pdp_id in result['pdps']
+ assert "name" in result['pdps'][pdp_id]
+ assert pdp_template["name"] == result['pdps'][pdp_id]["name"]
+ if keystone_project_id:
+ assert result["pdps"]
+ assert pdp_id in result['pdps']
+ assert "keystone_project_id" in result['pdps'][pdp_id]
+ assert keystone_project_id == result['pdps'][pdp_id]["keystone_project_id"]
+ return result
+
+
+def add_pdp(name="test_pdp", policy_id=None):
+ pdp_template['name'] = name
+ if policy_id:
+ pdp_template['security_pipeline'].append(policy_id)
+ req = requests.post(URL.format("/pdp"), json=pdp_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ pdp_id = list(result['pdps'].keys())[0]
+ if "result" in result:
+ assert result["result"]
+ assert "name" in result['pdps'][pdp_id]
+ assert pdp_template["name"] == result['pdps'][pdp_id]["name"]
+ return pdp_id
+
+
+def update_pdp(pdp_id, policy_id=None):
+ req = requests.get(URL.format("/pdp/{}".format(pdp_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "pdps" in result
+ assert pdp_id in result['pdps']
+ pipeline = result['pdps'][pdp_id]["security_pipeline"]
+ if policy_id not in pipeline:
+ pipeline.append(policy_id)
+ req = requests.patch(URL.format("/pdp/{}".format(pdp_id)),
+ json={"security_pipeline": pipeline})
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "pdps" in result
+ assert pdp_id in result['pdps']
+
+ req = requests.get(URL.format("/pdp/{}".format(pdp_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "pdps" in result
+ assert pdp_id in result['pdps']
+ assert policy_id in pipeline
+
+
+def map_to_keystone(pdp_id, keystone_project_id):
+ req = requests.patch(URL.format("/pdp/{}".format(pdp_id)), json={"keystone_project_id": keystone_project_id},
+ headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ if "result" in result:
+ assert result["result"]
+ assert pdp_id in result['pdps']
+ assert "name" in result['pdps'][pdp_id]
+ assert pdp_template["name"] == result['pdps'][pdp_id]["name"]
+ return pdp_id
+
+
+def delete_pdp(pdp_id):
+ req = requests.delete(URL.format("/pdp/{}".format(pdp_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "result" in result
+ assert result["result"]
+
+
diff --git a/moonv4/moon_interface/tests/apitests/utils/policies.py b/moonv4/moon_interface/tests/apitests/utils/policies.py
new file mode 100644
index 00000000..67be91e5
--- /dev/null
+++ b/moonv4/moon_interface/tests/apitests/utils/policies.py
@@ -0,0 +1,581 @@
+import requests
+
+URL = "http://172.18.0.11:38001{}"
+HEADERS = {"content-type": "application/json"}
+FILE = open("/tmp/test.log", "w")
+
+policy_template = {
+ "name": "test_policy",
+ "model_id": "",
+ "genre": "authz",
+ "description": "test",
+}
+
+subject_template = {
+ "name": "test_subject",
+ "description": "test",
+ "email": "mail",
+ "password": "my_pass",
+}
+
+object_template = {
+ "name": "test_subject",
+ "description": "test"
+}
+
+action_template = {
+ "name": "test_subject",
+ "description": "test"
+}
+
+subject_data_template = {
+ "name": "subject_data1",
+ "description": "description of the data subject"
+}
+
+object_data_template = {
+ "name": "object_data1",
+ "description": "description of the data subject"
+}
+
+action_data_template = {
+ "name": "action_data1",
+ "description": "description of the data subject"
+}
+
+subject_assignment_template = {
+ "id": "",
+ "category_id": "",
+ "scope_id": ""
+}
+
+
+def check_policy(policy_id=None):
+ req = requests.get(URL.format("/policies"))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "policies" in result
+ if policy_id:
+ assert result["policies"]
+ assert policy_id in result['policies']
+ assert "name" in result['policies'][policy_id]
+ assert policy_template["name"] == result['policies'][policy_id]["name"]
+
+
+def add_policy(name="test_policy"):
+ policy_template["name"] = name
+ req = requests.post(URL.format("/policies"), json=policy_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ policy_id = list(result['policies'].keys())[0]
+ if "result" in result:
+ assert result["result"]
+ assert "name" in result['policies'][policy_id]
+ assert policy_template["name"] == result['policies'][policy_id]["name"]
+ return policy_id
+
+
+def update_policy(policy_id, model_id):
+ req = requests.patch(URL.format("/policies/{}".format(policy_id)),
+ json={"model_id": model_id}, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ policy_id = list(result['policies'].keys())[0]
+ if "result" in result:
+ assert result["result"]
+ assert "model_id" in result['policies'][policy_id]
+ assert model_id == result['policies'][policy_id]["model_id"]
+
+
+def delete_policy(policy_id):
+ req = requests.delete(URL.format("/policies/{}".format(policy_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "result" in result
+ assert result["result"]
+
+
+def add_subject(policy_id=None, name="test_subject"):
+ subject_template['name'] = name
+ if policy_id:
+ req = requests.post(URL.format("/policies/{}/subjects".format(policy_id)),
+ json=subject_template, headers=HEADERS)
+ else:
+ req = requests.post(URL.format("/subjects"), json=subject_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert "subjects" in result
+ subject_id = list(result['subjects'].keys())[0]
+ return subject_id
+
+
+def update_subject(subject_id, policy_id=None, description=None):
+ if policy_id and not description:
+ req = requests.patch(URL.format("/policies/{}/subjects/{}".format(policy_id, subject_id)),
+ json={})
+ elif policy_id and description:
+ req = requests.patch(URL.format("/policies/{}/subjects/{}".format(policy_id, subject_id)),
+ json={"description": description})
+ else:
+ req = requests.patch(URL.format("/subjects/{}".format(subject_id)),
+ json={"description": description})
+ assert req.status_code == 200
+ result = req.json()
+ assert "subjects" in result
+ assert "name" in result["subjects"][subject_id]
+ assert subject_template["name"] == result["subjects"][subject_id]["name"]
+ assert "policy_list" in result["subjects"][subject_id]
+ if policy_id:
+ assert policy_id in result["subjects"][subject_id]["policy_list"]
+ if description:
+ assert description in result["subjects"][subject_id]["description"]
+
+
+def check_subject(subject_id=None, policy_id=None):
+ if policy_id:
+ req = requests.get(URL.format("/policies/{}/subjects".format(policy_id)))
+ else:
+ req = requests.get(URL.format("/subjects"))
+ assert req.status_code == 200
+ result = req.json()
+ assert "subjects" in result
+ assert "name" in result["subjects"][subject_id]
+ assert subject_template["name"] == result["subjects"][subject_id]["name"]
+ if policy_id:
+ assert "policy_list" in result["subjects"][subject_id]
+ assert policy_id in result["subjects"][subject_id]["policy_list"]
+
+
+def delete_subject(subject_id, policy_id=None):
+ if policy_id:
+ req = requests.delete(URL.format("/policies/{}/subjects/{}".format(policy_id, subject_id)))
+ else:
+ req = requests.delete(URL.format("/subjects/{}".format(subject_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "result" in result
+ assert result["result"]
+
+ if policy_id:
+ req = requests.get(URL.format("/policies/{}/subjects".format(policy_id)))
+ else:
+ req = requests.get(URL.format("/subjects"))
+ assert req.status_code == 200
+ result = req.json()
+ assert "subjects" in result
+ if subject_id in result["subjects"]:
+ assert "name" in result["subjects"][subject_id]
+ assert subject_template["name"] == result["subjects"][subject_id]["name"]
+ if policy_id:
+ assert "policy_list" in result["subjects"][subject_id]
+ assert policy_id not in result["subjects"][subject_id]["policy_list"]
+
+
+def add_object(policy_id=None, name="test_object"):
+ object_template['name'] = name
+ if policy_id:
+ req = requests.post(URL.format("/policies/{}/objects".format(policy_id)),
+ json=object_template, headers=HEADERS)
+ else:
+ req = requests.post(URL.format("/objects"), json=object_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert "objects" in result
+ object_id = list(result['objects'].keys())[0]
+ return object_id
+
+
+def update_object(object_id, policy_id):
+ req = requests.patch(URL.format("/policies/{}/objects/{}".format(policy_id, object_id)), json={})
+ assert req.status_code == 200
+ result = req.json()
+ assert "objects" in result
+ assert "name" in result["objects"][object_id]
+ assert object_template["name"] == result["objects"][object_id]["name"]
+ assert "policy_list" in result["objects"][object_id]
+ assert policy_id in result["objects"][object_id]["policy_list"]
+
+
+def check_object(object_id=None, policy_id=None):
+ if policy_id:
+ req = requests.get(URL.format("/policies/{}/objects".format(policy_id)))
+ else:
+ req = requests.get(URL.format("/objects"))
+ assert req.status_code == 200
+ result = req.json()
+ assert "objects" in result
+ assert "name" in result["objects"][object_id]
+ assert object_template["name"] == result["objects"][object_id]["name"]
+ if policy_id:
+ assert "policy_list" in result["objects"][object_id]
+ assert policy_id in result["objects"][object_id]["policy_list"]
+
+
+def delete_object(object_id, policy_id=None):
+ if policy_id:
+ req = requests.delete(URL.format("/policies/{}/objects/{}".format(policy_id, object_id)))
+ else:
+ req = requests.delete(URL.format("/objects/{}".format(object_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "result" in result
+ assert result["result"]
+
+ if policy_id:
+ req = requests.get(URL.format("/policies/{}/objects".format(policy_id)))
+ else:
+ req = requests.get(URL.format("/objects"))
+ assert req.status_code == 200
+ result = req.json()
+ assert "objects" in result
+ if object_id in result["objects"]:
+ assert "name" in result["objects"][object_id]
+ assert object_template["name"] == result["objects"][object_id]["name"]
+ if policy_id:
+ assert "policy_list" in result["objects"][object_id]
+ assert policy_id not in result["objects"][object_id]["policy_list"]
+
+
+def add_action(policy_id=None, name="test_action"):
+ action_template['name'] = name
+ if policy_id:
+ req = requests.post(URL.format("/policies/{}/actions".format(policy_id)),
+ json=action_template, headers=HEADERS)
+ else:
+ req = requests.post(URL.format("/actions"), json=action_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert "actions" in result
+ action_id = list(result['actions'].keys())[0]
+ return action_id
+
+
+def update_action(action_id, policy_id):
+ req = requests.patch(URL.format("/policies/{}/actions/{}".format(policy_id, action_id)), json={})
+ assert req.status_code == 200
+ result = req.json()
+ assert "actions" in result
+ assert "name" in result["actions"][action_id]
+ assert action_template["name"] == result["actions"][action_id]["name"]
+ assert "policy_list" in result["actions"][action_id]
+ assert policy_id in result["actions"][action_id]["policy_list"]
+
+
+def check_action(action_id=None, policy_id=None):
+ if policy_id:
+ req = requests.get(URL.format("/policies/{}/actions".format(policy_id)))
+ else:
+ req = requests.get(URL.format("/actions"))
+ assert req.status_code == 200
+ result = req.json()
+ assert "actions" in result
+ assert "name" in result["actions"][action_id]
+ assert action_template["name"] == result["actions"][action_id]["name"]
+ if policy_id:
+ assert "policy_list" in result["actions"][action_id]
+ assert policy_id in result["actions"][action_id]["policy_list"]
+
+
+def delete_action(action_id, policy_id=None):
+ if policy_id:
+ req = requests.delete(URL.format("/policies/{}/actions/{}".format(policy_id, action_id)))
+ else:
+ req = requests.delete(URL.format("/actions/{}".format(action_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert type(result) is dict
+ assert "result" in result
+ assert result["result"]
+
+ if policy_id:
+ req = requests.get(URL.format("/policies/{}/actions".format(policy_id)))
+ else:
+ req = requests.get(URL.format("/actions"))
+ assert req.status_code == 200
+ result = req.json()
+ assert "actions" in result
+ if action_id in result["actions"]:
+ assert "name" in result["actions"][action_id]
+ assert action_template["name"] == result["actions"][action_id]["name"]
+ if policy_id:
+ assert "policy_list" in result["actions"][action_id]
+ assert policy_id not in result["actions"][action_id]["policy_list"]
+
+
+def add_subject_data(policy_id, category_id, name="subject_data1"):
+ subject_data_template['name'] = name
+ req = requests.post(URL.format("/policies/{}/subject_data/{}".format(policy_id, category_id)),
+ json=subject_data_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert "subject_data" in result
+ subject_id = list(result['subject_data']['data'].keys())[0]
+ return subject_id
+
+
+def check_subject_data(policy_id, data_id, category_id):
+ req = requests.get(URL.format("/policies/{}/subject_data/{}".format(policy_id, category_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "subject_data" in result
+ for _data in result['subject_data']:
+ assert data_id in list(_data['data'].keys())
+ assert category_id == _data["category_id"]
+
+
+def add_object_data(policy_id, category_id, name="object_data1"):
+ object_data_template['name'] = name
+ req = requests.post(URL.format("/policies/{}/object_data/{}".format(policy_id, category_id)),
+ json=object_data_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert "object_data" in result
+ object_id = list(result['object_data']['data'].keys())[0]
+ return object_id
+
+
+def check_object_data(policy_id, data_id, category_id):
+ req = requests.get(URL.format("/policies/{}/object_data/{}".format(policy_id, category_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "object_data" in result
+ for _data in result['object_data']:
+ assert data_id in list(_data['data'].keys())
+ assert category_id == _data["category_id"]
+
+
+def add_action_data(policy_id, category_id, name="action_data1"):
+ action_data_template['name'] = name
+ req = requests.post(URL.format("/policies/{}/action_data/{}".format(policy_id, category_id)),
+ json=action_data_template, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert "action_data" in result
+ action_id = list(result['action_data']['data'].keys())[0]
+ return action_id
+
+
+def check_action_data(policy_id, data_id, category_id):
+ req = requests.get(URL.format("/policies/{}/action_data/{}".format(policy_id, category_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "action_data" in result
+ for _data in result['action_data']:
+ assert data_id in list(_data['data'].keys())
+ assert category_id == _data["category_id"]
+
+
+def add_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id):
+ req = requests.post(URL.format("/policies/{}/subject_assignments".format(policy_id)),
+ json={
+ "id": subject_id,
+ "category_id": subject_cat_id,
+ "data_id": subject_data_id
+ }, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert "subject_assignments" in result
+ assert result["subject_assignments"]
+
+
+def check_subject_assignments(policy_id, subject_id, subject_cat_id, subject_data_id):
+ req = requests.get(URL.format("/policies/{}/subject_assignments/{}/{}/{}".format(
+ policy_id, subject_id, subject_cat_id, subject_data_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "subject_assignments" in result
+ assert result["subject_assignments"]
+ for key in result["subject_assignments"]:
+ assert "subject_id" in result["subject_assignments"][key]
+ assert "category_id" in result["subject_assignments"][key]
+ assert "assignments" in result["subject_assignments"][key]
+ if result["subject_assignments"][key]['subject_id'] == subject_id and \
+ result["subject_assignments"][key]["category_id"] == subject_cat_id:
+ assert subject_data_id in result["subject_assignments"][key]["assignments"]
+
+
+def check_object_assignments(policy_id, object_id, object_cat_id, object_data_id):
+ req = requests.get(URL.format("/policies/{}/object_assignments/{}/{}/{}".format(
+ policy_id, object_id, object_cat_id, object_data_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "object_assignments" in result
+ assert result["object_assignments"]
+ for key in result["object_assignments"]:
+ assert "object_id" in result["object_assignments"][key]
+ assert "category_id" in result["object_assignments"][key]
+ assert "assignments" in result["object_assignments"][key]
+ if result["object_assignments"][key]['object_id'] == object_id and \
+ result["object_assignments"][key]["category_id"] == object_cat_id:
+ assert object_data_id in result["object_assignments"][key]["assignments"]
+
+
+def check_action_assignments(policy_id, action_id, action_cat_id, action_data_id):
+ req = requests.get(URL.format("/policies/{}/action_assignments/{}/{}/{}".format(
+ policy_id, action_id, action_cat_id, action_data_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "action_assignments" in result
+ assert result["action_assignments"]
+ for key in result["action_assignments"]:
+ assert "action_id" in result["action_assignments"][key]
+ assert "category_id" in result["action_assignments"][key]
+ assert "assignments" in result["action_assignments"][key]
+ if result["action_assignments"][key]['action_id'] == action_id and \
+ result["action_assignments"][key]["category_id"] == action_cat_id:
+ assert action_data_id in result["action_assignments"][key]["assignments"]
+
+
+def add_object_assignments(policy_id, object_id, object_cat_id, object_data_id):
+ req = requests.post(URL.format("/policies/{}/object_assignments".format(policy_id)),
+ json={
+ "id": object_id,
+ "category_id": object_cat_id,
+ "data_id": object_data_id
+ }, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert "object_assignments" in result
+ assert result["object_assignments"]
+
+
+def add_action_assignments(policy_id, action_id, action_cat_id, action_data_id):
+ req = requests.post(URL.format("/policies/{}/action_assignments".format(policy_id)),
+ json={
+ "id": action_id,
+ "category_id": action_cat_id,
+ "data_id": action_data_id
+ }, headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert "action_assignments" in result
+ assert result["action_assignments"]
+
+
+def delete_subject_assignment(policy_id, subject_id, subject_cat_id, subject_data_id):
+ req = requests.delete(URL.format("/policies/{}/subject_assignments/{}/{}/{}".format(
+ policy_id, subject_id, subject_cat_id, subject_data_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "result" in result
+ assert result["result"]
+
+ req = requests.get(URL.format("/policies/{}/subject_assignments/{}/{}/{}".format(
+ policy_id, subject_id, subject_cat_id, subject_data_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "subject_assignments" in result
+ assert result["subject_assignments"]
+ for key in result["subject_assignments"]:
+ assert "subject_id" in result["subject_assignments"][key]
+ assert "category_id" in result["subject_assignments"][key]
+ assert "assignments" in result["subject_assignments"][key]
+ if result["subject_assignments"][key]['subject_id'] == subject_id and \
+ result["subject_assignments"][key]["category_id"] == subject_cat_id:
+ assert subject_data_id not in result["subject_assignments"][key]["assignments"]
+
+
+def delete_object_assignment(policy_id, object_id, object_cat_id, object_data_id):
+ req = requests.delete(URL.format("/policies/{}/object_assignments/{}/{}/{}".format(
+ policy_id, object_id, object_cat_id, object_data_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "result" in result
+ assert result["result"]
+
+ req = requests.get(URL.format("/policies/{}/object_assignments/{}/{}/{}".format(
+ policy_id, object_id, object_cat_id, object_data_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "object_assignments" in result
+ assert result["object_assignments"]
+ for key in result["object_assignments"]:
+ assert "object_id" in result["object_assignments"][key]
+ assert "category_id" in result["object_assignments"][key]
+ assert "assignments" in result["object_assignments"][key]
+ if result["object_assignments"][key]['object_id'] == object_id and \
+ result["object_assignments"][key]["category_id"] == object_cat_id:
+ assert object_data_id not in result["object_assignments"][key]["assignments"]
+
+
+def delete_action_assignment(policy_id, action_id, action_cat_id, action_data_id):
+ req = requests.delete(URL.format("/policies/{}/action_assignments/{}/{}/{}".format(
+ policy_id, action_id, action_cat_id, action_data_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "result" in result
+ assert result["result"]
+
+ req = requests.get(URL.format("/policies/{}/action_assignments/{}/{}/{}".format(
+ policy_id, action_id, action_cat_id, action_data_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "action_assignments" in result
+ assert result["action_assignments"]
+ for key in result["action_assignments"]:
+ assert "action_id" in result["action_assignments"][key]
+ assert "category_id" in result["action_assignments"][key]
+ assert "assignments" in result["action_assignments"][key]
+ if result["action_assignments"][key]['action_id'] == action_id and \
+ result["action_assignments"][key]["category_id"] == action_cat_id:
+ assert action_data_id not in result["action_assignments"][key]["assignments"]
+
+
+def add_rule(policy_id, meta_rule_id, rule):
+ req = requests.post(URL.format("/policies/{}/rules".format(policy_id)),
+ json={
+ "meta_rule_id": meta_rule_id,
+ "rule": rule,
+ "enabled": True
+ },
+ headers=HEADERS)
+ assert req.status_code == 200
+ result = req.json()
+ assert "rules" in result
+ rule_id = list(result["rules"].keys())[0]
+ assert "policy_id" in result["rules"][rule_id]
+ assert policy_id == result["rules"][rule_id]["policy_id"]
+ assert "meta_rule_id" in result["rules"][rule_id]
+ assert meta_rule_id == result["rules"][rule_id]["meta_rule_id"]
+ assert rule == result["rules"][rule_id]["rule"]
+ return rule_id
+
+
+def check_rule(policy_id, meta_rule_id, rule_id, rule):
+ req = requests.get(URL.format("/policies/{}/rules".format(policy_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "rules" in result
+ assert "policy_id" in result["rules"]
+ assert policy_id == result["rules"]["policy_id"]
+ for item in result["rules"]["rules"]:
+ assert "meta_rule_id" in item
+ if meta_rule_id == item["meta_rule_id"]:
+ if rule_id == item["id"]:
+ assert rule == item["rule"]
+
+
+def delete_rule(policy_id, rule_id):
+ req = requests.delete(URL.format("/policies/{}/rules/{}".format(policy_id, rule_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "result" in result
+ assert result["result"]
+
+ req = requests.get(URL.format("/policies/{}/rules".format(policy_id)))
+ assert req.status_code == 200
+ result = req.json()
+ assert "rules" in result
+ assert "policy_id" in result["rules"]
+ assert policy_id == result["rules"]["policy_id"]
+ found_rule = False
+ for item in result["rules"]["rules"]:
+ if rule_id == item["id"]:
+ found_rule = True
+ assert not found_rule
diff --git a/moonv4/moon_interface/tools/api2rst.py b/moonv4/moon_interface/tools/api2rst.py
new file mode 100644
index 00000000..6d407bdf
--- /dev/null
+++ b/moonv4/moon_interface/tools/api2rst.py
@@ -0,0 +1,145 @@
+# 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 os
+import sys
+import requests
+import logging
+import time
+import json
+
+os.unsetenv("http_proxy")
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+HOST = "172.18.0.11"
+PORT = 38001
+COMPONENT = sys.argv[2] if len(sys.argv) > 1 else "Interface"
+FILENAME = sys.argv[2] if len(sys.argv) > 2 else "api.rst"
+CURRENT_TIME = time.strftime("%Y/%m/%d %H:%M:%S %Z")
+REVISION = time.strftime("%Y%m%d_%H%M%S_%Z")
+AUTHOR = "Thomas Duval <thomas.duval@orange.com>"
+
+logger.info("Writing to {}".format(FILENAME))
+
+toc = (
+ "generic",
+ "models",
+ "policies",
+ "pdp",
+ "meta_rules",
+ "meta_data",
+ "perimeter",
+ "data",
+ "assignments",
+ "rules",
+ "authz",
+)
+
+
+def get_api_list():
+ url = "http://{}:{}/api".format(HOST, PORT)
+ cnx = requests.get(url)
+ try:
+ return cnx.json()
+ except json.decoder.JSONDecodeError:
+ logger.error("Error decoding JSON on {}\n{}".format(url, cnx.content))
+ sys.exit(1)
+
+
+def analyse_description(desc):
+ result = ""
+ if not desc:
+ return "No description"
+ for line in desc.splitlines():
+ if line.strip().startswith(":"):
+ if ":request body:" in line:
+ result += ":request body:\n\n.. code-block:: json\n\n"
+ result += line.replace(":request body: ", "") + "\n\n"
+ elif ":return:" in line:
+ result += ":return:\n\n.. code-block:: json\n\n"
+ result += line.replace(":return: ", "") + "\n"
+ else:
+ result += line.strip() + "\n\n"
+ else:
+ result += line + "\n"
+ return result
+
+
+def filter_and_sort(list_group_api):
+ results = list()
+ keys = list_group_api.keys()
+ for element in toc:
+ if element in keys:
+ results.append(element)
+ for element in keys:
+ if element not in results:
+ results.append(element)
+ return results
+
+
+def main():
+ list_group_api = get_api_list()
+
+ _toc = filter_and_sort(list_group_api)
+
+ file_desc = open(FILENAME, "w")
+ length_of_title = len("Moon {component} API".format(component=COMPONENT))
+ file_desc.write(HEADERS.format(
+ component=COMPONENT,
+ date=CURRENT_TIME,
+ revision=REVISION,
+ title_headers="="*length_of_title,
+ author=AUTHOR
+ ))
+
+ for key in _toc:
+ logger.info(key)
+ file_desc.write("{}\n".format(key))
+ file_desc.write("{}\n\n".format("="*len(key)))
+ if "description" in list_group_api[key]:
+ file_desc.write("{}\n\n".format(list_group_api[key]["description"]))
+ version = "unknown"
+ logger.debug(list_group_api.keys())
+ if "version" in list_group_api[key]:
+ version = list_group_api[key]["version"]
+ file_desc.write("Version: {}\n\n".format(version))
+ for api in list_group_api[key]:
+ logger.info("\t{}".format(api))
+ if api in ("description", "version"):
+ continue
+ file_desc.write("{}\n".format(api))
+ file_desc.write("{}\n\n".format("-" * len(api)))
+
+ file_desc.write("{}\n\n".format(list_group_api[key][api]["description"]))
+
+ file_desc.write("URLs are:\n\n")
+ for _url in list_group_api[key][api]["urls"]:
+ file_desc.write("* {}\n".format(_url))
+
+ file_desc.write("\nMethods are:\n\n")
+ for _method in list_group_api[key][api]["methods"]:
+ file_desc.write("→ {}\n".format(_method))
+ file_desc.write("{}\n\n".format("~"*(len(_method) + 2)))
+ file_desc.write("{}\n\n".format(analyse_description(list_group_api[key][api]["methods"][_method])))
+
+HEADERS = """{title_headers}
+Moon {component} API
+{title_headers}
+
+:Info: See <https://git.opnfv.org/cgit/moon/> for code.
+:Author: {author}
+:Date: {date}
+:Revision: $Revision: {revision} $
+:Description: List of the API served by the Moon {component} component
+
+This document list all of the API connectors served by the Moon {component} component
+Here are Moon API with some examples of posted data and returned data.
+All requests must be prefixed with the host and port, for example: http://localhost:38001/authz/123456789/123456789/servers/list
+
+"""
+
+if __name__ == "__main__":
+ main()
diff --git a/moonv4/moon_interface/tools/get_keystone_token.py b/moonv4/moon_interface/tools/get_keystone_token.py
new file mode 100644
index 00000000..63b0d0b6
--- /dev/null
+++ b/moonv4/moon_interface/tools/get_keystone_token.py
@@ -0,0 +1,72 @@
+import requests
+from oslo_config import cfg
+from oslo_log import log as logging
+from moon_utilities import options # noqa
+from moon_utilities import exceptions
+
+CONF = cfg.CONF
+LOG = logging.getLogger(__name__)
+
+
+def login(user=None, password=None, domain=None, project=None, url=None):
+ print("""Configuration:
+ user: {user}
+ domain: {domain}
+ project: {project}
+ url: {url}""".format(
+ user=CONF.keystone.user,
+ domain=CONF.keystone.domain,
+ project=CONF.keystone.project,
+ url=CONF.keystone.url,
+ ))
+ if not user:
+ user = CONF.keystone.user
+ if not password:
+ password = CONF.keystone.password
+ if not domain:
+ domain = CONF.keystone.domain
+ if not project:
+ project = CONF.keystone.project
+ if not url:
+ url = CONF.keystone.url
+ headers = {
+ "Content-Type": "application/json"
+ }
+ data_auth = {
+ "auth": {
+ "identity": {
+ "methods": [
+ "password"
+ ],
+ "password": {
+ "user": {
+ "domain": {
+ "id": domain
+ },
+ "name": user,
+ "password": password
+ }
+ }
+ },
+ "scope": {
+ "project": {
+ "domain": {
+ "id": domain
+ },
+ "name": project
+ }
+ }
+ }
+ }
+
+ req = requests.post("{}/auth/tokens".format(url),
+ json=data_auth, headers=headers,
+ verify=False)
+
+ if req.status_code not in (200, 201):
+ LOG.error(req.text)
+ raise exceptions.KeystoneError
+ headers['X-Auth-Token'] = req.headers['X-Subject-Token']
+ return headers
+
+print(login()['X-Auth-Token'])
diff --git a/moonv4/moon_interface/tools/run.sh b/moonv4/moon_interface/tools/run.sh
new file mode 100644
index 00000000..d1db1f00
--- /dev/null
+++ b/moonv4/moon_interface/tools/run.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+http_proxy= /usr/bin/python3 /home/vdsq3226/projets/opnfv/opnfv-moon/moon_interface/tools/api2rst.py
+pandoc api.rst --toc -o api.pdf
+evince api.pdf