aboutsummaryrefslogtreecommitdiffstats
path: root/moon_utilities
diff options
context:
space:
mode:
Diffstat (limited to 'moon_utilities')
-rw-r--r--moon_utilities/.gitignore105
-rw-r--r--moon_utilities/Changelog54
-rw-r--r--moon_utilities/LICENSE202
-rw-r--r--moon_utilities/MANIFEST.in10
-rw-r--r--moon_utilities/README.md3
-rw-r--r--moon_utilities/conf/policy.json.d/cinder.policy.json104
-rw-r--r--moon_utilities/conf/policy.json.d/glance.policy.json63
-rw-r--r--moon_utilities/conf/policy.json.d/keystone.policy.json260
-rw-r--r--moon_utilities/conf/policy.json.d/neutron.policy.json235
-rw-r--r--moon_utilities/conf/policy.json.d/nova.policy.json485
-rw-r--r--moon_utilities/moon_utilities/__init__.py13
-rw-r--r--moon_utilities/moon_utilities/auth_functions.py307
-rw-r--r--moon_utilities/moon_utilities/exceptions.py903
-rw-r--r--moon_utilities/moon_utilities/generate_opst_policy.py503
-rw-r--r--moon_utilities/moon_utilities/install.py155
-rw-r--r--moon_utilities/moon_utilities/invalided_functions.py440
-rw-r--r--moon_utilities/moon_utilities/json_utils.py2076
-rw-r--r--moon_utilities/moon_utilities/security_functions.py83
-rw-r--r--moon_utilities/moon_utilities/update_opst_policies.py85
-rw-r--r--moon_utilities/requirements.txt3
-rw-r--r--moon_utilities/setup.py58
-rw-r--r--moon_utilities/tests/unit_python/api/__init__.py12
-rw-r--r--moon_utilities/tests/unit_python/api/test_auth_functions.py83
-rw-r--r--moon_utilities/tests/unit_python/api/test_import_to_cache.py775
-rw-r--r--moon_utilities/tests/unit_python/api/test_import_to_db.py772
-rw-r--r--moon_utilities/tests/unit_python/api/test_invalidate_function.py64
-rw-r--r--moon_utilities/tests/unit_python/api/test_security_functions.py18
-rw-r--r--moon_utilities/tests/unit_python/conftest.py172
-rw-r--r--moon_utilities/tests/unit_python/helpers/__init__.py13
-rw-r--r--moon_utilities/tests/unit_python/helpers/import_export_cache_helper.py234
-rw-r--r--moon_utilities/tests/unit_python/helpers/import_export_db_helper.py178
-rw-r--r--moon_utilities/tests/unit_python/helpers/slaves_helpers.py32
-rw-r--r--moon_utilities/tests/unit_python/mock_slaves.py50
-rw-r--r--moon_utilities/tests/unit_python/requirements.txt10
34 files changed, 8560 insertions, 0 deletions
diff --git a/moon_utilities/.gitignore b/moon_utilities/.gitignore
new file mode 100644
index 00000000..7bff7318
--- /dev/null
+++ b/moon_utilities/.gitignore
@@ -0,0 +1,105 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+
diff --git a/moon_utilities/Changelog b/moon_utilities/Changelog
new file mode 100644
index 00000000..61ae2fec
--- /dev/null
+++ b/moon_utilities/Changelog
@@ -0,0 +1,54 @@
+# Copyright 2018 Orange 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'.
+
+
+CHANGES
+=======
+
+0.1
+---
+- First version of the moon_utilities library.
+
+0.2
+---
+- Delete Keystone references in exceptions
+- Update the user used to authenticate actions in moon (moon_user_id)
+
+0.3
+---
+- Adding validation function
+- Update enforce decorator
+- Refactoring by adding base exception and json utilities from manager to utilities
+
+0.4
+---
+- Move authentication function from moon_manager to moon_utilities
+- Adding invalided_functions
+- Fix a bug in security_functions.py
+- Add logout functionality
+- Add re-login functionality
+
+0.5
+---
+- Add script to automatically generate OpenStack RBAC policy from policy.json original files
+
+0.6
+---
+- Add a prompt to enter the password at user creation, -p option to set the password in clear in the CLI
+- Move the import functionality in moon_utilities
+- Fix some bugs in generate_opst_policy
+- Fix some bugs when importing directly in cache
+- Add the global attribute functionality
+- Fix of not relevant yields in invalided_functions
+
+0.7
+---
+- Add an installation script
+- Update import json to db and cache functions
+
+0.8
+---
+- Add a change password function
+- Add of a method connecting the user with environment variables \ No newline at end of file
diff --git a/moon_utilities/LICENSE b/moon_utilities/LICENSE
new file mode 100644
index 00000000..d6456956
--- /dev/null
+++ b/moon_utilities/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/moon_utilities/MANIFEST.in b/moon_utilities/MANIFEST.in
new file mode 100644
index 00000000..21c2cf92
--- /dev/null
+++ b/moon_utilities/MANIFEST.in
@@ -0,0 +1,10 @@
+# Copyright 2018 Orange and its contributors
+# This software is distributed under the terms and conditions of the 'Apache-2.0'
+# license which can be found in the file 'LICENSE' in this package distribution
+# or at 'http://www.apache.org/licenses/LICENSE-2.0'.
+
+include README.md
+include LICENSE
+include Changelog
+include setup.py
+include requirements.txt
diff --git a/moon_utilities/README.md b/moon_utilities/README.md
new file mode 100644
index 00000000..78fdada6
--- /dev/null
+++ b/moon_utilities/README.md
@@ -0,0 +1,3 @@
+# moon_utilities
+
+Python library that implements miscellaneous functions for the Moon project \ No newline at end of file
diff --git a/moon_utilities/conf/policy.json.d/cinder.policy.json b/moon_utilities/conf/policy.json.d/cinder.policy.json
new file mode 100644
index 00000000..02af88bd
--- /dev/null
+++ b/moon_utilities/conf/policy.json.d/cinder.policy.json
@@ -0,0 +1,104 @@
+{
+ "context_is_admin": "role:admin",
+ "admin_or_owner": "is_admin:True or project_id:%(project_id)s",
+ "default": "rule:admin_or_owner",
+
+ "admin_api": "is_admin:True",
+
+ "volume:create": "",
+ "volume:delete": "rule:admin_or_owner",
+ "volume:get": "rule:admin_or_owner",
+ "volume:get_all": "rule:admin_or_owner",
+ "volume:get_volume_metadata": "rule:admin_or_owner",
+ "volume:delete_volume_metadata": "rule:admin_or_owner",
+ "volume:update_volume_metadata": "rule:admin_or_owner",
+ "volume:get_volume_admin_metadata": "rule:admin_api",
+ "volume:update_volume_admin_metadata": "rule:admin_api",
+ "volume:get_snapshot": "rule:admin_or_owner",
+ "volume:get_all_snapshots": "rule:admin_or_owner",
+ "volume:create_snapshot": "rule:admin_or_owner",
+ "volume:delete_snapshot": "rule:admin_or_owner",
+ "volume:update_snapshot": "rule:admin_or_owner",
+ "volume:extend": "rule:admin_or_owner",
+ "volume:update_readonly_flag": "rule:admin_or_owner",
+ "volume:retype": "rule:admin_or_owner",
+ "volume:update": "rule:admin_or_owner",
+
+ "volume_extension:types_manage": "rule:admin_api",
+ "volume_extension:types_extra_specs": "rule:admin_api",
+ "volume_extension:access_types_qos_specs_id": "rule:admin_api",
+ "volume_extension:access_types_extra_specs": "rule:admin_api",
+ "volume_extension:volume_type_access": "rule:admin_or_owner",
+ "volume_extension:volume_type_access:addProjectAccess": "rule:admin_api",
+ "volume_extension:volume_type_access:removeProjectAccess": "rule:admin_api",
+ "volume_extension:volume_type_encryption": "rule:admin_api",
+ "volume_extension:volume_encryption_metadata": "rule:admin_or_owner",
+ "volume_extension:extended_snapshot_attributes": "rule:admin_or_owner",
+ "volume_extension:volume_image_metadata": "rule:admin_or_owner",
+
+ "volume_extension:quotas:show": "",
+ "volume_extension:quotas:update": "rule:admin_api",
+ "volume_extension:quotas:delete": "rule:admin_api",
+ "volume_extension:quota_classes": "rule:admin_api",
+ "volume_extension:quota_classes:validate_setup_for_nested_quota_use": "rule:admin_api",
+
+ "volume_extension:volume_admin_actions:reset_status": "rule:admin_api",
+ "volume_extension:snapshot_admin_actions:reset_status": "rule:admin_api",
+ "volume_extension:backup_admin_actions:reset_status": "rule:admin_api",
+ "volume_extension:volume_admin_actions:force_delete": "rule:admin_api",
+ "volume_extension:volume_admin_actions:force_detach": "rule:admin_api",
+ "volume_extension:snapshot_admin_actions:force_delete": "rule:admin_api",
+ "volume_extension:backup_admin_actions:force_delete": "rule:admin_api",
+ "volume_extension:volume_admin_actions:migrate_volume": "rule:admin_api",
+ "volume_extension:volume_admin_actions:migrate_volume_completion": "rule:admin_api",
+
+ "volume_extension:volume_host_attribute": "rule:admin_api",
+ "volume_extension:volume_tenant_attribute": "rule:admin_or_owner",
+ "volume_extension:volume_mig_status_attribute": "rule:admin_api",
+ "volume_extension:hosts": "rule:admin_api",
+ "volume_extension:services:index": "rule:admin_api",
+ "volume_extension:services:update" : "rule:admin_api",
+
+ "volume_extension:volume_manage": "rule:admin_api",
+ "volume_extension:volume_unmanage": "rule:admin_api",
+
+ "volume_extension:capabilities": "rule:admin_api",
+
+ "volume:create_transfer": "rule:admin_or_owner",
+ "volume:accept_transfer": "",
+ "volume:delete_transfer": "rule:admin_or_owner",
+ "volume:get_all_transfers": "rule:admin_or_owner",
+
+ "volume_extension:replication:promote": "rule:admin_api",
+ "volume_extension:replication:reenable": "rule:admin_api",
+
+ "volume:enable_replication": "rule:admin_api",
+ "volume:disable_replication": "rule:admin_api",
+ "volume:failover_replication": "rule:admin_api",
+ "volume:list_replication_targets": "rule:admin_api",
+
+ "backup:create" : "",
+ "backup:delete": "rule:admin_or_owner",
+ "backup:get": "rule:admin_or_owner",
+ "backup:get_all": "rule:admin_or_owner",
+ "backup:restore": "rule:admin_or_owner",
+ "backup:backup-import": "rule:admin_api",
+ "backup:backup-export": "rule:admin_api",
+
+ "snapshot_extension:snapshot_actions:update_snapshot_status": "",
+ "snapshot_extension:snapshot_manage": "rule:admin_api",
+ "snapshot_extension:snapshot_unmanage": "rule:admin_api",
+
+ "consistencygroup:create" : "group:nobody",
+ "consistencygroup:delete": "group:nobody",
+ "consistencygroup:update": "group:nobody",
+ "consistencygroup:get": "group:nobody",
+ "consistencygroup:get_all": "group:nobody",
+
+ "consistencygroup:create_cgsnapshot" : "group:nobody",
+ "consistencygroup:delete_cgsnapshot": "group:nobody",
+ "consistencygroup:get_cgsnapshot": "group:nobody",
+ "consistencygroup:get_all_cgsnapshots": "group:nobody",
+
+ "scheduler_extension:scheduler_stats:get_pools" : "rule:admin_api"
+}
diff --git a/moon_utilities/conf/policy.json.d/glance.policy.json b/moon_utilities/conf/policy.json.d/glance.policy.json
new file mode 100644
index 00000000..5b1f6be7
--- /dev/null
+++ b/moon_utilities/conf/policy.json.d/glance.policy.json
@@ -0,0 +1,63 @@
+{
+ "context_is_admin": "role:admin",
+ "default": "role:admin",
+
+ "add_image": "",
+ "delete_image": "",
+ "get_image": "",
+ "get_images": "",
+ "modify_image": "",
+ "publicize_image": "role:admin",
+ "communitize_image": "",
+ "copy_from": "",
+
+ "download_image": "",
+ "upload_image": "",
+
+ "delete_image_location": "",
+ "get_image_location": "",
+ "set_image_location": "",
+
+ "add_member": "",
+ "delete_member": "",
+ "get_member": "",
+ "get_members": "",
+ "modify_member": "",
+
+ "manage_image_cache": "role:admin",
+
+ "get_task": "",
+ "get_tasks": "",
+ "add_task": "",
+ "modify_task": "",
+ "tasks_api_access": "role:admin",
+
+ "deactivate": "",
+ "reactivate": "",
+
+ "get_metadef_namespace": "",
+ "get_metadef_namespaces":"",
+ "modify_metadef_namespace":"",
+ "add_metadef_namespace":"",
+
+ "get_metadef_object":"",
+ "get_metadef_objects":"",
+ "modify_metadef_object":"",
+ "add_metadef_object":"",
+
+ "list_metadef_resource_types":"",
+ "get_metadef_resource_type":"",
+ "add_metadef_resource_type_association":"",
+
+ "get_metadef_property":"",
+ "get_metadef_properties":"",
+ "modify_metadef_property":"",
+ "add_metadef_property":"",
+
+ "get_metadef_tag":"",
+ "get_metadef_tags":"",
+ "modify_metadef_tag":"",
+ "add_metadef_tag":"",
+ "add_metadef_tags":""
+
+}
diff --git a/moon_utilities/conf/policy.json.d/keystone.policy.json b/moon_utilities/conf/policy.json.d/keystone.policy.json
new file mode 100644
index 00000000..263912bf
--- /dev/null
+++ b/moon_utilities/conf/policy.json.d/keystone.policy.json
@@ -0,0 +1,260 @@
+{
+ "admin_required": "role:admin",
+ "cloud_admin": "role:admin and (is_admin_project:True or domain_id:admin_domain_id)",
+ "service_role": "role:service",
+ "service_or_admin": "rule:admin_required or rule:service_role",
+ "owner": "user_id:%(user_id)s or user_id:%(target.token.user_id)s",
+ "admin_or_owner": "(rule:admin_required and domain_id:%(target.token.user.domain.id)s) or rule:owner",
+ "admin_and_matching_domain_id": "rule:admin_required and domain_id:%(domain_id)s",
+ "service_admin_or_owner": "rule:service_or_admin or rule:owner",
+
+ "default": "rule:admin_required",
+
+ "identity:get_region": "",
+ "identity:list_regions": "",
+ "identity:create_region": "rule:cloud_admin",
+ "identity:update_region": "rule:cloud_admin",
+ "identity:delete_region": "rule:cloud_admin",
+
+ "identity:get_service": "rule:admin_required",
+ "identity:list_services": "rule:admin_required",
+ "identity:create_service": "rule:cloud_admin",
+ "identity:update_service": "rule:cloud_admin",
+ "identity:delete_service": "rule:cloud_admin",
+
+ "identity:get_endpoint": "rule:admin_required",
+ "identity:list_endpoints": "rule:admin_required",
+ "identity:create_endpoint": "rule:cloud_admin",
+ "identity:update_endpoint": "rule:cloud_admin",
+ "identity:delete_endpoint": "rule:cloud_admin",
+
+ "identity:get_registered_limit": "",
+ "identity:list_registered_limits": "",
+ "identity:create_registered_limits": "rule:admin_required",
+ "identity:update_registered_limits": "rule:admin_required",
+ "identity:delete_registered_limit": "rule:admin_required",
+
+ "identity:get_limit": "",
+ "identity:list_limits": "",
+ "identity:create_limits": "rule:admin_required",
+ "identity:update_limits": "rule:admin_required",
+ "identity:delete_limit": "rule:admin_required",
+
+ "identity:get_domain": "rule:cloud_admin or rule:admin_and_matching_domain_id or token.project.domain.id:%(target.domain.id)s",
+ "identity:list_domains": "rule:cloud_admin",
+ "identity:create_domain": "rule:cloud_admin",
+ "identity:update_domain": "rule:cloud_admin",
+ "identity:delete_domain": "rule:cloud_admin",
+
+ "admin_and_matching_target_project_domain_id": "rule:admin_required and domain_id:%(target.project.domain_id)s",
+ "admin_and_matching_project_domain_id": "rule:admin_required and domain_id:%(project.domain_id)s",
+ "identity:get_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id or project_id:%(target.project.id)s",
+ "identity:list_projects": "rule:cloud_admin or rule:admin_and_matching_domain_id",
+ "identity:list_user_projects": "rule:owner or rule:admin_and_matching_domain_id",
+ "identity:create_project": "rule:cloud_admin or rule:admin_and_matching_project_domain_id",
+ "identity:update_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id",
+ "identity:delete_project": "rule:cloud_admin or rule:admin_and_matching_target_project_domain_id",
+ "identity:create_project_tag": "rule:admin_required",
+ "identity:delete_project_tag": "rule:admin_required",
+ "identity:get_project_tag": "rule:admin_required",
+ "identity:list_project_tags": "rule:admin_required",
+ "identity:delete_project_tags": "rule:admin_required",
+ "identity:update_project_tags": "rule:admin_required",
+
+ "admin_and_matching_target_user_domain_id": "rule:admin_required and domain_id:%(target.user.domain_id)s",
+ "admin_and_matching_user_domain_id": "rule:admin_required and domain_id:%(user.domain_id)s",
+ "identity:get_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id or rule:owner",
+ "identity:list_users": "rule:cloud_admin or rule:admin_and_matching_domain_id",
+ "identity:create_user": "rule:cloud_admin or rule:admin_and_matching_user_domain_id",
+ "identity:update_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id",
+ "identity:delete_user": "rule:cloud_admin or rule:admin_and_matching_target_user_domain_id",
+
+ "admin_and_matching_target_group_domain_id": "rule:admin_required and domain_id:%(target.group.domain_id)s",
+ "admin_and_matching_group_domain_id": "rule:admin_required and domain_id:%(group.domain_id)s",
+ "identity:get_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
+ "identity:list_groups": "rule:cloud_admin or rule:admin_and_matching_domain_id",
+ "identity:list_groups_for_user": "rule:owner or rule:admin_and_matching_target_user_domain_id",
+ "identity:create_group": "rule:cloud_admin or rule:admin_and_matching_group_domain_id",
+ "identity:update_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
+ "identity:delete_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
+ "identity:list_users_in_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
+ "identity:remove_user_from_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
+ "identity:check_user_in_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
+ "identity:add_user_to_group": "rule:cloud_admin or rule:admin_and_matching_target_group_domain_id",
+
+ "identity:get_credential": "rule:admin_required",
+ "identity:list_credentials": "rule:admin_required or user_id:%(user_id)s",
+ "identity:create_credential": "rule:admin_required",
+ "identity:update_credential": "rule:admin_required",
+ "identity:delete_credential": "rule:admin_required",
+
+ "identity:ec2_get_credential": "rule:admin_required or (rule:owner and user_id:%(target.credential.user_id)s)",
+ "identity:ec2_list_credentials": "rule:admin_required or rule:owner",
+ "identity:ec2_create_credential": "rule:admin_required or rule:owner",
+ "identity:ec2_delete_credential": "rule:admin_required or (rule:owner and user_id:%(target.credential.user_id)s)",
+
+ "identity:get_role": "rule:admin_required",
+ "identity:list_roles": "rule:admin_required",
+ "identity:create_role": "rule:cloud_admin",
+ "identity:update_role": "rule:cloud_admin",
+ "identity:delete_role": "rule:cloud_admin",
+
+ "identity:get_domain_role": "rule:cloud_admin or rule:get_domain_roles",
+ "identity:list_domain_roles": "rule:cloud_admin or rule:list_domain_roles",
+ "identity:create_domain_role": "rule:cloud_admin or rule:domain_admin_matches_domain_role",
+ "identity:update_domain_role": "rule:cloud_admin or rule:domain_admin_matches_target_domain_role",
+ "identity:delete_domain_role": "rule:cloud_admin or rule:domain_admin_matches_target_domain_role",
+ "domain_admin_matches_domain_role": "rule:admin_required and domain_id:%(role.domain_id)s",
+ "get_domain_roles": "rule:domain_admin_matches_target_domain_role or rule:project_admin_matches_target_domain_role",
+ "domain_admin_matches_target_domain_role": "rule:admin_required and domain_id:%(target.role.domain_id)s",
+ "project_admin_matches_target_domain_role": "rule:admin_required and project_domain_id:%(target.role.domain_id)s",
+ "list_domain_roles": "rule:domain_admin_matches_filter_on_list_domain_roles or rule:project_admin_matches_filter_on_list_domain_roles",
+ "domain_admin_matches_filter_on_list_domain_roles": "rule:admin_required and domain_id:%(domain_id)s",
+ "project_admin_matches_filter_on_list_domain_roles": "rule:admin_required and project_domain_id:%(domain_id)s",
+ "admin_and_matching_prior_role_domain_id": "rule:admin_required and domain_id:%(target.prior_role.domain_id)s",
+ "implied_role_matches_prior_role_domain_or_global": "(domain_id:%(target.implied_role.domain_id)s or None:%(target.implied_role.domain_id)s)",
+
+ "identity:get_implied_role": "rule:cloud_admin or rule:admin_and_matching_prior_role_domain_id",
+ "identity:list_implied_roles": "rule:cloud_admin or rule:admin_and_matching_prior_role_domain_id",
+ "identity:create_implied_role": "rule:cloud_admin or (rule:admin_and_matching_prior_role_domain_id and rule:implied_role_matches_prior_role_domain_or_global)",
+ "identity:delete_implied_role": "rule:cloud_admin or rule:admin_and_matching_prior_role_domain_id",
+ "identity:list_role_inference_rules": "rule:cloud_admin",
+ "identity:check_implied_role": "rule:cloud_admin or rule:admin_and_matching_prior_role_domain_id",
+
+ "identity:list_system_grants_for_user": "rule:admin_required",
+ "identity:check_system_grant_for_user": "rule:admin_required",
+ "identity:create_system_grant_for_user": "rule:admin_required",
+ "identity:revoke_system_grant_for_user": "rule:admin_required",
+
+ "identity:list_system_grants_for_group": "rule:admin_required",
+ "identity:check_system_grant_for_group": "rule:admin_required",
+ "identity:create_system_grant_for_group": "rule:admin_required",
+ "identity:revoke_system_grant_for_group": "rule:admin_required",
+
+ "identity:check_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
+ "identity:list_grants": "rule:cloud_admin or rule:domain_admin_for_list_grants or rule:project_admin_for_list_grants",
+ "identity:create_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
+ "identity:revoke_grant": "rule:cloud_admin or rule:domain_admin_for_grants or rule:project_admin_for_grants",
+ "domain_admin_for_grants": "rule:domain_admin_for_global_role_grants or rule:domain_admin_for_domain_role_grants",
+ "domain_admin_for_global_role_grants": "rule:admin_required and None:%(target.role.domain_id)s and rule:domain_admin_grant_match",
+ "domain_admin_for_domain_role_grants": "rule:admin_required and domain_id:%(target.role.domain_id)s and rule:domain_admin_grant_match",
+ "domain_admin_grant_match": "domain_id:%(domain_id)s or domain_id:%(target.project.domain_id)s",
+ "project_admin_for_grants": "rule:project_admin_for_global_role_grants or rule:project_admin_for_domain_role_grants",
+ "project_admin_for_global_role_grants": "rule:admin_required and None:%(target.role.domain_id)s and project_id:%(project_id)s",
+ "project_admin_for_domain_role_grants": "rule:admin_required and project_domain_id:%(target.role.domain_id)s and project_id:%(project_id)s",
+ "domain_admin_for_list_grants": "rule:admin_required and rule:domain_admin_grant_match",
+ "project_admin_for_list_grants": "rule:admin_required and project_id:%(project_id)s",
+
+ "admin_on_domain_filter": "rule:admin_required and domain_id:%(scope.domain.id)s",
+ "admin_on_project_filter": "rule:admin_required and project_id:%(scope.project.id)s",
+ "admin_on_domain_of_project_filter": "rule:admin_required and domain_id:%(target.project.domain_id)s",
+ "identity:list_role_assignments": "rule:cloud_admin or rule:admin_on_domain_filter or rule:admin_on_project_filter",
+ "identity:list_role_assignments_for_tree": "rule:cloud_admin or rule:admin_on_domain_of_project_filter",
+ "identity:get_policy": "rule:cloud_admin",
+ "identity:list_policies": "rule:cloud_admin",
+ "identity:create_policy": "rule:cloud_admin",
+ "identity:update_policy": "rule:cloud_admin",
+ "identity:delete_policy": "rule:cloud_admin",
+
+ "identity:check_token": "rule:admin_or_owner",
+ "identity:validate_token": "rule:service_admin_or_owner",
+ "identity:validate_token_head": "rule:service_or_admin",
+ "identity:revocation_list": "rule:service_or_admin",
+ "identity:revoke_token": "rule:admin_or_owner",
+
+ "identity:create_trust": "user_id:%(trust.trustor_user_id)s",
+ "identity:list_trusts": "",
+ "identity:list_roles_for_trust": "",
+ "identity:get_role_for_trust": "",
+ "identity:delete_trust": "",
+ "identity:get_trust": "",
+
+ "identity:create_consumer": "rule:admin_required",
+ "identity:get_consumer": "rule:admin_required",
+ "identity:list_consumers": "rule:admin_required",
+ "identity:delete_consumer": "rule:admin_required",
+ "identity:update_consumer": "rule:admin_required",
+
+ "identity:authorize_request_token": "rule:admin_required",
+ "identity:list_access_token_roles": "rule:admin_required",
+ "identity:get_access_token_role": "rule:admin_required",
+ "identity:list_access_tokens": "rule:admin_required",
+ "identity:get_access_token": "rule:admin_required",
+ "identity:delete_access_token": "rule:admin_required",
+
+ "identity:list_projects_for_endpoint": "rule:admin_required",
+ "identity:add_endpoint_to_project": "rule:admin_required",
+ "identity:check_endpoint_in_project": "rule:admin_required",
+ "identity:list_endpoints_for_project": "rule:admin_required",
+ "identity:remove_endpoint_from_project": "rule:admin_required",
+
+ "identity:create_endpoint_group": "rule:admin_required",
+ "identity:list_endpoint_groups": "rule:admin_required",
+ "identity:get_endpoint_group": "rule:admin_required",
+ "identity:update_endpoint_group": "rule:admin_required",
+ "identity:delete_endpoint_group": "rule:admin_required",
+ "identity:list_projects_associated_with_endpoint_group": "rule:admin_required",
+ "identity:list_endpoints_associated_with_endpoint_group": "rule:admin_required",
+ "identity:get_endpoint_group_in_project": "rule:admin_required",
+ "identity:list_endpoint_groups_for_project": "rule:admin_required",
+ "identity:add_endpoint_group_to_project": "rule:admin_required",
+ "identity:remove_endpoint_group_from_project": "rule:admin_required",
+
+ "identity:create_identity_provider": "rule:cloud_admin",
+ "identity:list_identity_providers": "rule:cloud_admin",
+ "identity:get_identity_provider": "rule:cloud_admin",
+ "identity:update_identity_provider": "rule:cloud_admin",
+ "identity:delete_identity_provider": "rule:cloud_admin",
+
+ "identity:create_protocol": "rule:cloud_admin",
+ "identity:update_protocol": "rule:cloud_admin",
+ "identity:get_protocol": "rule:cloud_admin",
+ "identity:list_protocols": "rule:cloud_admin",
+ "identity:delete_protocol": "rule:cloud_admin",
+
+ "identity:create_mapping": "rule:cloud_admin",
+ "identity:get_mapping": "rule:cloud_admin",
+ "identity:list_mappings": "rule:cloud_admin",
+ "identity:delete_mapping": "rule:cloud_admin",
+ "identity:update_mapping": "rule:cloud_admin",
+
+ "identity:create_service_provider": "rule:cloud_admin",
+ "identity:list_service_providers": "rule:cloud_admin",
+ "identity:get_service_provider": "rule:cloud_admin",
+ "identity:update_service_provider": "rule:cloud_admin",
+ "identity:delete_service_provider": "rule:cloud_admin",
+
+ "identity:get_auth_catalog": "",
+ "identity:get_auth_projects": "",
+ "identity:get_auth_domains": "",
+ "identity:get_auth_system": "",
+
+ "identity:list_projects_for_user": "",
+ "identity:list_domains_for_user": "",
+
+ "identity:list_revoke_events": "rule:service_or_admin",
+
+ "identity:create_policy_association_for_endpoint": "rule:cloud_admin",
+ "identity:check_policy_association_for_endpoint": "rule:cloud_admin",
+ "identity:delete_policy_association_for_endpoint": "rule:cloud_admin",
+ "identity:create_policy_association_for_service": "rule:cloud_admin",
+ "identity:check_policy_association_for_service": "rule:cloud_admin",
+ "identity:delete_policy_association_for_service": "rule:cloud_admin",
+ "identity:create_policy_association_for_region_and_service": "rule:cloud_admin",
+ "identity:check_policy_association_for_region_and_service": "rule:cloud_admin",
+ "identity:delete_policy_association_for_region_and_service": "rule:cloud_admin",
+ "identity:get_policy_for_endpoint": "rule:cloud_admin",
+ "identity:list_endpoints_for_policy": "rule:cloud_admin",
+
+ "identity:create_domain_config": "rule:cloud_admin",
+ "identity:get_domain_config": "rule:cloud_admin",
+ "identity:get_security_compliance_domain_config": "",
+ "identity:update_domain_config": "rule:cloud_admin",
+ "identity:delete_domain_config": "rule:cloud_admin",
+ "identity:get_domain_config_default": "rule:cloud_admin",
+
+ "identity:get_application_credential": "rule:admin_or_owner",
+ "identity:list_application_credentials": "rule:admin_or_owner",
+ "identity:create_application_credential": "rule:admin_or_owner",
+ "identity:delete_application_credential": "rule:admin_or_owner"
+}
diff --git a/moon_utilities/conf/policy.json.d/neutron.policy.json b/moon_utilities/conf/policy.json.d/neutron.policy.json
new file mode 100644
index 00000000..15f17203
--- /dev/null
+++ b/moon_utilities/conf/policy.json.d/neutron.policy.json
@@ -0,0 +1,235 @@
+{
+ "context_is_admin": "role:admin or user_name:neutron",
+ "owner": "tenant_id:%(tenant_id)s",
+ "admin_or_owner": "rule:context_is_admin or rule:owner",
+ "context_is_advsvc": "role:advsvc",
+ "admin_or_network_owner": "rule:context_is_admin or tenant_id:%(network:tenant_id)s",
+ "admin_owner_or_network_owner": "rule:owner or rule:admin_or_network_owner",
+ "admin_only": "rule:context_is_admin",
+ "regular_user": "",
+ "admin_or_data_plane_int": "rule:context_is_admin or role:data_plane_integrator",
+ "shared": "field:networks:shared=True",
+ "shared_subnetpools": "field:subnetpools:shared=True",
+ "shared_address_scopes": "field:address_scopes:shared=True",
+ "external": "field:networks:router:external=True",
+ "default": "rule:admin_or_owner",
+
+ "create_subnet": "rule:admin_or_network_owner",
+ "create_subnet:segment_id": "rule:admin_only",
+ "create_subnet:service_types": "rule:admin_only",
+ "get_subnet": "rule:admin_or_owner or rule:shared",
+ "get_subnet:segment_id": "rule:admin_only",
+ "update_subnet": "rule:admin_or_network_owner",
+ "update_subnet:service_types": "rule:admin_only",
+ "delete_subnet": "rule:admin_or_network_owner",
+
+ "create_subnetpool": "",
+ "create_subnetpool:shared": "rule:admin_only",
+ "create_subnetpool:is_default": "rule:admin_only",
+ "get_subnetpool": "rule:admin_or_owner or rule:shared_subnetpools",
+ "update_subnetpool": "rule:admin_or_owner",
+ "update_subnetpool:is_default": "rule:admin_only",
+ "delete_subnetpool": "rule:admin_or_owner",
+
+ "create_address_scope": "",
+ "create_address_scope:shared": "rule:admin_only",
+ "get_address_scope": "rule:admin_or_owner or rule:shared_address_scopes",
+ "update_address_scope": "rule:admin_or_owner",
+ "update_address_scope:shared": "rule:admin_only",
+ "delete_address_scope": "rule:admin_or_owner",
+
+ "create_network": "",
+ "get_network": "rule:admin_or_owner or rule:shared or rule:external or rule:context_is_advsvc",
+ "get_network:router:external": "rule:regular_user",
+ "get_network:segments": "rule:admin_only",
+ "get_network:provider:network_type": "rule:admin_only",
+ "get_network:provider:physical_network": "rule:admin_only",
+ "get_network:provider:segmentation_id": "rule:admin_only",
+ "get_network:queue_id": "rule:admin_only",
+ "get_network_ip_availabilities": "rule:admin_only",
+ "get_network_ip_availability": "rule:admin_only",
+ "create_network:shared": "rule:admin_only",
+ "create_network:router:external": "rule:admin_only",
+ "create_network:is_default": "rule:admin_only",
+ "create_network:segments": "rule:admin_only",
+ "create_network:provider:network_type": "rule:admin_only",
+ "create_network:provider:physical_network": "rule:admin_only",
+ "create_network:provider:segmentation_id": "rule:admin_only",
+ "update_network": "rule:admin_or_owner",
+ "update_network:segments": "rule:admin_only",
+ "update_network:shared": "rule:admin_only",
+ "update_network:provider:network_type": "rule:admin_only",
+ "update_network:provider:physical_network": "rule:admin_only",
+ "update_network:provider:segmentation_id": "rule:admin_only",
+ "update_network:router:external": "rule:admin_only",
+ "delete_network": "rule:admin_or_owner",
+
+ "create_segment": "rule:admin_only",
+ "get_segment": "rule:admin_only",
+ "update_segment": "rule:admin_only",
+ "delete_segment": "rule:admin_only",
+
+ "network_device": "field:port:device_owner=~^network:",
+ "create_port": "",
+ "create_port:device_owner": "not rule:network_device or rule:context_is_advsvc or rule:admin_or_network_owner",
+ "create_port:mac_address": "rule:context_is_advsvc or rule:admin_or_network_owner",
+ "create_port:fixed_ips:ip_address": "rule:context_is_advsvc or rule:admin_or_network_owner",
+ "create_port:fixed_ips:subnet_id": "rule:context_is_advsvc or rule:admin_or_network_owner or rule:shared",
+ "create_port:port_security_enabled": "rule:context_is_advsvc or rule:admin_or_network_owner",
+ "create_port:binding:host_id": "rule:admin_only",
+ "create_port:binding:profile": "rule:admin_only",
+ "create_port:mac_learning_enabled": "rule:context_is_advsvc or rule:admin_or_network_owner",
+ "create_port:allowed_address_pairs": "rule:admin_or_network_owner",
+ "get_port": "rule:context_is_advsvc or rule:admin_owner_or_network_owner",
+ "get_port:queue_id": "rule:admin_only",
+ "get_port:binding:vif_type": "rule:admin_only",
+ "get_port:binding:vif_details": "rule:admin_only",
+ "get_port:binding:host_id": "rule:admin_only",
+ "get_port:binding:profile": "rule:admin_only",
+ "update_port": "rule:admin_or_owner or rule:context_is_advsvc",
+ "update_port:device_owner": "not rule:network_device or rule:context_is_advsvc or rule:admin_or_network_owner",
+ "update_port:mac_address": "rule:admin_only or rule:context_is_advsvc",
+ "update_port:fixed_ips:ip_address": "rule:context_is_advsvc or rule:admin_or_network_owner",
+ "update_port:fixed_ips:subnet_id": "rule:context_is_advsvc or rule:admin_or_network_owner or rule:shared",
+ "update_port:port_security_enabled": "rule:context_is_advsvc or rule:admin_or_network_owner",
+ "update_port:binding:host_id": "rule:admin_only",
+ "update_port:binding:profile": "rule:admin_only",
+ "update_port:mac_learning_enabled": "rule:context_is_advsvc or rule:admin_or_network_owner",
+ "update_port:allowed_address_pairs": "rule:admin_or_network_owner",
+ "update_port:data_plane_status": "rule:admin_or_data_plane_int",
+ "delete_port": "rule:context_is_advsvc or rule:admin_owner_or_network_owner",
+
+ "get_router:ha": "rule:admin_only",
+ "create_router": "rule:regular_user",
+ "create_router:external_gateway_info:enable_snat": "rule:admin_only",
+ "create_router:distributed": "rule:admin_only",
+ "create_router:ha": "rule:admin_only",
+ "get_router": "http://192.168.1.50:31002/wrapper/authz/grant",
+ "get_router:distributed": "rule:admin_only",
+ "update_router": "rule:admin_or_owner",
+ "update_router:external_gateway_info": "rule:admin_or_owner",
+ "update_router:external_gateway_info:network_id": "rule:admin_or_owner",
+ "update_router:external_gateway_info:enable_snat": "rule:admin_only",
+ "update_router:distributed": "rule:admin_only",
+ "update_router:ha": "rule:admin_only",
+ "delete_router": "rule:admin_or_owner",
+
+ "add_router_interface": "rule:admin_or_owner",
+ "remove_router_interface": "rule:admin_or_owner",
+
+ "create_router:external_gateway_info:external_fixed_ips": "rule:admin_only",
+ "update_router:external_gateway_info:external_fixed_ips": "rule:admin_only",
+
+ "create_qos_queue": "rule:admin_only",
+ "get_qos_queue": "rule:admin_only",
+
+ "update_agent": "rule:admin_only",
+ "delete_agent": "rule:admin_only",
+ "get_agent": "rule:admin_only",
+
+ "create_dhcp-network": "rule:admin_only",
+ "delete_dhcp-network": "rule:admin_only",
+ "get_dhcp-networks": "rule:admin_only",
+ "create_l3-router": "rule:admin_only",
+ "delete_l3-router": "rule:admin_only",
+ "get_l3-routers": "rule:admin_only",
+ "get_dhcp-agents": "rule:admin_only",
+ "get_l3-agents": "rule:admin_only",
+ "get_loadbalancer-agent": "rule:admin_only",
+ "get_loadbalancer-pools": "rule:admin_only",
+ "get_agent-loadbalancers": "rule:admin_only",
+ "get_loadbalancer-hosting-agent": "rule:admin_only",
+
+ "create_floatingip": "rule:regular_user",
+ "create_floatingip:floating_ip_address": "rule:admin_only",
+ "update_floatingip": "rule:admin_or_owner",
+ "delete_floatingip": "rule:admin_or_owner",
+ "get_floatingip": "rule:admin_or_owner",
+
+ "create_network_profile": "rule:admin_only",
+ "update_network_profile": "rule:admin_only",
+ "delete_network_profile": "rule:admin_only",
+ "get_network_profiles": "",
+ "get_network_profile": "",
+ "update_policy_profiles": "rule:admin_only",
+ "get_policy_profiles": "",
+ "get_policy_profile": "",
+
+ "create_metering_label": "rule:admin_only",
+ "delete_metering_label": "rule:admin_only",
+ "get_metering_label": "rule:admin_only",
+
+ "create_metering_label_rule": "rule:admin_only",
+ "delete_metering_label_rule": "rule:admin_only",
+ "get_metering_label_rule": "rule:admin_only",
+
+ "get_service_provider": "rule:regular_user",
+ "get_lsn": "rule:admin_only",
+ "create_lsn": "rule:admin_only",
+
+ "create_flavor": "rule:admin_only",
+ "update_flavor": "rule:admin_only",
+ "delete_flavor": "rule:admin_only",
+ "get_flavors": "rule:regular_user",
+ "get_flavor": "rule:regular_user",
+ "create_service_profile": "rule:admin_only",
+ "update_service_profile": "rule:admin_only",
+ "delete_service_profile": "rule:admin_only",
+ "get_service_profiles": "rule:admin_only",
+ "get_service_profile": "rule:admin_only",
+
+ "get_policy": "rule:regular_user",
+ "create_policy": "rule:admin_only",
+ "update_policy": "rule:admin_only",
+ "delete_policy": "rule:admin_only",
+ "get_policy_bandwidth_limit_rule": "rule:regular_user",
+ "create_policy_bandwidth_limit_rule": "rule:admin_only",
+ "delete_policy_bandwidth_limit_rule": "rule:admin_only",
+ "update_policy_bandwidth_limit_rule": "rule:admin_only",
+ "get_policy_dscp_marking_rule": "rule:regular_user",
+ "create_policy_dscp_marking_rule": "rule:admin_only",
+ "delete_policy_dscp_marking_rule": "rule:admin_only",
+ "update_policy_dscp_marking_rule": "rule:admin_only",
+ "get_rule_type": "rule:regular_user",
+ "get_policy_minimum_bandwidth_rule": "rule:regular_user",
+ "create_policy_minimum_bandwidth_rule": "rule:admin_only",
+ "delete_policy_minimum_bandwidth_rule": "rule:admin_only",
+ "update_policy_minimum_bandwidth_rule": "rule:admin_only",
+
+ "restrict_wildcard": "(not field:rbac_policy:target_tenant=*) or rule:admin_only",
+ "create_rbac_policy": "",
+ "create_rbac_policy:target_tenant": "rule:restrict_wildcard",
+ "update_rbac_policy": "rule:admin_or_owner",
+ "update_rbac_policy:target_tenant": "rule:restrict_wildcard and rule:admin_or_owner",
+ "get_rbac_policy": "rule:admin_or_owner",
+ "delete_rbac_policy": "rule:admin_or_owner",
+
+ "create_flavor_service_profile": "rule:admin_only",
+ "delete_flavor_service_profile": "rule:admin_only",
+ "get_flavor_service_profile": "rule:regular_user",
+ "get_auto_allocated_topology": "rule:admin_or_owner",
+
+ "create_trunk": "rule:regular_user",
+ "get_trunk": "rule:admin_or_owner",
+ "delete_trunk": "rule:admin_or_owner",
+ "get_subports": "",
+ "add_subports": "rule:admin_or_owner",
+ "remove_subports": "rule:admin_or_owner",
+
+ "get_security_groups": "rule:admin_or_owner",
+ "get_security_group": "rule:admin_or_owner",
+ "create_security_group": "rule:admin_or_owner",
+ "update_security_group": "rule:admin_or_owner",
+ "delete_security_group": "rule:admin_or_owner",
+ "get_security_group_rules": "rule:admin_or_owner",
+ "get_security_group_rule": "rule:admin_or_owner",
+ "create_security_group_rule": "rule:admin_or_owner",
+ "delete_security_group_rule": "rule:admin_or_owner",
+
+ "get_loggable_resources": "rule:admin_only",
+ "create_log": "rule:admin_only",
+ "update_log": "rule:admin_only",
+ "delete_log": "rule:admin_only",
+ "get_logs": "rule:admin_only",
+ "get_log": "rule:admin_only"
+}
diff --git a/moon_utilities/conf/policy.json.d/nova.policy.json b/moon_utilities/conf/policy.json.d/nova.policy.json
new file mode 100644
index 00000000..da8f5740
--- /dev/null
+++ b/moon_utilities/conf/policy.json.d/nova.policy.json
@@ -0,0 +1,485 @@
+{
+ "context_is_admin": "role:admin",
+ "admin_or_owner": "is_admin:True or project_id:%(project_id)s",
+ "default": "rule:admin_or_owner",
+
+ "cells_scheduler_filter:TargetCellFilter": "is_admin:True",
+
+ "compute:create": "",
+ "compute:create:attach_network": "",
+ "compute:create:attach_volume": "",
+ "compute:create:forced_host": "is_admin:True",
+
+ "compute:get": "",
+ "compute:get_all": "",
+ "compute:get_all_tenants": "is_admin:True",
+
+ "compute:update": "",
+
+ "compute:get_instance_metadata": "",
+ "compute:get_all_instance_metadata": "",
+ "compute:get_all_instance_system_metadata": "",
+ "compute:update_instance_metadata": "",
+ "compute:delete_instance_metadata": "",
+
+ "compute:get_instance_faults": "",
+ "compute:get_diagnostics": "",
+ "compute:get_instance_diagnostics": "",
+
+ "compute:start": "rule:admin_or_owner",
+ "compute:stop": "rule:admin_or_owner",
+
+ "compute:get_lock": "",
+ "compute:lock": "rule:admin_or_owner",
+ "compute:unlock": "rule:admin_or_owner",
+ "compute:unlock_override": "rule:admin_api",
+
+ "compute:get_vnc_console": "",
+ "compute:get_spice_console": "",
+ "compute:get_rdp_console": "",
+ "compute:get_serial_console": "",
+ "compute:get_mks_console": "",
+ "compute:get_console_output": "",
+
+ "compute:reset_network": "",
+ "compute:inject_network_info": "",
+ "compute:add_fixed_ip": "",
+ "compute:remove_fixed_ip": "",
+
+ "compute:attach_volume": "",
+ "compute:detach_volume": "",
+ "compute:swap_volume": "",
+
+ "compute:attach_interface": "",
+ "compute:detach_interface": "",
+
+ "compute:set_admin_password": "",
+
+ "compute:rescue": "",
+ "compute:unrescue": "",
+
+ "compute:suspend": "",
+ "compute:resume": "",
+
+ "compute:pause": "",
+ "compute:unpause": "",
+
+ "compute:shelve": "",
+ "compute:shelve_offload": "",
+ "compute:unshelve": "",
+
+ "compute:snapshot": "",
+ "compute:snapshot_volume_backed": "",
+ "compute:backup": "",
+
+ "compute:resize": "",
+ "compute:confirm_resize": "",
+ "compute:revert_resize": "",
+
+ "compute:rebuild": "",
+ "compute:reboot": "",
+ "compute:delete": "rule:admin_or_owner",
+ "compute:soft_delete": "rule:admin_or_owner",
+ "compute:force_delete": "rule:admin_or_owner",
+
+ "compute:security_groups:add_to_instance": "",
+ "compute:security_groups:remove_from_instance": "",
+
+ "compute:restore": "",
+
+ "compute:volume_snapshot_create": "",
+ "compute:volume_snapshot_delete": "",
+
+ "admin_api": "is_admin:True",
+ "compute_extension:accounts": "rule:admin_api",
+ "compute_extension:admin_actions": "rule:admin_api",
+ "compute_extension:admin_actions:pause": "rule:admin_or_owner",
+ "compute_extension:admin_actions:unpause": "rule:admin_or_owner",
+ "compute_extension:admin_actions:suspend": "rule:admin_or_owner",
+ "compute_extension:admin_actions:resume": "rule:admin_or_owner",
+ "compute_extension:admin_actions:lock": "rule:admin_or_owner",
+ "compute_extension:admin_actions:unlock": "rule:admin_or_owner",
+ "compute_extension:admin_actions:resetNetwork": "rule:admin_api",
+ "compute_extension:admin_actions:injectNetworkInfo": "rule:admin_api",
+ "compute_extension:admin_actions:createBackup": "rule:admin_or_owner",
+ "compute_extension:admin_actions:migrateLive": "rule:admin_api",
+ "compute_extension:admin_actions:resetState": "rule:admin_api",
+ "compute_extension:admin_actions:migrate": "rule:admin_api",
+ "compute_extension:aggregates": "rule:admin_api",
+ "compute_extension:agents": "rule:admin_api",
+ "compute_extension:attach_interfaces": "",
+ "compute_extension:baremetal_nodes": "rule:admin_api",
+ "compute_extension:cells": "rule:admin_api",
+ "compute_extension:cells:create": "rule:admin_api",
+ "compute_extension:cells:delete": "rule:admin_api",
+ "compute_extension:cells:update": "rule:admin_api",
+ "compute_extension:cells:sync_instances": "rule:admin_api",
+ "compute_extension:certificates": "",
+ "compute_extension:cloudpipe": "rule:admin_api",
+ "compute_extension:cloudpipe_update": "rule:admin_api",
+ "compute_extension:config_drive": "",
+ "compute_extension:console_output": "",
+ "compute_extension:consoles": "",
+ "compute_extension:createserverext": "",
+ "compute_extension:deferred_delete": "",
+ "compute_extension:disk_config": "",
+ "compute_extension:evacuate": "rule:admin_api",
+ "compute_extension:extended_server_attributes": "rule:admin_api",
+ "compute_extension:extended_status": "",
+ "compute_extension:extended_availability_zone": "",
+ "compute_extension:extended_ips": "",
+ "compute_extension:extended_ips_mac": "",
+ "compute_extension:extended_vif_net": "",
+ "compute_extension:extended_volumes": "",
+ "compute_extension:fixed_ips": "rule:admin_api",
+ "compute_extension:flavor_access": "",
+ "compute_extension:flavor_access:addTenantAccess": "rule:admin_api",
+ "compute_extension:flavor_access:removeTenantAccess": "rule:admin_api",
+ "compute_extension:flavor_disabled": "",
+ "compute_extension:flavor_rxtx": "",
+ "compute_extension:flavor_swap": "",
+ "compute_extension:flavorextradata": "",
+ "compute_extension:flavorextraspecs:index": "",
+ "compute_extension:flavorextraspecs:show": "",
+ "compute_extension:flavorextraspecs:create": "rule:admin_api",
+ "compute_extension:flavorextraspecs:update": "rule:admin_api",
+ "compute_extension:flavorextraspecs:delete": "rule:admin_api",
+ "compute_extension:flavormanage": "rule:admin_api",
+ "compute_extension:floating_ip_dns": "",
+ "compute_extension:floating_ip_pools": "",
+ "compute_extension:floating_ips": "",
+ "compute_extension:floating_ips_bulk": "rule:admin_api",
+ "compute_extension:fping": "",
+ "compute_extension:fping:all_tenants": "rule:admin_api",
+ "compute_extension:hide_server_addresses": "is_admin:False",
+ "compute_extension:hosts": "rule:admin_api",
+ "compute_extension:hypervisors": "rule:admin_api",
+ "compute_extension:image_size": "",
+ "compute_extension:instance_actions": "",
+ "compute_extension:instance_actions:events": "rule:admin_api",
+ "compute_extension:instance_usage_audit_log": "rule:admin_api",
+ "compute_extension:keypairs": "",
+ "compute_extension:keypairs:index": "",
+ "compute_extension:keypairs:show": "",
+ "compute_extension:keypairs:create": "",
+ "compute_extension:keypairs:delete": "",
+ "compute_extension:multinic": "",
+ "compute_extension:networks": "rule:admin_api",
+ "compute_extension:networks:view": "",
+ "compute_extension:networks_associate": "rule:admin_api",
+ "compute_extension:os-tenant-networks": "",
+ "compute_extension:quotas:show": "",
+ "compute_extension:quotas:update": "rule:admin_api",
+ "compute_extension:quotas:delete": "rule:admin_api",
+ "compute_extension:quota_classes": "",
+ "compute_extension:rescue": "",
+ "compute_extension:security_group_default_rules": "rule:admin_api",
+ "compute_extension:security_groups": "",
+ "compute_extension:server_diagnostics": "rule:admin_api",
+ "compute_extension:server_groups": "",
+ "compute_extension:server_password": "",
+ "compute_extension:server_usage": "",
+ "compute_extension:services": "rule:admin_api",
+ "compute_extension:shelve": "",
+ "compute_extension:shelveOffload": "rule:admin_api",
+ "compute_extension:simple_tenant_usage:show": "rule:admin_or_owner",
+ "compute_extension:simple_tenant_usage:list": "rule:admin_api",
+ "compute_extension:unshelve": "",
+ "compute_extension:users": "rule:admin_api",
+ "compute_extension:virtual_interfaces": "",
+ "compute_extension:virtual_storage_arrays": "",
+ "compute_extension:volumes": "",
+ "compute_extension:volume_attachments:index": "",
+ "compute_extension:volume_attachments:show": "",
+ "compute_extension:volume_attachments:create": "",
+ "compute_extension:volume_attachments:update": "",
+ "compute_extension:volume_attachments:delete": "",
+ "compute_extension:volumetypes": "",
+ "compute_extension:availability_zone:list": "",
+ "compute_extension:availability_zone:detail": "rule:admin_api",
+ "compute_extension:used_limits_for_admin": "rule:admin_api",
+ "compute_extension:migrations:index": "rule:admin_api",
+ "compute_extension:os-assisted-volume-snapshots:create": "rule:admin_api",
+ "compute_extension:os-assisted-volume-snapshots:delete": "rule:admin_api",
+ "compute_extension:console_auth_tokens": "rule:admin_api",
+ "compute_extension:os-server-external-events:create": "rule:admin_api",
+
+ "network:get_all": "",
+ "network:get": "",
+ "network:create": "",
+ "network:delete": "",
+ "network:associate": "",
+ "network:disassociate": "",
+ "network:get_vifs_by_instance": "",
+ "network:allocate_for_instance": "",
+ "network:deallocate_for_instance": "",
+ "network:validate_networks": "",
+ "network:get_instance_uuids_by_ip_filter": "",
+ "network:get_instance_id_by_floating_address": "",
+ "network:setup_networks_on_host": "",
+ "network:get_backdoor_port": "",
+
+ "network:get_floating_ip": "",
+ "network:get_floating_ip_pools": "",
+ "network:get_floating_ip_by_address": "",
+ "network:get_floating_ips_by_project": "",
+ "network:get_floating_ips_by_fixed_address": "",
+ "network:allocate_floating_ip": "",
+ "network:associate_floating_ip": "",
+ "network:disassociate_floating_ip": "",
+ "network:release_floating_ip": "",
+ "network:migrate_instance_start": "",
+ "network:migrate_instance_finish": "",
+
+ "network:get_fixed_ip": "",
+ "network:get_fixed_ip_by_address": "",
+ "network:add_fixed_ip_to_instance": "",
+ "network:remove_fixed_ip_from_instance": "",
+ "network:add_network_to_project": "",
+ "network:get_instance_nw_info": "",
+
+ "network:get_dns_domains": "",
+ "network:add_dns_entry": "",
+ "network:modify_dns_entry": "",
+ "network:delete_dns_entry": "",
+ "network:get_dns_entries_by_address": "",
+ "network:get_dns_entries_by_name": "",
+ "network:create_private_dns_domain": "",
+ "network:create_public_dns_domain": "",
+ "network:delete_dns_domain": "",
+ "network:attach_external_network": "rule:admin_api",
+ "network:get_vif_by_mac_address": "",
+
+ "os_compute_api:servers:detail:get_all_tenants": "is_admin:True",
+ "os_compute_api:servers:index:get_all_tenants": "is_admin:True",
+ "os_compute_api:servers:confirm_resize": "",
+ "os_compute_api:servers:create": "",
+ "os_compute_api:servers:create:attach_network": "",
+ "os_compute_api:servers:create:attach_volume": "",
+ "os_compute_api:servers:create:forced_host": "rule:admin_api",
+ "os_compute_api:servers:delete": "",
+ "os_compute_api:servers:update": "",
+ "os_compute_api:servers:detail": "",
+ "os_compute_api:servers:index": "",
+ "os_compute_api:servers:reboot": "",
+ "os_compute_api:servers:rebuild": "",
+ "os_compute_api:servers:resize": "",
+ "os_compute_api:servers:revert_resize": "",
+ "os_compute_api:servers:show": "",
+ "os_compute_api:servers:create_image": "",
+ "os_compute_api:servers:create_image:allow_volume_backed": "",
+ "os_compute_api:servers:start": "rule:admin_or_owner",
+ "os_compute_api:servers:stop": "rule:admin_or_owner",
+ "os_compute_api:os-access-ips:discoverable": "",
+ "os_compute_api:os-access-ips": "",
+ "os_compute_api:os-admin-actions": "rule:admin_api",
+ "os_compute_api:os-admin-actions:discoverable": "",
+ "os_compute_api:os-admin-actions:reset_network": "rule:admin_api",
+ "os_compute_api:os-admin-actions:inject_network_info": "rule:admin_api",
+ "os_compute_api:os-admin-actions:reset_state": "rule:admin_api",
+ "os_compute_api:os-admin-password": "",
+ "os_compute_api:os-admin-password:discoverable": "",
+ "os_compute_api:os-aggregates:discoverable": "",
+ "os_compute_api:os-aggregates:index": "rule:admin_api",
+ "os_compute_api:os-aggregates:create": "rule:admin_api",
+ "os_compute_api:os-aggregates:show": "rule:admin_api",
+ "os_compute_api:os-aggregates:update": "rule:admin_api",
+ "os_compute_api:os-aggregates:delete": "rule:admin_api",
+ "os_compute_api:os-aggregates:add_host": "rule:admin_api",
+ "os_compute_api:os-aggregates:remove_host": "rule:admin_api",
+ "os_compute_api:os-aggregates:set_metadata": "rule:admin_api",
+ "os_compute_api:os-agents": "rule:admin_api",
+ "os_compute_api:os-agents:discoverable": "",
+ "os_compute_api:os-attach-interfaces": "",
+ "os_compute_api:os-attach-interfaces:discoverable": "",
+ "os_compute_api:os-baremetal-nodes": "rule:admin_api",
+ "os_compute_api:os-baremetal-nodes:discoverable": "",
+ "os_compute_api:os-block-device-mapping-v1:discoverable": "",
+ "os_compute_api:os-cells": "rule:admin_api",
+ "os_compute_api:os-cells:create": "rule:admin_api",
+ "os_compute_api:os-cells:delete": "rule:admin_api",
+ "os_compute_api:os-cells:update": "rule:admin_api",
+ "os_compute_api:os-cells:sync_instances": "rule:admin_api",
+ "os_compute_api:os-cells:discoverable": "",
+ "os_compute_api:os-certificates:create": "",
+ "os_compute_api:os-certificates:show": "",
+ "os_compute_api:os-certificates:discoverable": "",
+ "os_compute_api:os-cloudpipe": "rule:admin_api",
+ "os_compute_api:os-cloudpipe:discoverable": "",
+ "os_compute_api:os-config-drive": "",
+ "os_compute_api:os-consoles:discoverable": "",
+ "os_compute_api:os-consoles:create": "",
+ "os_compute_api:os-consoles:delete": "",
+ "os_compute_api:os-consoles:index": "",
+ "os_compute_api:os-consoles:show": "",
+ "os_compute_api:os-console-output:discoverable": "",
+ "os_compute_api:os-console-output": "",
+ "os_compute_api:os-remote-consoles": "",
+ "os_compute_api:os-remote-consoles:discoverable": "",
+ "os_compute_api:os-create-backup:discoverable": "",
+ "os_compute_api:os-create-backup": "rule:admin_or_owner",
+ "os_compute_api:os-deferred-delete": "",
+ "os_compute_api:os-deferred-delete:discoverable": "",
+ "os_compute_api:os-disk-config": "",
+ "os_compute_api:os-disk-config:discoverable": "",
+ "os_compute_api:os-evacuate": "rule:admin_api",
+ "os_compute_api:os-evacuate:discoverable": "",
+ "os_compute_api:os-extended-server-attributes": "rule:admin_api",
+ "os_compute_api:os-extended-server-attributes:discoverable": "",
+ "os_compute_api:os-extended-status": "",
+ "os_compute_api:os-extended-status:discoverable": "",
+ "os_compute_api:os-extended-availability-zone": "",
+ "os_compute_api:os-extended-availability-zone:discoverable": "",
+ "os_compute_api:extensions": "",
+ "os_compute_api:extension_info:discoverable": "",
+ "os_compute_api:os-extended-volumes": "",
+ "os_compute_api:os-extended-volumes:discoverable": "",
+ "os_compute_api:os-fixed-ips": "rule:admin_api",
+ "os_compute_api:os-fixed-ips:discoverable": "",
+ "os_compute_api:os-flavor-access": "",
+ "os_compute_api:os-flavor-access:discoverable": "",
+ "os_compute_api:os-flavor-access:remove_tenant_access": "rule:admin_api",
+ "os_compute_api:os-flavor-access:add_tenant_access": "rule:admin_api",
+ "os_compute_api:os-flavor-rxtx": "",
+ "os_compute_api:os-flavor-rxtx:discoverable": "",
+ "os_compute_api:flavors:discoverable": "",
+ "os_compute_api:os-flavor-extra-specs:discoverable": "",
+ "os_compute_api:os-flavor-extra-specs:index": "",
+ "os_compute_api:os-flavor-extra-specs:show": "",
+ "os_compute_api:os-flavor-extra-specs:create": "rule:admin_api",
+ "os_compute_api:os-flavor-extra-specs:update": "rule:admin_api",
+ "os_compute_api:os-flavor-extra-specs:delete": "rule:admin_api",
+ "os_compute_api:os-flavor-manage:discoverable": "",
+ "os_compute_api:os-flavor-manage": "rule:admin_api",
+ "os_compute_api:os-floating-ip-dns": "",
+ "os_compute_api:os-floating-ip-dns:discoverable": "",
+ "os_compute_api:os-floating-ip-dns:domain:update": "rule:admin_api",
+ "os_compute_api:os-floating-ip-dns:domain:delete": "rule:admin_api",
+ "os_compute_api:os-floating-ip-pools": "",
+ "os_compute_api:os-floating-ip-pools:discoverable": "",
+ "os_compute_api:os-floating-ips": "",
+ "os_compute_api:os-floating-ips:discoverable": "",
+ "os_compute_api:os-floating-ips-bulk": "rule:admin_api",
+ "os_compute_api:os-floating-ips-bulk:discoverable": "",
+ "os_compute_api:os-fping": "",
+ "os_compute_api:os-fping:discoverable": "",
+ "os_compute_api:os-fping:all_tenants": "rule:admin_api",
+ "os_compute_api:os-hide-server-addresses": "is_admin:False",
+ "os_compute_api:os-hide-server-addresses:discoverable": "",
+ "os_compute_api:os-hosts": "rule:admin_api",
+ "os_compute_api:os-hosts:discoverable": "",
+ "os_compute_api:os-hypervisors": "rule:admin_api",
+ "os_compute_api:os-hypervisors:discoverable": "",
+ "os_compute_api:images:discoverable": "",
+ "os_compute_api:image-size": "",
+ "os_compute_api:image-size:discoverable": "",
+ "os_compute_api:os-instance-actions": "",
+ "os_compute_api:os-instance-actions:discoverable": "",
+ "os_compute_api:os-instance-actions:events": "rule:admin_api",
+ "os_compute_api:os-instance-usage-audit-log": "rule:admin_api",
+ "os_compute_api:os-instance-usage-audit-log:discoverable": "",
+ "os_compute_api:ips:discoverable": "",
+ "os_compute_api:ips:index": "rule:admin_or_owner",
+ "os_compute_api:ips:show": "rule:admin_or_owner",
+ "os_compute_api:os-keypairs:discoverable": "",
+ "os_compute_api:os-keypairs": "",
+ "os_compute_api:os-keypairs:index": "rule:admin_api or user_id:%(user_id)s",
+ "os_compute_api:os-keypairs:show": "rule:admin_api or user_id:%(user_id)s",
+ "os_compute_api:os-keypairs:create": "rule:admin_api or user_id:%(user_id)s",
+ "os_compute_api:os-keypairs:delete": "rule:admin_api or user_id:%(user_id)s",
+ "os_compute_api:limits:discoverable": "",
+ "os_compute_api:limits": "",
+ "os_compute_api:os-lock-server:discoverable": "",
+ "os_compute_api:os-lock-server:lock": "rule:admin_or_owner",
+ "os_compute_api:os-lock-server:unlock": "rule:admin_or_owner",
+ "os_compute_api:os-lock-server:unlock:unlock_override": "rule:admin_api",
+ "os_compute_api:os-migrate-server:discoverable": "",
+ "os_compute_api:os-migrate-server:migrate": "rule:admin_api",
+ "os_compute_api:os-migrate-server:migrate_live": "rule:admin_api",
+ "os_compute_api:os-multinic": "",
+ "os_compute_api:os-multinic:discoverable": "",
+ "os_compute_api:os-networks": "rule:admin_api",
+ "os_compute_api:os-networks:view": "",
+ "os_compute_api:os-networks:discoverable": "",
+ "os_compute_api:os-networks-associate": "rule:admin_api",
+ "os_compute_api:os-networks-associate:discoverable": "",
+ "os_compute_api:os-pause-server:discoverable": "",
+ "os_compute_api:os-pause-server:pause": "rule:admin_or_owner",
+ "os_compute_api:os-pause-server:unpause": "rule:admin_or_owner",
+ "os_compute_api:os-pci:pci_servers": "",
+ "os_compute_api:os-pci:discoverable": "",
+ "os_compute_api:os-pci:index": "rule:admin_api",
+ "os_compute_api:os-pci:detail": "rule:admin_api",
+ "os_compute_api:os-pci:show": "rule:admin_api",
+ "os_compute_api:os-personality:discoverable": "",
+ "os_compute_api:os-preserve-ephemeral-rebuild:discoverable": "",
+ "os_compute_api:os-quota-sets:discoverable": "",
+ "os_compute_api:os-quota-sets:show": "rule:admin_or_owner",
+ "os_compute_api:os-quota-sets:defaults": "",
+ "os_compute_api:os-quota-sets:update": "rule:admin_api",
+ "os_compute_api:os-quota-sets:delete": "rule:admin_api",
+ "os_compute_api:os-quota-sets:detail": "rule:admin_api",
+ "os_compute_api:os-quota-class-sets:update": "rule:admin_api",
+ "os_compute_api:os-quota-class-sets:show": "is_admin:True or quota_class:%(quota_class)s",
+ "os_compute_api:os-quota-class-sets:discoverable": "",
+ "os_compute_api:os-rescue": "",
+ "os_compute_api:os-rescue:discoverable": "",
+ "os_compute_api:os-scheduler-hints:discoverable": "",
+ "os_compute_api:os-security-group-default-rules:discoverable": "",
+ "os_compute_api:os-security-group-default-rules": "rule:admin_api",
+ "os_compute_api:os-security-groups": "",
+ "os_compute_api:os-security-groups:discoverable": "",
+ "os_compute_api:os-server-diagnostics": "rule:admin_api",
+ "os_compute_api:os-server-diagnostics:discoverable": "",
+ "os_compute_api:os-server-password": "",
+ "os_compute_api:os-server-password:discoverable": "",
+ "os_compute_api:os-server-usage": "",
+ "os_compute_api:os-server-usage:discoverable": "",
+ "os_compute_api:os-server-groups": "",
+ "os_compute_api:os-server-groups:discoverable": "",
+ "os_compute_api:os-services": "rule:admin_api",
+ "os_compute_api:os-services:discoverable": "",
+ "os_compute_api:server-metadata:discoverable": "",
+ "os_compute_api:server-metadata:index": "rule:admin_or_owner",
+ "os_compute_api:server-metadata:show": "rule:admin_or_owner",
+ "os_compute_api:server-metadata:delete": "rule:admin_or_owner",
+ "os_compute_api:server-metadata:create": "rule:admin_or_owner",
+ "os_compute_api:server-metadata:update": "rule:admin_or_owner",
+ "os_compute_api:server-metadata:update_all": "rule:admin_or_owner",
+ "os_compute_api:servers:discoverable": "",
+ "os_compute_api:os-shelve:shelve": "",
+ "os_compute_api:os-shelve:shelve:discoverable": "",
+ "os_compute_api:os-shelve:shelve_offload": "rule:admin_api",
+ "os_compute_api:os-simple-tenant-usage:discoverable": "",
+ "os_compute_api:os-simple-tenant-usage:show": "rule:admin_or_owner",
+ "os_compute_api:os-simple-tenant-usage:list": "rule:admin_api",
+ "os_compute_api:os-suspend-server:discoverable": "",
+ "os_compute_api:os-suspend-server:suspend": "rule:admin_or_owner",
+ "os_compute_api:os-suspend-server:resume": "rule:admin_or_owner",
+ "os_compute_api:os-tenant-networks": "rule:admin_or_owner",
+ "os_compute_api:os-tenant-networks:discoverable": "",
+ "os_compute_api:os-shelve:unshelve": "",
+ "os_compute_api:os-user-data:discoverable": "",
+ "os_compute_api:os-virtual-interfaces": "",
+ "os_compute_api:os-virtual-interfaces:discoverable": "",
+ "os_compute_api:os-volumes": "",
+ "os_compute_api:os-volumes:discoverable": "",
+ "os_compute_api:os-volumes-attachments:index": "",
+ "os_compute_api:os-volumes-attachments:show": "",
+ "os_compute_api:os-volumes-attachments:create": "",
+ "os_compute_api:os-volumes-attachments:update": "",
+ "os_compute_api:os-volumes-attachments:delete": "",
+ "os_compute_api:os-volumes-attachments:discoverable": "",
+ "os_compute_api:os-availability-zone:list": "",
+ "os_compute_api:os-availability-zone:discoverable": "",
+ "os_compute_api:os-availability-zone:detail": "rule:admin_api",
+ "os_compute_api:os-used-limits": "rule:admin_api",
+ "os_compute_api:os-used-limits:discoverable": "",
+ "os_compute_api:os-migrations:index": "rule:admin_api",
+ "os_compute_api:os-migrations:discoverable": "",
+ "os_compute_api:os-assisted-volume-snapshots:create": "rule:admin_api",
+ "os_compute_api:os-assisted-volume-snapshots:delete": "rule:admin_api",
+ "os_compute_api:os-assisted-volume-snapshots:discoverable": "",
+ "os_compute_api:os-console-auth-tokens": "rule:admin_api",
+ "os_compute_api:os-server-external-events:create": "rule:admin_api"
+}
diff --git a/moon_utilities/moon_utilities/__init__.py b/moon_utilities/moon_utilities/__init__.py
new file mode 100644
index 00000000..d1e99258
--- /dev/null
+++ b/moon_utilities/moon_utilities/__init__.py
@@ -0,0 +1,13 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+__version__ = "0.8"
diff --git a/moon_utilities/moon_utilities/auth_functions.py b/moon_utilities/moon_utilities/auth_functions.py
new file mode 100644
index 00000000..08a0ec22
--- /dev/null
+++ b/moon_utilities/moon_utilities/auth_functions.py
@@ -0,0 +1,307 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+"""
+"""
+
+import binascii
+import hashlib
+import os
+import hug
+import logging
+import os
+import getpass
+from tinydb import TinyDB, Query
+from moon_utilities import exceptions
+
+LOGGER = logging.getLogger("moon.utilities.auth_functions")
+db = None
+
+
+def init_db(db_filename="db.json"):
+ global db
+ db = TinyDB(db_filename)
+
+
+def xor_encode(data, key):
+ """
+ Encode data with the given key
+
+ :param data: the data to encode
+ :param key: the key ie password
+ :return: a xor-ed version of the 2 strings
+ """
+ if not data:
+ return ""
+ if not key:
+ raise exceptions.EncryptError
+ return binascii.hexlify(
+ ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(data, key)).encode("utf-8")).decode("utf-8")
+
+
+def xor_decode(data, key):
+ """
+ Decode data with the given key
+
+ :param data: the data to decode
+ :param key: the key ie password
+ :return: a xor-ed version of the 2 strings
+ """
+ if not data:
+ return ""
+ if not key:
+ raise exceptions.DecryptError
+ data = binascii.a2b_hex(data.encode("utf-8")).decode("utf-8")
+ return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(data, key))
+
+
+# From https://github.com/timothycrosley/hug/blob/develop/examples/secure_auth_with_db_example.py
+
+def hash_password(password, salt):
+ """
+ Securely hash a password using a provided salt
+ :param password:
+ :param salt:
+ :return: Hex encoded SHA512 hash of provided password
+ """
+ password = str(password).encode('utf-8')
+ salt = str(salt).encode('utf-8')
+ return hashlib.sha512(password + salt).hexdigest()
+
+
+def gen_api_key(username):
+ """
+ Create a random API key for a user
+ :param username:
+ :return: Hex encoded SHA512 random string
+ """
+ salt = str(os.urandom(64)).encode('utf-8')
+ return hash_password(username, salt)
+
+
+def get_api_key_for_user(username):
+ """
+ Return the API key for a particular user
+ :param username:
+ :return: API key
+ """
+ global db
+ if db is None:
+ init_db()
+ user_model = Query()
+ user = db.get(user_model.username == username)
+
+ if not user:
+ LOGGER.warning("User %s not found", username)
+ return False
+
+ return user['api_key']
+
+
+def del_api_key_for_user(username):
+ """
+ Delete the API key for a particular user
+ :param username:
+ :return: API key
+ """
+ global db
+ if db is None:
+ init_db()
+ user_model = Query()
+ users = db.search(user_model.username == username)
+
+ if not users:
+ LOGGER.warning("User %s not found", username)
+ return False
+ try:
+ for user in users:
+ user['api_key'] = None
+ db.write_back(users)
+ return True
+ except Exception as e:
+ LOGGER.exception(e)
+ return False
+
+
+def connect_from_env():
+ try:
+ user = os.environ["MOON_USERNAME"]
+ pw = os.environ["MOON_PASSWORD"]
+ except KeyError:
+ LOGGER.error("Set your credentials with moonrc")
+ exit(-1)
+
+ return get_api_key(user, pw)
+
+
+@hug.cli("get_key")
+def get_api_key(username, password):
+ """
+ Authenticate a username and password against our database
+ :param username:
+ :param password:
+ :return: authenticated username
+ """
+ global db
+ if db is None:
+ init_db()
+ user_model = Query()
+ user = db.get(user_model.username == username)
+
+ if not user:
+ LOGGER.warning("User %s not found", username)
+ return False
+
+ if user['password'] == hash_password(password, user.get('salt')):
+ return user['api_key']
+
+ return False
+
+
+@hug.cli()
+def authenticate_user(username, password):
+ """
+ Authenticate a username and password against our database
+ :param username:
+ :param password:
+ :return: authenticated username
+ """
+ global db
+ if db is None:
+ init_db()
+ user_model = Query()
+ users = db.search(user_model.username == username)
+
+ if not users:
+ LOGGER.warning("User %s not found", username)
+ return False
+
+ for user in users:
+ # Note: will only update the first item
+ if user['password'] == hash_password(password, user.get('salt')):
+ if not user['api_key']:
+ api_key = gen_api_key(username)
+ user['api_key'] = api_key
+ db.write_back(users)
+ return user['username']
+ LOGGER.warning("Wrong password for user %s", username)
+ return False
+
+
+@hug.cli()
+def change_password(username, current_password, new_password):
+ """
+ Change the password of the user in the database
+ :param username:
+ :param current_password:
+ :param new_password:
+ :return: True or False
+ """
+
+ if current_password == "": # nosec (not a hardcoded password)
+ current_password = getpass.getpass()
+
+ is_password_ok = authenticate_user(username, current_password)
+ if not is_password_ok:
+ return False
+
+ if new_password == "": # nosec (not a hardcoded password)
+ new_password = getpass.getpass()
+
+ global db
+ if db is None:
+ init_db()
+ user_model = Query()
+ user = db.search(user_model.username == username)[0]
+
+ salt = user['salt']
+ password = hash_password(new_password, salt)
+ api_key = gen_api_key(username)
+
+ user_id = db.update({'password': password, 'api_key': api_key}, doc_ids=[user.doc_id])
+
+ return {
+ 'result': 'success',
+ 'eid': user_id,
+ 'user_created': user,
+ 'api_key': api_key
+ }
+
+
+@hug.cli()
+def authenticate_key(api_key):
+ """
+ Authenticate an API key against our database
+ :param api_key:
+ :return: authenticated username
+ """
+ global db
+ if db is None:
+ init_db()
+ try:
+ if not api_key:
+ return False
+ user_model = Query()
+ user = db.search(user_model.api_key == api_key)[0]
+ if user:
+ return user['username']
+ except Exception as e:
+ LOGGER.exception(e)
+ LOGGER.error("Cannot retrieve user for this authentication key {}".format(api_key))
+ return False
+
+
+"""
+ API Methods start here
+"""
+
+api_key_authentication = hug.authentication.api_key(authenticate_key)
+basic_authentication = hug.authentication.basic(authenticate_user)
+
+
+@hug.cli("add_user") # nosec (not a hardcoded password)
+def add_user(username, password=""):
+ """
+ CLI Parameter to add a user to the database
+ :param username:
+ :param password: if not given, a password prompt is displayed
+ :return: JSON status output
+ """
+ global db
+ if db is None:
+ init_db()
+ user_model = Query()
+ if db.search(user_model.username == username):
+ return {
+ 'error': 'User {0} already exists'.format(username)
+ }
+
+ if password == "": # nosec (not a hardcoded password)
+ password = getpass.getpass()
+
+ salt = hashlib.sha512(str(os.urandom(64)).encode('utf-8')).hexdigest()
+ password = hash_password(password, salt)
+ api_key = gen_api_key(username)
+
+ user = {
+ 'username': username,
+ 'password': password,
+ 'salt': salt,
+ 'api_key': api_key
+ }
+ user_id = db.insert(user)
+
+ return {
+ 'result': 'success',
+ 'eid': user_id,
+ 'user_created': user,
+ 'api_key': api_key
+ }
diff --git a/moon_utilities/moon_utilities/exceptions.py b/moon_utilities/moon_utilities/exceptions.py
new file mode 100644
index 00000000..4e016e70
--- /dev/null
+++ b/moon_utilities/moon_utilities/exceptions.py
@@ -0,0 +1,903 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import logging
+
+logger = logging.getLogger("moon.utilities.exceptions")
+_ = str
+
+
+class MoonErrorMetaClass(type):
+
+ def __init__(cls, name, bases, dct):
+ super(MoonErrorMetaClass, cls).__init__(name, bases, dct)
+ cls.hierarchy += "/" + str(name)
+
+
+class MoonError(BaseException):
+ __metaclass__ = MoonErrorMetaClass
+ hierarchy = ""
+ description = _("There is an error requesting the Moon platform.")
+ code = 400
+ title = 'Moon Error'
+ logger = "ERROR"
+
+ def __init__(self, message="", status_code=None, payload=""):
+ if message:
+ self.description = message
+ if status_code:
+ self.code = status_code
+ self.payload = payload
+ super(MoonError, self).__init__()
+
+ def __str__(self):
+ return "{}: {}".format(self.code, self.title)
+
+ def __del__(self):
+ message = "{} ({}) {}".format(self.hierarchy, self.description, self.payload)
+ if self.logger == "ERROR":
+ try:
+ logger.error(message)
+ except AttributeError:
+ logger.error(message)
+ elif self.logger == "WARNING":
+ try:
+ logger.warning(message)
+ except AttributeError:
+ logger.warning(message)
+ elif self.logger == "CRITICAL":
+ try:
+ logger.critical(message)
+ except AttributeError:
+ logger.critical(message)
+ elif self.logger == "AUTHZ":
+ try:
+ logger.error(message)
+ except AttributeError:
+ logger.error(message)
+ else:
+ try:
+ logger.info(message)
+ except AttributeError:
+ logger.info(message)
+
+ # def to_dict(self):
+ # rv = dict(self.payload or ())
+ # rv['message'] = "{} ({})".format(self.hierarchy, self.description)
+ # rv['title'] = self.title
+ # rv['code'] = self.code
+ # return rv
+
+
+# Exceptions for Tenant
+
+class TenantException(MoonError):
+ description = _("There is an error requesting this tenant.")
+ code = 400
+ title = 'Tenant Error'
+ logger = "ERROR"
+
+
+class TenantUnknown(TenantException):
+ description = _("The tenant is unknown.")
+ code = 400
+ title = 'Tenant Unknown'
+ logger = "ERROR"
+
+
+class TenantAddedNameExisting(TenantException):
+ description = _("The tenant name is existing.")
+ code = 400
+ title = 'Added Tenant Name Existing'
+ logger = "ERROR"
+
+
+class TenantNoIntraExtension(TenantException):
+ description = _("The tenant has not intra_extension.")
+ code = 400
+ title = 'Tenant No Intra_Extension'
+ logger = "ERROR"
+
+
+class TenantNoIntraAuthzExtension(TenantNoIntraExtension):
+ description = _("The tenant has not intra_admin_extension.")
+ code = 400
+ title = 'Tenant No Intra_Admin_Extension'
+ logger = "ERROR"
+
+
+# Exceptions for IntraExtension
+
+
+class IntraExtensionException(MoonError):
+ description = _("There is an error requesting this IntraExtension.")
+ code = 400
+ title = 'Extension Error'
+
+
+class IntraExtensionUnknown(IntraExtensionException):
+ description = _("The intra_extension is unknown.")
+ code = 400
+ title = 'Intra Extension Unknown'
+ logger = "Error"
+
+
+class ModelUnknown(MoonError):
+ description = _("The model is unknown.")
+ code = 400
+ title = 'Model Unknown'
+ logger = "Error"
+
+
+class ModelContentError(MoonError):
+ description = _("The model content is invalid.")
+ code = 400
+ title = 'Model Unknown'
+ logger = "Error"
+
+
+class ModelExisting(MoonError):
+ description = _("The model already exists.")
+ code = 409
+ title = 'Model Error'
+ logger = "Error"
+
+
+# Authz exceptions
+
+class AuthzException(MoonError):
+ description = _("There is an authorization error requesting this IntraExtension.")
+ code = 403
+ title = 'Authz Exception'
+ logger = "AUTHZ"
+
+
+# Auth exceptions
+
+class AuthException(MoonError):
+ description = _("There is an authentication error requesting this API. "
+ "You must provide a valid token from Keystone.")
+ code = 401
+ title = 'Auth Exception'
+ logger = "AUTHZ"
+
+
+# Admin exceptions
+
+class AdminException(MoonError):
+ description = _("There is an error requesting this Authz IntraExtension.")
+ code = 400
+ title = 'Authz Exception'
+ logger = "AUTHZ"
+
+
+class AdminMetaData(AdminException):
+ code = 400
+ title = 'Metadata Exception'
+
+
+class AdminPerimeter(AdminException):
+ code = 400
+ title = 'Perimeter Exception'
+
+
+class AdminScope(AdminException):
+ code = 400
+ title = 'Scope Exception'
+
+
+class AdminAssignment(AdminException):
+ code = 400
+ title = 'Assignment Exception'
+
+
+class AdminMetaRule(AdminException):
+ code = 400
+ title = 'Aggregation Algorithm Exception'
+
+
+class AdminRule(AdminException):
+ code = 400
+ title = 'Rule Exception'
+
+
+class CategoryNameInvalid(AdminMetaData):
+ description = _("The given category name is invalid.")
+ code = 400
+ title = 'Category Name Invalid'
+ logger = "ERROR"
+
+
+class SubjectCategoryExisting(AdminMetaData):
+ description = _("The given subject category already exists.")
+ code = 409
+ title = 'Subject Category Existing'
+ logger = "ERROR"
+
+
+class ObjectCategoryExisting(AdminMetaData):
+ description = _("The given object category already exists.")
+ code = 409
+ title = 'Object Category Existing'
+ logger = "ERROR"
+
+
+class ActionCategoryExisting(AdminMetaData):
+ description = _("The given action category already exists.")
+ code = 409
+ title = 'Action Category Existing'
+ logger = "ERROR"
+
+
+class SubjectCategoryUnknown(AdminMetaData):
+ description = _("The given subject category is unknown.")
+ code = 400
+ title = 'Subject Category Unknown'
+ logger = "ERROR"
+
+
+class DeleteSubjectCategoryWithMetaRule(MoonError):
+ description = _("Cannot delete subject category used in meta rule ")
+ code = 400
+ title = 'Subject Category With Meta Rule Error'
+ logger = "Error"
+
+
+class DeleteObjectCategoryWithMetaRule(MoonError):
+ description = _("Cannot delete Object category used in meta rule ")
+ code = 400
+ title = 'Object Category With Meta Rule Error'
+ logger = "Error"
+
+
+class ObjectCategoryUnknown(AdminMetaData):
+ description = _("The given object category is unknown.")
+ code = 400
+ title = 'Object Category Unknown'
+ logger = "ERROR"
+
+
+class DeleteActionCategoryWithMetaRule(MoonError):
+ description = _("Cannot delete Action category used in meta rule ")
+ code = 400
+ title = 'Action Category With Meta Rule Error'
+ logger = "Error"
+
+
+class ActionCategoryUnknown(AdminMetaData):
+ description = _("The given action category is unknown.")
+ code = 400
+ title = 'Action Category Unknown'
+ logger = "ERROR"
+
+
+class PerimeterContentError(AdminPerimeter):
+ description = _("Perimeter content is invalid.")
+ code = 400
+ title = 'Perimeter content is invalid.'
+ logger = "ERROR"
+
+
+class DeletePerimeterWithAssignment(MoonError):
+ description = _("Cannot delete perimeter with assignment")
+ code = 400
+ title = 'Perimeter With Assignment Error'
+ logger = "Error"
+
+
+class SubjectUnknown(AdminPerimeter):
+ description = _("The given subject is unknown.")
+ code = 400
+ title = 'Subject Unknown'
+ logger = "ERROR"
+
+
+class ObjectUnknown(AdminPerimeter):
+ description = _("The given object is unknown.")
+ code = 400
+ title = 'Object Unknown'
+ logger = "ERROR"
+
+
+class ActionUnknown(AdminPerimeter):
+ description = _("The given action is unknown.")
+ code = 400
+ title = 'Action Unknown'
+ logger = "ERROR"
+
+
+class SubjectExisting(AdminPerimeter):
+ description = _("The given subject is existing.")
+ code = 409
+ title = 'Subject Existing'
+ logger = "ERROR"
+
+
+class ObjectExisting(AdminPerimeter):
+ description = _("The given object is existing.")
+ code = 409
+ title = 'Object Existing'
+ logger = "ERROR"
+
+
+class ActionExisting(AdminPerimeter):
+ description = _("The given action is existing.")
+ code = 409
+ title = 'Action Existing'
+ logger = "ERROR"
+
+
+class SubjectNameExisting(AdminPerimeter):
+ description = _("The given subject name is existing.")
+ code = 409
+ title = 'Subject Name Existing'
+ logger = "ERROR"
+
+
+class ObjectNameExisting(AdminPerimeter):
+ description = _("The given object name is existing.")
+ code = 409
+ title = 'Object Name Existing'
+ logger = "ERROR"
+
+
+class ActionNameExisting(AdminPerimeter):
+ description = _("The given action name is existing.")
+ code = 409
+ title = 'Action Name Existing'
+ logger = "ERROR"
+
+
+class ObjectsWriteNoAuthorized(AdminPerimeter):
+ description = _("The modification on Objects is not authorized.")
+ code = 400
+ title = 'Objects Write No Authorized'
+ logger = "AUTHZ"
+
+
+class ActionsWriteNoAuthorized(AdminPerimeter):
+ description = _("The modification on Actions is not authorized.")
+ code = 400
+ title = 'Actions Write No Authorized'
+ logger = "AUTHZ"
+
+
+class SubjectScopeUnknown(AdminScope):
+ description = _("The given subject scope is unknown.")
+ code = 400
+ title = 'Subject Scope Unknown'
+ logger = "ERROR"
+
+
+class ObjectScopeUnknown(AdminScope):
+ description = _("The given object scope is unknown.")
+ code = 400
+ title = 'Object Scope Unknown'
+ logger = "ERROR"
+
+
+class ActionScopeUnknown(AdminScope):
+ description = _("The given action scope is unknown.")
+ code = 400
+ title = 'Action Scope Unknown'
+ logger = "ERROR"
+
+
+class SubjectScopeExisting(AdminScope):
+ description = _("The given subject scope is existing.")
+ code = 409
+ title = 'Subject Scope Existing'
+ logger = "ERROR"
+
+
+class ObjectScopeExisting(AdminScope):
+ description = _("The given object scope is existing.")
+ code = 409
+ title = 'Object Scope Existing'
+ logger = "ERROR"
+
+
+class ActionScopeExisting(AdminScope):
+ description = _("The given action scope is existing.")
+ code = 409
+ title = 'Action Scope Existing'
+ logger = "ERROR"
+
+
+class SubjectScopeNameExisting(AdminScope):
+ description = _("The given subject scope name is existing.")
+ code = 409
+ title = 'Subject Scope Name Existing'
+ logger = "ERROR"
+
+
+class ObjectScopeNameExisting(AdminScope):
+ description = _("The given object scope name is existing.")
+ code = 409
+ title = 'Object Scope Name Existing'
+ logger = "ERROR"
+
+
+class ActionScopeNameExisting(AdminScope):
+ description = _("The given action scope name is existing.")
+ code = 409
+ title = 'Action Scope Name Existing'
+ logger = "ERROR"
+
+
+class SubjectAssignmentUnknown(AdminAssignment):
+ description = _("The given subject assignment value is unknown.")
+ code = 400
+ title = 'Subject Assignment Unknown'
+ logger = "ERROR"
+
+
+class ObjectAssignmentUnknown(AdminAssignment):
+ description = _("The given object assignment value is unknown.")
+ code = 400
+ title = 'Object Assignment Unknown'
+ logger = "ERROR"
+
+
+class ActionAssignmentUnknown(AdminAssignment):
+ description = _("The given action assignment value is unknown.")
+ code = 400
+ title = 'Action Assignment Unknown'
+ logger = "ERROR"
+
+
+class SubjectAssignmentExisting(AdminAssignment):
+ description = _("The given subject assignment value is existing.")
+ code = 409
+ title = 'Subject Assignment Existing'
+ logger = "ERROR"
+
+
+class ObjectAssignmentExisting(AdminAssignment):
+ description = _("The given object assignment value is existing.")
+ code = 409
+ title = 'Object Assignment Existing'
+ logger = "ERROR"
+
+
+class ActionAssignmentExisting(AdminAssignment):
+ description = _("The given action assignment value is existing.")
+ code = 409
+ title = 'Action Assignment Existing'
+ logger = "ERROR"
+
+
+class AggregationAlgorithmNotExisting(AdminMetaRule):
+ description = _("The given aggregation algorithm is not existing.")
+ code = 400
+ title = 'Aggregation Algorithm Not Existing'
+ logger = "ERROR"
+
+
+class AggregationAlgorithmUnknown(AdminMetaRule):
+ description = _("The given aggregation algorithm is unknown.")
+ code = 400
+ title = 'Aggregation Algorithm Unknown'
+ logger = "ERROR"
+
+
+class SubMetaRuleAlgorithmNotExisting(AdminMetaRule):
+ description = _("The given sub_meta_rule algorithm is unknown.")
+ code = 400
+ title = 'Sub_meta_rule Algorithm Unknown'
+ logger = "ERROR"
+
+
+class MetaRuleUnknown(AdminMetaRule):
+ description = _("The given meta rule is unknown.")
+ code = 400
+ title = 'Meta Rule Unknown'
+ logger = "ERROR"
+
+
+class MetaRuleNotLinkedWithPolicyModel(MoonError):
+ description = _("The meta rule is not found in the model attached to the policy.")
+ code = 400
+ title = 'MetaRule Not Linked With Model - Policy'
+ logger = "Error"
+
+
+class CategoryNotAssignedMetaRule(MoonError):
+ description = _("The category is not found in the meta rules attached to the policy.")
+ code = 400
+ title = 'Category Not Linked With Meta Rule - Policy'
+ logger = "Error"
+
+
+class SubMetaRuleNameExisting(AdminMetaRule):
+ description = _("The sub meta rule name already exists.")
+ code = 409
+ title = 'Sub Meta Rule Name Existing'
+ logger = "ERROR"
+
+
+class MetaRuleExisting(AdminMetaRule):
+ description = _("The meta rule already exists.")
+ code = 409
+ title = 'Meta Rule Existing'
+ logger = "ERROR"
+
+
+class MetaRuleContentError(AdminMetaRule):
+ description = _("Invalid content of meta rule.")
+ code = 400
+ title = 'Meta Rule Error'
+ logger = "ERROR"
+
+
+class MetaRuleUpdateError(AdminMetaRule):
+ description = _("Meta_rule is used in Rule.")
+ code = 400
+ title = 'Meta_Rule Update Error'
+ logger = "ERROR"
+
+
+class RuleExisting(AdminRule):
+ description = _("The rule already exists.")
+ code = 409
+ title = 'Rule Existing'
+ logger = "ERROR"
+
+
+class RuleContentError(AdminRule):
+ description = _("Invalid content of rule.")
+ code = 400
+ title = 'Rule Error'
+ logger = "ERROR"
+
+
+class RuleUnknown(AdminRule):
+ description = _("The rule for that request doesn't exist.")
+ code = 400
+ title = 'Rule Unknown'
+ logger = "ERROR"
+
+
+# Consul exceptions
+
+
+class ConsulError(MoonError):
+ description = _("There is an error connecting to Consul.")
+ code = 400
+ title = 'Consul error'
+ logger = "ERROR"
+
+
+class ConsulComponentNotFound(ConsulError):
+ description = _("The component do not exist in Consul database.")
+ code = 500
+ title = 'Consul error'
+ logger = "WARNING"
+
+
+class ConsulComponentContentError(ConsulError):
+ description = _("invalid content of component .")
+ code = 500
+ title = 'Consul Content error'
+ logger = "WARNING"
+
+
+# Containers exceptions
+
+
+class DockerError(MoonError):
+ description = _("There is an error with Docker.")
+ code = 400
+ title = 'Docker error'
+ logger = "ERROR"
+
+
+class ContainerMissing(DockerError):
+ description = _("Some containers are missing.")
+ code = 400
+ title = 'Container missing'
+ logger = "ERROR"
+
+
+class WrapperConflict(MoonError):
+ description = _("A Wrapper already exist for the specified slave.")
+ code = 409
+ title = 'Wrapper conflict'
+ logger = "ERROR"
+
+
+class PipelineConflict(MoonError):
+ description = _("A Pipeline already exist for the specified slave.")
+ code = 409
+ title = 'Pipeline conflict'
+ logger = "ERROR"
+
+
+class PipelineUnknown(MoonError):
+ description = _("This Pipeline is unknown from the system.")
+ code = 400
+ title = 'Pipeline Unknown'
+ logger = "ERROR"
+
+
+class WrapperUnknown(MoonError):
+ description = _("This Wrapper is unknown from the system.")
+ code = 400
+ title = 'Wrapper Unknown'
+ logger = "ERROR"
+
+
+class SlaveNameUnknown(MoonError):
+ description = _("The slave is unknown.")
+ code = 400
+ title = 'Slave Unknown'
+ logger = "Error"
+
+
+class SlaveExisting(MoonError):
+ description = _("The slave already exists.")
+ code = 409
+ title = 'Slave Error'
+ logger = "Error"
+
+
+class PdpUnknown(MoonError):
+ description = _("The pdp is unknown.")
+ code = 400
+ title = 'Pdp Unknown'
+ logger = "Error"
+
+
+class PdpExisting(MoonError):
+ description = _("The pdp already exists.")
+ code = 409
+ title = 'Pdp Error'
+ logger = "Error"
+
+
+class PdpContentError(MoonError):
+ description = _("Invalid content of pdp.")
+ code = 400
+ title = 'Pdp Error'
+ logger = "Error"
+
+
+class PdpInUse(MoonError):
+ description = _("The pdp is inuse.")
+ code = 400
+ title = 'Pdp Inuse'
+ logger = "Error"
+
+
+class PdpKeystoneMappingConflict(MoonError):
+ description = _("A pdp is already mapped to that Keystone project.")
+ code = 409
+ title = 'Pdp Mapping Error'
+ logger = "Error"
+
+
+class PolicyUnknown(MoonError):
+ description = _("The policy is unknown.")
+ code = 400
+ title = 'Policy Unknown'
+ logger = "Error"
+
+
+class PolicyContentError(MoonError):
+ description = _("The policy content is invalid.")
+ code = 400
+ title = 'Policy Content Error'
+ logger = "Error"
+
+
+class PolicyExisting(MoonError):
+ description = _("The policy already exists.")
+ code = 409
+ title = 'Policy Already Exists'
+ logger = "Error"
+
+
+class PolicyUpdateError(MoonError):
+ description = _("The policy data is used.")
+ code = 400
+ title = 'Policy update error'
+ logger = "Error"
+
+
+class DeleteData(MoonError):
+ description = _("Cannot delete data with assignment")
+ code = 400
+ title = 'Data Error'
+ logger = "Error"
+
+
+class DeleteCategoryWithData(MoonError):
+ description = _("Cannot delete category with data")
+ code = 400
+ title = 'Category With Data Error'
+ logger = "Error"
+
+
+class DeleteCategoryWithMetaRule(MoonError):
+ description = _("Cannot delete category with meta rule")
+ code = 400
+ title = 'Category With MetaRule Error'
+ logger = "Error"
+
+
+class DeleteCategoryWithAssignment(MoonError):
+ description = _("Cannot delete category with assignment ")
+ code = 400
+ title = 'Category With Assignment Error'
+ logger = "Error"
+
+
+class DeleteModelWithPolicy(MoonError):
+ description = _("Cannot delete model with policy")
+ code = 400
+ title = 'Model With Policy Error'
+ logger = "Error"
+
+
+class DeletePolicyWithPdp(MoonError):
+ description = _("Cannot delete policy with pdp")
+ code = 400
+ title = 'Policy With PDP Error'
+ logger = "Error"
+
+
+class DeletePolicyWithPerimeter(MoonError):
+ description = _("Cannot delete policy with perimeter")
+ code = 400
+ title = 'Policy With Perimeter Error'
+ logger = "Error"
+
+
+class DeletePolicyWithData(MoonError):
+ description = _("Cannot delete policy with data")
+ code = 400
+ title = 'Policy With Data Error'
+ logger = "Error"
+
+
+class DeletePolicyWithRules(MoonError):
+ description = _("Cannot delete policy with rules")
+ code = 400
+ title = 'Policy With Rule Error'
+ logger = "Error"
+
+
+class DeleteMetaRuleWithModel(MoonError):
+ description = _("Cannot delete meta rule with model")
+ code = 400
+ title = 'Meta rule With Model Error'
+ logger = "Error"
+
+
+class DeleteMetaRuleWithRule(MoonError):
+ description = _("Cannot delete meta rule with rule")
+ code = 400
+ title = 'Meta rule With Model Error'
+ logger = "Error"
+
+
+class DataContentError(MoonError):
+ description = _("The data Content Error.")
+ code = 400
+ title = 'Data Content Error'
+ logger = "Error"
+
+
+class DataUnknown(MoonError):
+ description = _("The data unknown.")
+ code = 400
+ title = 'Data Unknown'
+ logger = "Error"
+
+
+class ValidationContentError(MoonError):
+ description = _("The Content validation incorrect.")
+ code = 400
+ title = 'Invalid Content'
+ logger = "Error"
+
+ def __init__(self, message=""):
+ self.message = message
+ super().__init__(message)
+
+ def __str__(self):
+ return self.message
+
+
+class ValidationKeyError(MoonError):
+ description = _("The Key validation incorrect.")
+ code = 400
+ title = 'Invalid Key'
+ logger = "Error"
+
+ def __init__(self, message=""):
+ self.message = message
+ super().__init__(message)
+
+ def __str__(self):
+ return self.message
+
+
+class ForbiddenOverride(MoonError):
+ description = _("Forbidden override flag.")
+ code = 500
+ title = 'Forbidden override.'
+ logger = "Error"
+
+
+class InvalidJson(MoonError):
+ description = _("Invalid Json")
+ code = 400
+ title = 'Invalid Json.'
+ logger = "Error"
+
+
+class UnknownName(MoonError):
+ description = _("Name is Unknown")
+ code = 400
+ title = 'Unknown Name.'
+ logger = "Error"
+
+
+class UnknownId(MoonError):
+ description = _("ID is Unknown")
+ code = 400
+ title = 'Unknown ID.'
+ logger = "Error"
+
+
+class MissingIdOrName(MoonError):
+ description = _("Name or ID is missing")
+ code = 400
+ title = 'Missing ID or Name.'
+ logger = "Error"
+
+
+class UnknownField(MoonError):
+ description = _("Field is Unknown")
+ code = 400
+ title = 'Unknown Field.'
+ logger = "Error"
+
+
+class DecryptError(MoonError):
+ description = _("Cannot decrypt API key")
+ code = 401
+ title = 'API Key Error.'
+ logger = "Error"
+
+
+class EncryptError(MoonError):
+ description = _("Cannot encrypt API key")
+ code = 401
+ title = 'API Key Error.'
+ logger = "Error"
+
+
+class AttributeUnknownError(MoonError):
+ description = _("Cannot find attribute")
+ code = 401
+ title = 'Attribute Error.'
+ logger = "Error"
+
+
+class AttributeValueUnknownError(MoonError):
+ description = _("Cannot find value for this attribute")
+ code = 401
+ title = 'Attribute Value Error.'
+ logger = "Error"
+
diff --git a/moon_utilities/moon_utilities/generate_opst_policy.py b/moon_utilities/moon_utilities/generate_opst_policy.py
new file mode 100644
index 00000000..4e357911
--- /dev/null
+++ b/moon_utilities/moon_utilities/generate_opst_policy.py
@@ -0,0 +1,503 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+"""
+Generate a policy template from a list of OpenStack policy.json file
+"""
+import argparse
+import json
+import logging
+import os
+import re
+import glob
+import copy
+
+
+FILES = [
+ "cinder.policy.json",
+ "glance.policy.json",
+ "keystone.policy.json",
+ "neutron.policy.json",
+ "nova.policy.json",
+]
+policy_in = {
+ "pdps": [
+ {
+ "name": "external_pdp",
+ "keystone_project_id": "",
+ "description": "",
+ "policies": [{"name": "OpenStack RBAC Policy"}]
+ }
+ ],
+
+ "policies": [
+ {
+ "name": "OpenStack RBAC Policy",
+ "genre": "authz",
+ "description": "A RBAC policy similar of what you can find through policy.json files",
+ "model": {"name": "OPST_RBAC"}, "mandatory": True, "override": True
+ }
+ ],
+
+ "models": [
+ {
+ "name": "OPST_RBAC",
+ "description": "",
+ "meta_rules": [{"name": "rbac"}],
+ "override": True
+ }
+ ],
+
+ "subjects": [
+ {"name": "admin", "description": "", "extra": {},
+ "policies": [{"name": "OpenStack RBAC Policy"}]}
+ ],
+
+ "subject_categories": [{"name": "role", "description": "a role in OpenStack"}],
+
+ "subject_data": [
+ {"name": "admin", "description": "the admin role",
+ "policies": [], "category": {"name": "role"}},
+ {"name": "member", "description": "the member role",
+ "policies": [], "category": {"name": "role"}}
+ ],
+
+ "subject_assignments": [
+ {"subject": {"name": "admin"}, "category": {"name": "role"},
+ "assignments": [{"name": "admin"}, {"name": "member"}]},
+ ],
+
+ "objects": [
+ {"name": "all", "description": "describe all element of a project", "extra": {},
+ "policies": [{"name": "OpenStack RBAC Policy"}]},
+ ],
+
+ "object_categories": [{"name": "id", "description": "the UID of each virtual machine"}],
+
+ "object_data": [
+ {
+ "name": "all",
+ "description": "represents all virtual machines in this project",
+ "policies": [],
+ "category": {"name": "id"}},
+ ],
+
+ "object_assignments": [
+ {"object": {"name": "all"}, "category": {"name": "id"}, "assignments": [{"name": "all"}]}
+ ],
+
+ "actions": [],
+
+ "action_categories": [{"name": "action_id", "description": ""}],
+
+ "action_data": [],
+
+ "action_assignments": [],
+
+ "meta_rules": [
+ {
+ "name": "rbac", "description": "",
+ "subject_categories": [{"name": "role"}],
+ "object_categories": [{"name": "id"}],
+ "action_categories": [{"name": "action_id"}]
+ }
+ ],
+
+ "rules": [],
+
+}
+
+policy_out = copy.deepcopy(policy_in)
+
+AUTO_EXCLUDE_KEYS = """
+context_is_admin
+admin_or_owner
+admin_api
+default
+owner
+context_is_advsvc
+admin_or_network_owner
+admin_owner_or_network_owner
+admin_only
+regular_user
+admin_or_data_plane_int
+shared
+shared_subnetpools
+shared_address_scopes
+external
+admin_required
+cloud_admin
+service_role
+service_or_admin
+admin_and_matching_domain_id
+service_admin_or_owner
+"""
+
+logger = logging.getLogger(__name__)
+__rules = []
+
+
+def init():
+ """
+ Initialize the application
+ :return: argument given in the command line
+ """
+ global policy_in, policy_out
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--verbose", '-v', action='store_true', help='verbose mode')
+ parser.add_argument("--debug", '-d', action='store_true', help='debug mode')
+ parser.add_argument("--dir",
+ help='directory containing policy files, defaults to ./policy.json.d',
+ default="./policy.json.d")
+ parser.add_argument("--template", "-t",
+ help='use a specific template file, defaults to internal template',
+ default="")
+ parser.add_argument("--indent", '-i', help='indent the output (default:None)', type=int,
+ default=None)
+ parser.add_argument("--output", '-o', help='output name, defaults to opst_default_policy.json',
+ type=str, default="opst_default_policy.json")
+ parser.add_argument("--exclude", "-x",
+ help="Exclude some attributes in output "
+ "(example: \"actions,*_categories\")",
+ default="")
+ args = parser.parse_args()
+ logging_format = "%(levelname)s: %(message)s"
+ if args.verbose:
+ logging.basicConfig(level=logging.INFO, format=logging_format)
+ if args.debug:
+ logging.basicConfig(level=logging.DEBUG, format=logging_format)
+ else:
+ logging.basicConfig(format=logging_format)
+ if args.template:
+ try:
+ policy_in = json.loads(open(args.template).read())
+ policy_out = copy.deepcopy(policy_in)
+ logger.info("Using template {}".format(args.template))
+ policy_out.pop('rules')
+ policy_out['rules'] = []
+ for cpt, item in enumerate(policy_in['rules']):
+ if "templates" not in item:
+ policy_out['rules'].append(item)
+ policy_out.pop('action_assignments')
+ policy_out['action_assignments'] = []
+ for cpt, item in enumerate(policy_in['action_assignments']):
+ if "templates" not in item:
+ policy_out['action_assignments'].append(item)
+
+ except json.decoder.JSONDecodeError as e:
+ logger.error("Cannot decode template file {}".format(args.template))
+ if args.debug:
+ logger.exception(e)
+
+ return args
+
+
+def get_json(filename):
+ """
+ retrieve rule from a JSON file
+ :param filename: url of the file
+ :return: list of rules in this file
+ """
+ _json_file = json.loads(open(filename).read())
+ keys = list(_json_file.keys())
+ values = list(_json_file.values())
+ for value in values:
+ if value in keys:
+ keys.remove(value)
+ return keys
+
+
+def get_flat(filename):
+ """
+ retrieve rule from a flat text file
+ :param filename: url of the file
+ :return: list of rules in this file
+ """
+ results = []
+ for line in open(filename):
+ key = line.split('"')[1]
+ results.append(key)
+ return results
+
+
+def get_opst_rules(args):
+ """
+ Get all rules in each policy.json
+ :param args: arguments given in the command line
+ :return: all rules in a dict
+ """
+ results = {}
+ for filename in glob.glob(os.path.join(args.dir, "**/*.json"), recursive=True):
+ logger.info("Reading {}".format(filename))
+ component = filename.replace("policy.json", "").strip("/")
+ component = os.path.basename(component).split(".")[0]
+ try:
+ keys = get_json(filename)
+ except json.decoder.JSONDecodeError:
+ keys = get_flat(filename)
+ for _key in AUTO_EXCLUDE_KEYS.splitlines():
+ if _key in keys:
+ keys.remove(_key)
+ results[component] = keys
+ logger.info("Adding {} definitions in {}".format(len(keys), component))
+ return results
+
+
+def get_policy_name():
+ """
+ Retrieve the policy name from the policy dict
+ Useful if the policy data comes from a template
+ """
+ for _policy in policy_in.get("policies"):
+ return _policy.get("name")
+
+
+def get_meta_rule_name():
+ """
+ Retrieve the policy name from the policy dict
+ Useful if the policy data comes from a template
+ """
+ for _policy in policy_in.get("meta_rules"):
+ return _policy.get("name")
+
+
+def get_default_data(data, category):
+ """
+ Find the default value from a list of data, return the first one if no default found
+ :param data: the data to search in
+ :param category: the category of the data
+ :return: one name contained in data
+ """
+ for _data in data:
+ if _data.get("category").get("name") == category:
+ if _data.get("extra", {}).get("action") == "default":
+ return _data.get("name")
+ # default: return the first one
+ for _data in data:
+ if _data.get("category").get("name") == category:
+ return _data.get("name")
+
+
+def get_meta_rule(meta_rule_name=None):
+ for meta_rule in policy_in['meta_rules']:
+ if meta_rule_name == meta_rule.get('name'):
+ return meta_rule
+ else:
+ return policy_in['meta_rules'][0]
+
+
+def build_actions(opst_rule, component):
+ _output = {
+ "name": opst_rule,
+ "description": "{} action for {}".format(opst_rule, component),
+ "extra": {"component": component},
+ "policies": []
+ }
+ policy_out['actions'].append(_output)
+
+
+def build_action_data(opst_rule, component):
+ _output = {
+ "name": opst_rule,
+ "description": "{} action for {}".format(opst_rule, component),
+ "policies": [],
+ "category": {"name": "action_id"}
+ }
+ policy_out['action_data'].append(_output)
+
+
+def build_action_assignments_with_templates(opst_rule):
+ for assignment in policy_in['action_assignments']:
+ for template in assignment.get('templates', []):
+ name = template.get('action', {}).get('name')
+ new = None
+ if "filter:" in name:
+ if "*" == name.split(":")[-1].strip():
+ new = copy.deepcopy(template)
+ new['action']['name'] = opst_rule
+ else:
+ for _str in name.split(":")[-1].strip().split(","):
+ if _str.strip() in opst_rule:
+ new = copy.deepcopy(template)
+ new['action']['name'] = opst_rule
+ if new:
+ policy_out['action_assignments'].append(new)
+
+
+def build_action_assignments(opst_rule):
+ _output = {
+ "action": {"name": opst_rule},
+ "category": {"name": "action_id"},
+ "assignments": [{"name": opst_rule}, ]}
+ policy_out['action_assignments'].append(_output)
+ build_action_assignments_with_templates(opst_rule)
+
+
+def add_rule(rule):
+ # TODO: check rule before adding it
+ if rule in __rules:
+ # note: don't add the rule if already added
+ return
+ __rules.append(rule)
+ _raw_rule = {
+ "subject_data": [],
+ "object_data": [],
+ "action_data": []
+ }
+ cpt = 0
+ for _ in get_meta_rule().get("subject_categories"):
+ _raw_rule["subject_data"].append({"name": rule[cpt]})
+ cpt += 1
+ for _ in get_meta_rule().get("object_categories"):
+ _raw_rule["object_data"].append({"name": rule[cpt]})
+ cpt += 1
+ for _ in get_meta_rule().get("action_categories"):
+ _raw_rule["action_data"].append({"name": rule[cpt]})
+ cpt += 1
+
+ _output = {
+ "meta_rule": {"name": get_meta_rule_name()},
+ "rule": _raw_rule,
+ "policy": {"name": get_policy_name()},
+ "instructions": [{"decision": "grant"}],
+ "enabled": True
+ }
+ policy_out['rules'].append(_output)
+
+
+def check_filter_on_template(data_list, opst_rule):
+ for cpt, _data in enumerate(data_list):
+ if "filter:" in _data:
+ filter_str = _data.partition(":")[-1]
+ if filter_str == "*":
+ data_list[cpt] = opst_rule
+ add_rule(data_list)
+ else:
+ for _str in filter_str.split(","):
+ if _str.strip() in opst_rule:
+ data_list[cpt] = opst_rule
+ add_rule(data_list)
+ break
+
+
+def build_rules_with_templates(rule, opst_rule):
+ meta_rule = get_meta_rule()
+ for template in rule.get("templates", []):
+ data_list = []
+ for cat in meta_rule.get("subject_categories"):
+ for item in template.get("subject"):
+ if item.get("category") == cat.get('name'):
+ data_list.append(item.get("name"))
+ break
+ for cat in meta_rule.get("object_categories"):
+ for item in template.get("object"):
+ if item.get("category") == cat.get('name'):
+ data_list.append(item.get("name"))
+ break
+ for cat in meta_rule.get("action_categories"):
+ for item in template.get("action"):
+ if item.get("category") == cat.get('name'):
+ data_list.append(item.get("name"))
+ break
+ check_filter_on_template(data_list, opst_rule)
+
+
+def build_rules(opst_rule):
+ rules = policy_in.get("rules")
+ for rule in rules:
+ if isinstance(rule, dict):
+ build_rules_with_templates(rule, opst_rule)
+ else:
+ add_rule(rule)
+
+
+def build_dict(results):
+ """
+ Build the dictionary given the actions found in the policy.json files
+ :param results: list of rule for each component
+ :return: nothing
+ """
+ policy_out["rules"] = []
+ for component in results:
+ for opst_rule in results[component]:
+ build_actions(opst_rule, component)
+ build_action_data(opst_rule, component)
+ build_action_assignments(opst_rule)
+ build_rules(opst_rule)
+
+
+def exclude_attrs(args):
+ """
+ Exclude attributes from the output JSON file
+ :param args: arguments given in the command line
+ :return: nothing
+ """
+ attrs_to_exclude = []
+ if not args.exclude:
+ return
+ for excl_item in args.exclude.split(","):
+ excl_item = excl_item.replace("*", ".*").strip()
+ logger.debug("excl_item=%s", excl_item)
+ for attr in policy_in:
+ logger.debug("attr=%s", attr)
+ if re.match(excl_item, attr):
+ attrs_to_exclude.append(attr)
+ for attr in attrs_to_exclude:
+ logger.info("Deleting %s", attr)
+ policy_out.pop(attr)
+
+
+def write_tests(rules):
+ if "admin" not in map(lambda x: x.get("name"), policy_in.get("subjects")):
+ logger.warning("Don't write tests in output because, there is no 'admin' user")
+ return
+ if "all" not in map(lambda x: x.get("name"), policy_in.get("objects")):
+ logger.warning("Don't write tests in output because, there is no 'all' object")
+ return
+ if "checks" not in policy_in:
+ policy_out["checks"] = {"granted": [], "denied": []}
+ if "granted" not in policy_in["checks"]:
+ policy_out["checks"]["granted"] = []
+ if "denied" not in policy_in["checks"]:
+ policy_out["checks"]["denied"] = []
+ for component in rules:
+ for rule in rules.get(component):
+ policy_out["checks"]["granted"].append(("admin", "all", rule))
+ if "test_user" in map(lambda x: x.get("name"), policy_in.get("subjects")):
+ for component in rules:
+ for rule in rules.get(component):
+ policy_out["checks"]["denied"].append(("test_user", "all", rule))
+
+
+def write_dict(args):
+ """
+ Write the dictionary in the output filename given in command line
+ :param args: arguments given in the command line
+ :return: nothing
+ """
+ json.dump(policy_out, open(args.output, "w"), indent=args.indent)
+
+
+def main():
+ """
+ Main end point
+ :return: nothing
+ """
+ args = init()
+ rules = get_opst_rules(args)
+ build_dict(rules)
+ write_tests(rules)
+ exclude_attrs(args)
+ write_dict(args)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/moon_utilities/moon_utilities/install.py b/moon_utilities/moon_utilities/install.py
new file mode 100644
index 00000000..236dfe06
--- /dev/null
+++ b/moon_utilities/moon_utilities/install.py
@@ -0,0 +1,155 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+"""
+Install the Moon platform
+"""
+
+import argparse
+import logging
+import os
+import subprocess # nosec
+import sys
+import getpass
+
+try:
+ import pytest
+except ModuleNotFoundError:
+ subprocess.call([sys.executable, "-m", "pip", "install", "pytest", "--upgrade"]) # nosec
+ subprocess.call([sys.executable, "-m", "pip", "install", "pytest-cov", "--upgrade"]) # nosec
+ subprocess.call([sys.executable, "-m", "pip", "install", "cliff", "--upgrade"]) # nosec
+ subprocess.call([sys.executable, "-m", "pip", "install", "requests_mock", "--upgrade"]) # nosec
+ import pytest
+try:
+ from git import Repo
+except ModuleNotFoundError:
+ subprocess.call([sys.executable, "-m", "pip", "install", "GitPython", "--upgrade"]) # nosec
+ from git import Repo
+
+COMPONENTS = {
+ "moon_utilities": [],
+ "moon_cache": [],
+ "moon_manager": [],
+ "moon_engine": [],
+}
+
+logger = logging.getLogger(__name__)
+
+
+def init():
+ """
+ Initialize the application
+ :return: argument given in the command line
+ """
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--verbose", '-v', action='store_true', help='verbose mode')
+ parser.add_argument("--debug", '-d', action='store_true', help='debug mode')
+ parser.add_argument("--pre", '-p', action='store_true', help='install packages in dev mode')
+ parser.add_argument("--git", '-g', action='store_true', help='install packages from source tree')
+ parser.add_argument("--tests", '-t', action='store_true', help='run tests on each package')
+ parser.add_argument("--username", '-u', help='set the username for the Gitlab server')
+ parser.add_argument("--password", '-pa', help='set the password for the Gitlab server')
+ parser.add_argument("--password-file", '-pf',
+ help='set the filename of the file containing all passwords for the '
+ 'Gitlab server')
+ parser.add_argument("--do-not-clean", '-dnc', action='store_true',
+ help='do not clean the dev environment')
+ args = parser.parse_args()
+ logging_format = "%(levelname)s: %(message)s"
+ if args.verbose:
+ logging.basicConfig(level=logging.INFO, format=logging_format)
+ if args.debug:
+ logging.basicConfig(level=logging.DEBUG, format=logging_format)
+ else:
+ logging.basicConfig(format=logging_format)
+
+ if args.password_file:
+ logger.info("Using {} as password file".format(args.password_file))
+ for line in open(args.password_file):
+ try:
+ comp, user, password = line.split(":")
+ if comp in COMPONENTS:
+ COMPONENTS[comp] = [user, password.strip()]
+ else:
+ logger.error("Unknown component {} in password file".format(comp))
+ except ValueError:
+ # empty line
+ pass
+ return args
+
+
+def install_from_pkg(package, args):
+ logger.info(f"Installing from pkg {package}")
+ command = [sys.executable, "-m", "pip", "install", package, "--upgrade"]
+ if args.pre:
+ command.append("--pre")
+ subprocess.call(command) # nosec
+
+
+def install_from_src(package, args):
+ logger.info(f"Installing {package} from source...")
+ if os.path.isdir(os.path.join("src", package)):
+ repo = Repo("src/" + package)
+ repo.remote().pull()
+ else:
+ if args.password_file:
+ Repo.clone_from("https://{}:{}@gitlab.forge.orange-labs.fr/moon/{}.git".format(
+ COMPONENTS[package][0], COMPONENTS[package][1], package),
+ to_path=os.path.join(os.getcwd(), "src", package))
+ elif args.username:
+ logger.info(f"installing with {args.username}")
+ Repo.clone_from("https://{}:{}@gitlab.forge.orange-labs.fr/moon/{}.git".format(
+ args.username, args.password, package),
+ to_path=os.path.join(os.getcwd(), "src", package))
+ else:
+ Repo.clone_from("https://gitlab.forge.orange-labs.fr/moon/{}.git".format(package),
+ to_path=os.path.join(os.getcwd(), "src", package))
+
+ # logger.info(f"Installing from source {package}")
+ cur_dir = os.getcwd()
+ os.chdir(os.path.join("src", package))
+ command = [sys.executable, "-m", "pip", "install", "-r", "requirements.txt"]
+ subprocess.call(command) # nosec
+ command = [sys.executable, "-m", "pip", "install", "."]
+ subprocess.call(command) # nosec
+
+ if args.tests:
+ pytest.main(["tests/unit_python"])
+
+ os.chdir(cur_dir)
+
+
+def clean_git():
+ subprocess.call(["rm", "-rf", "src"]) # nosec
+
+
+def main():
+ args = init()
+ if not args.git:
+ for component in COMPONENTS:
+ install_from_pkg(component, args)
+ else:
+ try:
+ try:
+ os.mkdir("src")
+ except FileExistsError:
+ pass
+ if args.username and not args.password:
+ args.password = getpass.getpass(f"Give the password for {args.username} Gitlab")
+ for component in COMPONENTS:
+ install_from_src(component, args)
+ finally:
+ if not args.do_not_clean:
+ clean_git()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/moon_utilities/moon_utilities/invalided_functions.py b/moon_utilities/moon_utilities/invalided_functions.py
new file mode 100644
index 00000000..1c24d3f4
--- /dev/null
+++ b/moon_utilities/moon_utilities/invalided_functions.py
@@ -0,0 +1,440 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import logging
+import requests
+
+logger = logging.getLogger("moon.utilities." + __name__)
+
+
+def invalidate_assignment_in_slaves(slaves, policy_id, perimeter_id, category_id, data_id, type):
+ """
+ Send a request to one or more slaves to invalidate specific assignments
+ :param slaves: list of slaves
+ :param policy_id: the ID of the concerned policy
+ :param perimeter_id: the ID of the concerned perimeter
+ :param category_id: the ID of the concerned category
+ :param data_id: the ID of the concerned data
+ :return: None
+ """
+
+ hostname, port = "", ""
+ uri = "update/assignment"
+ result = []
+ for key, value in slaves.get('slaves', {}).items():
+ if value.get("extra", {}).get("status") != "up":
+ continue
+ try:
+ hostname = value.get("extra", {}).get("server_ip")
+ port = value.get("extra", {}).get("port")
+ if policy_id and perimeter_id and category_id and data_id:
+ update = requests.delete("http://{}:{}/{}/{}/{}/{}/{}/{}".format(
+ hostname, port, uri, policy_id, type, perimeter_id, category_id, data_id),
+ timeout=1
+ )
+ elif policy_id and perimeter_id and category_id:
+ update = requests.delete("http://{}:{}/{}/{}/{}/{}/{}".format(
+ hostname, port, uri, policy_id, type, perimeter_id, category_id),
+ timeout=1
+ )
+ elif policy_id and perimeter_id:
+ update = requests.delete("http://{}:{}/{}/{}/{}/{}".format(
+ hostname, port, uri, policy_id, type, perimeter_id),
+ timeout=1
+ )
+ elif policy_id:
+ update = requests.delete("http://{}:{}/{}/{}/{}".format(
+ hostname, port, uri, policy_id, type),
+ timeout=1
+ )
+
+ logger.debug("result {} {}:{} = {}".format(
+ update.status_code,
+ hostname,
+ port,
+ update.text))
+ result.append(value.get("name"))
+ except requests.exceptions.ConnectionError:
+ logger.warning(
+ "Cannot reach {}:{}".format(hostname, port))
+ except requests.models.InvalidURL:
+ logger.warning(
+ "Invalid URL {}:{}".format(hostname, port))
+ return result
+
+
+def invalidate_data_in_slaves(slaves, policy_id, category_id, data_id, type):
+ """
+ Send a request to one or more slaves to invalidate specific data
+ :param slaves: list of slaves
+ :param policy_id: the ID of the concerned policy
+ :param category_id: the ID of the concerned category
+ :param data_id: the ID of the concerned data
+ :return: None
+ """
+
+ hostname, port = "", ""
+ uri = "update/data"
+ result = []
+ for key, value in slaves.get('slaves', {}).items():
+ if value.get("extra", {}).get("status") != "up":
+ continue
+ try:
+ hostname = value.get("extra", {}).get("server_ip")
+ port = value.get("extra", {}).get("port")
+ update = requests.delete("http://{}:{}/{}/{}/{}".format(
+ hostname, port, uri, data_id, type),
+ timeout=1
+ )
+ logger.debug("result {} {}:{} = {}".format(
+ update.status_code,
+ hostname,
+ port,
+ update.text))
+ result.append(value.get("name"))
+ except requests.exceptions.ConnectionError:
+ logger.warning(
+ "Cannot reach {}:{}".format(hostname, port))
+ except requests.models.InvalidURL:
+ logger.warning(
+ "Invalid URL {}:{}".format(hostname, port))
+ return result
+
+
+def invalidate_perimeter_in_slaves(slaves, policy_id, perimeter_id, type, data=None,
+ is_delete=True):
+ """
+ Send a request to one or more slaves to invalidate specific perimeter
+ :param slaves: list of slaves
+ :param policy_id: the ID of the concerned policy
+ :param perimeter_id: the ID of the concerned perimeter
+ :return: None
+ """
+
+ hostname, port = "", ""
+ uri = "update/perimeter"
+ result = []
+ for key, value in slaves.get('slaves', {}).items():
+ if value.get("extra", {}).get("status") != "up":
+ continue
+ try:
+ hostname = value.get("extra", {}).get("server_ip")
+ port = value.get("extra", {}).get("port")
+ if is_delete:
+ update = requests.delete("http://{}:{}/{}/{}/{}/{}".format(
+ hostname, port, uri, perimeter_id, policy_id, type),
+ timeout=1
+ )
+ else:
+ update = requests.put("http://{}:{}/{}/{}/{}/{}".format(
+ hostname, port, uri, perimeter_id, policy_id, type),
+ data=data,
+ timeout=1
+ )
+ logger.debug("result {} {}:{} = {}".format(
+ update.status_code,
+ hostname,
+ port,
+ update.text))
+ result.append(value.get("name"))
+ except requests.exceptions.ConnectionError:
+ logger.warning(
+ "Cannot reach {}:{}".format(hostname, port))
+ except requests.models.InvalidURL:
+ logger.warning(
+ "Invalid URL {}:{}".format(hostname, port))
+ return result
+
+
+def invalidate_pdp_in_slaves(slaves, pdp_id, is_delete=True, data=None):
+ """
+ Send a request to one or more slaves to invalidate specific PDPs
+ :param slaves: list of slaves
+ :param pdp_id: the ID of the concerned PDP
+ :return: None
+ """
+
+ hostname, port = "", ""
+ uri = "update/pdp"
+ result = []
+ for key, value in slaves.get('slaves', {}).items():
+ if value.get("extra", {}).get("status") != "up":
+ continue
+ try:
+ hostname = value.get("extra", {}).get("server_ip")
+ port = value.get("extra", {}).get("port")
+ if is_delete:
+ update = requests.delete("http://{}:{}/{}/{}".format(
+ hostname, port, uri, pdp_id),
+ timeout=1
+ )
+ else:
+ update = requests.put("http://{}:{}/{}/{}".format(
+ hostname, port, uri, pdp_id),
+ data=data,
+ timeout=1
+ )
+ logger.debug("result {} {}:{} = {}".format(
+ update.status_code,
+ hostname,
+ port,
+ update.text))
+ result.append(value.get("name"))
+ except requests.exceptions.ConnectionError:
+ logger.warning(
+ "Cannot reach {}:{}".format(hostname, port))
+ except requests.models.InvalidURL:
+ logger.warning(
+ "Invalid URL {}:{}".format(hostname, port))
+ return result
+
+
+def invalidate_policy_in_slaves(slaves, policy_id, is_delete=True, data=None):
+ """
+ Send a request to one or more slaves to invalidate specific policies
+ :param slaves: list of slaves
+ :param policy_id: the ID of the concerned policy
+ :return: None
+ """
+
+ hostname, port = "", ""
+ uri = "update/policy"
+ result = []
+ for key, value in slaves.get('slaves', {}).items():
+ if value.get("extra", {}).get("status") != "up":
+ continue
+ try:
+ hostname = value.get("extra", {}).get("server_ip")
+ port = value.get("extra", {}).get("port")
+ if is_delete:
+ update = requests.delete("http://{}:{}/{}/{}".format(
+ hostname, port, uri, policy_id),
+ timeout=1
+ )
+ else:
+ update = requests.put("http://{}:{}/{}/{}".format(
+ hostname, port, uri, policy_id),
+ data=data,
+ timeout=1
+ )
+
+ logger.debug("result {} {}:{} = {}".format(
+ update.status_code,
+ hostname,
+ port,
+ update.text))
+ result.append(value.get("name"))
+ except requests.exceptions.ConnectionError:
+ logger.warning(
+ "Cannot reach {}:{}".format(hostname, port))
+ except requests.models.InvalidURL:
+ logger.warning(
+ "Invalid URL {}:{}".format(hostname, port))
+ return result
+
+
+def invalidate_rules_in_slaves(slaves, policy_id, rule_id):
+ """
+ Send a request to one or more slaves to invalidate specific rules
+ :param slaves: list of slaves
+ :param policy_id: the ID of the concerned policy
+ :param rule_id: the ID of the concerned rule
+ :return: None
+ """
+
+ hostname, port = "", ""
+ uri = "update/rule"
+ result = []
+ for key, value in slaves.get('slaves', {}).items():
+ if value.get("extra", {}).get("status") != "up":
+ continue
+ try:
+ hostname = value.get("extra", {}).get("server_ip")
+ port = value.get("extra", {}).get("port")
+ update = requests.delete("http://{}:{}/{}/{}/{}".format(
+ hostname, port, uri, policy_id, rule_id),
+ timeout=1
+ )
+ logger.debug("result {} {}:{} = {}".format(
+ update.status_code,
+ hostname,
+ port,
+ update.text))
+ result.append(value.get("name"))
+ except requests.exceptions.ConnectionError:
+ logger.warning(
+ "Cannot reach {}:{}".format(hostname, port))
+ except requests.models.InvalidURL:
+ logger.warning(
+ "Invalid URL {}:{}".format(hostname, port))
+ return result
+
+
+def invalidate_model_in_slaves(slaves, model_id, is_delete=True, data=None):
+ """
+ Send a request to one or more slaves to invalidate specific models
+ :param slaves: list of slaves
+ :param model_id: the ID of the concerned model
+ :return: None
+ """
+
+ hostname, port = "", ""
+ uri = "update/model"
+ result = []
+ for key, value in slaves.get('slaves', {}).items():
+ if value.get("extra", {}).get("status") != "up":
+ continue
+ try:
+ hostname = value.get("extra", {}).get("server_ip")
+ port = value.get("extra", {}).get("port")
+ if is_delete:
+ update = requests.delete("http://{}:{}/{}/{}".format(
+ hostname, port, uri, model_id),
+ timeout=1
+ )
+ else:
+ update = requests.put("http://{}:{}/{}/{}".format(
+ hostname, port, uri, model_id),
+ data=data,
+ timeout=1
+ )
+ logger.debug("result {} {}:{} = {}".format(
+ update.status_code,
+ hostname,
+ port,
+ update.text))
+ result.append(value.get("name"))
+ except requests.exceptions.ConnectionError:
+ logger.warning(
+ "Cannot reach {}:{}".format(hostname, port))
+ except requests.models.InvalidURL:
+ logger.warning(
+ "Invalid URL {}:{}".format(hostname, port))
+ return result
+
+
+def invalidate_meta_data_in_slaves(slaves, category_id, type):
+ """
+ Send a request to one or more slaves to invalidate specific meta data
+ :param slaves: list of slaves
+ :param category_id: the ID of the concerned category
+ :return: None
+ """
+
+ hostname, port = "", ""
+ uri = "update/meta_data"
+ result = []
+ for key, value in slaves.get('slaves', {}).items():
+ if value.get("extra", {}).get("status") != "up":
+ continue
+ try:
+ hostname = value.get("extra", {}).get("server_ip")
+ port = value.get("extra", {}).get("port")
+ update = requests.delete("http://{}:{}/{}/{}/{}".format(
+ hostname, port, uri, category_id, type),
+ data={
+ "category_id": category_id
+ },
+ timeout=1
+ )
+ logger.debug("result {} {}:{} = {}".format(
+ update.status_code,
+ hostname,
+ port,
+ update.text))
+ result.append(value.get("name"))
+ except requests.exceptions.ConnectionError:
+ logger.warning(
+ "Cannot reach {}:{}".format(hostname, port))
+ except requests.models.InvalidURL:
+ logger.warning(
+ "Invalid URL {}:{}".format(hostname, port))
+ return result
+
+
+def invalidate_meta_rule_in_slaves(slaves, meta_rule_id, is_delete=True, data=None):
+ """
+ Send a request to one or more slaves to invalidate specific meta rules
+ :param slaves: list of slaves
+ :param meta_rule_id: the ID of the concerned policy
+ :return: None
+ """
+
+ hostname, port = "", ""
+ uri = "update/meta_rule"
+ result = []
+ for key, value in slaves.get('slaves', {}).items():
+ if value.get("extra", {}).get("status") != "up":
+ continue
+ try:
+ hostname = value.get("extra", {}).get("server_ip")
+ port = value.get("extra", {}).get("port")
+ if is_delete:
+ update = requests.delete("http://{}:{}/{}/{}".format(
+ hostname, port, uri, meta_rule_id),
+ timeout=1
+ )
+ else:
+ update = requests.put("http://{}:{}/{}/{}".format(
+ hostname, port, uri, meta_rule_id),
+ data=data,
+ timeout=1
+ )
+
+ logger.debug("result {} {}:{} = {}".format(
+ update.status_code,
+ hostname,
+ port,
+ update.text))
+ result.append(value.get("name"))
+ except requests.exceptions.ConnectionError:
+ logger.warning(
+ "Cannot reach {}:{}".format(hostname, port))
+ except requests.models.InvalidURL:
+ logger.warning(
+ "Invalid URL {}:{}".format(hostname, port))
+
+
+def invalidate_attributes_in_slaves(slaves, name, value=None):
+ """
+ Send a request to one or more slaves to invalidate specific data
+ :param slaves: list of slaves
+ :param name: the name of the attribute to invalidate
+ :param value: the value that has changed
+ :return: a list of updated slaves
+ """
+
+ hostname, port = "", ""
+ uri = "update/attributes"
+ result = []
+ for key, value in slaves.items():
+ try:
+ hostname = value.get("extra", {}).get("server_ip")
+ port = value.get("extra", {}).get("port")
+ update = requests.delete("http://{}:{}/{}/{}".format(
+ hostname, port, uri, name),
+ headers={"x-api-key": value.get("extra", {}).get("api_key")},
+ timeout=1
+ )
+ if update.status_code in (200, 202, 206, 208):
+ result.append(value.get("name"))
+ else:
+ logger.warning("Error when updating {} ({})".format(key, update.status_code))
+ except requests.exceptions.ConnectionError:
+ logger.warning(
+ "Cannot reach {}:{}".format(hostname, port))
+ except requests.models.InvalidURL:
+ logger.warning(
+ "Invalid URL {}:{}".format(hostname, port))
+ return result
+
+
diff --git a/moon_utilities/moon_utilities/json_utils.py b/moon_utilities/moon_utilities/json_utils.py
new file mode 100644
index 00000000..52ab5be4
--- /dev/null
+++ b/moon_utilities/moon_utilities/json_utils.py
@@ -0,0 +1,2076 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import html
+import json
+import logging
+
+from moon_utilities import exceptions
+
+LOGGER = logging.getLogger("moon.utilities." + __name__)
+
+
+class Manager:
+ __policy_manager = None
+ __model_manager = None
+ __pdp_manager = None
+
+ def get_meta_rules(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def set_subject_data(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def set_object_data(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def set_action_data(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_subject_data(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_object_data(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_action_data(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_rule(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_meta_rule(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_subject_assignment(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_object_assignment(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_action_assignment(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_subject_assignments(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_object_assignments(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_action_assignments(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_policies(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_subject_category(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_object_category(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_action_category(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_subject_categories(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_object_categories(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_action_categories(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_subject(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_object(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_action(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_subjects(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_objects(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_actions(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_policy(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def update_policy(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_models(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def update_model(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_model(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_pdp(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def update_pdp(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def add_pdp(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+ def get_rules(self, **kwargs):
+ raise NotImplementedError # pragma: no cover
+
+
+class CacheManager(Manager):
+ __policy_manager = None
+ __model_manager = None
+ __pdp_manager = None
+
+ def __init__(self, cache):
+ self.__cache = cache
+
+ def get_meta_rules(self, **kwargs):
+ return self.__cache.meta_rules
+
+ def set_subject_data(self, **kwargs):
+ value = kwargs.get("value", {})
+ value["category_id"] = kwargs.get("category_id", "")
+ value["policy_id"] = kwargs.get("policy_id", "")
+ return self.__cache.add_subject_data(
+ policy_id=kwargs.get("policy_id", ""),
+ category_id=kwargs.get("category_id", ""),
+ data=value
+ )
+
+ def set_object_data(self, **kwargs):
+ value = kwargs.get("value", {})
+ value["category_id"] = kwargs.get("category_id", "")
+ value["policy_id"] = kwargs.get("policy_id", "")
+ return self.__cache.add_object_data(
+ policy_id=kwargs.get("policy_id", ""),
+ category_id=kwargs.get("category_id", ""),
+ data=value
+ )
+
+ def set_action_data(self, **kwargs):
+ value = kwargs.get("value", {})
+ value["category_id"] = kwargs.get("category_id", "")
+ value["policy_id"] = kwargs.get("policy_id", "")
+ return self.__cache.add_action_data(
+ policy_id=kwargs.get("policy_id", ""),
+ category_id=kwargs.get("category_id", ""),
+ data=value
+ )
+
+ def get_subject_data(self, **kwargs):
+ if "policy_id" in kwargs:
+ results = []
+ for data in self.__cache.subject_data:
+ if data.get("policy_id") == kwargs["policy_id"]:
+ if data.get("category_id") == kwargs.get("category_id"):
+ results.append(data)
+ elif not kwargs.get("category_id"):
+ results.append(data)
+ if "data_id" in kwargs:
+ for res in results:
+ if kwargs.get("data_id") in res.get("data"):
+ return [res, ]
+ else:
+ return results
+ else:
+ return self.__cache.subject_data
+
+ def get_object_data(self, **kwargs):
+ if "policy_id" in kwargs:
+ results = []
+ for data in self.__cache.object_data:
+ if data.get("policy_id") == kwargs["policy_id"]:
+ if data.get("category_id") == kwargs.get("category_id"):
+ results.append(data)
+ elif not kwargs.get("category_id"):
+ results.append(data)
+ return results
+ else:
+ return self.__cache.object_data
+
+ def get_action_data(self, **kwargs):
+ if "policy_id" in kwargs:
+ results = []
+ for data in self.__cache.action_data:
+ if data.get("policy_id") == kwargs["policy_id"]:
+ if data.get("category_id") == kwargs.get("category_id"):
+ results.append(data)
+ elif not kwargs.get("category_id"):
+ results.append(data)
+ return results
+ else:
+ return self.__cache.action_data
+
+ def add_rule(self, **kwargs):
+ value = {
+ 'policy_id': kwargs.get('policy_id'),
+ 'meta_rule_id': kwargs.get('meta_rule_id'),
+ 'value': kwargs.get('value')
+ }
+ return self.__cache.add_rule(value)
+
+ def add_meta_rule(self, **kwargs):
+ return self.__cache.add_meta_rule(kwargs.get("value"))
+
+ def add_subject_assignment(self, **kwargs):
+ return self.__cache.add_subject_assignment(
+ policy_id=kwargs.get("policy_id"),
+ perimeter_id=kwargs.get("subject_id"),
+ category_id=kwargs.get("category_id"),
+ data_id=kwargs.get("data_id"),
+ )
+
+ def add_object_assignment(self, **kwargs):
+ return self.__cache.add_object_assignment(
+ policy_id=kwargs.get("policy_id"),
+ perimeter_id=kwargs.get("object_id"),
+ category_id=kwargs.get("category_id"),
+ data_id=kwargs.get("data_id"),
+ )
+
+ def add_action_assignment(self, **kwargs):
+ return self.__cache.add_action_assignment(
+ policy_id=kwargs.get("policy_id"),
+ perimeter_id=kwargs.get("action_id"),
+ category_id=kwargs.get("category_id"),
+ data_id=kwargs.get("data_id"),
+ )
+
+ def get_subject_assignments(self, **kwargs):
+ return self.__cache.subject_assignments
+
+ def get_object_assignments(self, **kwargs):
+ return self.__cache.object_assignments
+
+ def get_action_assignments(self, **kwargs):
+ return self.__cache.action_assignments
+
+ def get_policies(self, **kwargs):
+ return self.__cache.policies
+
+ def add_subject_category(self, **kwargs):
+ if kwargs.get("value", {}).get("name") != html.escape(kwargs.get("value", {}).get("name")):
+ raise exceptions.ValidationContentError('Forbidden characters in string')
+ if kwargs.get("category_id"):
+ if kwargs.get("category_id") in self.__cache.subject_categories:
+ raise exceptions.SubjectCategoryExisting
+ self.__cache.add_subject_category(kwargs.get("value"))
+
+ def add_object_category(self, **kwargs):
+ if kwargs.get("value", {}).get("name") != html.escape(kwargs.get("value", {}).get("name")):
+ raise exceptions.ValidationContentError('Forbidden characters in string')
+ if kwargs.get("category_id"):
+ if kwargs.get("category_id") in self.__cache.object_categories:
+ raise exceptions.ObjectCategoryExisting
+ self.__cache.add_object_category(kwargs.get("value"))
+
+ def add_action_category(self, **kwargs):
+ if kwargs.get("value", {}).get("name") != html.escape(kwargs.get("value", {}).get("name")):
+ raise exceptions.ValidationContentError('Forbidden characters in string')
+ if kwargs.get("category_id"):
+ if kwargs.get("category_id") in self.__cache.action_categories:
+ raise exceptions.ActionCategoryExisting
+ self.__cache.add_action_category(kwargs.get("value"))
+
+ def get_subject_categories(self, **kwargs):
+ return self.__cache.subject_categories
+
+ def get_object_categories(self, **kwargs):
+ return self.__cache.object_categories
+
+ def get_action_categories(self, **kwargs):
+ return self.__cache.action_categories
+
+ def add_subject(self, **kwargs):
+ if kwargs.get("value", {}).get("name") != html.escape(kwargs.get("value", {}).get("name")):
+ raise exceptions.ValidationContentError('Forbidden characters in string')
+ value = kwargs.get("value")
+ if kwargs.get("policy_id"):
+ value["policy_list"] = [kwargs.get("policy_id")]
+ if kwargs.get("perimeter_id"):
+ return self.__cache.update_subject(kwargs.get("perimeter_id"), value)
+ else:
+ return self.__cache.add_subject(value)
+
+ def add_object(self, **kwargs):
+ if kwargs.get("value", {}).get("name") != html.escape(kwargs.get("value", {}).get("name")):
+ raise exceptions.ValidationContentError('Forbidden characters in string')
+ value = kwargs.get("value")
+ if kwargs.get("policy_id"):
+ value["policy_list"] = [kwargs.get("policy_id")]
+ if kwargs.get("perimeter_id"):
+ return self.__cache.update_object(kwargs.get("perimeter_id"), value)
+ else:
+ return self.__cache.add_object(value)
+
+ def add_action(self, **kwargs):
+ if kwargs.get("value", {}).get("name") != html.escape(kwargs.get("value", {}).get("name")):
+ raise exceptions.ValidationContentError('Forbidden characters in string')
+ value = kwargs.get("value")
+ if kwargs.get("policy_id"):
+ value["policy_list"] = [kwargs.get("policy_id")]
+ if kwargs.get("perimeter_id"):
+ return self.__cache.update_action(kwargs.get("perimeter_id"), value)
+ else:
+ return self.__cache.add_action(value)
+
+ def get_subjects(self, **kwargs):
+ results = {}
+ subjects = self.__cache.subjects
+ for policy_id in subjects:
+ results.update(subjects[policy_id])
+ return results
+
+ def get_objects(self, **kwargs):
+ results = {}
+ objects = self.__cache.objects
+ for policy_id in objects:
+ results.update(objects[policy_id])
+ return results
+
+ def get_actions(self, **kwargs):
+ results = {}
+ actions = self.__cache.actions
+ for policy_id in actions:
+ results.update(actions[policy_id])
+ return results
+
+ def add_policy(self, **kwargs):
+ return self.__cache.add_policy(kwargs.get("value"))
+
+ def update_policy(self, **kwargs):
+ self.__cache.update_policy(kwargs.get("policy_id"), kwargs.get("value"))
+
+ def get_models(self, **kwargs):
+ return self.__cache.models
+
+ def update_model(self, **kwargs):
+ self.__cache.update_model(kwargs.get("model_id"), kwargs.get("value"))
+
+ def add_model(self, **kwargs):
+ if kwargs.get("value", {}).get("name") != html.escape(kwargs.get("value", {}).get("name")):
+ raise exceptions.ValidationContentError('Forbidden characters in string')
+ self.__cache.add_model(kwargs.get("value"))
+
+ def get_pdp(self, **kwargs):
+ return self.__cache.pdp
+
+ def update_pdp(self, **kwargs):
+ self.__cache.add_pdp(pdp_id=kwargs.get("pdp_id"), data=kwargs.get("value"))
+
+ def add_pdp(self, **kwargs):
+ self.__cache.add_pdp(data=kwargs.get("value"))
+
+ def get_rules(self, **kwargs):
+ return self.__cache.rules
+
+
+class DBManager(Manager):
+ __policy_manager = None
+ __model_manager = None
+ __pdp_manager = None
+
+ def __init__(self, driver): # pragma: no cover
+ self.__policy_manager = driver.PolicyManager
+ self.__model_manager = driver.ModelManager
+ self.__pdp_manager = driver.PDPManager
+
+ @property
+ def meta_rules(self):
+ return self.get_meta_rules()
+
+ def get_meta_rules(self, **kwargs):
+ return self.__model_manager.get_meta_rules(
+ moon_user_id=kwargs.get("moon_user_id"),
+ meta_rule_id=kwargs.get("meta_rule_id")
+ )
+
+ def set_subject_data(self, **kwargs):
+ value = self.__policy_manager.set_subject_data(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ category_id=kwargs.get("category_id"),
+ value=kwargs.get("value")
+ )
+ return value
+
+ def set_object_data(self, **kwargs):
+ return self.__policy_manager.add_object_data(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ category_id=kwargs.get("category_id"),
+ value=kwargs.get("value")
+ )
+
+ def set_action_data(self, **kwargs):
+ return self.__policy_manager.add_action_data(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ category_id=kwargs.get("category_id"),
+ value=kwargs.get("value")
+ )
+
+ @property
+ def subject_data(self):
+ _data = []
+ for policy in self.__policy_manager.get_policies(moon_user_id="admin"):
+ for category in self.__model_manager.get_subject_categories(moon_user_id="admin"):
+ _data += self.__policy_manager.get_subject_data(moon_user_id="admin",
+ policy_id=policy,
+ category_id=category)
+ return _data
+
+ def get_subject_data(self, **kwargs):
+ return self.__policy_manager.get_subject_data(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ data_id=kwargs.get("data_id"),
+ category_id=kwargs.get("category_id")
+ )
+
+ @property
+ def object_data(self):
+ _data = []
+ for policy in self.__policy_manager.get_policies(moon_user_id="admin"):
+ _data += self.__policy_manager.get_object_data(moon_user_id="admin",
+ policy_id=policy)
+ return _data
+
+ def get_object_data(self, **kwargs):
+ return self.__policy_manager.get_object_data(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ data_id=kwargs.get("data_id"),
+ category_id=kwargs.get("category_id")
+ )
+
+ @property
+ def action_data(self):
+ _data = []
+ for policy in self.__policy_manager.get_policies(moon_user_id="admin"):
+ _data += self.__policy_manager.get_action_data(moon_user_id="admin",
+ policy_id=policy)
+ return _data
+
+ def get_action_data(self, **kwargs):
+ return self.__policy_manager.get_action_data(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ data_id=kwargs.get("data_id"),
+ category_id=kwargs.get("category_id")
+ )
+
+ def add_rule(self, **kwargs):
+ return self.__policy_manager.add_rule(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ meta_rule_id=kwargs.get("meta_rule_id"),
+ value=kwargs.get("value")
+ )
+
+ def add_meta_rule(self, **kwargs):
+ return self.__model_manager.add_meta_rule(
+ moon_user_id=kwargs.get("moon_user_id"),
+ meta_rule_id=kwargs.get("meta_rule_id"),
+ value=kwargs.get("value")
+ )
+
+ @property
+ def subject_assignments(self):
+ _assignments = {}
+ for policy in self.__policy_manager.get_policies(moon_user_id="admin"):
+ _assignments.update(self.__policy_manager.get_subject_assignments(
+ moon_user_id="admin",
+ policy_id=policy))
+ return _assignments
+
+ def add_subject_assignment(self, **kwargs):
+ return self.__policy_manager.add_subject_assignment(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ subject_id=kwargs.get("subject_id"),
+ category_id=kwargs.get("category_id"),
+ data_id=kwargs.get("data_id")
+ )
+
+ @property
+ def object_assignments(self):
+ _assignments = {}
+ for policy in self.__policy_manager.get_policies(moon_user_id="admin"):
+ _assignments.update(self.__policy_manager.get_object_assignments(
+ moon_user_id="admin",
+ policy_id=policy))
+ return _assignments
+
+ def add_object_assignment(self, **kwargs):
+ return self.__policy_manager.add_object_assignment(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ object_id=kwargs.get("object_id"),
+ category_id=kwargs.get("category_id"),
+ data_id=kwargs.get("data_id")
+ )
+
+ @property
+ def action_assignments(self):
+ _assignments = {}
+ for policy in self.__policy_manager.get_policies(moon_user_id="admin"):
+ _assignments.update(self.__policy_manager.get_action_assignments(
+ moon_user_id="admin",
+ policy_id=policy))
+ return _assignments
+
+ def add_action_assignment(self, **kwargs):
+ return self.__policy_manager.add_action_assignment(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ action_id=kwargs.get("action_id"),
+ category_id=kwargs.get("category_id"),
+ data_id=kwargs.get("data_id")
+ )
+
+ def get_subject_assignments(self, **kwargs):
+ return self.__policy_manager.get_subject_assignments(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ category_id=kwargs.get("category_id")
+ )
+
+ def get_object_assignments(self, **kwargs):
+ return self.__policy_manager.get_object_assignments(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ category_id=kwargs.get("category_id")
+ )
+
+ def get_action_assignments(self, **kwargs):
+ return self.__policy_manager.get_action_assignments(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ category_id=kwargs.get("category_id")
+ )
+
+ def get_policies(self, **kwargs):
+ return self.__policy_manager.get_policies(moon_user_id=kwargs.get("moon_user_id"))
+
+ @property
+ def subject_categories(self):
+ return self.__model_manager.get_subject_categories(moon_user_id="admin")
+
+ def add_subject_category(self, **kwargs):
+ return self.__model_manager.add_subject_category(
+ moon_user_id=kwargs.get("moon_user_id"),
+ category_id=kwargs.get("category_id"),
+ value=kwargs.get("value")
+ )
+
+ @property
+ def object_categories(self):
+ return self.__model_manager.get_object_categories(moon_user_id="admin")
+
+ def add_object_category(self, **kwargs):
+ return self.__model_manager.add_object_category(
+ moon_user_id=kwargs.get("moon_user_id"),
+ category_id=kwargs.get("category_id"),
+ value=kwargs.get("value")
+ )
+
+ @property
+ def action_categories(self):
+ return self.__model_manager.get_action_categories(moon_user_id="admin")
+
+ def add_action_category(self, **kwargs):
+ return self.__model_manager.add_action_category(
+ moon_user_id=kwargs.get("moon_user_id"),
+ category_id=kwargs.get("category_id"),
+ value=kwargs.get("value")
+ )
+
+ def get_subject_categories(self, **kwargs):
+ return self.__model_manager.get_subject_categories(
+ moon_user_id=kwargs.get("moon_user_id")
+ )
+
+ def get_object_categories(self, **kwargs):
+ return self.__model_manager.get_object_categories(
+ moon_user_id=kwargs.get("moon_user_id")
+ )
+
+ def get_action_categories(self, **kwargs):
+ return self.__model_manager.get_action_categories(
+ moon_user_id=kwargs.get("moon_user_id")
+ )
+
+ @property
+ def subjects(self):
+ _perimeter = {}
+ for policy in self.__policy_manager.get_policies(moon_user_id="admin"):
+ _perimeter.update(self.__policy_manager.get_subjects(moon_user_id="admin",
+ policy_id=policy))
+ return _perimeter
+
+ def add_subject(self, **kwargs):
+ if kwargs.get("perimeter_id"):
+ return self.__policy_manager.update_subject(
+ moon_user_id=kwargs.get("moon_user_id"),
+ perimeter_id=kwargs.get("perimeter_id"),
+ value=kwargs.get("value")
+ )
+ else:
+ return self.__policy_manager.add_subject(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ value=kwargs.get("value")
+ )
+
+ @property
+ def objects(self):
+ _perimeter = {}
+ for policy in self.__policy_manager.get_policies(moon_user_id="admin"):
+ _perimeter.update(self.__policy_manager.get_objects(moon_user_id="admin",
+ policy_id=policy))
+ return _perimeter
+
+ def add_object(self, **kwargs):
+ if kwargs.get("perimeter_id"):
+ return self.__policy_manager.update_object(
+ moon_user_id=kwargs.get("moon_user_id"),
+ perimeter_id=kwargs.get("perimeter_id"),
+ value=kwargs.get("value")
+ )
+ else:
+ return self.__policy_manager.add_object(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ value=kwargs.get("value")
+ )
+
+ @property
+ def actions(self):
+ _perimeter = {}
+ for policy in self.__policy_manager.get_policies(moon_user_id="admin"):
+ _perimeter.update(self.__policy_manager.get_actions(moon_user_id="admin",
+ policy_id=policy))
+ return _perimeter
+
+ def add_action(self, **kwargs):
+ if kwargs.get("perimeter_id"):
+ return self.__policy_manager.update_action(
+ moon_user_id=kwargs.get("moon_user_id"),
+ perimeter_id=kwargs.get("perimeter_id"),
+ value=kwargs.get("value")
+ )
+ else:
+ return self.__policy_manager.add_action(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ value=kwargs.get("value")
+ )
+
+ def get_subjects(self, **kwargs):
+ return self.__policy_manager.get_subjects(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id")
+ )
+
+ def get_objects(self, **kwargs):
+ return self.__policy_manager.get_objects(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id")
+ )
+
+ def get_actions(self, **kwargs):
+ return self.__policy_manager.get_actions(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id")
+ )
+
+ @property
+ def policies(self):
+ return self.__policy_manager.get_policies(moon_user_id="admin")
+
+ def add_policy(self, **kwargs):
+ return self.__policy_manager.add_policy(
+ moon_user_id=kwargs.get("moon_user_id"),
+ value=kwargs.get("value")
+ )
+
+ def update_policy(self, **kwargs):
+ return self.__policy_manager.update_policy(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id"),
+ value=kwargs.get("value"))
+
+ @property
+ def models(self):
+ return self.get_models()
+
+ def get_models(self, **kwargs):
+ return self.__model_manager.get_models(moon_user_id=kwargs.get("moon_user_id"))
+
+ def update_model(self, **kwargs):
+ return self.__model_manager.update_model(
+ moon_user_id=kwargs.get("moon_user_id"),
+ model_id=kwargs.get("model_id"),
+ value=kwargs.get("value")
+ )
+
+ def add_model(self, **kwargs):
+ return self.__model_manager.add_model(
+ moon_user_id=kwargs.get("moon_user_id"),
+ value=kwargs.get("value")
+ )
+
+ @property
+ def pdp(self):
+ return self.get_pdp()
+
+ def get_pdp(self, **kwargs):
+ return self.__pdp_manager.get_pdp(moon_user_id=kwargs.get("moon_user_id"))
+
+ def update_pdp(self, **kwargs):
+ return self.__pdp_manager.update_pdp(
+ moon_user_id=kwargs.get("moon_user_id"),
+ pdp_id=kwargs.get("pdp_id"),
+ value=kwargs.get("value")
+ )
+
+ def add_pdp(self, **kwargs):
+ return self.__pdp_manager.add_pdp(
+ moon_user_id=kwargs.get("moon_user_id"),
+ value=kwargs.get("value")
+ )
+
+ @property
+ def rules(self):
+ _rules = []
+ for policy in self.__policy_manager.get_policies(moon_user_id="admin"):
+ _rules.append(self.__policy_manager.get_rules(moon_user_id="admin",
+ policy_id=policy))
+ return _rules
+
+ def get_rules(self, **kwargs):
+ return self.__policy_manager.get_rules(
+ moon_user_id=kwargs.get("moon_user_id"),
+ policy_id=kwargs.get("policy_id")
+ )
+
+
+class JsonUtils:
+ @staticmethod
+ def get_override(json_content):
+ if "override" in json_content:
+ return json_content["override"]
+ return False
+
+ @staticmethod
+ def get_mandatory(json_content):
+ if "mandatory" in json_content:
+ return json_content["mandatory"]
+ return False
+
+ @staticmethod
+ def copy_field_if_exists(json_in, json_out, field_name, type_field, default_value=None):
+ if field_name in json_in:
+ json_out[field_name] = json_in[field_name]
+ else:
+ if type_field is bool:
+ if default_value is None:
+ default_value = False
+ json_out[field_name] = default_value
+ if type_field is str:
+ if default_value is None:
+ default_value = ""
+ json_out[field_name] = default_value
+ if type_field is dict:
+ json_out[field_name] = dict()
+ if type_field is list:
+ json_out[field_name] = []
+
+ @staticmethod
+ def _get_element_in_db_from_id(element_type, element_id, user_id, policy_id, category_id,
+ meta_rule_id, manager):
+ # the item is supposed to be in the db, we check it exists!
+ if element_type == "model":
+ data_db = manager.get_models(moon_user_id=user_id, model_id=element_id)
+ elif element_type == "policy":
+ data_db = manager.get_policies(moon_user_id=user_id, policy_id=element_id)
+ elif element_type == "subject":
+ data_db = manager.get_subjects(moon_user_id=user_id, policy_id=policy_id, perimeter_id=element_id)
+ elif element_type == "object":
+ data_db = manager.get_objects(moon_user_id=user_id, policy_id=policy_id, perimeter_id=element_id)
+ elif element_type == "action":
+ data_db = manager.get_actions(moon_user_id=user_id, policy_id=policy_id, perimeter_id=element_id)
+ elif element_type == "subject_category":
+ data_db = manager.get_subject_categories(moon_user_id=user_id, category_id=element_id)
+ elif element_type == "object_category":
+ data_db = manager.get_object_categories(moon_user_id=user_id, category_id=element_id)
+ elif element_type == "action_category":
+ data_db = manager.get_action_categories(moon_user_id=user_id, category_id=element_id)
+ elif element_type == "meta_rule":
+ data_db = manager.get_meta_rules(moon_user_id=user_id, meta_rule_id=element_id)
+ elif element_type == "subject_data":
+ data_db = manager.get_subject_data(moon_user_id=user_id, policy_id=policy_id, data_id=element_id,
+ category_id=category_id)
+ elif element_type == "object_data":
+ data_db = manager.get_object_data(moon_user_id=user_id, policy_id=policy_id, data_id=element_id,
+ category_id=category_id)
+ elif element_type == "action_data":
+ data_db = manager.get_action_data(moon_user_id=user_id, policy_id=policy_id,
+ data_id=element_id,
+ category_id=category_id)
+ elif element_type == "meta_rule":
+ data_db = manager.get_meta_rules(moon_user_id=user_id, meta_rule_id=meta_rule_id)
+ else:
+ raise Exception("Conversion of {} not implemented yet!".format(element_type))
+
+ # do some post processing ... the result should be {key : { .... .... } }
+ if element_type == "subject_data" or element_type == "object_data" or element_type == "action_data":
+ if data_db is not None and isinstance(data_db, list):
+ # TODO remove comments after fixing the bug on moondb when adding metarule:
+ # we can have several identical entries !
+ # if len(data_db) > 1:
+ # raise Exception("Several {} with the same id : {}".format(element_type, data_db))
+ data_db = data_db[0]
+
+ if data_db is not None and data_db["data"] is not None and isinstance(data_db["data"],
+ dict):
+ # TODO remove comments after fixing the bug on moondb when adding metarule:
+ # we can have several identical entries !
+ # if len(data_db["data"].values()) != 1:
+ # raise Exception("Several {} with the same id : {}".format(element_type, data_db))
+ # data_db = data_db["data"]
+ # TODO remove these two lines after fixing the bug on moondb when adding metarule:
+ # we can have several identical entries !
+ list_values = list(data_db["data"].values())
+ data_db = list_values[0]
+ return data_db
+
+ @staticmethod
+ def _get_element_id_in_db_from_name(element_type, element_name, user_id, policy_id, category_id,
+ meta_rule_id, manager):
+ if element_type == "model":
+ data_db = manager.get_models(moon_user_id=user_id)
+ elif element_type == "policy":
+ data_db = manager.get_policies(moon_user_id=user_id)
+ elif element_type == "subject":
+ data_db = manager.get_subjects(moon_user_id=user_id, policy_id=policy_id)
+ elif element_type == "object":
+ data_db = manager.get_objects(moon_user_id=user_id, policy_id=policy_id)
+ elif element_type == "action":
+ data_db = manager.get_actions(moon_user_id=user_id,policy_id= policy_id)
+ elif element_type == "subject_category":
+ data_db = manager.get_subject_categories(moon_user_id=user_id)
+ elif element_type == "object_category":
+ data_db = manager.get_object_categories(moon_user_id=user_id)
+ elif element_type == "action_category":
+ data_db = manager.get_action_categories(moon_user_id=user_id)
+ elif element_type == "meta_rule":
+ data_db = manager.get_meta_rules(moon_user_id=user_id)
+ elif element_type == "subject_data":
+ data_db = manager.get_subject_data(moon_user_id=user_id, policy_id=policy_id,
+ category_id=category_id)
+ elif element_type == "object_data":
+ data_db = manager.get_object_data(moon_user_id=user_id, policy_id=policy_id,
+ category_id=category_id)
+ elif element_type == "action_data":
+ data_db = manager.get_action_data(moon_user_id=user_id, policy_id=policy_id,
+ category_id=category_id)
+ elif element_type == "meta_rule":
+ data_db = manager.get_meta_rules(moon_user_id=user_id)
+ elif element_type == "rule":
+ data_db = manager.get_rules(moon_user_id=user_id, policy_id=policy_id)
+ else:
+ raise exceptions.MoonError("Conversion of {} not implemented yet!".format(element_type))
+
+ if isinstance(data_db, dict):
+ for key_id in data_db:
+ if isinstance(data_db[key_id], dict) and "name" in data_db[key_id]:
+ if data_db[key_id]["name"] == element_name:
+ return key_id
+ else:
+ for elt in data_db:
+ if isinstance(elt, dict) and "data" in elt:
+ # we handle here subject_data, object_data and action_data...
+ for data_key in elt["data"]:
+ data = elt["data"][data_key]
+ if "name" in data and data["name"] == element_name:
+ return data_key
+ if "value" in data and data["value"]["name"] == element_name:
+ return data_key
+ return None
+
+ @staticmethod
+ def convert_name_to_id(json_in, json_out, field_name_in, field_name_out, element_type, manager,
+ user_id, policy_id=None, category_id=None, meta_rule_id=None,
+ field_mandatory=True):
+ if field_name_in not in json_in:
+ raise exceptions.UnknownField(
+ "The field {} is not in the input json".format(field_name_in))
+
+ if "id" in json_in[field_name_in]:
+ data_db = JsonUtils._get_element_in_db_from_id(element_type,
+ json_in[field_name_in]["id"], user_id,
+ policy_id, category_id, meta_rule_id,
+ manager)
+ if data_db is None:
+ raise exceptions.UnknownId("No {} with id {} found in database".format(element_type,
+ json_in[field_name_in]["id"]))
+ json_out[field_name_out] = json_in[field_name_in]["id"]
+
+ elif "name" in json_in[field_name_in]:
+ id_in_db = JsonUtils._get_element_id_in_db_from_name(element_type,
+ json_in[field_name_in]["name"],
+ user_id, policy_id, category_id,
+ meta_rule_id, manager)
+ if id_in_db is None:
+ raise exceptions.UnknownName(
+ "No {} with name {} found in database".format(element_type,
+ json_in[field_name_in]["name"]))
+ json_out[field_name_out] = id_in_db
+ elif field_mandatory is True:
+ raise exceptions.MissingIdOrName(
+ "No id or name found in the input json {}".format(json_in))
+
+ @staticmethod
+ def convert_id_to_name(id_, json_out, field_name_out, element_type, manager, user_id,
+ policy_id=None, category_id=None, meta_rule_id=None):
+ json_out[field_name_out] = {
+ "name": JsonUtils.convert_id_to_name_string(id_, element_type, manager, user_id,
+ policy_id, category_id, meta_rule_id)}
+
+ @staticmethod
+ def __convert_results_to_element(element):
+ if isinstance(element, dict) and "name" not in element and "value" not in element:
+ list_values = [v for v in element.values()]
+ elif isinstance(element, list):
+ list_values = element
+ else:
+ list_values = []
+ list_values.append(element)
+ return list_values[0]
+
+ @staticmethod
+ def convert_id_to_name_string(id_, element_type, manager, user_id,
+ policy_id=None, category_id=None, meta_rule_id=None):
+
+ element = JsonUtils._get_element_in_db_from_id(element_type, id_, user_id, policy_id,
+ category_id, meta_rule_id, manager)
+ if element is None:
+ raise exceptions.UnknownId("No {} with id {} found in database".format(
+ element_type, id_))
+ res = JsonUtils.__convert_results_to_element(element)
+ if "name" in res:
+ return res["name"]
+ if "value" in res and "name" in res["value"]:
+ return res["value"]["name"]
+ return None
+
+ @staticmethod
+ def convert_names_to_ids(json_in, json_out, field_name_in, field_name_out, element_type,
+ manager, user_id, policy_id=None, category_id=None, meta_rule_id=None,
+ field_mandatory=True):
+ ids = []
+ if field_name_in not in json_in:
+ raise exceptions.UnknownField("The field {} is not in the input json".format(
+ field_name_in))
+
+ for elt in json_in[field_name_in]:
+ if "id" in elt:
+ data_db = JsonUtils._get_element_in_db_from_id(element_type, elt["id"], user_id,
+ policy_id, category_id,
+ meta_rule_id, manager)
+ if data_db is None:
+ raise exceptions.UnknownId(
+ "No {} with id {} found in database".format(element_type, elt["id"]))
+ ids.append(elt["id"])
+ elif "name" in elt:
+ id_in_db = JsonUtils._get_element_id_in_db_from_name(element_type, elt["name"],
+ user_id, policy_id,
+ category_id, meta_rule_id,
+ manager)
+ if id_in_db is None:
+ LOGGER.debug("No {} with name {} found in database".format(element_type, elt["name"]))
+ raise exceptions.UnknownName(
+ "No {} with name {} found in database".format(element_type, elt["name"]))
+ ids.append(id_in_db)
+ elif "attr" in elt:
+ ids.append("attributes:" + elt['attr'])
+ elif field_mandatory is True:
+ raise exceptions.MissingIdOrName(
+ "No id or name found in the input json {}".format(elt))
+ json_out[field_name_out] = ids
+
+ @staticmethod
+ def convert_ids_to_names(ids, json_out, field_name_out, element_type, manager, user_id,
+ policy_id=None, category_id=None, meta_rule_id=None):
+ res_array = []
+ for id_ in ids:
+ element = JsonUtils._get_element_in_db_from_id(element_type, id_, user_id, policy_id,
+ category_id, meta_rule_id, manager)
+ if element is None:
+ raise exceptions.UnknownId("No {} with id {} found in database".format(
+ element_type, id_))
+ res = JsonUtils.__convert_results_to_element(element)
+ if "name" in res:
+ res_array.append({"name": res["name"]})
+ if "value" in res and "name" in res["value"]:
+ res_array.append({"name": res["value"]["name"]})
+ json_out[field_name_out] = res_array
+
+
+class JsonImport(object):
+ __user_id = None
+ __manager = None
+ __driver = None
+
+ def __init__(self, driver_name="db", driver=None):
+ self.__driver = driver_name
+ if driver_name == "db":
+ self.__manager = DBManager(driver)
+ else:
+ self.__manager = CacheManager(driver)
+
+ @property
+ def driver(self):
+ return self.__manager
+
+ def _reorder_rules_ids(self, rule, ordered_perimeter_categories_ids, json_data_ids, policy_id,
+ get_function):
+ ordered_json_ids = [None] * len(ordered_perimeter_categories_ids)
+ _exc = None
+ data = get_function(moon_user_id=self.__user_id, policy_id=policy_id)
+ for _data in data:
+ for item in json_data_ids:
+ if not _data['data']:
+ continue
+ if _data.get('data').get(item):
+ index = ordered_perimeter_categories_ids.index(_data["category_id"])
+ if _data["category_id"] not in ordered_perimeter_categories_ids:
+ _exc = exceptions.InvalidJson(
+ "The category id {} of the rule {} does not match the meta rule".format(
+ _data["category_id"], rule))
+ continue
+ if ordered_json_ids[index] is not None:
+ _exc = exceptions.InvalidJson(
+ "The category id {} of the rule {} shall not be used "
+ "twice in the same rule".format(
+ _data["category_id"], rule))
+ ordered_json_ids[index] = item
+ if None in ordered_json_ids:
+ for cpt, _id in enumerate(ordered_perimeter_categories_ids):
+ if _id.startswith("attributes:"):
+ if not ordered_json_ids[cpt]:
+ ordered_json_ids[cpt] = json_data_ids[cpt]
+
+ if _exc:
+ raise _exc
+ return ordered_json_ids
+
+ def _import_rules(self, json_rules):
+ if not isinstance(json_rules, list):
+ raise exceptions.InvalidJson("rules shall be a list!")
+
+ for json_rule in json_rules:
+ json_to_use = dict()
+ JsonUtils.copy_field_if_exists(json_rule, json_to_use, "instructions", str)
+ JsonUtils.copy_field_if_exists(json_rule, json_to_use, "enabled", bool,
+ default_value=True)
+
+ json_ids = dict()
+ JsonUtils.convert_name_to_id(json_rule, json_ids, "policy", "policy_id", "policy",
+ self.__manager, self.__user_id)
+ JsonUtils.convert_name_to_id(json_rule, json_to_use, "meta_rule", "meta_rule_id",
+ "meta_rule", self.__manager, self.__user_id)
+ json_subject_ids = dict()
+ json_object_ids = dict()
+ json_action_ids = dict()
+ JsonUtils.convert_names_to_ids(json_rule["rule"], json_subject_ids, "subject_data",
+ "subject", "subject_data", self.__manager,
+ self.__user_id,
+ json_ids["policy_id"])
+ JsonUtils.convert_names_to_ids(json_rule["rule"], json_object_ids, "object_data",
+ "object", "object_data", self.__manager,
+ self.__user_id,
+ json_ids["policy_id"])
+ JsonUtils.convert_names_to_ids(json_rule["rule"], json_action_ids, "action_data",
+ "action", "action_data", self.__manager,
+ self.__user_id,
+ json_ids["policy_id"])
+
+ meta_rule = self.__manager.get_meta_rules(
+ moon_user_id=self.__user_id,
+ meta_rule_id=json_to_use["meta_rule_id"]
+ )
+ meta_rule = [v for v in meta_rule.values()]
+ meta_rule = meta_rule[0]
+
+ json_to_use_rule = self._reorder_rules_ids(json_rule, meta_rule["subject_categories"],
+ json_subject_ids["subject"],
+ json_ids["policy_id"],
+ self.__manager.get_subject_data)
+ json_to_use_rule = json_to_use_rule + self._reorder_rules_ids(
+ json_rule, meta_rule["object_categories"],
+ json_object_ids["object"],
+ json_ids["policy_id"],
+ self.__manager.get_object_data)
+ json_to_use_rule = json_to_use_rule + self._reorder_rules_ids(
+ json_rule,
+ meta_rule["action_categories"],
+ json_action_ids["action"],
+ json_ids["policy_id"],
+ self.__manager.get_action_data)
+ json_to_use["rule"] = json_to_use_rule
+ try:
+ LOGGER.debug("Adding / updating a rule from json {}".format(json_to_use))
+ self.__manager.add_rule(
+ moon_user_id=self.__user_id,
+ policy_id=json_ids["policy_id"],
+ meta_rule_id=json_to_use["meta_rule_id"],
+ value=json_to_use
+ )
+ except exceptions.RuleExisting as e:
+ LOGGER.error("rule existing {}".format(e))
+ except exceptions.PolicyUnknown:
+ raise exceptions.PolicyUnknown("Unknown policy with id {}".format(
+ json_ids["policy_id"]))
+
+ def _import_meta_rules(self, json_meta_rules):
+ imported_mrule = []
+ for json_meta_rule in json_meta_rules:
+ json_to_use = dict()
+ JsonUtils.copy_field_if_exists(json_meta_rule, json_to_use, "name", str)
+ JsonUtils.copy_field_if_exists(json_meta_rule, json_to_use, "description", str)
+ JsonUtils.convert_names_to_ids(json_meta_rule, json_to_use, "subject_categories",
+ "subject_categories", "subject_category",
+ self.__manager,
+ self.__user_id)
+ JsonUtils.convert_names_to_ids(json_meta_rule, json_to_use, "object_categories",
+ "object_categories", "object_category",
+ self.__manager,
+ self.__user_id)
+ JsonUtils.convert_names_to_ids(json_meta_rule, json_to_use, "action_categories",
+ "action_categories", "action_category",
+ self.__manager,
+ self.__user_id)
+ LOGGER.debug("Adding / updating a metarule from json {}".format(json_meta_rule))
+ try:
+ meta_rule = self.__manager.add_meta_rule(
+ moon_user_id=self.__user_id,
+ meta_rule_id=None,
+ value=json_to_use
+ )
+ LOGGER.debug("Added / updated meta rule : {}".format(meta_rule))
+ imported_mrule.append(meta_rule)
+ except exceptions.MetaRuleExisting:
+ pass
+ return imported_mrule
+
+ def _import_subject_object_action_assignments(self, json_item_assignments, type_element):
+ import_method = None
+ get_method = None
+ if type_element == "subject":
+ import_method = self.__manager.add_subject_assignment
+ get_method = self.__manager.get_subject_data
+ elif type_element == "object":
+ import_method = self.__manager.add_object_assignment
+ get_method = self.__manager.get_object_data
+ elif type_element == "action":
+ import_method = self.__manager.add_action_assignment
+ get_method = self.__manager.get_action_data
+
+ if not isinstance(json_item_assignments, list):
+ raise exceptions.InvalidJson(type_element + " assignments shall be a list!")
+
+ # get the policy id related to the user
+ policies = self.__manager.get_policies(moon_user_id=self.__user_id)
+
+ for json_item_assignment in json_item_assignments:
+ item_override = JsonUtils.get_override(json_item_assignment)
+ if item_override is True:
+ raise exceptions.ForbiddenOverride(
+ "{} assignments do not support override flag !".format(type_element))
+
+ json_assignment = dict()
+ JsonUtils.convert_name_to_id(json_item_assignment, json_assignment, "category",
+ "category_id", type_element + "_category",
+ self.__manager,
+ self.__user_id)
+
+ has_found_data = False
+ # loop over policies
+ for policy_id in policies:
+ json_data = dict()
+ try:
+ JsonUtils.convert_name_to_id(json_item_assignment, json_assignment,
+ type_element, "id", type_element,
+ self.__manager,
+ self.__user_id, policy_id)
+ JsonUtils.convert_names_to_ids(json_item_assignment, json_data, "assignments",
+ "data_id", type_element + "_data",
+ self.__manager,
+ self.__user_id, policy_id,
+ json_assignment["category_id"])
+ has_found_data = True
+ except exceptions.UnknownName:
+ # the category or data has not been found in this policy:
+ # we look into the next one
+ continue
+ for data_id in json_data["data_id"]:
+ # find the policy related to the current data
+ data = get_method(moon_user_id=self.__user_id, policy_id=policy_id,
+ data_id=data_id,
+ category_id=json_assignment["category_id"])
+ if data is not None and len(data) == 1:
+ LOGGER.debug(
+ "Adding / updating a {} assignment from json {}".format(
+ type_element,
+ json_assignment))
+ args = {"moon_user_id": self.__user_id, "policy_id": policy_id,
+ type_element + "_id": json_assignment["id"],
+ "category_id": json_assignment["category_id"], "data_id": data_id}
+ try:
+ import_method(**args)
+ except exceptions.SubjectAssignmentExisting:
+ pass
+ except exceptions.ObjectAssignmentExisting:
+ pass
+ except exceptions.ActionAssignmentExisting:
+ pass
+ else:
+ raise exceptions.DataUnknown("Unknown data with id {}".format(data_id))
+
+ # case the data has not been found in any policies
+ if has_found_data is False:
+ raise exceptions.InvalidJson(
+ "The json contains unknown {} data or category : {}".format(
+ type_element,
+ json_item_assignment))
+
+ def _import_subject_object_action_datas(self, json_items_data, mandatory_policy_ids,
+ type_element):
+ import_method = None
+ if type_element == "subject":
+ import_method = self.__manager.set_subject_data
+ elif type_element == "object":
+ import_method = self.__manager.set_object_data
+ elif type_element == "action":
+ import_method = self.__manager.set_action_data
+
+ if not isinstance(json_items_data, list):
+ raise exceptions.InvalidJson(type_element + " data shall be a list!")
+
+ for json_item_data in json_items_data:
+ item_override = JsonUtils.get_override(json_items_data)
+ if item_override is True:
+ raise exceptions.ForbiddenOverride(
+ "{} datas do not support override flag !".format(type_element))
+ json_to_use = dict()
+ JsonUtils.copy_field_if_exists(json_item_data, json_to_use, "name", str)
+ JsonUtils.copy_field_if_exists(json_item_data, json_to_use, "description", str)
+ json_policy = dict()
+ # field_mandatory : not mandatory if there is some mandatory policies
+ JsonUtils.convert_names_to_ids(json_item_data, json_policy, "policies", "policy_id",
+ "policy",
+ self.__manager, self.__user_id,
+ field_mandatory=len(mandatory_policy_ids) == 0)
+ json_category = dict()
+ JsonUtils.convert_name_to_id(json_item_data, json_category, "category", "category_id",
+ type_element + "_category",
+ self.__manager, self.__user_id)
+ policy_ids = []
+ if "policy_id" in json_policy:
+ policy_ids = json_policy["policy_id"]
+
+ for policy_id in policy_ids:
+ if policy_id is not None and policy_id not in mandatory_policy_ids:
+ mandatory_policy_ids.append(policy_id)
+
+ if len(mandatory_policy_ids) == 0:
+ raise exceptions.InvalidJson("Invalid data, the policy shall be set when "
+ "importing {}".format(json_item_data))
+ category_id = None
+ if "category_id" in json_category:
+ category_id = json_category["category_id"]
+ if category_id is None:
+ raise exceptions.InvalidJson(
+ "Invalid data, the category shall be set when importing {}".format(
+ json_item_data))
+
+ for policy_id in mandatory_policy_ids:
+ try:
+ import_method(moon_user_id=self.__user_id, policy_id=policy_id,
+ category_id=category_id,
+ value=json_to_use)
+ except exceptions.PolicyUnknown:
+ raise exceptions.PolicyUnknown("Unknown policy with id {}".format(policy_id))
+ except exceptions.SubjectScopeExisting:
+ pass
+ except exceptions.ObjectScopeExisting:
+ pass
+ except exceptions.ActionScopeExisting:
+ pass
+ except Exception as e:
+ LOGGER.exception(str(e))
+ raise e
+
+ def _import_subject_object_action_categories(self, json_item_categories, type_element):
+ imported_oac = []
+ import_method = None
+ get_method = None
+ if type_element == "subject":
+ import_method = self.__manager.add_subject_category
+ get_method = self.__manager.get_subject_categories
+ elif type_element == "object":
+ import_method = self.__manager.add_object_category
+ get_method = self.__manager.get_object_categories
+ elif type_element == "action":
+ import_method = self.__manager.add_action_category
+ get_method = self.__manager.get_action_categories
+
+ categories = get_method(moon_user_id=self.__user_id)
+
+ if not isinstance(json_item_categories, list):
+ raise exceptions.InvalidJson(type_element + " categories shall be a list!")
+
+ for json_item_category in json_item_categories:
+ json_to_use = dict()
+ JsonUtils.copy_field_if_exists(json_item_category, json_to_use, "name", str)
+
+ # check if category with the same name exists : do this in moondb ?
+ existing_id = None
+ for category_key in categories:
+ if categories[category_key]["name"] == json_to_use["name"]:
+ existing_id = category_key
+
+ JsonUtils.copy_field_if_exists(json_item_category, json_to_use, "description", str)
+ item_override = JsonUtils.get_override(json_item_category)
+ if item_override is True:
+ raise exceptions.ForbiddenOverride(
+ "{} categories do not support override flag !".format(type_element))
+
+ try:
+ import_method(moon_user_id=self.__user_id, category_id=existing_id,
+ value=json_to_use)
+ except (exceptions.SubjectCategoryExisting, exceptions.ObjectCategoryExisting,
+ exceptions.ActionCategoryExisting):
+ # it already exists: do nothing
+ LOGGER.warning("Ignored {} category with name {} is already in the database".format(
+ type_element, json_to_use["name"]))
+ except Exception as e:
+ LOGGER.warning("Error while importing the category : {}".format(str(e)))
+ LOGGER.exception(str(e))
+ raise e
+ imported_oac.append({
+ 'category': type_element,
+ 'name': json_to_use["name"]})
+ return imported_oac
+
+ def _import_subject_object_action(self, json_items, mandatory_policy_ids, type_element):
+ import_method = None
+ get_method = None
+ if type_element == "subject":
+ import_method = self.__manager.add_subject
+ get_method = self.__manager.get_subjects
+ elif type_element == "object":
+ import_method = self.__manager.add_object
+ get_method = self.__manager.get_objects
+ elif type_element == "action":
+ import_method = self.__manager.add_action
+ get_method = self.__manager.get_actions
+
+ if not isinstance(json_items, list):
+ raise exceptions.InvalidJson(type_element + " items shall be a list!")
+
+ for json_item in json_items:
+ json_without_policy_name = dict()
+ JsonUtils.copy_field_if_exists(json_item, json_without_policy_name, "name", str)
+ JsonUtils.copy_field_if_exists(json_item, json_without_policy_name, "description", str)
+ JsonUtils.copy_field_if_exists(json_item, json_without_policy_name, "extra", dict)
+
+ policy_list_ids = {}
+ JsonUtils.convert_names_to_ids(json_item, policy_list_ids, "policies",
+ "policy_list", "policy", self.__manager,
+ self.__user_id,
+ field_mandatory=False)
+ policy_ids = policy_list_ids["policy_list"]
+ # json_without_policy_name["policies"] = []
+ for mandatory_policy_id in mandatory_policy_ids:
+ if mandatory_policy_id not in policy_ids:
+ policy_ids.append(mandatory_policy_id)
+ # policy_ids and json_without_policy_name are references to the same array...
+ # json_without_policy_name["policy_list"].append(mandatory_policy_id)
+
+ item_override = JsonUtils.get_override(json_item)
+ if item_override is True:
+ raise exceptions.ForbiddenOverride("{} does not support override flag !".format(
+ type_element))
+
+ if len(policy_ids) == 0:
+ raise exceptions.PolicyUnknown(
+ "a {} needs at least one policy to be created or updated : {}".format(
+ type_element, json.dumps(json_item)))
+
+ for policy_id in policy_ids:
+ try:
+ items_in_db = get_method(moon_user_id=self.__user_id, policy_id=policy_id)
+ items_in_db = items_in_db.get(policy_id, {})
+ key = None
+ for key_in_db in items_in_db:
+ if items_in_db[key_in_db]["name"] == json_without_policy_name["name"]:
+ key = key_in_db
+ break
+ try:
+ element = import_method(moon_user_id=self.__user_id, policy_id=policy_id,
+ perimeter_id=key,
+ value=json_without_policy_name)
+ LOGGER.debug("Added / updated {} : {}".format(type_element, element))
+ except exceptions.PolicyExisting:
+ pass
+
+ except exceptions.PolicyUnknown:
+ LOGGER.error("Unknown policy when adding a {}!".format(
+ type_element))
+ raise exceptions.PolicyUnknown("Unknown policy when adding a {}!".format(
+ type_element))
+ except Exception as e:
+ LOGGER.exception(str(e))
+ raise e
+
+ def _import_policies(self, json_policies):
+ policy_mandatory_ids = []
+ policy_mandatory_names = []
+
+ if not isinstance(json_policies, list):
+ raise exceptions.InvalidJson("policies shall be a list!")
+
+ for json_policy in json_policies:
+ # TODO put this in moondb
+ # policy_in_db =
+ # self.driver.PolicyManager.get_policies_by_name(json_without_model_name["name"])
+ policies = self.__manager.get_policies(moon_user_id=self.__user_id)
+ policy_in_db = None
+ policy_id = None
+ for policy_key in policies:
+ if policies[policy_key]["name"] == json_policy["name"]:
+ policy_in_db = policies[policy_key]
+ policy_id = policy_key
+ # end TODO
+ if policy_in_db is None:
+ policy_does_exist = False
+ else:
+ policy_does_exist = True
+
+ policy_override = JsonUtils.get_override(json_policy)
+ policy_mandatory = JsonUtils.get_mandatory(json_policy)
+
+ if policy_override is False and policy_does_exist:
+ if policy_id:
+ policy_mandatory_ids.append(policy_id)
+ policy_mandatory_names.append(json_policy["name"])
+ LOGGER.warning(
+ "Existing policy not updated because of the override option is not set !")
+ continue
+
+ json_without_model_name = dict()
+ JsonUtils.copy_field_if_exists(json_policy, json_without_model_name, "name", str)
+ JsonUtils.copy_field_if_exists(json_policy, json_without_model_name, "description", str)
+ JsonUtils.copy_field_if_exists(json_policy, json_without_model_name, "genre", str)
+ JsonUtils.convert_name_to_id(json_policy, json_without_model_name, "model", "model_id",
+ "model", self.__manager, self.__user_id,
+ field_mandatory=False)
+
+ if not policy_does_exist:
+ LOGGER.debug("Creating policy {} ".format(json_without_model_name))
+ added_policy = self.__manager.add_policy(
+ moon_user_id=self.__user_id,
+ value=json_without_model_name)
+ if policy_mandatory is True:
+ keys = list(added_policy.keys())
+ policy_mandatory_ids.append(keys[0])
+ policy_mandatory_names.append(json_policy["name"])
+ elif policy_override is True:
+ LOGGER.debug("Updating policy {} ".format(json_without_model_name))
+ self.__manager.update_policy(moon_user_id=self.__user_id,
+ policy_id=policy_id,
+ value=json_without_model_name)
+ if policy_mandatory is True:
+ policy_mandatory_ids.append(policy_id)
+ policy_mandatory_names.append(json_policy["name"])
+ return [policy_mandatory_ids, policy_mandatory_names]
+
+ def _import_models_with_new_meta_rules(self, json_models):
+ if not isinstance(json_models, list):
+ raise exceptions.InvalidJson("models shall be a list!")
+
+ for json_model in json_models:
+ models = self.__manager.get_models(moon_user_id=self.__user_id)
+ model_in_db = None
+ model_id = None
+ for model_key in models:
+ if ("id" in json_model and model_key == json_model["id"]) or (
+ "name" in json_model and models[model_key]["name"] == json_model["name"]):
+ model_in_db = models[model_key]
+ model_id = model_key
+
+ # this should not occur as the model has been put in db previously in
+ # import_models_without_new_meta_rules
+ if model_in_db is None:
+ raise exceptions.ModelUnknown("Unknown model")
+
+ json_key = dict()
+ JsonUtils.convert_names_to_ids(json_model, json_key, "meta_rules", "meta_rule_id",
+ "meta_rule", self.__manager, self.__user_id)
+ for meta_rule_id in json_key["meta_rule_id"]:
+ if meta_rule_id not in model_in_db["meta_rules"]:
+ model_in_db["meta_rules"].append(meta_rule_id)
+
+ self.__manager.update_model(moon_user_id=self.__user_id,
+ model_id=model_id,
+ value=model_in_db)
+
+ def _import_models_without_new_meta_rules(self, json_models):
+ if not isinstance(json_models, list):
+ raise exceptions.InvalidJson("models shall be a list!")
+ imported_model_names = []
+ for json_model in json_models:
+ json_without_new_metarules = dict()
+ JsonUtils.copy_field_if_exists(json_model, json_without_new_metarules, "name", str)
+
+ models = self.__manager.get_models(moon_user_id=self.__user_id)
+ model_in_db = None
+ model_id = None
+ for model_key in models:
+ if models[model_key]["name"] == json_without_new_metarules["name"]:
+ model_in_db = models[model_key]
+ model_id = model_key
+
+ JsonUtils.copy_field_if_exists(json_model, json_without_new_metarules, "description",
+ str)
+ if model_in_db is None:
+ model_does_exist = False
+ else:
+ json_without_new_metarules["meta_rules"] = model_in_db["meta_rules"]
+ model_does_exist = True
+ model_override = JsonUtils.get_override(json_model)
+ if not model_does_exist:
+ LOGGER.debug("Creating model {} ".format(json_without_new_metarules))
+ self.__manager.add_model(moon_user_id=self.__user_id,
+ value=json_without_new_metarules)
+ elif model_override is True:
+ LOGGER.debug(
+ "Updating model with id {} : {} ".format(model_id, json_without_new_metarules))
+ self.__manager.update_model(moon_user_id=self.__user_id,
+ model_id=model_id,
+ value=json_without_new_metarules)
+ if "name" in json_without_new_metarules:
+ imported_model_names.append(json_without_new_metarules["name"])
+ return imported_model_names
+
+ def _import_pdps(self, json_pdps):
+ if not isinstance(json_pdps, list):
+ raise exceptions.InvalidJson("pdps shall be a list!")
+ imported_pdp_names = []
+ for json_pdp in json_pdps:
+ json_to_use = dict()
+ JsonUtils.copy_field_if_exists(json_pdp, json_to_use, "name", str)
+ JsonUtils.copy_field_if_exists(json_pdp, json_to_use, "vim_project_id", str)
+ JsonUtils.copy_field_if_exists(json_pdp, json_to_use, "security_pipeline", list)
+ JsonUtils.copy_field_if_exists(json_pdp, json_to_use, "description", str)
+
+ pdps = self.__manager.get_pdp(moon_user_id=self.__user_id)
+ exists = False
+ for pdp_key in pdps:
+ if pdps[pdp_key]["name"] == json_to_use["name"]:
+ self.__manager.update_pdp(moon_user_id=self.__user_id, pdp_id=pdp_key,
+ value=json_to_use)
+ exists = True
+ if exists is False:
+ self.__manager.add_pdp(moon_user_id=self.__user_id, value=json_to_use)
+ imported_pdp_names.append(json_to_use["name"])
+
+ def import_json(self, **kwargs):
+ if self.__driver == "db":
+ if "body" in kwargs:
+ return self.__import_json_to_db(kwargs.get("body")).keys()
+ else:
+ raise Exception("Bad argument given...")
+ else:
+ if "body" in kwargs:
+ return self.__import_json_to_cache(kwargs.get("body")).keys()
+ else:
+ raise Exception("Bad argument given...")
+
+ def __import_json_to_db(self, body):
+ imported_data = {}
+
+ LOGGER.debug("Importing content: {} ...".format(body))
+
+ # first import the models without the meta rules as they are not yet defined
+ if "models" in body:
+ LOGGER.info("Importing models...")
+ imported_model_names = self._import_models_without_new_meta_rules(body["models"])
+ imported_data['models'] = imported_model_names
+
+
+
+ # import subjects, object, action_categories
+ list_element = [{"key": "subject"}, {"key": "object"}, {"key": "action"}]
+ for elt in list_element:
+ in_key = elt["key"]
+ key = in_key + "_categories"
+ if key in body:
+ LOGGER.info("Importing {}...".format(key))
+ imported_oac = self._import_subject_object_action_categories(body[key], in_key)
+ imported_data[key] = imported_oac
+
+ # import meta rules
+ if "meta_rules" in body:
+ LOGGER.info("Importing meta rules...")
+ imported_mrules = self._import_meta_rules(body["meta_rules"])
+ imported_data["meta_rules"] = imported_mrules
+
+ # add the metarule to model
+ if "models" in body:
+ LOGGER.info("Updating models with meta rules...")
+ self._import_models_with_new_meta_rules(body["models"])
+
+ # import the policies that depends on the models
+ mandatory_policy_ids = []
+ if "policies" in body:
+ LOGGER.info("Importing policies...")
+ mandatory_policy_ids, policy_mandatory_names = self._import_policies(body["policies"])
+ imported_data["policies"] = {
+ 'id': mandatory_policy_ids,
+ 'name': policy_mandatory_names}
+
+ # import subjects, object, action
+ for elt in list_element:
+ in_key = elt["key"]
+ key = in_key + "s"
+ if key in body:
+ LOGGER.info("Importing {}...".format(key))
+ imported_sub = self._import_subject_object_action(body[key], mandatory_policy_ids, in_key)
+ imported_data[key] = imported_sub
+
+ # import subjects, object, action data
+ for elt in list_element:
+ in_key = elt["key"]
+ key = in_key + "_data"
+ if key in body:
+ LOGGER.info("Importing {}...".format(key))
+ imported_sub =self._import_subject_object_action_datas(body[key], mandatory_policy_ids,
+ in_key)
+ imported_data[key] = imported_sub
+
+ # import subjects assignments, idem for object and action
+ for elt in list_element:
+ in_key = elt["key"]
+ key = in_key + "_assignments"
+ if key in body:
+ LOGGER.info("Importing {}...".format(key))
+ imported_sub = self._import_subject_object_action_assignments(body[key], in_key)
+ imported_data[key] = imported_sub
+
+ # import rules
+ if "rules" in body:
+ LOGGER.info("Importing rules...")
+ imported_sub = self._import_rules(body["rules"])
+ imported_data["rules"] = imported_sub
+
+ # import pdps
+ if "pdps" in body:
+ LOGGER.info("Importing pdps...")
+ imported_sub = self._import_pdps(body["pdps"])
+ imported_data["pdps"] = imported_sub
+
+ return imported_data
+
+ def __import_json_to_cache(self, body):
+ imported_data = {}
+
+ LOGGER.debug("Importing content: {} ...".format(body))
+
+ # first import the models without the meta rules as they are not yet defined
+ if "models" in body:
+ LOGGER.info("Importing models...")
+ imported_model_names = self._import_models_without_new_meta_rules(body["models"])
+ imported_data['models'] = imported_model_names
+
+
+ # import subjects, object, action_categories
+ list_element = [{"key": "subject"}, {"key": "object"}, {"key": "action"}]
+ for elt in list_element:
+ in_key = elt["key"]
+ key = in_key + "_categories"
+ if key in body:
+ LOGGER.info("Importing {}...".format(key))
+ imported_oac = self._import_subject_object_action_categories(body[key], in_key)
+ imported_data[key] = imported_oac
+
+ # import meta rules
+ if "meta_rules" in body:
+ LOGGER.info("Importing meta rules...")
+ imported_mrules = self._import_meta_rules(body["meta_rules"])
+ imported_data["meta_rules"] = imported_mrules
+
+ # add the metarule to model
+ if "models" in body:
+ LOGGER.info("Updating models with meta rules...")
+ self._import_models_with_new_meta_rules(body["models"])
+
+ # import the policies that depends on the models
+ mandatory_policy_ids = []
+ if "policies" in body:
+ LOGGER.info("Importing policies...")
+ mandatory_policy_ids, policy_mandatory_names = self._import_policies(body["policies"])
+ imported_data["policies"] = {
+ 'id': mandatory_policy_ids,
+ 'name': policy_mandatory_names}
+
+ # import subjects, object, action
+ for elt in list_element:
+ in_key = elt["key"]
+ key = in_key + "s"
+ if key in body:
+ LOGGER.info("Importing {}...".format(key))
+ imported_sub = self._import_subject_object_action(body[key], mandatory_policy_ids, in_key)
+ imported_data[key] = imported_sub
+
+ #import subjects, object, action data
+ for elt in list_element:
+ in_key = elt["key"]
+ key = in_key + "_data"
+ if key in body:
+ LOGGER.info("Importing {}...".format(key))
+ imported_sub= self._import_subject_object_action_datas(body[key], mandatory_policy_ids,
+ in_key)
+ imported_data[key] = imported_sub
+
+ # import subjects assignments, idem for object and action
+ for elt in list_element:
+ in_key = elt["key"]
+ key = in_key + "_assignments"
+ if key in body:
+ LOGGER.info("Importing {}...".format(key))
+ imported_sub = self._import_subject_object_action_assignments(body[key], in_key)
+ imported_data[key] = imported_sub
+
+ # import rules
+ if "rules" in body:
+ LOGGER.info("Importing rules...")
+ imported_sub = self._import_rules(body["rules"])
+ imported_data["rules"] = imported_sub
+
+ # import pdps
+ if "pdps" in body:
+ LOGGER.info("Importing pdps...")
+ imported_sub = self._import_pdps(body["pdps"])
+ imported_data["pdps"] = imported_sub
+ return imported_data
+
+
+class JsonExport(object):
+ __user_id = None
+ __dirver = None
+ __manager = None
+
+ def __init__(self, driver_name="db", driver=None):
+ self.__driver = driver_name
+ if driver_name == "db":
+ self.__manager = DBManager(driver)
+ else:
+ self.__manager = CacheManager(driver)
+
+ def _export_rules(self, json_content):
+ policies = self.__manager.get_policies(moon_user_id=self.__user_id)
+ rules_array = []
+
+ for policy_key in policies:
+ rules = self.__manager.get_rules(moon_user_id=self.__user_id, policy_id=policy_key)
+ rules = rules["rules"]
+ for rule in rules:
+ rule_dict = dict()
+ JsonUtils.copy_field_if_exists(rule, rule_dict, "instructions", dict)
+ JsonUtils.copy_field_if_exists(rule, rule_dict, "enabled", True)
+ JsonUtils.convert_id_to_name(rule["meta_rule_id"], rule_dict, "meta_rule",
+ "meta_rule", self.__manager, self.__user_id)
+ JsonUtils.convert_id_to_name(policy_key, rule_dict, "policy", "policy",
+ self.__manager, self.__user_id)
+ ids = rule["rule"]
+ rule_description = dict()
+ meta_rule = self.__manager.get_meta_rules(moon_user_id=self.__user_id,
+ meta_rule_id=rule["meta_rule_id"])
+ meta_rule = [v for v in meta_rule.values()]
+ meta_rule = meta_rule[0]
+ index_subject_data = len(meta_rule["subject_categories"]) - 1
+ index_object_data = len(meta_rule["subject_categories"]) + len(
+ meta_rule["object_categories"]) - 1
+ index_action_data = len(meta_rule["subject_categories"]) + len(
+ meta_rule["object_categories"]) + len(meta_rule["action_categories"]) - 1
+ ids_subject_data = [ids[0]] if len(meta_rule["subject_categories"]) == 1 else ids[
+ 0:index_subject_data]
+ ids_object_data = [ids[index_object_data]] if len(
+ meta_rule["object_categories"]) == 1 else ids[
+ index_subject_data + 1:index_object_data]
+ ids_action_date = [ids[index_action_data]] if len(
+ meta_rule["action_categories"]) == 1 else ids[
+ index_object_data + 1:index_action_data]
+ JsonUtils.convert_ids_to_names(ids_subject_data, rule_description, "subject_data",
+ "subject_data", self.__manager, self.__user_id,
+ policy_key)
+ JsonUtils.convert_ids_to_names(ids_object_data, rule_description, "object_data",
+ "object_data", self.__manager, self.__user_id,
+ policy_key)
+ JsonUtils.convert_ids_to_names(ids_action_date, rule_description, "action_data",
+ "action_data", self.__manager, self.__user_id,
+ policy_key)
+ rule_dict["rule"] = rule_description
+ rules_array.append(rule_dict)
+
+ if len(rules_array) > 0:
+ json_content['rules'] = rules_array
+
+ def _export_meta_rules(self, json_content):
+ meta_rules = self.__manager.get_meta_rules(moon_user_id=self.__user_id)
+ meta_rules_array = []
+ for meta_rule_key in meta_rules:
+ meta_rule_dict = dict()
+ JsonUtils.copy_field_if_exists(meta_rules[meta_rule_key], meta_rule_dict, "name", str)
+ JsonUtils.copy_field_if_exists(meta_rules[meta_rule_key], meta_rule_dict, "description",
+ str)
+ JsonUtils.convert_ids_to_names(meta_rules[meta_rule_key]["subject_categories"],
+ meta_rule_dict, "subject_categories", "subject_category",
+ self.__manager, self.__user_id)
+ JsonUtils.convert_ids_to_names(meta_rules[meta_rule_key]["object_categories"],
+ meta_rule_dict, "object_categories", "object_category",
+ self.__manager, self.__user_id)
+ JsonUtils.convert_ids_to_names(meta_rules[meta_rule_key]["action_categories"],
+ meta_rule_dict, "action_categories", "action_category",
+ self.__manager, self.__user_id)
+ meta_rules_array.append(meta_rule_dict)
+ if len(meta_rules_array) > 0:
+ json_content['meta_rules'] = meta_rules_array
+
+ def _export_subject_object_action_assignments(self, type_element, json_content):
+ export_method_data = None
+ if type_element == "subject":
+ export_method_data = self.__manager.get_subject_assignments
+ elif type_element == "object":
+ export_method_data = self.__manager.get_object_assignments
+ if type_element == "action":
+ export_method_data = self.__manager.get_action_assignments
+ policies = self.__manager.get_policies(moon_user_id=self.__user_id)
+ element_assignments_array = []
+ for policy_key in policies:
+ assignments = export_method_data(moon_user_id=self.__user_id, policy_id=policy_key)
+ for assignment_key in assignments:
+ assignment_dict = dict()
+ JsonUtils.convert_id_to_name(assignments[assignment_key][type_element + "_id"],
+ assignment_dict, type_element, type_element,
+ self.__manager, self.__user_id, policy_key)
+ JsonUtils.convert_id_to_name(assignments[assignment_key]["category_id"],
+ assignment_dict, "category",
+ type_element + "_category", self.__manager,
+ self.__user_id, policy_key)
+ JsonUtils.convert_ids_to_names(assignments[assignment_key]["assignments"],
+ assignment_dict, "assignments",
+ type_element + "_data", self.__manager,
+ self.__user_id,
+ policy_key)
+ element_assignments_array.append(assignment_dict)
+ LOGGER.info("Exporting {} assignment {}".format(type_element, assignment_dict))
+ if len(element_assignments_array) > 0:
+ json_content[type_element + '_assignments'] = element_assignments_array
+
+ def _export_subject_object_action_datas(self, type_element, json_content):
+ export_method_data = None
+ if type_element == "subject":
+ export_method_data = self.__manager.get_subject_data
+ elif type_element == "object":
+ export_method_data = self.__manager.get_object_data
+ if type_element == "action":
+ export_method_data = self.__manager.get_action_data
+ policies = self.__manager.get_policies(moon_user_id=self.__user_id)
+ element_datas_array = []
+ for policy_key in policies:
+ datas = export_method_data(moon_user_id=self.__user_id, policy_id=policy_key)
+ for data_group in datas:
+ policy_id = data_group["policy_id"]
+ category_id = data_group["category_id"]
+ for data_key in data_group["data"]:
+ data_dict = dict()
+ if type_element == 'subject':
+ JsonUtils.copy_field_if_exists(data_group["data"][data_key], data_dict,
+ "name", str)
+ JsonUtils.copy_field_if_exists(data_group["data"][data_key], data_dict,
+ "description", str)
+ else:
+ JsonUtils.copy_field_if_exists(data_group["data"][data_key], data_dict,
+ "name", str)
+ JsonUtils.copy_field_if_exists(data_group["data"][data_key], data_dict,
+ "description", str)
+
+ JsonUtils.convert_id_to_name(policy_id, data_dict, "policy", "policy",
+ self.__manager, self.__user_id)
+ JsonUtils.convert_id_to_name(category_id, data_dict, "category",
+ type_element + "_category", self.__manager,
+ self.__user_id, policy_key)
+ LOGGER.info("Exporting {} data {}".format(type_element, data_dict))
+ element_datas_array.append(data_dict)
+
+ if len(element_datas_array) > 0:
+ json_content[type_element + '_data'] = element_datas_array
+
+ def _export_subject_object_action_categories(self, type_element, json_content):
+ export_method = None
+ if type_element == "subject":
+ export_method = self.__manager.get_subject_categories
+ elif type_element == "object":
+ export_method = self.__manager.get_object_categories
+ if type_element == "action":
+ export_method = self.__manager.get_action_categories
+ element_categories = export_method(moon_user_id=self.__user_id)
+ element_categories_array = []
+ for element_category_key in element_categories:
+ element_category = dict()
+ JsonUtils.copy_field_if_exists(element_categories[element_category_key],
+ element_category, "name", str)
+ JsonUtils.copy_field_if_exists(element_categories[element_category_key],
+ element_category, "description", str)
+ element_categories_array.append(element_category)
+ LOGGER.info("Exporting {} category {}".format(type_element, element_category))
+ if len(element_categories_array) > 0:
+ json_content[type_element + '_categories'] = element_categories_array
+
+ def _export_subject_object_action(self, type_element, json_content):
+ export_method = None
+ if type_element == "subject":
+ export_method = self.__manager.get_subjects
+ elif type_element == "object":
+ export_method = self.__manager.get_objects
+ if type_element == "action":
+ export_method = self.__manager.get_actions
+ policies = self.__manager.get_policies(moon_user_id=self.__user_id)
+ element_dict = dict()
+ elements_array = []
+ for policy_key in policies:
+ elements = export_method(moon_user_id=self.__user_id, policy_id=policy_key)
+ for element_key in elements:
+ element = dict()
+ JsonUtils.copy_field_if_exists(elements[element_key], element, "name", str)
+ JsonUtils.copy_field_if_exists(elements[element_key], element, "description", str)
+ JsonUtils.copy_field_if_exists(elements[element_key], element, "extra", dict)
+ if element["name"] not in element_dict:
+ element["policies"] = []
+ element_dict[element["name"]] = element
+ current_element = element_dict[element["name"]]
+ current_element["policies"].append({"name": JsonUtils.convert_id_to_name_string(
+ policy_key, "policy", self.__manager, self.__user_id)})
+
+ for key in element_dict:
+ LOGGER.info("Exporting {} {}".format(type_element, element_dict[key]))
+ elements_array.append(element_dict[key])
+
+ if len(elements_array) > 0:
+ json_content[type_element + 's'] = elements_array
+
+ def _export_policies(self, json_content):
+ policies = self.__manager.get_policies(moon_user_id = self.__user_id)
+ policies_array = []
+ for policy_key in policies:
+ policy = dict()
+ JsonUtils.copy_field_if_exists(policies[policy_key], policy, "name", str)
+ JsonUtils.copy_field_if_exists(policies[policy_key], policy, "genre", str)
+ JsonUtils.copy_field_if_exists(policies[policy_key], policy, "description", str)
+ JsonUtils.convert_id_to_name(policies[policy_key]["model_id"], policy, "model", "model",
+ self.__manager, self.__user_id)
+ LOGGER.info("Exporting policy {}".format(policy))
+ policies_array.append(policy)
+ if len(policies_array) > 0:
+ json_content["policies"] = policies_array
+
+ def _export_models(self, json_content):
+ models = self.__manager.get_models(moon_user_id=self.__user_id)
+ models_array = []
+ for model_key in models:
+ model = dict()
+ JsonUtils.copy_field_if_exists(models[model_key], model, "name", str)
+ JsonUtils.copy_field_if_exists(models[model_key], model, "description", str)
+ JsonUtils.convert_ids_to_names(models[model_key]["meta_rules"], model, "meta_rules",
+ "meta_rule", self.__manager, self.__user_id)
+ LOGGER.info("Exporting model {}".format(model))
+ models_array.append(model)
+ if len(models_array) > 0:
+ json_content["models"] = models_array
+
+ def _export_pdps(self, json_content):
+ pdps = self.__manager.get_pdp(moon_user_id=self.__user_id)
+ pdps_array = []
+ for pdp_key in pdps:
+ LOGGER.info("Exporting pdp {}".format(pdps[pdp_key]))
+ pdps_array.append(pdps[pdp_key])
+ if len(pdps_array) > 0:
+ json_content["pdps"] = pdps_array
+
+ def export_json(self, **kwargs):
+ if self.__driver == "db":
+ if "moon_user_id" in kwargs:
+ return self.__export_json_from_db(kwargs.get("moon_user_id"))
+ else:
+ raise Exception("Bad argument given...")
+ else:
+ if "body" in kwargs:
+ return self.__export_json_from_db(kwargs.get("body"))
+ else:
+ raise Exception("Bad argument given...")
+
+ def __export_json_from_db(self, moon_user_id=None):
+ self.__user_id = moon_user_id
+
+ json_content = dict()
+
+ LOGGER.info("Exporting pdps...")
+ self._export_pdps(json_content)
+ LOGGER.info("Exporting policies...")
+ self._export_policies(json_content)
+ LOGGER.info("Exporting models...")
+ self._export_models(json_content)
+ # export subjects, subject_data, subject_categories, subject_assignements
+ # idem for object and action
+ list_element = [{"key": "subject"}, {"key": "object"}, {"key": "action"}]
+ for elt in list_element:
+ LOGGER.info("Exporting {}s...".format(elt["key"]))
+ self._export_subject_object_action(elt["key"], json_content)
+ LOGGER.info("Exporting {} categories...".format(elt["key"]))
+ self._export_subject_object_action_categories(elt["key"], json_content)
+ LOGGER.info("Exporting {} data...".format(elt["key"]))
+ self._export_subject_object_action_datas(elt["key"], json_content)
+ LOGGER.info("Exporting {} assignments...".format(elt["key"]))
+ self._export_subject_object_action_assignments(elt["key"], json_content)
+ LOGGER.info("Exporting meta rules...")
+ self._export_meta_rules(json_content)
+ LOGGER.info("Exporting rules...")
+ self._export_rules(json_content)
+
+ return json_content
diff --git a/moon_utilities/moon_utilities/security_functions.py b/moon_utilities/moon_utilities/security_functions.py
new file mode 100644
index 00000000..07aaa965
--- /dev/null
+++ b/moon_utilities/moon_utilities/security_functions.py
@@ -0,0 +1,83 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+
+import logging
+from moon_utilities import exceptions
+import html
+import hug
+
+LOGGER = logging.getLogger("moon.utilities." + __name__)
+
+
+def enforce(action_names, object_name, **extra):
+ """Fake version of the enforce decorator"""
+ def wrapper_func(func):
+ def wrapper_args(*args, **kwargs):
+ # TODO: implement the enforce decorator
+ return func(*args, **kwargs)
+ return wrapper_args
+ return wrapper_func
+
+
+def validate_data(data):
+ def __validate_string(string):
+ temp_str = html.escape(string)
+ if string != temp_str:
+ raise exceptions.ValidationContentError('Forbidden characters in string')
+
+ def __validate_list_or_tuple(container):
+ for i in container:
+ validate_data(i)
+
+ def __validate_dict(dictionary):
+ for key in dictionary:
+ validate_data(dictionary[key])
+
+ if isinstance(data, bool):
+ return True
+ if data is None:
+ data = ""
+ if isinstance(data, str):
+ __validate_string(data)
+ elif isinstance(data, list) or isinstance(data, tuple):
+ __validate_list_or_tuple(data)
+ elif isinstance(data, dict):
+ __validate_dict(data)
+ else:
+ raise exceptions.ValidationContentError('Value is Not String or Container or Dictionary: {}'.format(data))
+
+
+def validate_input(*validators):
+ """Validation only succeeds if all passed in validators return no errors"""
+ body_state = {"name", "id", "category_id", "data_id"}
+
+ def validate_all_input(fields, **kwargs):
+ try:
+ for validator in validators:
+ # errors = validator(fields)
+ if validator not in fields:
+ raise exceptions.ValidationKeyError('Invalid Key :{} not found'.format(validator))
+
+ for field in body_state:
+ if field in fields:
+ try:
+ validate_data(fields[field])
+ except exceptions.ValidationContentError as e:
+ raise exceptions.ValidationContentError("Key: '{}', [{}]".format(field, str(e)))
+ except Exception as e:
+ LOGGER.exception(e)
+ raise e
+ return fields
+
+ validate_all_input.__doc__ = " and ".join(validator.__doc__ for validator in validators)
+ return validate_all_input
diff --git a/moon_utilities/moon_utilities/update_opst_policies.py b/moon_utilities/moon_utilities/update_opst_policies.py
new file mode 100644
index 00000000..4a629181
--- /dev/null
+++ b/moon_utilities/moon_utilities/update_opst_policies.py
@@ -0,0 +1,85 @@
+# Copyright 2019 Orange 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'.
+"""
+Update policy files of an OpenStack platform
+"""
+
+import argparse
+import logging
+import os
+
+
+COMPONENTS = [
+ "cinder",
+ "glance",
+ "keystone",
+ "neutron",
+ "nova",
+]
+
+
+logger = logging.getLogger(__name__)
+
+
+def init():
+ """
+ Initialize the application
+ :return: argument given in the command line
+ """
+ global policy
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--verbose", '-v', action='store_true', help='verbose mode')
+ parser.add_argument("--debug", '-d', action='store_true', help='debug mode')
+ parser.add_argument("--dir",
+ help='directory containing policy files, defaults to /etc',
+ default="/etc")
+ parser.add_argument("--exclude", "-x",
+ help="Exclude some components "
+ "(example: \"nova,neutron\")",
+ default="")
+ parser.add_argument("--include", "-i",
+ help="Only include some components "
+ "(example: \"nova,neutron\")",
+ default="")
+ args = parser.parse_args()
+ logging_format = "%(levelname)s: %(message)s"
+ if args.verbose:
+ logging.basicConfig(level=logging.INFO, format=logging_format)
+ if args.debug:
+ logging.basicConfig(level=logging.DEBUG, format=logging_format)
+ else:
+ logging.basicConfig(format=logging_format)
+
+ return args
+
+
+def update_component(component, args):
+ """
+
+ :param component:
+ :return:
+ """
+ filename = os.path.join(args.dir, component, "policy.json")
+ logger.info(f"Updating {component} ({filename})")
+ if not os.path.isfile(filename):
+ logger.error(f"Cannot find {filename}")
+ return
+
+
+def main():
+ args = init()
+ if args.include:
+ for component in args.include.split(","):
+ update_component(component, args)
+ else:
+ excl_comp = args.exclude.split(",")
+ for component in COMPONENTS:
+ if component in excl_comp:
+ continue
+ update_component(component, args)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/moon_utilities/requirements.txt b/moon_utilities/requirements.txt
new file mode 100644
index 00000000..5c2032c1
--- /dev/null
+++ b/moon_utilities/requirements.txt
@@ -0,0 +1,3 @@
+requests
+hug
+tinydb
diff --git a/moon_utilities/setup.py b/moon_utilities/setup.py
new file mode 100644
index 00000000..f5fa746f
--- /dev/null
+++ b/moon_utilities/setup.py
@@ -0,0 +1,58 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+from setuptools import setup, find_packages
+import moon_utilities
+
+with open('requirements.txt') as f:
+ required = list(filter(
+ lambda s: (len(s.strip()) > 0 and s.strip()[0] != '#'),
+ f.read().split('\n')))
+
+setup(
+
+ name='moon_utilities',
+
+ version=moon_utilities.__version__,
+
+ packages=find_packages(),
+
+ author='Thomas Duval',
+
+ author_email='thomas.duval@orange.com',
+
+ description='Some utilities for all the Moon components',
+
+ long_description=open('README.md').read(),
+
+ install_requires=required,
+
+ include_package_data=True,
+
+ url='',
+
+ classifiers=[
+ 'Programming Language :: Python :: 3',
+ 'Development Status :: 1 - Planning',
+ 'License :: OSI Approved',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ ],
+
+ entry_points={
+ 'console_scripts': [
+ 'generate_opst_policy = moon_utilities.generate_opst_policy:main',
+ ],
+
+ }
+
+)
diff --git a/moon_utilities/tests/unit_python/api/__init__.py b/moon_utilities/tests/unit_python/api/__init__.py
new file mode 100644
index 00000000..1856aa2c
--- /dev/null
+++ b/moon_utilities/tests/unit_python/api/__init__.py
@@ -0,0 +1,12 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
diff --git a/moon_utilities/tests/unit_python/api/test_auth_functions.py b/moon_utilities/tests/unit_python/api/test_auth_functions.py
new file mode 100644
index 00000000..70af19c1
--- /dev/null
+++ b/moon_utilities/tests/unit_python/api/test_auth_functions.py
@@ -0,0 +1,83 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import os
+from uuid import uuid4
+import pytest
+from moon_utilities.auth_functions import xor_encode, xor_decode
+from moon_utilities import exceptions
+from moon_utilities.auth_functions import init_db, add_user, authenticate_user
+from moon_utilities.auth_functions import authenticate_key, get_api_key, del_api_key_for_user
+
+
+def test_xor():
+ uuid1 = uuid4().hex
+ my_key = uuid4().hex
+ crypted_data = xor_encode(uuid1, my_key)
+ assert uuid1 != crypted_data
+ decrypted_data = xor_decode(crypted_data, my_key)
+ assert uuid1 == decrypted_data
+
+
+def test_decrypt_exceptions():
+ with pytest.raises(exceptions.DecryptError):
+ uuid1 = uuid4().hex
+ my_key = uuid4().hex
+ crypted_data = xor_encode(uuid1, my_key)
+ assert uuid1 != crypted_data
+ my_key = False
+ xor_decode(crypted_data, my_key)
+ with pytest.raises(exceptions.DecryptError):
+ uuid1 = uuid4().hex
+ my_key = uuid4().hex
+ crypted_data = xor_encode(uuid1, my_key)
+ assert uuid1 != crypted_data
+ my_key = ""
+ xor_decode(crypted_data, my_key)
+
+
+def test_encrypt_exceptions():
+ with pytest.raises(exceptions.EncryptError):
+ uuid1 = uuid4().hex
+ my_key = False
+ xor_encode(uuid1, my_key)
+ with pytest.raises(exceptions.EncryptError):
+ uuid1 = uuid4().hex
+ my_key = ""
+ xor_encode(uuid1, my_key)
+
+
+def test_auth_api():
+ try:
+ os.remove("/tmp/test.db")
+ except FileNotFoundError:
+ pass
+ init_db("/tmp/test.db")
+ # create the user
+ result = add_user("test_user", "1234567890")
+ assert result
+ # trying to auth the user
+ assert authenticate_user("test_user", "1234567890")
+ assert not authenticate_user("bad_test_user", "1234567890")
+ assert not authenticate_key(None)
+ assert not authenticate_key("")
+ assert authenticate_key(result['api_key']) == "test_user"
+ assert get_api_key("test_user", "1234567890") == result['api_key']
+ # logout the user
+ assert del_api_key_for_user("test_user")
+ assert get_api_key("test_user", "1234567890") != result['api_key']
+ assert get_api_key("test_user", "1234567890") is None
+ # re-authent user
+ assert authenticate_user("test_user", "1234567890")
+ # check that the previous api_key is not valid again
+ assert get_api_key("test_user", "1234567890") != result['api_key']
+ assert get_api_key("test_user", "1234567890")
diff --git a/moon_utilities/tests/unit_python/api/test_import_to_cache.py b/moon_utilities/tests/unit_python/api/test_import_to_cache.py
new file mode 100644
index 00000000..01e717fb
--- /dev/null
+++ b/moon_utilities/tests/unit_python/api/test_import_to_cache.py
@@ -0,0 +1,775 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import helpers.import_export_cache_helper as import_export_helper
+import pytest
+from moon_utilities import exceptions
+
+
+MODEL_WITHOUT_META_RULES = [
+ {"models": [{"name": "test model", "description": "", "meta_rules": []}]},
+ {"models": [{"name": "test model", "description": "new description", "meta_rules": [],
+ "override": True}]},
+ {"models": [{"name": "test model", "description": "description not taken into account",
+ "meta_rules": [], "override": False}]}
+]
+
+POLICIES = [
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}]},
+ {"policies": [{"name": "test policy", "genre": "authz",
+ "description": "new description not taken into account",
+ "model": {"name": "test model"}, "mandatory": True}]},
+ {"policies": [
+ {"name": "test policy", "genre": "not authz ?", "description": "generates an exception",
+ "model": {"name": "test model"}, "override": True}]},
+ {"models": [{"name": "test model", "description": "", "meta_rules": []}], "policies": [
+ {"name": "test policy", "genre": "not authz ?", "description": "changes taken into account",
+ "model": {"name": "test model"}, "override": True}]},
+]
+
+SUBJECTS = [
+ {"subjects": [
+ {"name": "testuser", "description": "description of the subject", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}], "subjects": [
+ {"name": "testuser", "description": "description of the subject", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test other policy", "genre": "authz", "description": "description",
+ "model": {}, "mandatory": True}], "subjects": [
+ {"name": "testuser", "description": "description of the subject", "extra": {},
+ "policies": []}]},
+ {"subjects": [{"name": "testuser", "description": "new description of the subject",
+ "extra": {"email": "new-email@test.com"},
+ "policies": [{"name": "test other policy"}]}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}], "subjects": [
+ {"name": "testuser", "description": "description of the subject", "extra": {},
+ "policies": [{"name": "test policy"}]}]}]
+
+OBJECTS = [
+ {"objects": [{"name": "test object", "description": "description of the object", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}],
+ "objects": [{"name": "test object", "description": "description of the object", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test other policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": True}],
+ "objects": [{"name": "test object", "description": "description of the object", "extra": {},
+ "policies": []}]},
+ {"objects": [{"name": "test object", "description": "new description of the object",
+ "extra": {"test": "test extra"},
+ "policies": [{"name": "test other policy"}]}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}],
+ "objects": [{"name": "test object", "description": "description of the object", "extra": {},
+ "policies": [{"name": "test policy"}]}]},
+]
+
+ACTIONS = [
+ {"actions": [
+ {"name": "test action", "description": "description of the action", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}], "actions": [
+ {"name": "test action", "description": "description of the action", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test other policy", "genre": "authz", "description": "description",
+ "model": {}, "mandatory": True}], "actions": [
+ {"name": "test action", "description": "description of the action", "extra": {},
+ "policies": []}]},
+ {"actions": [{"name": "test action", "description": "new description of the action",
+ "extra": {"test": "test extra"},
+ "policies": [{"name": "test other policy"}]}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}], "actions": [
+ {"name": "test action", "description": "description of the action", "extra": {},
+ "policies": [{"name": "test policy"}]}]}]
+
+SUBJECT_CATEGORIES = [{"subject_categories": [
+ {"name": "test subject categories", "description": "subject category description"}]},
+ {"subject_categories": [{"name": "test subject categories",
+ "description": "new subject category description"}]}]
+
+OBJECT_CATEGORIES = [{"object_categories": [
+ {"name": "test object categories", "description": "object category description"}]},
+ {"object_categories": [{"name": "test object categories",
+ "description": "new object category description"}]}]
+
+ACTION_CATEGORIES = [{"action_categories": [
+ {"name": "test action categories", "description": "action category description"}]},
+ {"action_categories": [{"name": "test action categories",
+ "description": "new action category description"}]}]
+
+# meta_rules import is needed otherwise the search for data do not work !!!
+PRE_DATA = {"models": [
+ {
+ "name": "test model", "description": "",
+ "meta_rules": [{"name": "good meta rule"},
+ {"name": "other good meta rule"}]}],
+ "policies": [
+ {"name": "test other policy", "genre": "authz", "description": "description",
+ "model": {"name": "test model"}, "mandatory": True}],
+ "subject_categories": [
+ {"name": "test subject categories", "description": "subject category description"},
+ {"name": "other test subject categories",
+ "description": "subject category description"}],
+ "object_categories": [
+ {"name": "test object categories", "description": "object category description"},
+ {"name": "other test object categories",
+ "description": "object category description"}],
+ "action_categories": [
+ {"name": "test action categories", "description": "action category description"},
+ {"name": "other test action categories",
+ "description": "action category description"}],
+ "meta_rules": [
+ {
+ "name": "good meta rule", "description": "valid meta rule",
+ "subject_categories": [{"name": "test subject categories"}],
+ "object_categories": [{"name": "test object categories"}],
+ "action_categories": [{"name": "test action categories"}]
+ },
+ {
+ "name": "other good meta rule", "description": "valid meta rule",
+ "subject_categories": [{"name": "other test subject categories"}],
+ "object_categories": [{"name": "other test object categories"}],
+ "action_categories": [{"name": "other test action categories"}]
+ }]}
+
+SUBJECT_DATA = [{"subject_data": [
+ {"name": "not valid subject data", "description": "", "policies": [{}], "category": {}}]},
+ {"subject_data": [
+ {"name": "not valid subject data", "description": "", "policies": [{}],
+ "category": {"name": "test subject categories"}}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description",
+ "model": {"name": "test model"}, "mandatory": True}], "subject_data": [
+ {"name": "one valid subject data", "description": "description",
+ "policies": [{}], "category": {"name": "test subject categories"}}]},
+ {"subject_data": [{"name": "valid subject data", "description": "description",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test subject categories"}}]},
+ {"subject_data": [{"name": "valid subject data", "description": "new description",
+ "policies": [{"name": "test other policy"}],
+ "category": {"name": "test subject categories"}}]}]
+
+OBJECT_DATA = [{"object_data": [
+ {"name": "not valid object data", "description": "", "policies": [{}], "category": {}}]},
+ {"object_data": [
+ {"name": "not valid object data", "description": "", "policies": [{}],
+ "category": {"name": "test object categories"}}]},
+ {"policies": [{"name": "test policy", "genre": "authz", "description": "description",
+ "model": {"name": "test model"}, "mandatory": True}], "object_data": [
+ {"name": "one valid object data", "description": "description", "policies": [{}],
+ "category": {"name": "test object categories"}}]},
+ {"object_data": [{"name": "valid object data", "description": "description",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test object categories"}}]},
+ {"object_data": [{"name": "valid object data", "description": "new description",
+ "policies": [{"name": "test other policy"}],
+ "category": {"name": "test object categories"}}]}]
+
+ACTION_DATA = [{"action_data": [
+ {"name": "not valid action data", "description": "", "policies": [{}], "category": {}}]},
+ {"action_data": [
+ {"name": "not valid action data", "description": "", "policies": [{}],
+ "category": {"name": "test action categories"}}]},
+ {"policies": [{"name": "test policy", "genre": "authz", "description": "description",
+ "model": {"name": "test model"}, "mandatory": True}], "action_data": [
+ {"name": "one valid action data", "description": "description", "policies": [{}],
+ "category": {"name": "test action categories"}}]},
+ {"action_data": [{"name": "valid action data", "description": "description",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test action categories"}}]},
+ {"action_data": [{"name": "valid action data", "description": "new description",
+ "policies": [{"name": "test other policy"}],
+ "category": {"name": "test action categories"}}]}]
+
+PRE_META_RULES = {"subject_categories": [
+ {"name": "test subject categories", "description": "subject category description"}],
+ "object_categories": [{"name": "test object categories",
+ "description": "object category description"}],
+ "action_categories": [{"name": "test action categories",
+ "description": "object action description"}]}
+
+META_RULES = [{"meta_rules": [{"name": "bad meta rule", "description": "not valid meta rule",
+ "subject_categories": [{"name": "not valid category"}],
+ "object_categories": [{"name": "test object categories"}],
+ "action_categories": [{"name": "test action categories"}]}]},
+ {"meta_rules": [{"name": "bad meta rule", "description": "not valid meta rule",
+ "subject_categories": [{"name": "test subject categories"}],
+ "object_categories": [{"name": "not valid category"}],
+ "action_categories": [{"name": "test action categories"}]}]},
+ {"meta_rules": [{"name": "bad meta rule", "description": "not valid meta rule",
+ "subject_categories": [{"name": "test subject categories"}],
+ "object_categories": [{"name": "test object categories"}],
+ "action_categories": [{"name": "not valid category"}]}]},
+ {"meta_rules": [{"name": "good meta rule", "description": "valid meta rule",
+ "subject_categories": [{"name": "test subject categories"}],
+ "object_categories": [{"name": "test object categories"}],
+ "action_categories": [{"name": "test action categories"}]}]}]
+
+PRE_ASSIGNMENTS = {"models": [
+ {"name": "test model", "description": "", "meta_rules": [{"name": "good meta rule"}]}],
+ "policies": [
+ {"name": "test policy", "genre": "authz", "description": "description",
+ "model": {"name": "test model"}, "mandatory": True}],
+ "subject_categories": [{"name": "test subject categories",
+ "description": "subject category description"}],
+ "object_categories": [{"name": "test object categories",
+ "description": "object category description"}],
+ "action_categories": [{"name": "test action categories",
+ "description": "object action description"}],
+ "subjects": [{"name": "testuser", "description": "description of the subject",
+ "extra": {}, "policies": [{"name": "test policy"}]}],
+ "objects": [{"name": "test object", "description": "description of the object",
+ "extra": {}, "policies": [{"name": "test policy"}]}],
+ "actions": [{"name": "test action", "description": "description of the action",
+ "extra": {}, "policies": [{"name": "test policy"}]}],
+ "meta_rules": [{"name": "good meta rule", "description": "valid meta rule",
+ "subject_categories": [{"name": "test subject categories"}],
+ "object_categories": [{"name": "test object categories"}],
+ "action_categories": [{"name": "test action categories"}]}],
+ "subject_data": [{"name": "subject data", "description": "test subject data",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test subject categories"}}],
+ "object_data": [{"name": "object data", "description": "test object data",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test object categories"}}],
+ "action_data": [{"name": "action data", "description": "test action data",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test action categories"}}]}
+
+SUBJECT_ASSIGNMENTS = [
+ {"subject_assignments": [
+ {"subject": {"name": "unknown"},
+ "category": {"name": "test subject categories"},
+ "assignments": [{"name": "subject data"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"subject_assignments": [
+ {"subject": {"name": "testuser"},
+ "category": {"name": "unknown"},
+ "assignments": [{"name": "subject data"}]}],
+ "exception": exceptions.UnknownName
+ },
+ {"subject_assignments": [
+ {"subject": {"name": "testuser"},
+ "category": {"name": "test subject categories"},
+ "assignments": [{"name": "unknown"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"subject_assignments": [
+ {"subject": {"name": "testuser"},
+ "category": {"name": "test subject categories"},
+ "assignments": [{"name": "subject data"}]}],
+ "exception": None
+ }]
+
+OBJECT_ASSIGNMENTS = [
+ {"object_assignments": [
+ {"object": {"name": "unknown"},
+ "category": {"name": "test object categories"},
+ "assignments": [{"name": "object data"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"object_assignments": [
+ {"object": {"name": "test object"},
+ "category": {"name": "unknown"},
+ "assignments": [{"name": "object data"}]}],
+ "exception": exceptions.UnknownName
+ },
+ {"object_assignments": [
+ {"object": {"name": "test object"},
+ "category": {"name": "test object categories"},
+ "assignments": [{"name": "unknown"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"object_assignments": [
+ {"object": {"name": "test object"},
+ "category": {"name": "test object categories"},
+ "assignments": [{"name": "object data"}]}],
+ "exception": None
+ }]
+
+ACTION_ASSIGNMENTS = [
+ {"action_assignments": [
+ {"action": {"name": "unknown"},
+ "category": {"name": "test action categories"},
+ "assignments": [{"name": "action data"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"action_assignments": [
+ {"action": {"name": "test action"},
+ "category": {"name": "unknown"},
+ "assignments": [{"name": "action data"}]}],
+ "exception": exceptions.UnknownName
+ },
+ {"action_assignments": [
+ {"action": {"name": "test action"},
+ "category": {"name": "test action categories"},
+ "assignments": [{"name": "unknown"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"action_assignments": [
+ {"action": {"name": "test action"},
+ "category": {"name": "test action categories"},
+ "assignments": [{"name": "action data"}]}],
+ "exception": None
+ }]
+
+RULES = [{"rules": [{"meta_rule": {"name": "unknown meta rule"}, "policy": {"name": "test "
+ "policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "subject data"}], "object_data": [{"name": "object data"}],
+ "action_data": [{"name": "action data"}]}}]},
+ {"rules": [{"meta_rule": {"name": "good meta rule"}, "policy": {"name": "unknown "
+ "policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "subject data"}],
+ "object_data": [{"name": "object data"}],
+ "action_data": [{"name": "action data"}]}}]},
+ {"rules": [{"meta_rule": {"name": "good meta rule"}, "policy": {"name": "test policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "unknown subject data"}],
+ "object_data": [{"name": "object data"}],
+ "action_data": [{"name": "action data"}]}}]},
+ {"rules": [{"meta_rule": {"name": "good meta rule"}, "policy": {"name": "test policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "subject data"}],
+ "object_data": [{"name": "unknown object data"}],
+ "action_data": [{"name": "action data"}]}}]},
+ {"rules": [{"meta_rule": {"name": "good meta rule"}, "policy": {"name": "test policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "subject data"}],
+ "object_data": [{"name": "object data"}],
+ "action_data": [{"name": "unknown action data"}]}}]},
+ {"rules": [{"meta_rule": {"name": "good meta rule"}, "policy": {"name": "test policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "subject data"}],
+ "object_data": [{"name": "object data"}],
+ "action_data": [{"name": "action data"}]}}]}]
+
+
+def test_import_models_without_new_meta_rules():
+ from moon_utilities import json_utils
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ import_to_cache = json_utils.JsonImport(driver_name="cache", driver=_cache)
+
+ import_export_helper.clean_all()
+ counter = 0
+ for models_description in MODEL_WITHOUT_META_RULES:
+ data = import_to_cache.import_json(body=models_description)
+ assert "models" in data
+ models = _cache.models
+ assert len(list(models.keys())) == 1
+ values = list(models.values())
+ assert values[0]["name"] == "test model"
+ if counter == 0:
+ assert len(values[0]["description"]) == 0
+ if counter == 1 or counter == 2:
+ assert values[0]["description"] == "new description"
+ counter = counter + 1
+ import_export_helper.clean_all()
+
+
+def test_import_policies():
+ from moon_utilities import json_utils
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ import_to_cache = json_utils.JsonImport(driver_name="cache", driver=_cache)
+
+ counter = -1
+ for policy_description in POLICIES:
+ counter = counter + 1
+ if counter == 2:
+ with pytest.raises(exceptions.UnknownName):
+ import_to_cache.import_json(body=policy_description)
+ continue
+ else:
+ data = import_to_cache.import_json(body=policy_description)
+ assert "policies" in data
+ if counter == 2:
+ assert "models" in data
+
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ policies = _cache.policies
+ assert len(list(policies.keys())) == 1
+ values = list(policies.values())
+ assert values[0]["name"] == "test policy"
+ if counter < 3:
+ assert values[0]["genre"] == "authz"
+ assert values[0]["description"] == "description"
+ else:
+ assert values[0]["genre"] == "not authz ?"
+ assert values[0]["description"] == "changes taken into account"
+ assert len(values[0]["model_id"]) > 0
+
+
+def test_import_subject_object_action():
+ from moon_utilities import json_utils
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ import_to_cache = json_utils.JsonImport(driver_name="cache", driver=_cache)
+
+ type_elements = ["subject", "object", "action"]
+
+ for type_element in type_elements:
+ import_export_helper.clean_all()
+ counter = -1
+ # set the getters and the comparison values
+ if type_element == "subject":
+ elements = SUBJECTS
+ clean_method = import_export_helper.clean_subjects
+ name = "testuser"
+ key_extra = "email"
+ value_extra = "new-email@test.com"
+ elif type_element == "object":
+ elements = OBJECTS
+ clean_method = import_export_helper.clean_objects
+ name = "test object"
+ key_extra = "test"
+ value_extra = "test extra"
+ else:
+ elements = ACTIONS
+ clean_method = import_export_helper.clean_actions
+ name = "test action"
+ key_extra = "test"
+ value_extra = "test extra"
+
+ for element in elements:
+ counter = counter + 1
+ if counter == 2 or counter == 4:
+ clean_method()
+ if counter == 3:
+ clean_method()
+ data = import_to_cache.import_json(body=element)
+ elif counter < 2:
+ with pytest.raises(exceptions.PolicyUnknown) as exception_info:
+ import_to_cache.import_json(body=element)
+ assert '400: Policy Unknown' == str(exception_info.value)
+ continue
+ else:
+ data = import_to_cache.import_json(body=element)
+ assert data
+
+ if counter != 3:
+ assert type_element+"s" in data
+ assert "policies" in data
+
+ get_elements = getattr(_cache, type_element + "s")
+
+ policy_key = list(get_elements.keys())[0]
+ assert len(list(get_elements[policy_key].keys())) == 1
+ values = list(get_elements[policy_key].values())
+ assert values[0]["name"] == name
+ if counter == 2 or counter == 4:
+ assert values[0]["description"] == "description of the " + type_element
+ if counter == 3:
+ assert values[0]["description"] == "new description of the " + type_element
+ assert values[0]["extra"][key_extra] == value_extra
+
+ assert len(values[0]["policy_list"]) == 1
+ import_export_helper.clean_all()
+
+
+def test_import_subject_object_action_categories():
+ from moon_utilities import json_utils
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ import_to_cache = json_utils.JsonImport(driver_name="cache", driver=_cache)
+
+ type_elements = ["subject", "object", "action"]
+
+ for type_element in type_elements:
+ import_export_helper.clean_all()
+ counter = -1
+ # set the getters and the comparison values
+ if type_element == "subject":
+ elements = SUBJECT_CATEGORIES
+ elif type_element == "object":
+ elements = OBJECT_CATEGORIES
+ else:
+ elements = ACTION_CATEGORIES
+
+ for element in elements:
+ data = import_to_cache.import_json(body=element)
+ counter = counter + 1
+ assert type_element + "_categories" in data
+ get_elements = getattr(_cache, type_element + "_categories")
+ assert len(list(get_elements.keys())) == 1
+ values = list(get_elements.values())
+ assert values[0]["name"] == "test " + type_element + " categories"
+ assert values[0]["description"] == type_element + " category description"
+
+
+def test_import_meta_rules():
+ from moon_utilities import json_utils
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ import_to_cache = json_utils.JsonImport(driver_name="cache", driver=_cache)
+
+ import_export_helper.clean_all()
+ # import some categories
+ data = import_to_cache.import_json(body=PRE_META_RULES)
+ for cat in ['subject_categories', 'object_categories', 'action_categories']:
+ assert cat in data
+
+ counter = -1
+ for meta_rule in META_RULES:
+ counter = counter + 1
+ if counter != 3:
+ with pytest.raises(exceptions.UnknownName) as exception_info:
+ import_to_cache.import_json(body=meta_rule)
+ assert '400: Unknown Name.' == str(exception_info.value)
+ continue
+ else:
+ data = import_to_cache.import_json(body=meta_rule)
+ assert "meta_rules" in data
+ assert _cache.meta_rules
+
+ meta_rules = _cache.meta_rules
+ key = list(meta_rules.keys())[0]
+ assert isinstance(meta_rules, dict)
+ assert meta_rules[key]["name"] == "good meta rule"
+ assert meta_rules[key]["description"] == "valid meta rule"
+ assert len(meta_rules[key]["subject_categories"]) == 1
+ assert len(meta_rules[key]["object_categories"]) == 1
+ assert len(meta_rules[key]["action_categories"]) == 1
+
+ subject_category_key = meta_rules[key]["subject_categories"][0]
+ object_category_key = meta_rules[key]["object_categories"][0]
+ action_category_key = meta_rules[key]["action_categories"][0]
+
+ sub_cat = _cache.subject_categories
+ assert sub_cat[subject_category_key]["name"] == "test subject categories"
+
+ ob_cat = _cache.object_categories
+ assert ob_cat[object_category_key]["name"] == "test object categories"
+
+ ac_cat = _cache.action_categories
+ assert ac_cat[action_category_key]["name"] == "test action categories"
+
+ import_export_helper.clean_all()
+
+
+def test_import_subject_object_action_assignments():
+ from moon_utilities import json_utils
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ import_to_cache = json_utils.JsonImport(driver_name="cache", driver=_cache)
+
+ import_export_helper.clean_all()
+
+ data = import_to_cache.import_json(body=PRE_ASSIGNMENTS)
+ for item in PRE_ASSIGNMENTS.keys():
+ assert item in data
+
+ type_elements = ["subject", "object", "action"]
+
+ for type_element in type_elements:
+ counter = -1
+ if type_element == "subject":
+ datas = SUBJECT_ASSIGNMENTS
+ elif type_element == "object":
+ datas = OBJECT_ASSIGNMENTS
+ else:
+ datas = ACTION_ASSIGNMENTS
+
+ for assignments in datas:
+ counter = counter + 1
+ my_exception = assignments.pop("exception")
+ if my_exception:
+ with pytest.raises(my_exception) as exception_info:
+ import_to_cache.import_json(body=assignments)
+ assert '400:' in str(exception_info.value)
+ else:
+ data = import_to_cache.import_json(body=assignments)
+ assert type_element+"_assignments" in data
+ assert getattr(_cache, type_element+"_assignments")
+
+ assert len(getattr(_cache, type_element+"_assignments")) == 1
+
+
+def test_import_rules():
+ from moon_utilities import json_utils
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ import_to_cache = json_utils.JsonImport(driver_name="cache", driver=_cache)
+
+ import_export_helper.clean_all()
+
+ data = import_to_cache.import_json(body=PRE_ASSIGNMENTS)
+ for item in PRE_ASSIGNMENTS.keys():
+ assert item in data
+
+ counter = -1
+ for rule in RULES:
+ counter = counter + 1
+ if counter < 5:
+ with pytest.raises(exceptions.UnknownName) as exception_info:
+ import_to_cache.import_json(body=rule)
+
+ assert '400: Unknown Name.' == str(exception_info.value)
+ continue
+ data = import_to_cache.import_json(body=rule)
+ assert "rules" in data
+ policies = _cache.policies
+ policy_id = None
+ for policy in policies:
+ if policies[policy]['name'] == rule['rules'][0]['policy']['name']:
+ policy_id = policy
+ break
+
+ assert policy_id
+ rules = _cache.rules
+ assert len(rules) == 1
+ rule_content = list(rules.values())[0]
+ assert policy_id == rule_content["policy_id"]
+ assert rule_content["rules"]
+ assert len(rule_content["rules"]) == 1
+ assert rule_content["rules"][0]["enabled"]
+ assert rule_content["rules"][0]["instructions"][0]["decision"] == "grant"
+
+ meta_rules = _cache.meta_rules
+ assert meta_rules[list(meta_rules.keys())[0]]["name"] == "good meta rule"
+
+
+def test_import_subject_object_action_data():
+ from moon_utilities import json_utils
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ import_to_cache = json_utils.JsonImport(driver_name="cache", driver=_cache)
+
+ type_elements = ["subject", "object", "action"]
+
+ for type_element in type_elements:
+ import_export_helper.clean_all()
+ data = import_to_cache.import_json(body=PRE_DATA)
+ for key in PRE_DATA.keys():
+ assert key in data
+ counter = -1
+ if type_element == "subject":
+ elements = SUBJECT_DATA
+ get_method = _cache.subject_data
+ get_categories = _cache.subject_categories
+ elif type_element == "object":
+ elements = OBJECT_DATA
+ get_method = _cache.object_data
+ get_categories = _cache.object_categories
+ else:
+ elements = ACTION_DATA
+ get_method = _cache.action_data
+ get_categories = _cache.action_categories
+
+ for element in elements:
+ counter = counter + 1
+ if counter == 0 or counter == 1:
+ with pytest.raises(exceptions.MissingIdOrName) as exception_info:
+ import_to_cache.import_json(body=element)
+ assert '400: Missing ID or Name.' == str(exception_info.value)
+ continue
+ else:
+ data = import_to_cache.import_json(body=element)
+ for key in element.keys():
+ assert key in data
+
+ policies = _cache.policies
+ categories = get_categories
+ case_tested = False
+ for policy_key in policies.keys():
+ policy = policies[policy_key]
+ for category_key in categories:
+ get_elements = get_method
+ _all_data = []
+ for _data in get_elements:
+ if category_key == _data["category_id"] and policy_key == _data["policy_id"]:
+ _all_data.append(_data)
+ get_elements = _all_data
+ if not get_elements:
+ continue
+ if policy["name"] == "test policy":
+ assert len(get_elements) == 1
+ el = get_elements[0]
+ assert isinstance(el["data"], dict)
+ if counter == 2:
+ assert len(el["data"].keys()) == 1
+ el = el["data"][list(el["data"].keys())[0]]
+ if "value" in el:
+ el = el["value"]
+ assert el["name"] == "one valid " + type_element + " data"
+ if counter == 3:
+ assert len(el["data"].keys()) == 2
+ el1 = el["data"][list(el["data"].keys())[0]]
+ el2 = el["data"][list(el["data"].keys())[1]]
+ if "value" in el1:
+ el1 = el1["value"]
+ el2 = el2["value"]
+ assert (el1["name"] == "one valid " + type_element + " data" and el2[
+ "name"] == "valid " + type_element + " data") or (el2[
+ "name"] == "one valid " + type_element + " data" and
+ el1[
+ "name"] == "valid " + type_element + " data")
+ assert el1["description"] == "description"
+ assert el2["description"] == "description"
+
+ case_tested = True
+
+ if policy["name"] == "test other policy":
+ if counter == 4:
+ assert len(get_elements) == 1
+ el = get_elements[0]
+ assert isinstance(el["data"], dict)
+ assert len(el["data"].keys()) == 1
+ el = el["data"][list(el["data"].keys())[0]]
+ if "value" in el:
+ el = el["value"]
+ assert el["name"] == "valid " + type_element + " data"
+ assert el["description"] == "new description"
+ case_tested = True
+
+ assert case_tested is True
+
+
+def test_clean():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ import_export_helper.clean_all()
+ assert not _cache.subject_categories
+ assert not _cache.object_categories
+ assert not _cache.action_categories
+ assert not _cache.subjects
+ assert not _cache.objects
+ assert not _cache.actions
+ assert not _cache.subject_data
+ assert not _cache.object_data
+ assert not _cache.action_data
+ assert not _cache.subject_assignments
+ assert not _cache.object_assignments
+ assert not _cache.action_assignments
+ assert not _cache.models
+ assert not _cache.pdp
+ assert not _cache.policies
diff --git a/moon_utilities/tests/unit_python/api/test_import_to_db.py b/moon_utilities/tests/unit_python/api/test_import_to_db.py
new file mode 100644
index 00000000..34479b8c
--- /dev/null
+++ b/moon_utilities/tests/unit_python/api/test_import_to_db.py
@@ -0,0 +1,772 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import pytest
+from moon_utilities import exceptions
+import helpers.import_export_db_helper as import_export_helper
+
+
+MODEL_WITHOUT_META_RULES = [
+ {"models": [{"name": "test model", "description": "", "meta_rules": []}]},
+ {"models": [{"name": "test model", "description": "new description", "meta_rules": [],
+ "override": True}]},
+ {"models": [{"name": "test model", "description": "description not taken into account",
+ "meta_rules": [], "override": False}]}
+]
+
+POLICIES = [
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}]},
+ {"policies": [{"name": "test policy", "genre": "authz",
+ "description": "new description not taken into account",
+ "model": {"name": "test model"}, "mandatory": True}]},
+ {"policies": [
+ {"name": "test policy", "genre": "not authz ?", "description": "generates an exception",
+ "model": {"name": "test model"}, "override": True}]},
+ {"models": [{"name": "test model", "description": "", "meta_rules": []}], "policies": [
+ {"name": "test policy", "genre": "not authz ?", "description": "changes taken into account",
+ "model": {"name": "test model"}, "override": True}]},
+]
+
+SUBJECTS = [
+ {"subjects": [
+ {"name": "testuser", "description": "description of the subject", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}], "subjects": [
+ {"name": "testuser", "description": "description of the subject", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test other policy", "genre": "authz", "description": "description",
+ "model": {}, "mandatory": True}], "subjects": [
+ {"name": "testuser", "description": "description of the subject", "extra": {},
+ "policies": []}]},
+ {"subjects": [{"name": "testuser", "description": "new description of the subject",
+ "extra": {"email": "new-email@test.com"},
+ "policies": [{"name": "test other policy"}]}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}], "subjects": [
+ {"name": "testuser", "description": "description of the subject", "extra": {},
+ "policies": [{"name": "test policy"}]}]}]
+
+OBJECTS = [
+ {"objects": [{"name": "test object", "description": "description of the object", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}],
+ "objects": [{"name": "test object", "description": "description of the object", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test other policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": True}],
+ "objects": [{"name": "test object", "description": "description of the object", "extra": {},
+ "policies": []}]},
+ {"objects": [{"name": "test object", "description": "new description of the object",
+ "extra": {"test": "test extra"},
+ "policies": [{"name": "test other policy"}]}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}],
+ "objects": [{"name": "test object", "description": "description of the object", "extra": {},
+ "policies": [{"name": "test policy"}]}]},
+]
+
+ACTIONS = [{"actions": [
+ {"name": "test action", "description": "description of the action", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}], "actions": [
+ {"name": "test action", "description": "description of the action", "extra": {},
+ "policies": []}]},
+ {"policies": [
+ {"name": "test other policy", "genre": "authz", "description": "description",
+ "model": {}, "mandatory": True}], "actions": [
+ {"name": "test action", "description": "description of the action", "extra": {},
+ "policies": []}]},
+ {"actions": [{"name": "test action", "description": "new description of the action",
+ "extra": {"test": "test extra"},
+ "policies": [{"name": "test other policy"}]}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description", "model": {},
+ "mandatory": False}], "actions": [
+ {"name": "test action", "description": "description of the action", "extra": {},
+ "policies": [{"name": "test policy"}]}]}]
+
+SUBJECT_CATEGORIES = [{"subject_categories": [
+ {"name": "test subject categories", "description": "subject category description"}]},
+ {"subject_categories": [{"name": "test subject categories",
+ "description": "new subject category description"}]}]
+
+OBJECT_CATEGORIES = [{"object_categories": [
+ {"name": "test object categories", "description": "object category description"}]},
+ {"object_categories": [{"name": "test object categories",
+ "description": "new object category description"}]}]
+
+ACTION_CATEGORIES = [{"action_categories": [
+ {"name": "test action categories", "description": "action category description"}]},
+ {"action_categories": [{"name": "test action categories",
+ "description": "new action category description"}]}]
+
+# meta_rules import is needed otherwise the search for data do not work !!!
+PRE_DATA = {"models": [{"name": "test model", "description": "",
+ "meta_rules": [{"name": "good meta rule"},
+ {"name": "other good meta rule"}]}],
+ "policies": [
+ {"name": "test other policy", "genre": "authz", "description": "description",
+ "model": {"name": "test model"}, "mandatory": True}],
+ "subject_categories": [
+ {"name": "test subject categories", "description": "subject category description"},
+ {"name": "other test subject categories",
+ "description": "subject category description"}],
+ "object_categories": [
+ {"name": "test object categories", "description": "object category description"},
+ {"name": "other test object categories",
+ "description": "object category description"}],
+ "action_categories": [
+ {"name": "test action categories", "description": "action category description"},
+ {"name": "other test action categories",
+ "description": "action category description"}],
+ "meta_rules": [{"name": "good meta rule", "description": "valid meta rule",
+ "subject_categories": [{"name": "test subject categories"}],
+ "object_categories": [{"name": "test object categories"}],
+ "action_categories": [{"name": "test action categories"}]},
+ {"name": "other good meta rule", "description": "valid meta rule",
+ "subject_categories": [{"name": "other test subject categories"}],
+ "object_categories": [{"name": "other test object categories"}],
+ "action_categories": [{"name": "other test action categories"}]}]}
+
+SUBJECT_DATA = [{"subject_data": [
+ {"name": "not valid subject data", "description": "", "policies": [{}], "category": {}}]},
+ {"subject_data": [
+ {"name": "not valid subject data", "description": "", "policies": [{}],
+ "category": {"name": "test subject categories"}}]},
+ {"policies": [
+ {"name": "test policy", "genre": "authz", "description": "description",
+ "model": {"name": "test model"}, "mandatory": True}], "subject_data": [
+ {"name": "one valid subject data", "description": "description",
+ "policies": [{}], "category": {"name": "test subject categories"}}]},
+ {"subject_data": [{"name": "valid subject data", "description": "description",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test subject categories"}}]},
+ {"subject_data": [{"name": "valid subject data", "description": "new description",
+ "policies": [{"name": "test other policy"}],
+ "category": {"name": "test subject categories"}}]}]
+
+OBJECT_DATA = [{"object_data": [
+ {"name": "not valid object data", "description": "", "policies": [{}], "category": {}}]},
+ {"object_data": [
+ {"name": "not valid object data", "description": "", "policies": [{}],
+ "category": {"name": "test object categories"}}]},
+ {"policies": [{"name": "test policy", "genre": "authz", "description": "description",
+ "model": {"name": "test model"}, "mandatory": True}], "object_data": [
+ {"name": "one valid object data", "description": "description", "policies": [{}],
+ "category": {"name": "test object categories"}}]},
+ {"object_data": [{"name": "valid object data", "description": "description",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test object categories"}}]},
+ {"object_data": [{"name": "valid object data", "description": "new description",
+ "policies": [{"name": "test other policy"}],
+ "category": {"name": "test object categories"}}]}]
+
+ACTION_DATA = [{"action_data": [
+ {"name": "not valid action data", "description": "", "policies": [{}], "category": {}}]},
+ {"action_data": [
+ {"name": "not valid action data", "description": "", "policies": [{}],
+ "category": {"name": "test action categories"}}]},
+ {"policies": [{"name": "test policy", "genre": "authz", "description": "description",
+ "model": {"name": "test model"}, "mandatory": True}], "action_data": [
+ {"name": "one valid action data", "description": "description", "policies": [{}],
+ "category": {"name": "test action categories"}}]},
+ {"action_data": [{"name": "valid action data", "description": "description",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test action categories"}}]},
+ {"action_data": [{"name": "valid action data", "description": "new description",
+ "policies": [{"name": "test other policy"}],
+ "category": {"name": "test action categories"}}]}]
+
+PRE_META_RULES = {"subject_categories": [
+ {"name": "test subject categories", "description": "subject category description"}],
+ "object_categories": [{"name": "test object categories",
+ "description": "object category description"}],
+ "action_categories": [{"name": "test action categories",
+ "description": "object action description"}]}
+
+META_RULES = [{"meta_rules": [{"name": "bad meta rule", "description": "not valid meta rule",
+ "subject_categories": [{"name": "not valid category"}],
+ "object_categories": [{"name": "test object categories"}],
+ "action_categories": [{"name": "test action categories"}]}]},
+ {"meta_rules": [{"name": "bad meta rule", "description": "not valid meta rule",
+ "subject_categories": [{"name": "test subject categories"}],
+ "object_categories": [{"name": "not valid category"}],
+ "action_categories": [{"name": "test action categories"}]}]},
+ {"meta_rules": [{"name": "bad meta rule", "description": "not valid meta rule",
+ "subject_categories": [{"name": "test subject categories"}],
+ "object_categories": [{"name": "test object categories"}],
+ "action_categories": [{"name": "not valid category"}]}]},
+ {"meta_rules": [{"name": "good meta rule", "description": "valid meta rule",
+ "subject_categories": [{"name": "test subject categories"}],
+ "object_categories": [{"name": "test object categories"}],
+ "action_categories": [{"name": "test action categories"}]}]}]
+
+PRE_ASSIGNMENTS = {"models": [
+ {"name": "test model", "description": "", "meta_rules": [{"name": "good meta rule"}]}],
+ "policies": [
+ {"name": "test policy", "genre": "authz", "description": "description",
+ "model": {"name": "test model"}, "mandatory": True}],
+ "subject_categories": [{"name": "test subject categories",
+ "description": "subject category description"}],
+ "object_categories": [{"name": "test object categories",
+ "description": "object category description"}],
+ "action_categories": [{"name": "test action categories",
+ "description": "object action description"}],
+ "subjects": [{"name": "testuser", "description": "description of the subject",
+ "extra": {}, "policies": [{"name": "test policy"}]}],
+ "objects": [{"name": "test object", "description": "description of the object",
+ "extra": {}, "policies": [{"name": "test policy"}]}],
+ "actions": [{"name": "test action", "description": "description of the action",
+ "extra": {}, "policies": [{"name": "test policy"}]}],
+ "meta_rules": [{"name": "good meta rule", "description": "valid meta rule",
+ "subject_categories": [{"name": "test subject categories"}],
+ "object_categories": [{"name": "test object categories"}],
+ "action_categories": [{"name": "test action categories"}]}],
+ "subject_data": [{"name": "subject data", "description": "test subject data",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test subject categories"}}],
+ "object_data": [{"name": "object data", "description": "test object data",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test object categories"}}],
+ "action_data": [{"name": "action data", "description": "test action data",
+ "policies": [{"name": "test policy"}],
+ "category": {"name": "test action categories"}}]}
+
+SUBJECT_ASSIGNMENTS = [
+ {"subject_assignments": [
+ {"subject": {"name": "unknown"},
+ "category": {"name": "test subject categories"},
+ "assignments": [{"name": "subject data"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"subject_assignments": [
+ {"subject": {"name": "testuser"},
+ "category": {"name": "unknown"},
+ "assignments": [{"name": "subject data"}]}],
+ "exception": exceptions.UnknownName
+ },
+ {"subject_assignments": [
+ {"subject": {"name": "testuser"},
+ "category": {"name": "test subject categories"},
+ "assignments": [{"name": "unknown"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"subject_assignments": [
+ {"subject": {"name": "testuser"},
+ "category": {"name": "test subject categories"},
+ "assignments": [{"name": "subject data"}]}],
+ "exception": None
+ }]
+
+OBJECT_ASSIGNMENTS = [
+ {"object_assignments": [
+ {"object": {"name": "unknown"},
+ "category": {"name": "test object categories"},
+ "assignments": [{"name": "object data"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"object_assignments": [
+ {"object": {"name": "test object"},
+ "category": {"name": "unknown"},
+ "assignments": [{"name": "object data"}]}],
+ "exception": exceptions.UnknownName
+ },
+ {"object_assignments": [
+ {"object": {"name": "test object"},
+ "category": {"name": "test object categories"},
+ "assignments": [{"name": "unknown"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"object_assignments": [
+ {"object": {"name": "test object"},
+ "category": {"name": "test object categories"},
+ "assignments": [{"name": "object data"}]}],
+ "exception": None
+ }]
+
+ACTION_ASSIGNMENTS = [
+ {"action_assignments": [
+ {"action": {"name": "unknown"},
+ "category": {"name": "test action categories"},
+ "assignments": [{"name": "action data"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"action_assignments": [
+ {"action": {"name": "test action"},
+ "category": {"name": "unknown"},
+ "assignments": [{"name": "action data"}]}],
+ "exception": exceptions.UnknownName
+ },
+ {"action_assignments": [
+ {"action": {"name": "test action"},
+ "category": {"name": "test action categories"},
+ "assignments": [{"name": "unknown"}]}],
+ "exception": exceptions.InvalidJson
+ },
+ {"action_assignments": [
+ {"action": {"name": "test action"},
+ "category": {"name": "test action categories"},
+ "assignments": [{"name": "action data"}]}],
+ "exception": None
+ }]
+
+RULES = [{"rules": [{"meta_rule": {"name": "unknown meta rule"}, "policy": {"name": "test "
+ "policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "subject data"}], "object_data": [{"name": "object data"}],
+ "action_data": [{"name": "action data"}]}}]},
+ {"rules": [{"meta_rule": {"name": "good meta rule"}, "policy": {"name": "unknown "
+ "policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "subject data"}],
+ "object_data": [{"name": "object data"}],
+ "action_data": [{"name": "action data"}]}}]},
+ {"rules": [{"meta_rule": {"name": "good meta rule"}, "policy": {"name": "test policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "unknown subject data"}],
+ "object_data": [{"name": "object data"}],
+ "action_data": [{"name": "action data"}]}}]},
+ {"rules": [{"meta_rule": {"name": "good meta rule"}, "policy": {"name": "test policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "subject data"}],
+ "object_data": [{"name": "unknown object data"}],
+ "action_data": [{"name": "action data"}]}}]},
+ {"rules": [{"meta_rule": {"name": "good meta rule"}, "policy": {"name": "test policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "subject data"}],
+ "object_data": [{"name": "object data"}],
+ "action_data": [{"name": "unknown action data"}]}}]},
+ {"rules": [{"meta_rule": {"name": "good meta rule"}, "policy": {"name": "test policy"},
+ "instructions": ({"decision": "grant"},), "enabled": True, "rule": {
+ "subject_data": [{"name": "subject data"}],
+ "object_data": [{"name": "object data"}],
+ "action_data": [{"name": "action data"}]}}]}]
+
+
+def test_import_models_without_new_meta_rules():
+ from moon_utilities import json_utils
+ from moon_manager import db_driver
+ import_to_db = json_utils.JsonImport(driver_name="db", driver=db_driver)
+ _cache = import_to_db.driver
+
+ import_export_helper.clean_all()
+ counter = 0
+ for models_description in MODEL_WITHOUT_META_RULES:
+ data = import_to_db.import_json(body=models_description)
+ assert "models" in data
+ models = _cache.get_models()
+ assert len(list(models.keys())) == 1
+ values = list(models.values())
+ assert values[0]["name"] == "test model"
+ if counter == 0:
+ assert len(values[0]["description"]) == 0
+ if counter == 1 or counter == 2:
+ assert values[0]["description"] == "new description"
+ counter = counter + 1
+ import_export_helper.clean_all()
+
+
+def test_import_policies():
+ from moon_utilities import json_utils
+ from moon_manager import db_driver
+ import_to_db = json_utils.JsonImport(driver_name="db", driver=db_driver)
+ _cache = import_to_db.driver
+
+ counter = -1
+ for policy_description in POLICIES:
+ counter = counter + 1
+ if counter == 2:
+ with pytest.raises(exceptions.UnknownName):
+ import_to_db.import_json(body=policy_description)
+ continue
+ else:
+ data = import_to_db.import_json(body=policy_description)
+ assert "policies" in data
+ if counter == 2:
+ assert "models" in data
+
+ policies = db_driver.PolicyManager.get_policies(moon_user_id="admin")
+ assert len(list(policies.keys())) == 1
+ values = list(policies.values())
+ assert values[0]["name"] == "test policy"
+ if counter < 3:
+ assert values[0]["genre"] == "authz"
+ assert values[0]["description"] == "description"
+ else:
+ assert values[0]["genre"] == "not authz ?"
+ assert values[0]["description"] == "changes taken into account"
+ assert len(values[0]["model_id"]) > 0
+
+
+def test_import_subject_object_action():
+ from moon_utilities import json_utils
+ from moon_manager import db_driver
+ import_to_db = json_utils.JsonImport(driver_name="db", driver=db_driver)
+ _cache = import_to_db.driver
+
+ type_elements = ["subject", "object", "action"]
+
+ for type_element in type_elements:
+ import_export_helper.clean_all()
+ counter = -1
+ # set the getters and the comparison values
+ if type_element == "subject":
+ elements = SUBJECTS
+ clean_method = import_export_helper.clean_subjects
+ name = "testuser"
+ key_extra = "email"
+ value_extra = "new-email@test.com"
+ elif type_element == "object":
+ elements = OBJECTS
+ clean_method = import_export_helper.clean_objects
+ name = "test object"
+ key_extra = "test"
+ value_extra = "test extra"
+ else:
+ elements = ACTIONS
+ clean_method = import_export_helper.clean_actions
+ name = "test action"
+ key_extra = "test"
+ value_extra = "test extra"
+
+ for element in elements:
+ counter = counter + 1
+ if counter == 2 or counter == 4:
+ clean_method()
+ if counter == 3:
+ clean_method()
+ data = import_to_db.import_json(body=element)
+ elif counter < 2:
+ with pytest.raises(exceptions.PolicyUnknown) as exception_info:
+ import_to_db.import_json(body=element)
+ assert '400: Policy Unknown' == str(exception_info.value)
+ continue
+ else:
+ data = import_to_db.import_json(body=element)
+ assert data
+
+ if counter != 3:
+ assert type_element+"s" in data
+ assert "policies" in data
+
+ get_elements = getattr(_cache, type_element + "s")
+
+ assert len(list(get_elements.keys())) == 1
+ values = list(get_elements.values())
+ assert values[0]["name"] == name
+ if counter == 2 or counter == 4:
+ assert values[0]["description"] == "description of the " + type_element
+ if counter == 3:
+ assert values[0]["description"] == "new description of the " + type_element
+ assert values[0]["extra"][key_extra] == value_extra
+
+ assert len(values[0]["policy_list"]) == 1
+ import_export_helper.clean_all()
+
+
+def test_import_subject_object_action_categories():
+ from moon_utilities import json_utils
+ from moon_manager import db_driver
+ import_to_db = json_utils.JsonImport(driver_name="db", driver=db_driver)
+ _cache = import_to_db.driver
+
+ type_elements = ["subject", "object", "action"]
+
+ for type_element in type_elements:
+ import_export_helper.clean_all()
+ counter = -1
+ # set the getters and the comparison values
+ if type_element == "subject":
+ elements = SUBJECT_CATEGORIES
+ elif type_element == "object":
+ elements = OBJECT_CATEGORIES
+ else:
+ elements = ACTION_CATEGORIES
+
+ for element in elements:
+ data = import_to_db.import_json(body=element)
+ counter = counter + 1
+ assert type_element + "_categories" in data
+ get_elements = getattr(_cache, type_element + "_categories")
+ assert len(list(get_elements.keys())) == 1
+ values = list(get_elements.values())
+ assert values[0]["name"] == "test " + type_element + " categories"
+ assert values[0]["description"] == type_element + " category description"
+
+
+def test_import_meta_rules():
+ from moon_utilities import json_utils
+ from moon_manager import db_driver
+ import_to_db = json_utils.JsonImport(driver_name="db", driver=db_driver)
+ _cache = import_to_db.driver
+
+ import_export_helper.clean_all()
+ # import some categories
+ data = import_to_db.import_json(body=PRE_META_RULES)
+ for cat in ['subject_categories', 'object_categories', 'action_categories']:
+ assert cat in data
+
+ counter = -1
+ for meta_rule in META_RULES:
+ counter = counter + 1
+ if counter != 3:
+ with pytest.raises(exceptions.UnknownName) as exception_info:
+ import_to_db.import_json(body=meta_rule)
+ assert '400: Unknown Name.' == str(exception_info.value)
+ continue
+ else:
+ data = import_to_db.import_json(body=meta_rule)
+ assert "meta_rules" in data
+ assert _cache.meta_rules
+
+ meta_rules = _cache.meta_rules
+ key = list(meta_rules.keys())[0]
+ assert isinstance(meta_rules, dict)
+ assert meta_rules[key]["name"] == "good meta rule"
+ assert meta_rules[key]["description"] == "valid meta rule"
+ assert len(meta_rules[key]["subject_categories"]) == 1
+ assert len(meta_rules[key]["object_categories"]) == 1
+ assert len(meta_rules[key]["action_categories"]) == 1
+
+ subject_category_key = meta_rules[key]["subject_categories"][0]
+ object_category_key = meta_rules[key]["object_categories"][0]
+ action_category_key = meta_rules[key]["action_categories"][0]
+
+ sub_cat = _cache.subject_categories
+ assert sub_cat[subject_category_key]["name"] == "test subject categories"
+
+ ob_cat = _cache.object_categories
+ assert ob_cat[object_category_key]["name"] == "test object categories"
+
+ ac_cat = _cache.action_categories
+ assert ac_cat[action_category_key]["name"] == "test action categories"
+
+ import_export_helper.clean_all()
+
+
+def test_import_subject_object_action_assignments():
+ from moon_utilities import json_utils
+ from moon_manager import db_driver
+ import_to_db = json_utils.JsonImport(driver_name="db", driver=db_driver)
+ _cache = import_to_db.driver
+
+ import_export_helper.clean_all()
+
+ data = import_to_db.import_json(body=PRE_ASSIGNMENTS)
+ for item in PRE_ASSIGNMENTS.keys():
+ assert item in data
+
+ type_elements = ["subject", "object", "action"]
+
+ for type_element in type_elements:
+ counter = -1
+ if type_element == "subject":
+ datas = SUBJECT_ASSIGNMENTS
+ elif type_element == "object":
+ datas = OBJECT_ASSIGNMENTS
+ else:
+ datas = ACTION_ASSIGNMENTS
+
+ for assignments in datas:
+ counter = counter + 1
+ my_exception = assignments.pop("exception")
+ if my_exception:
+ with pytest.raises(my_exception) as exception_info:
+ import_to_db.import_json(body=assignments)
+ assert '400:' in str(exception_info.value)
+ else:
+ data = import_to_db.import_json(body=assignments)
+ assert type_element+"_assignments" in data
+ assert getattr(_cache, type_element+"_assignments")
+
+ assert len(getattr(_cache, type_element+"_assignments")) == 1
+
+
+def test_import_rules():
+ from moon_utilities import json_utils
+ from moon_manager import db_driver
+ import_to_db = json_utils.JsonImport(driver_name="db", driver=db_driver)
+ _cache = import_to_db.driver
+
+ import_export_helper.clean_all()
+
+ data = import_to_db.import_json(body=PRE_ASSIGNMENTS)
+ for item in PRE_ASSIGNMENTS.keys():
+ assert item in data
+
+ counter = -1
+ for rule in RULES:
+ counter = counter + 1
+ if counter < 5:
+ with pytest.raises(exceptions.UnknownName) as exception_info:
+ import_to_db.import_json(body=rule)
+
+ assert '400: Unknown Name.' == str(exception_info.value)
+ continue
+ data = import_to_db.import_json(body=rule)
+ assert "rules" in data
+ policies = _cache.policies
+ policy_id = None
+ for policy in policies:
+ if policies[policy]['name'] == rule['rules'][0]['policy']['name']:
+ policy_id = policy
+ break
+
+ assert policy_id
+ rules = []
+ for _rule in _cache.rules:
+ if policy_id == _rule['policy_id']:
+ rules.append(_rule)
+ assert len(rules) == 1
+ rule_content = rules[0]
+ assert policy_id == rule_content["policy_id"]
+ assert rule_content["rules"]
+ assert len(rule_content["rules"]) == 1
+ # FIXME: this is different from cache tests (where we have a "value" attribute)
+ assert rule_content["rules"][0]["enabled"]
+ assert rule_content["rules"][0]["instructions"][0]["decision"] == "grant"
+
+ meta_rules = _cache.meta_rules
+ assert meta_rules[list(meta_rules.keys())[0]]["name"] == "good meta rule"
+
+
+def test_import_subject_object_action_data():
+ from moon_utilities import json_utils
+ from moon_manager import db_driver
+ import_to_db = json_utils.JsonImport(driver_name="db", driver=db_driver)
+ _cache = import_to_db.driver
+
+ type_elements = ["subject", "object", "action"]
+
+ for type_element in type_elements:
+ import_export_helper.clean_all()
+ data = import_to_db.import_json(body=PRE_DATA)
+ for key in PRE_DATA.keys():
+ assert key in data
+ counter = -1
+ if type_element == "subject":
+ elements = SUBJECT_DATA
+ get_method = _cache.get_subject_data
+ get_categories = _cache.subject_categories
+ elif type_element == "object":
+ elements = OBJECT_DATA
+ get_method = _cache.get_object_data
+ get_categories = _cache.object_categories
+ else:
+ elements = ACTION_DATA
+ get_method = _cache.get_action_data
+ get_categories = _cache.action_categories
+
+ for element in elements:
+ counter = counter + 1
+ if counter == 0 or counter == 1:
+ with pytest.raises(exceptions.MissingIdOrName) as exception_info:
+ import_to_db.import_json(body=element)
+ assert '400: Missing ID or Name.' == str(exception_info.value)
+ continue
+ else:
+ data = import_to_db.import_json(body=element)
+ for key in element.keys():
+ assert key in data
+
+ policies = _cache.policies
+ categories = get_categories
+ case_tested = False
+ for policy_key in policies.keys():
+ policy = policies[policy_key]
+ for category_key in categories:
+ get_elements = get_method(policy_id=policy_key, category_id=category_key)
+ _all_data = []
+ for _data in get_elements:
+ if category_key == _data["category_id"] and \
+ policy_key == _data["policy_id"]:
+ _all_data.append(_data)
+ get_elements = _all_data
+ if not get_elements:
+ continue
+ if policy["name"] == "test policy":
+ assert len(get_elements) == 1
+ el = get_elements[0]
+ assert isinstance(el["data"], dict)
+ if counter == 2:
+ assert len(el["data"].keys()) == 1
+ el = el["data"][list(el["data"].keys())[0]]
+ if "value" in el:
+ el = el["value"]
+ assert el["name"] == "one valid " + type_element + " data"
+ if counter == 3:
+ assert len(el["data"].keys()) == 2
+ el1 = el["data"][list(el["data"].keys())[0]]
+ el2 = el["data"][list(el["data"].keys())[1]]
+ if "value" in el1:
+ el1 = el1["value"]
+ el2 = el2["value"]
+ assert (el1["name"] == "one valid " + type_element + " data" and
+ el2["name"] == "valid " + type_element + " data") or \
+ (el2["name"] == "one valid " + type_element + " data" and
+ el1["name"] == "valid " + type_element + " data")
+ assert el1["description"] == "description"
+ assert el2["description"] == "description"
+
+ case_tested = True
+ break
+
+ if policy["name"] == "test other policy":
+ if counter == 4:
+ assert len(get_elements) == 1
+ el = get_elements[0]
+ assert isinstance(el["data"], dict)
+ assert len(el["data"].keys()) == 1
+ el = el["data"][list(el["data"].keys())[0]]
+ if "value" in el:
+ el = el["value"]
+ assert el["name"] == "valid " + type_element + " data"
+ assert el["description"] == "new description"
+ case_tested = True
+ break
+
+ assert case_tested is True
+
+
+def test_clean():
+ from moon_utilities import json_utils
+ from moon_manager import db_driver
+ import_to_db = json_utils.JsonImport(driver_name="db", driver=db_driver)
+ _cache = import_to_db.driver
+ import_export_helper.clean_all()
+ assert not _cache.subject_categories
+ assert not _cache.object_categories
+ assert not _cache.action_categories
+ assert not _cache.subjects
+ assert not _cache.objects
+ assert not _cache.actions
+ assert not _cache.subject_data
+ assert not _cache.object_data
+ assert not _cache.action_data
+ assert not _cache.subject_assignments
+ assert not _cache.object_assignments
+ assert not _cache.action_assignments
+ assert not _cache.models
+ assert not _cache.pdp
+ assert not _cache.policies
diff --git a/moon_utilities/tests/unit_python/api/test_invalidate_function.py b/moon_utilities/tests/unit_python/api/test_invalidate_function.py
new file mode 100644
index 00000000..ed0357dc
--- /dev/null
+++ b/moon_utilities/tests/unit_python/api/test_invalidate_function.py
@@ -0,0 +1,64 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import moon_utilities.invalided_functions
+
+
+def test_invalidate_assignment_in_slaves(slaves):
+ result = moon_utilities.invalided_functions.invalidate_assignment_in_slaves(
+ slaves, "098764321", "098764321", "098764321", "098764321", 'subject')
+ assert result
+ assert "slave_test" in list(result)
+
+
+def test_invalidate_data_in_slaves(slaves):
+ result = moon_utilities.invalided_functions.invalidate_data_in_slaves(
+ slaves, "__policy_id__", "__category_id__", "098764321", "subject")
+ assert result
+ assert "slave_test" in list(result)
+
+
+def test_invalidate_perimeter_in_slaves(slaves):
+ result = moon_utilities.invalided_functions.invalidate_perimeter_in_slaves(
+ slaves, "098764321", "098764321", "subject", is_delete=False)
+ assert result
+ assert "slave_test" in list(result)
+
+
+def test_invalidate_pdp_in_slaves(slaves):
+ result = moon_utilities.invalided_functions.invalidate_pdp_in_slaves(
+ slaves, "098764321", is_delete=False)
+ assert result
+ assert "slave_test" in list(result)
+
+
+def test_invalidate_policy_in_slaves(slaves):
+ result = moon_utilities.invalided_functions.invalidate_policy_in_slaves(
+ slaves, "098764321", is_delete=False)
+ assert result
+ assert "slave_test" in list(result)
+
+
+def test_invalidate_rules_in_slaves():
+ pass
+
+
+def test_invalidate_model_in_slaves():
+ pass
+
+
+def test_invalidate_meta_data_in_slaves():
+ pass
+
+
+def test_invalidate_meta_rule_in_slaves():
+ pass
diff --git a/moon_utilities/tests/unit_python/api/test_security_functions.py b/moon_utilities/tests/unit_python/api/test_security_functions.py
new file mode 100644
index 00000000..469a70a2
--- /dev/null
+++ b/moon_utilities/tests/unit_python/api/test_security_functions.py
@@ -0,0 +1,18 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+from moon_utilities.security_functions import enforce
+
+
+def test_enforce():
+ # TODO: implement the test
+ assert True
diff --git a/moon_utilities/tests/unit_python/conftest.py b/moon_utilities/tests/unit_python/conftest.py
new file mode 100644
index 00000000..da55d3ff
--- /dev/null
+++ b/moon_utilities/tests/unit_python/conftest.py
@@ -0,0 +1,172 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import mock_slaves
+import os
+import pytest
+import requests_mock
+import yaml
+
+
+__CONF = """
+debug: true
+
+database:
+ url: sqlite:////tmp/database_test.db
+ driver: moon_manager.plugins.sql
+ migration_dir: moon_manager.api.db.migrations
+
+dashboard:
+ root: ../dashboard/www/
+
+management:
+ url: http://127.0.0.1:8000
+ user: admin
+ password: admin
+ token_file: db.json
+
+orchestration:
+ driver: moon_manager.plugins.pyorchestrator
+ connection: local
+ port: 10000...10100
+ config_dir: /tmp
+
+information:
+ openstack:
+ driver: moon_manager.plugins.moon_openstack_plugin
+ url: http://keystone:5000/v3
+ user: admin
+ password: p4ssw0rd
+ domain: default
+ project: admin
+ check_token: false
+ certificate: false
+ global_attrs:
+ driver: moon_manager.plugins.global_attrs
+ attributes:
+ mode:
+ values:
+ - build
+ - run
+ default: build
+ url: file:/etc/moon/mode
+ #url: https://127.0.0.1:8080/mode
+ #url: mysql+pymysql://moon:p4sswOrd1@db/moon_mode
+ #url: sqlite:////tmp/database.db
+ #url: driver://moon_manager.plugins.my_plugin
+
+plugins:
+ directory: /var/moon/plugins
+
+components:
+ manager:
+ port: 8080
+ bind: 0.0.0.0
+ hostname: manager
+
+logging:
+ version: 1
+
+ formatters:
+ brief:
+ format: "%(levelname)s %(name)s %(message)-30s"
+ custom:
+ format: "%(asctime)-15s %(levelname)s %(name)s %(message)s"
+
+ handlers:
+ console:
+ class : logging.StreamHandler
+ formatter: custom
+ level : INFO
+ stream : ext://sys.stdout
+ file:
+ class : logging.handlers.RotatingFileHandler
+ formatter: custom
+ level : DEBUG
+ filename: /tmp/moon.log
+ maxBytes: 1048576
+ backupCount: 3
+
+ loggers:
+ moon:
+ level: DEBUG
+ handlers: [console, file]
+ propagate: no
+
+ root:
+ level: ERROR
+ handlers: [console]
+"""
+
+
+@pytest.fixture
+def slaves():
+ return {
+ "slaves": {
+ "d464cc58a0cd46dea3191ba70f4e7df8": {
+ "name": "slave_test",
+ "address": "",
+ "description": "...",
+ "extra": {
+ "description": "...",
+ "starttime": 1543851265.76279,
+ "port": 10000,
+ "server_ip": "127.0.0.1",
+ "status": "up",
+ "api_key": "e58a882a6b658a22660f00a0c273e7f6b4c4eb5abe54eccba2cae307905d67e374"
+ "6537bd790c41887e11840c2d186b6d6eeec0e426bcfa7a872cc3417a35124a"
+ }
+ }
+ }
+ }
+
+
+@pytest.fixture(autouse=True)
+def no_requests(monkeypatch):
+ """ Modify the response from Requests module
+ """
+ with requests_mock.Mocker(real_http=True) as m:
+ try:
+ os.remove("/tmp/database_test.db")
+ except FileNotFoundError:
+ pass
+ try:
+ os.remove("/tmp/moon.pwd")
+ except FileNotFoundError:
+ pass
+ print("Configure...")
+ from moon_manager.api.configuration import init_database, set_configuration
+ set_configuration(yaml.safe_load(__CONF))
+ print("Create a new user")
+ from moon_utilities.auth_functions import add_user, init_db, get_api_key_for_user
+ init_db()
+ # try:
+ # user = add_user("admin", "admin")
+ # manager_api_key = user["api_key"]
+ # except KeyError:
+ # print("User already exists")
+ # manager_api_key = get_api_key_for_user("admin")
+ print("Initialize the database")
+ init_database()
+ from moon_manager import db_driver
+ db_driver.init()
+
+ mock_slaves.register_slaves(m)
+
+ print("End registering URI")
+
+ # from moon_manager.pip_driver import InformationManager
+ # InformationManager.set_auth()
+
+ yield m
+
+ # InformationManager.unset_auth()
diff --git a/moon_utilities/tests/unit_python/helpers/__init__.py b/moon_utilities/tests/unit_python/helpers/__init__.py
new file mode 100644
index 00000000..2a5459c2
--- /dev/null
+++ b/moon_utilities/tests/unit_python/helpers/__init__.py
@@ -0,0 +1,13 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+
diff --git a/moon_utilities/tests/unit_python/helpers/import_export_cache_helper.py b/moon_utilities/tests/unit_python/helpers/import_export_cache_helper.py
new file mode 100644
index 00000000..ff22abe2
--- /dev/null
+++ b/moon_utilities/tests/unit_python/helpers/import_export_cache_helper.py
@@ -0,0 +1,234 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import logging
+
+logger = logging.getLogger("moon.manager.test.api." + __name__)
+
+
+def clean_models():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ keys = list(_cache.models.keys())
+ for key in keys:
+ _cache.delete_model(key)
+
+
+def clean_policies():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ keys = list(_cache.policies.keys())
+ for key in keys:
+ _cache.delete_policy(key)
+
+
+def clean_subjects():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ policy_keys = list(_cache.policies.keys())
+ subjects = _cache.subjects
+ for policy_key in policy_keys:
+ for key in subjects:
+ try:
+ _cache.delete_subject(policy_key, key)
+ except AttributeError:
+ pass
+ _cache.delete_subject()
+
+
+def clean_objects():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ policy_keys = list(_cache.policies.keys())
+ objects = _cache.objects
+ for policy_key in policy_keys:
+ for key in objects:
+ try:
+ _cache.delete_object(policy_key, key)
+ except AttributeError:
+ pass
+ _cache.delete_object()
+
+
+def clean_actions():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ policy_keys = list(_cache.policies.keys())
+ actions = _cache.actions
+ for policy_key in policy_keys:
+ for key in actions:
+ try:
+ _cache.delete_action(policy_key, key)
+ except AttributeError:
+ pass
+ _cache.delete_action()
+
+
+def clean_subject_categories():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ categories = list(_cache.subject_categories.keys())
+ for key in categories:
+ _cache.delete_subject_category(key)
+
+
+def clean_object_categories():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ categories = list(_cache.object_categories.keys())
+ for key in categories:
+ _cache.delete_object_category(key)
+
+
+def clean_action_categories():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ categories = list(_cache.action_categories.keys())
+ for key in categories:
+ _cache.delete_action_category(key)
+
+
+def clean_subject_data():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ _cache.delete_subject_data()
+
+
+def clean_object_data():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ _cache.delete_object_data()
+
+
+def clean_action_data():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+ _cache.delete_action_data()
+
+
+def clean_meta_rule():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ categories = list(_cache.meta_rules.keys())
+ for key in categories:
+ _cache.delete_meta_rule(key)
+
+
+def clean_subject_assignments():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ if not _cache.subject_assignments:
+ return
+ for policy_key in _cache.policies.keys():
+ if policy_key not in _cache.subject_assignments:
+ continue
+ for key in _cache.subject_assignments[policy_key]:
+ # policy_key = _cache.subject_assignments[policy_key][key]["policy_id"]
+ subject_key = _cache.subject_assignments[policy_key][key]["subject_id"]
+ cat_key = _cache.subject_assignments[policy_key][key]["category_id"]
+ data_keys = _cache.subject_assignments[policy_key][key]["assignments"]
+ for data_key in data_keys:
+ _cache.delete_subject_assignment(
+ policy_id=policy_key,
+ perimeter_id=subject_key,
+ category_id=cat_key,
+ data_id=data_key
+ )
+ _cache.delete_subject_assignment()
+
+
+def clean_object_assignments():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ if not _cache.object_assignments:
+ return
+ for policy_key in _cache.policies.keys():
+ if policy_key not in _cache.object_assignments:
+ continue
+ for key in _cache.object_assignments[policy_key]:
+ # policy_key = _cache.object_assignments[policy_key][key]["policy_id"]
+ object_key = _cache.object_assignments[policy_key][key]["object_id"]
+ cat_key = _cache.object_assignments[policy_key][key]["category_id"]
+ data_keys = _cache.object_assignments[policy_key][key]["assignments"]
+ for data_key in data_keys:
+ _cache.delete_object_assignment(
+ policy_id=policy_key,
+ perimeter_id=object_key,
+ category_id=cat_key,
+ data_id=data_key
+ )
+ _cache.delete_object_assignment()
+
+
+def clean_action_assignments():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ if not _cache.action_assignments:
+ return
+ for policy_key in _cache.policies.keys():
+ if policy_key not in _cache.action_assignments:
+ continue
+ for key in _cache.action_assignments[policy_key]:
+ action_key = _cache.action_assignments[policy_key][key]["action_id"]
+ cat_key = _cache.action_assignments[policy_key][key]["category_id"]
+ data_keys = _cache.action_assignments[policy_key][key]["assignments"]
+ for data_key in data_keys:
+ _cache.delete_action_assignment(
+ policy_id=policy_key,
+ perimeter_id=action_key,
+ category_id=cat_key,
+ data_id=data_key
+ )
+ _cache.delete_action_assignment()
+
+
+def clean_rules():
+ from moon_cache.cache import Cache
+ _cache = Cache.getInstance()
+
+ rules = list(_cache.rules.keys())
+ for key in rules:
+ _cache.delete_rule(key)
+
+
+def clean_all():
+ clean_rules()
+
+ clean_subject_assignments()
+ clean_object_assignments()
+ clean_action_assignments()
+
+ clean_subject_data()
+ clean_object_data()
+ clean_action_data()
+
+ clean_actions()
+ clean_objects()
+ clean_subjects()
+
+ clean_policies()
+ clean_models()
+ clean_meta_rule()
+
+ clean_subject_categories()
+ clean_object_categories()
+ clean_action_categories()
diff --git a/moon_utilities/tests/unit_python/helpers/import_export_db_helper.py b/moon_utilities/tests/unit_python/helpers/import_export_db_helper.py
new file mode 100644
index 00000000..ecb9fa26
--- /dev/null
+++ b/moon_utilities/tests/unit_python/helpers/import_export_db_helper.py
@@ -0,0 +1,178 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+import logging
+
+logger = logging.getLogger("moon.manager.test.api." + __name__)
+
+
+def clean_models():
+ from moon_manager import db_driver as driver
+ keys = driver.ModelManager.get_models(moon_user_id="admin")
+ for key in keys:
+ driver.ModelManager.delete_model(moon_user_id="admin", model_id=key)
+
+
+def clean_policies():
+ from moon_manager import db_driver as driver
+ keys = driver.PolicyManager.get_policies(moon_user_id="admin")
+ for key in keys:
+ driver.PolicyManager.delete_policy(moon_user_id="admin", policy_id=key)
+
+
+def clean_subjects():
+ from moon_manager import db_driver as driver
+ for policy in driver.PolicyManager.get_policies(moon_user_id="admin"):
+ subjects = driver.PolicyManager.get_subjects(moon_user_id="admin", policy_id=policy)
+ for key in subjects:
+ driver.PolicyManager.delete_subject(moon_user_id="admin", policy_id=policy,
+ perimeter_id=key)
+
+
+def clean_objects():
+ from moon_manager import db_driver as driver
+ for policy in driver.PolicyManager.get_policies(moon_user_id="admin"):
+ objects = driver.PolicyManager.get_objects(moon_user_id="admin", policy_id=policy)
+ for key in objects:
+ driver.PolicyManager.delete_object(moon_user_id="admin", policy_id=policy,
+ perimeter_id=key)
+
+
+def clean_actions():
+ from moon_manager import db_driver as driver
+ for policy in driver.PolicyManager.get_policies(moon_user_id="admin"):
+ actions = driver.PolicyManager.get_actions(moon_user_id="admin", policy_id=policy)
+ for key in actions:
+ driver.PolicyManager.delete_action(moon_user_id="admin", policy_id=policy,
+ perimeter_id=key)
+
+
+def clean_subject_categories():
+ from moon_manager import db_driver as driver
+ categories = driver.ModelManager.get_subject_categories(moon_user_id="admin")
+
+ for key in categories:
+ driver.ModelManager.delete_subject_category(moon_user_id="admin", category_id=key)
+
+
+def clean_object_categories():
+ from moon_manager import db_driver as driver
+ categories = driver.ModelManager.get_object_categories(moon_user_id="admin")
+
+ for key in categories:
+ driver.ModelManager.delete_object_category(moon_user_id="admin", category_id=key)
+
+
+def clean_action_categories():
+ from moon_manager import db_driver as driver
+ categories = driver.ModelManager.get_action_categories(moon_user_id="admin")
+
+ for key in categories:
+ driver.ModelManager.delete_action_category(moon_user_id="admin", category_id=key)
+
+
+def clean_subject_data():
+ from moon_manager import db_driver as driver
+ policies = driver.PolicyManager.get_policies(moon_user_id="admin")
+ categories = driver.ModelManager.get_subject_categories(moon_user_id="admin")
+ for policy in policies:
+ for category in categories:
+ data_object = driver.PolicyManager.get_subject_data(
+ moon_user_id="admin", policy_id=policy, category_id=category)
+ for data_item in data_object:
+ for data in data_item.get("data", {}):
+ driver.PolicyManager.delete_subject_data(moon_user_id="admin", policy_id=policy,
+ category_id=category, data_id=data)
+
+
+def clean_object_data():
+ from moon_manager import db_driver as driver
+ policies = driver.PolicyManager.get_policies(moon_user_id="admin")
+ categories = driver.ModelManager.get_object_categories(moon_user_id="admin")
+ for policy in policies:
+ for category in categories:
+ data_object = driver.PolicyManager.get_object_data(
+ moon_user_id="admin", policy_id=policy, category_id=category)
+ for data_item in data_object:
+ for data in data_item.get("data", {}):
+ driver.PolicyManager.delete_object_data(moon_user_id="admin", policy_id=policy,
+ category_id=category, data_id=data)
+
+
+def clean_action_data():
+ from moon_manager import db_driver as driver
+ policies = driver.PolicyManager.get_policies(moon_user_id="admin")
+ categories = driver.ModelManager.get_action_categories(moon_user_id="admin")
+ for policy in policies:
+ for category in categories:
+ data_object = driver.PolicyManager.get_action_data(
+ moon_user_id="admin", policy_id=policy, category_id=category)
+ for data_item in data_object:
+ for data in data_item.get("data", {}):
+ driver.PolicyManager.delete_action_data(moon_user_id="admin", policy_id=policy,
+ category_id=category, data_id=data)
+
+
+def clean_meta_rule():
+ from moon_manager import db_driver as driver
+ keys = driver.ModelManager.get_meta_rules(moon_user_id="admin")
+
+ for key in keys:
+ driver.ModelManager.delete_meta_rule(moon_user_id="admin", meta_rule_id=key)
+
+
+def clean_subject_assignments():
+ pass
+
+
+def clean_object_assignments():
+ pass
+
+
+def clean_action_assignments():
+ pass
+
+
+def clean_rules():
+ from moon_manager import db_driver as driver
+
+ policies = driver.PolicyManager.get_policies(moon_user_id="admin")
+
+ for policy in policies:
+ rules = driver.PolicyManager.get_rules(moon_user_id="admin", policy_id=policy)
+
+ for rule in rules:
+ driver.PolicyManager.delete_rule(moon_user_id="admin", policy_id=policy, rule_id=rule)
+
+
+def clean_all():
+ clean_rules()
+
+ clean_subject_assignments()
+ clean_object_assignments()
+ clean_action_assignments()
+
+ clean_subject_data()
+ clean_object_data()
+ clean_action_data()
+
+ clean_actions()
+ clean_objects()
+ clean_subjects()
+
+ clean_policies()
+ clean_models()
+ clean_meta_rule()
+
+ clean_subject_categories()
+ clean_object_categories()
+ clean_action_categories()
diff --git a/moon_utilities/tests/unit_python/helpers/slaves_helpers.py b/moon_utilities/tests/unit_python/helpers/slaves_helpers.py
new file mode 100644
index 00000000..1b2764d2
--- /dev/null
+++ b/moon_utilities/tests/unit_python/helpers/slaves_helpers.py
@@ -0,0 +1,32 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+
+SLAVES = {
+ "slaves": {
+ "d464cc58a0cd46dea3191ba70f4e7df8": {
+ "name": "slave_test",
+ "address": "",
+ "description": "...",
+ "extra": {
+ "description": "...",
+ "starttime": 1543851265.76279,
+ "port": 10000,
+ "server_ip": "127.0.0.1",
+ "status": "down",
+ "api_key": "e58a882a6b658a22660f00a0c273e7f6b4c4eb5abe54eccba2cae307905d67e3746537"
+ "bd790c41887e11840c2d186b6d6eeec0e426bcfa7a872cc3417a35124a"
+ }
+ }
+ }
+}
+
diff --git a/moon_utilities/tests/unit_python/mock_slaves.py b/moon_utilities/tests/unit_python/mock_slaves.py
new file mode 100644
index 00000000..f3ac04d8
--- /dev/null
+++ b/moon_utilities/tests/unit_python/mock_slaves.py
@@ -0,0 +1,50 @@
+# Software Name: MOON
+
+# Version: 5.4
+
+# SPDX-FileCopyrightText: Copyright (c) 2018-2020 Orange and its contributors
+# SPDX-License-Identifier: Apache-2.0
+
+# This software is distributed under the 'Apache License 2.0',
+# the text of which is available at 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+# or see the "LICENSE" file for more details.
+
+
+
+def register_slaves(m):
+ m.register_uri(
+ 'DELETE', 'http://127.0.0.1:10000/update/assignment/098764321/subject/098764321/098764321/098764321',
+ json={}
+ )
+ m.register_uri(
+ 'DELETE', 'http://127.0.0.1:10000/update/data/098764321/subject',
+ json={}
+ )
+ m.register_uri(
+ 'PUT', 'http://127.0.0.1:10000/update/perimeter/098764321/098764321/subject',
+ json={}
+ )
+ m.register_uri(
+ 'PUT', 'http://127.0.0.1:10000/update/pdp/098764321',
+ json={}
+ )
+ m.register_uri(
+ 'PUT', 'http://127.0.0.1:10000/update/policy/098764321',
+ json={}
+ )
+ m.register_uri(
+ 'PUT', 'http://127.0.0.1:10000/update/rules/1234567890',
+ json={}
+ )
+ m.register_uri(
+ 'PUT', 'http://127.0.0.1:10000/update/model/1234567890',
+ json={}
+ )
+ m.register_uri(
+ 'PUT', 'http://127.0.0.1:10000/update/meta_data/1234567890',
+ json={}
+ )
+ m.register_uri(
+ 'PUT', 'http://127.0.0.1:10000/update/meta_rule/1234567890',
+ json={}
+ )
diff --git a/moon_utilities/tests/unit_python/requirements.txt b/moon_utilities/tests/unit_python/requirements.txt
new file mode 100644
index 00000000..91cbc2c0
--- /dev/null
+++ b/moon_utilities/tests/unit_python/requirements.txt
@@ -0,0 +1,10 @@
+pytest
+pbr
+pytest-cov
+cliff
+requests_mock
+tinydb
+moon_manager
+moon_cache
+sqlalchemy
+pymysql \ No newline at end of file