aboutsummaryrefslogtreecommitdiffstats
path: root/moon_utilities/moon_utilities
diff options
context:
space:
mode:
Diffstat (limited to 'moon_utilities/moon_utilities')
-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
9 files changed, 4565 insertions, 0 deletions
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()