From d182202fc6001983541504ed323d68479086317e Mon Sep 17 00:00:00 2001 From: WuKong Date: Sat, 22 Apr 2017 13:25:07 +0200 Subject: add moonv4 Change-Id: I247af788d0b0fb961fbc85416486b241eb1d807c Signed-off-by: WuKong --- moonv4/moon_utilities/LICENSE | 204 +++++++++ moonv4/moon_utilities/MANIFEST.in | 9 + moonv4/moon_utilities/README.rst | 9 + moonv4/moon_utilities/moon_utilities/__init__.py | 6 + moonv4/moon_utilities/moon_utilities/api.py | 28 ++ moonv4/moon_utilities/moon_utilities/exceptions.py | 505 +++++++++++++++++++++ moonv4/moon_utilities/moon_utilities/misc.py | 47 ++ moonv4/moon_utilities/moon_utilities/options.py | 300 ++++++++++++ .../moon_utilities/security_functions.py | 405 +++++++++++++++++ moonv4/moon_utilities/requirements.txt | 6 + moonv4/moon_utilities/setup.py | 41 ++ 11 files changed, 1560 insertions(+) create mode 100644 moonv4/moon_utilities/LICENSE create mode 100644 moonv4/moon_utilities/MANIFEST.in create mode 100644 moonv4/moon_utilities/README.rst create mode 100644 moonv4/moon_utilities/moon_utilities/__init__.py create mode 100644 moonv4/moon_utilities/moon_utilities/api.py create mode 100644 moonv4/moon_utilities/moon_utilities/exceptions.py create mode 100644 moonv4/moon_utilities/moon_utilities/misc.py create mode 100644 moonv4/moon_utilities/moon_utilities/options.py create mode 100644 moonv4/moon_utilities/moon_utilities/security_functions.py create mode 100644 moonv4/moon_utilities/requirements.txt create mode 100644 moonv4/moon_utilities/setup.py (limited to 'moonv4/moon_utilities') diff --git a/moonv4/moon_utilities/LICENSE b/moonv4/moon_utilities/LICENSE new file mode 100644 index 00000000..4143aac2 --- /dev/null +++ b/moonv4/moon_utilities/LICENSE @@ -0,0 +1,204 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +--- License for python-keystoneclient versions prior to 2.1 --- + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of this project nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/moonv4/moon_utilities/MANIFEST.in b/moonv4/moon_utilities/MANIFEST.in new file mode 100644 index 00000000..1f674d50 --- /dev/null +++ b/moonv4/moon_utilities/MANIFEST.in @@ -0,0 +1,9 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. + +include README.rst +include LICENSE +include setup.py +include requirements.txt diff --git a/moonv4/moon_utilities/README.rst b/moonv4/moon_utilities/README.rst new file mode 100644 index 00000000..ded4e99a --- /dev/null +++ b/moonv4/moon_utilities/README.rst @@ -0,0 +1,9 @@ +Core module for the Moon project +================================ + +This package contains the core module for the Moon project +It is designed to provide authorization features to all OpenStack components. + +For any other information, refer to the parent project: + + https://git.opnfv.org/moon diff --git a/moonv4/moon_utilities/moon_utilities/__init__.py b/moonv4/moon_utilities/moon_utilities/__init__.py new file mode 100644 index 00000000..903c6518 --- /dev/null +++ b/moonv4/moon_utilities/moon_utilities/__init__.py @@ -0,0 +1,6 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. + +__version__ = "0.1.0" diff --git a/moonv4/moon_utilities/moon_utilities/api.py b/moonv4/moon_utilities/moon_utilities/api.py new file mode 100644 index 00000000..8e80c21d --- /dev/null +++ b/moonv4/moon_utilities/moon_utilities/api.py @@ -0,0 +1,28 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. + + +class APIList(object): + + API_LIST = () + + def __init__(self, api_list): + self.API_LIST = api_list + + def list_api(self, ctx): + api = dict() + for obj in self.API_LIST: + api[obj.__name__] = dict() + api[obj.__name__]["description"] = obj.__doc__.strip() if obj.__doc__ else "" + api[obj.__name__]["version"] = obj.__version__ + api[obj.__name__]["commands"] = dict() + for cmd in filter(lambda x: not x.startswith("__"), dir(obj)): + doc = eval("obj.{}.__doc__".format(cmd)) + if not doc: + doc = "" + api[obj.__name__]["commands"][cmd] = doc.strip() + return api + + diff --git a/moonv4/moon_utilities/moon_utilities/exceptions.py b/moonv4/moon_utilities/moon_utilities/exceptions.py new file mode 100644 index 00000000..f642fb57 --- /dev/null +++ b/moonv4/moon_utilities/moon_utilities/exceptions.py @@ -0,0 +1,505 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. + +from oslo_log import log as logging +from werkzeug.exceptions import HTTPException +LOG = logging.getLogger(__name__) +_ = str + + +class MoonErrorMetaClass(type): + + def __init__(cls, name, bases, dct): + super(MoonErrorMetaClass, cls).__init__(name, bases, dct) + cls.hierarchy += "/"+str(name) + + +class MoonError(HTTPException): + __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: + LOG.error(message) + except AttributeError: + LOG.error(message) + elif self.logger == "WARNING": + try: + LOG.warning(message) + except AttributeError: + LOG.warning(message) + elif self.logger == "CRITICAL": + try: + LOG.critical(message) + except AttributeError: + LOG.critical(message) + elif self.logger == "AUTHZ": + try: + LOG.authz(self.hierarchy) + LOG.error(message) + except AttributeError: + LOG.error(message) + else: + try: + LOG.info(message) + except AttributeError: + LOG.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 ModelExisting(MoonError): + description = _("The model already exists.") + code = 409 + title = 'Model Error' + logger = "Error" + + +class RootExtensionUnknown(IntraExtensionUnknown): + description = _("The root_extension is unknown.") + code = 400 + title = 'Root Extension Unknown' + logger = "Error" + + +class RootPDPNotInitialized(IntraExtensionException): + description = _("The root_extension is not initialized.") + code = 400 + title = 'Root Extension Not Initialized' + logger = "Error" + + +class IntraExtensionCreationError(IntraExtensionException): + description = _("The arguments for the creation of this Extension were malformed.") + code = 400 + title = 'Intra Extension Creation 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 SubjectCategoryNameExisting(AdminMetaData): + description = _("The given subject category name already exists.") + code = 409 + title = 'Subject Category Name Existing' + logger = "ERROR" + + +class SubjectCategoryExisting(AdminMetaData): + description = _("The given subject category already exists.") + code = 409 + title = 'Subject Category Existing' + logger = "ERROR" + + +class ObjectCategoryNameExisting(AdminMetaData): + description = _("The given object category name already exists.") + code = 409 + title = 'Object Category Name Existing' + logger = "ERROR" + + +class ObjectCategoryExisting(AdminMetaData): + description = _("The given object category already exists.") + code = 409 + title = 'Object Category Existing' + logger = "ERROR" + + +class ActionCategoryNameExisting(AdminMetaData): + description = _("The given action category name already exists.") + code = 409 + title = 'Action Category Name 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 ObjectCategoryUnknown(AdminMetaData): + description = _("The given object category is unknown.") + code = 400 + title = 'Object Category Unknown' + logger = "ERROR" + + +class ActionCategoryUnknown(AdminMetaData): + description = _("The given action category is unknown.") + code = 400 + title = 'Action Category Unknown' + 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 SubjectNameExisting(AdminPerimeter): + description = _("The given subject name is existing.") + code = 400 + title = 'Subject Name Existing' + logger = "ERROR" + + +class ObjectNameExisting(AdminPerimeter): + description = _("The given object name is existing.") + code = 400 + title = 'Object Name Existing' + logger = "ERROR" + + +class ActionNameExisting(AdminPerimeter): + description = _("The given action name is existing.") + code = 400 + 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 SubjectScopeNameExisting(AdminScope): + description = _("The given subject scope name is existing.") + code = 400 + title = 'Subject Scope Name Existing' + logger = "ERROR" + + +class ObjectScopeNameExisting(AdminScope): + description = _("The given object scope name is existing.") + code = 400 + title = 'Object Scope Name Existing' + logger = "ERROR" + + +class ActionScopeNameExisting(AdminScope): + description = _("The given action scope name is existing.") + code = 400 + 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 = 400 + title = 'Subject Assignment Existing' + logger = "ERROR" + + +class ObjectAssignmentExisting(AdminAssignment): + description = _("The given object assignment value is existing.") + code = 400 + title = 'Object Assignment Existing' + logger = "ERROR" + + +class ActionAssignmentExisting(AdminAssignment): + description = _("The given action assignment value is existing.") + code = 400 + 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 sub meta rule is unknown.") + code = 400 + title = 'Sub Meta Rule Unknown' + logger = "ERROR" + + +class SubMetaRuleNameExisting(AdminMetaRule): + description = _("The sub meta rule name already exists.") + code = 400 + title = 'Sub Meta Rule Name Existing' + logger = "ERROR" + + +class MetaRuleExisting(AdminMetaRule): + description = _("The sub meta rule already exists.") + code = 400 + title = 'Sub Meta Rule Existing' + logger = "ERROR" + + +class RuleExisting(AdminRule): + description = _("The rule already exists.") + code = 400 + title = 'Rule Existing' + logger = "ERROR" + + +class RuleUnknown(AdminRule): + description = _("The rule for that request doesn't exist.") + code = 400 + title = 'Rule Unknown' + logger = "ERROR" + + +class KeystoneError(MoonError): + description = _("There is an error connecting to Keystone.") + code = 400 + title = 'Keystone error' + logger = "ERROR" + + +class KeystoneProjectError(KeystoneError): + description = _("There is an error retrieving projects from the Keystone service.") + code = 400 + title = 'Keystone project error' + logger = "ERROR" + + +class KeystoneUserError(KeystoneError): + description = _("There is an error retrieving users from the Keystone service.") + code = 400 + title = 'Keystone user error' + logger = "ERROR" + + +class KeystoneUserConflict(KeystoneUserError): + description = _("A user with that name already exist.") + code = 400 + title = 'Keystone user error' + logger = "ERROR" + + diff --git a/moonv4/moon_utilities/moon_utilities/misc.py b/moonv4/moon_utilities/moon_utilities/misc.py new file mode 100644 index 00000000..d13b4511 --- /dev/null +++ b/moonv4/moon_utilities/moon_utilities/misc.py @@ -0,0 +1,47 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. + + +import os +import re +import types +import requests +from oslo_log import log as logging +from oslo_config import cfg +import oslo_messaging +from moon_utilities import exceptions +from oslo_config.cfg import ConfigOpts + +LOG = logging.getLogger(__name__) +CONF = cfg.CONF + + +def get_uuid_from_name(name, elements, **kwargs): + LOG.error("get_uuid_from_name {} {} {}".format(name, elements, kwargs)) + for element in elements: + if type(elements[element]) is dict and elements[element].get('name') == name: + if kwargs: + for args in kwargs: + if elements[element].get(args) != kwargs[args]: + LOG.error("get_uuid_from_name2 {} {} {}".format(args, elements[element].get(args), kwargs[args])) + return + else: + return element + else: + return element + + +def get_name_from_uuid(uuid, elements, **kwargs): + for element in elements: + if element == uuid: + if kwargs: + for args in kwargs: + if elements[element].get(args) != kwargs[args]: + return + else: + return elements[element].get('name') + else: + return elements[element].get('name') + diff --git a/moonv4/moon_utilities/moon_utilities/options.py b/moonv4/moon_utilities/moon_utilities/options.py new file mode 100644 index 00000000..8b8ccca4 --- /dev/null +++ b/moonv4/moon_utilities/moon_utilities/options.py @@ -0,0 +1,300 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. + +import os +import sys +from oslo_config import cfg +from oslo_log import log as logging +from moon_utilities import __version__ + +LOG = logging.getLogger(__name__) +CONF = cfg.CONF + +__CWD__ = os.path.dirname(os.path.abspath(__file__)) + + +def configure(domain="moon", version=__version__, usage=""): + # FIXME (dthom): put DEBUG as default log level doesn't work + extra_log_level_defaults = [ + '{}=DEBUG'.format(__name__), + ] + # LOG.setLevel(logging.DEBUG) + logging.set_defaults( + default_log_levels=logging.get_default_log_levels() + extra_log_level_defaults) + + logging.register_options(CONF) + logging.setup(CONF, domain) + + CONF.register_opts(get_opts()) + + # rabbit_group = cfg.OptGroup(name='messenger', + # title='Messenger options') + # CONF.register_group(rabbit_group) + # CONF.register_opts(get_messenger_opts(), group="messenger") + + slave_group = cfg.OptGroup(name='slave', + title='Messenger options') + CONF.register_group(slave_group) + CONF.register_opts(get_slave_opts(), group="slave") + + database_group = cfg.OptGroup(name='database', + title='Database options') + CONF.register_group(database_group) + CONF.register_opts(get_database_opts(), group="database") + + database_configuration_group = cfg.OptGroup(name='database_configuration', + title='Database configuration options') + CONF.register_group(database_configuration_group) + CONF.register_opts(get_database_configuration_opts(), group="database_configuration") + + orchestrator_group = cfg.OptGroup(name='orchestrator', + title='Orchestrator options') + CONF.register_group(orchestrator_group) + CONF.register_opts(get_orchestrator_opts(), group="orchestrator") + + secrouter_group = cfg.OptGroup(name='security_router', + title='Security Router options') + CONF.register_group(secrouter_group) + CONF.register_opts(get_security_router_opts(), group="security_router") + + manager_group = cfg.OptGroup(name='security_manager', + title='Manager options') + CONF.register_group(manager_group) + CONF.register_opts(get_manager_opts(), group="security_manager") + + secpolicy_group = cfg.OptGroup(name='security_policy', + title='Security policy options') + CONF.register_group(secpolicy_group) + CONF.register_opts(get_security_policy_opts(), group="security_policy") + + secfunction_group = cfg.OptGroup(name='security_function', + title='Security function options') + CONF.register_group(secfunction_group) + CONF.register_opts(get_security_function_opts(), group="security_function") + + interface_group = cfg.OptGroup(name='interface', + title='Interface options') + CONF.register_group(interface_group) + CONF.register_opts(get_interface_opts(), group="interface") + + keystone_group = cfg.OptGroup(name='keystone', + title='Keystone options') + CONF.register_group(keystone_group) + CONF.register_opts(get_keystone_opts(), group="keystone") + + filename = "moon.conf" + for _filename in ( + "/etc/moon/{}", + "conf/{}", + "../conf/{}", + ): + try: + default_config_files = (_filename.format(filename), ) + CONF(args=sys.argv[1:], + project=domain, + # version=pbr.version.VersionInfo('keystone').version_string(), + version=version, + usage=usage, + default_config_files=default_config_files) + except cfg.ConfigFilesNotFoundError: + continue + else: + LOG.info("Using {} configuration file".format(_filename.format(filename))) + return _filename.format(filename) + + +def get_opts(): + return [ + cfg.StrOpt('proxy', + default="", + help='Proxy server to use'), + cfg.StrOpt('dist_dir', + default="", + help='Directory where the python packages can be found'), + cfg.StrOpt('plugin_dir', + default="", + help='Directory where the python plugins can be found'), + cfg.StrOpt('docker_url', + default="unix://var/run/docker.sock", + help='Docker URL to connect to.'), + cfg.StrOpt('policy_directory', + default="/etc/moon/policies", + help='Directory containing all the intra-extension templates'), + cfg.StrOpt('root_policy_directory', + default="/etc/moon/policies/policy_root", + help='Directory containing the Root intra-extension template'), + cfg.StrOpt('master', + default="", + help='URL of the Moon Master'), + cfg.StrOpt('master_login', + default="", + help='Login to log into the Moon Master'), + cfg.StrOpt('master_password', + default="", + help='Password for the Moon Master'), + ] + + +# def get_messenger_opts(): +# return [ +# cfg.StrOpt('host', +# default="0.0.0.0", +# help='RabbitMQ server name or IP.'), +# cfg.IntOpt('port', +# default=8800, +# help='RabbitMQ server port.'), +# ] + + +def get_orchestrator_opts(): + return [ + cfg.StrOpt('host', + default="127.0.0.1", + help='Host binding'), + cfg.IntOpt('port', + default=38000, + help='Port number of the server'), + ] + + +def get_slave_opts(): + return [ + cfg.StrOpt('slave_name', + default="", + help='name of the slave'), + cfg.StrOpt('master_url', + default="", + help='URL of the RabbitMQ bus of the Master, ' + 'example: master_url=rabbit://moon:p4sswOrd1@messenger:5672/moon'), + cfg.StrOpt('master_login', + default="", + help='login name of the master administrator, example: master_login=admin'), + cfg.StrOpt('master_password', + default="", + help='password of the master administrator, example: master_password=XXXXXXX'), + ] + + +def get_security_router_opts(): + return [ + cfg.StrOpt('container', + default="", + help='Name of the container to download (if empty build from scratch)'), + cfg.StrOpt('host', + default="127.0.0.1", + help='Host binding'), + cfg.IntOpt('port', + default=38001, + help='Port number of the server'), + ] + + +def get_manager_opts(): + return [ + cfg.StrOpt('container', + default="", + help='Name of the container to download (if empty build from scratch)'), + cfg.StrOpt('host', + default="127.0.0.1", + help='Host binding'), + cfg.IntOpt('port', + default=38001, + help='Port number of the server'), + ] + + +def get_security_policy_opts(): + return [ + cfg.StrOpt('container', + default="", + help='Name of the container to download (if empty build from scratch)'), + ] + + +def get_security_function_opts(): + return [ + cfg.StrOpt('container', + default="", + help='Name of the container to download (if empty build from scratch)'), + ] + + +def get_interface_opts(): + return [ + cfg.StrOpt('container', + default="", + help='Name of the container to download (if empty build from scratch)'), + cfg.StrOpt('host', + default="127.0.0.1", + help='Host binding'), + cfg.IntOpt('port', + default=38002, + help='Port number of the server'), + ] + + +def get_database_opts(): + return [ + cfg.StrOpt('url', + default="mysql+pymysql://moonuser:password@localhost/moon", + help='URL of the database'), + cfg.StrOpt('driver', + default="sql", + help='Driver binding'), + ] + + +def get_database_configuration_opts(): + return [ + cfg.StrOpt('url', + default="", + help='URL of the database'), + cfg.StrOpt('driver', + default="memory", + help='Driver binding'), + ] + + +def get_keystone_opts(): + return [ + cfg.StrOpt('url', + default="http://localhost:35357", + help='URL of the Keystone manager.'), + cfg.StrOpt('user', + default="admin", + help='Username of the Keystone manager.'), + cfg.StrOpt('password', + default="nomoresecrete", + help='Password of the Keystone manager.'), + cfg.StrOpt('project', + default="admin", + help='Project used to connect to the Keystone manager.'), + cfg.StrOpt('domain', + default="Default", + help='Default domain for the Keystone manager.'), + cfg.StrOpt('check_token', + default="true", + help='If true, yes or strict, always check Keystone tokens against the server'), + cfg.StrOpt('server_crt', + default="", + help='If using Keystone in HTTPS mode, give a certificate filename here'), + ] + +filename = configure() + + +def get_docker_template_dir(templatename="template.dockerfile"): + path = os.path.dirname(os.path.abspath(filename)) + PATHS = ( + path, + os.path.join(path, "dockers"), + "/etc/moon/" + "~/.moon/" + ) + for _path in PATHS: + if os.path.isfile(os.path.join(_path, templatename)): + return _path + raise Exception("Configuration error, cannot find docker template in {}".format(PATHS)) + diff --git a/moonv4/moon_utilities/moon_utilities/security_functions.py b/moonv4/moon_utilities/moon_utilities/security_functions.py new file mode 100644 index 00000000..2ad52a4c --- /dev/null +++ b/moonv4/moon_utilities/moon_utilities/security_functions.py @@ -0,0 +1,405 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. + + +import copy +import re +import types +import requests +from uuid import uuid4 +from oslo_log import log as logging +from oslo_config import cfg +import oslo_messaging +from moon_utilities import exceptions +from oslo_config.cfg import ConfigOpts +# from moon_db.core import PDPManager, ModelManager, PolicyManager + +LOG = logging.getLogger(__name__) +CONF = cfg.CONF + + +def filter_input(func_or_str): + + def __filter(string): + if string and type(string) is str: + return "".join(re.findall("[\w\- +]*", string)) + return string + + def __filter_dict(arg): + result = dict() + for key in arg.keys(): + if key == "email": + result["email"] = __filter_email(arg[key]) + elif key == "password": + result["password"] = arg['password'] + else: + result[key] = __filter(arg[key]) + return result + + def __filter_email(string): + if string and type(string) is str: + return "".join(re.findall("[\w@\._\- +]*", string)) + return string + + def wrapped(*args, **kwargs): + _args = [] + for arg in args: + if isinstance(arg, str): + arg = __filter(arg) + elif isinstance(arg, list): + arg = [__filter(item) for item in arg] + elif isinstance(arg, tuple): + arg = (__filter(item) for item in arg) + elif isinstance(arg, dict): + arg = __filter_dict(arg) + _args.append(arg) + for arg in kwargs: + if type(kwargs[arg]) is str: + kwargs[arg] = __filter(kwargs[arg]) + if isinstance(kwargs[arg], str): + kwargs[arg] = __filter(kwargs[arg]) + elif isinstance(kwargs[arg], list): + kwargs[arg] = [__filter(item) for item in kwargs[arg]] + elif isinstance(kwargs[arg], tuple): + kwargs[arg] = (__filter(item) for item in kwargs[arg]) + elif isinstance(kwargs[arg], dict): + kwargs[arg] = __filter_dict(kwargs[arg]) + return func_or_str(*_args, **kwargs) + + if isinstance(func_or_str, str): + return __filter(func_or_str) + if isinstance(func_or_str, list): + return [__filter(item) for item in func_or_str] + if isinstance(func_or_str, tuple): + return (__filter(item) for item in func_or_str) + if isinstance(func_or_str, dict): + return __filter_dict(func_or_str) + if isinstance(func_or_str, types.FunctionType): + return wrapped + return None + + +def enforce(action_names, object_name, **extra): + """Fake version of the enforce decorator""" + def wrapper_func(func): + def wrapper_args(*args, **kwargs): + # LOG.info("kwargs={}".format(kwargs)) + # kwargs['user_id'] = kwargs.pop('user_id', "admin") + # LOG.info("Calling enforce on {} with args={} kwargs={}".format(func.__name__, args, kwargs)) + return func(*args, **kwargs) + return wrapper_args + return wrapper_func + + +def login(user=None, password=None, domain=None, project=None, url=None): + if not user: + user = CONF.keystone.user + if not password: + password = CONF.keystone.password + if not domain: + domain = CONF.keystone.domain + if not project: + project = CONF.keystone.project + if not url: + url = CONF.keystone.url + headers = { + "Content-Type": "application/json" + } + data_auth = { + "auth": { + "identity": { + "methods": [ + "password" + ], + "password": { + "user": { + "domain": { + "id": domain + }, + "name": user, + "password": password + } + } + }, + "scope": { + "project": { + "domain": { + "id": domain + }, + "name": project + } + } + } + } + + req = requests.post("{}/auth/tokens".format(url), + json=data_auth, headers=headers, + verify=CONF.keystone.server_crt) + + if req.status_code in (200, 201, 204): + headers['X-Auth-Token'] = req.headers['X-Subject-Token'] + return headers + LOG.error(req.text) + raise exceptions.KeystoneError + + +def logout(headers, url=None): + if not url: + url = CONF.keystone.url + headers['X-Subject-Token'] = headers['X-Auth-Token'] + req = requests.delete("{}/auth/tokens".format(url), headers=headers, verify=CONF.keystone.server_crt) + if req.status_code in (200, 201, 204): + return + LOG.error(req.text) + raise exceptions.KeystoneError + +__transport_master = oslo_messaging.get_transport(cfg.CONF, CONF.slave.master_url) +__transport = oslo_messaging.get_transport(CONF) + + +def call(endpoint, ctx=None, method="get_status", **kwargs): + if not ctx: + ctx = dict() + if 'call_master' in ctx and ctx['call_master'] and CONF.slave.master_url: + transport = __transport_master + # LOG.info("Calling master {} on {}...".format(method, endpoint)) + else: + transport = __transport + # LOG.info("Calling {} on {}...".format(method, endpoint)) + target = oslo_messaging.Target(topic=endpoint, version='1.0') + client = oslo_messaging.RPCClient(transport, target) + return client.call(ctx, method, **kwargs) + + +class Context: + + def __init__(self, _keystone_project_id, _subject, _object, _action, _request_id): + from moon_db.core import PDPManager, ModelManager, PolicyManager + self.PolicyManager = PolicyManager + self.ModelManager = ModelManager + self.PDPManager = PDPManager + self.__keystone_project_id = _keystone_project_id + self.__pdp_id = None + self.__pdp_value = None + LOG.info("Context pdp={}".format(PDPManager.get_pdp("admin"))) + for _pdp_key, _pdp_value in PDPManager.get_pdp("admin").items(): + if _pdp_value["keystone_project_id"] == _keystone_project_id: + self.__pdp_id = _pdp_key + self.__pdp_value = copy.deepcopy(_pdp_value) + break + LOG.info("Context pdp_value={}".format(self.__pdp_value)) + self.__subject = _subject + self.__object = _object + self.__action = _action + self.__current_request = None + self.__request_id = _request_id + self.__index = 0 + self.__init_initial_request() + self.__headers = [] + policies = PolicyManager.get_policies("admin") + models = ModelManager.get_models("admin") + LOG.info("Context policies={}".format(policies)) + LOG.info("Context models={}".format(models)) + for policy_id in self.__pdp_value["security_pipeline"]: + model_id = policies[policy_id]["model_id"] + for meta_rule in models[model_id]["meta_rules"]: + self.__headers.append(meta_rule) + self.__meta_rules = ModelManager.get_meta_rules("admin") + LOG.info("Context meta_rules={}".format(self.__meta_rules)) + LOG.info("Context headers={}".format(self.__headers)) + # call("moon_manager", + # method="get_meta_rules", + # ctx={"id": self.__intra_extension_id, + # "user_id": "admin", + # "method": "get_sub_meta_rules"}, + # args={})["sub_meta_rules"] + # for key in self.__intra_extension["pdp_pipeline"]: + # LOG.info("__meta_rules={}".format(self.__meta_rules)) + # for meta_rule_key in self.__meta_rules: + # if self.__meta_rules[meta_rule_key]['name'] == key.split(":", maxsplit=1)[-1]: + # self.__headers.append({"name": self.__meta_rules[meta_rule_key]['name'], "id": meta_rule_key}) + # break + # else: + # LOG.warning("Cannot find meta_rule_key {}".format(key)) + self.__pdp_set = {} + self.__init_pdp_set() + + def __init_initial_request(self): + subjects = self.PolicyManager.get_subjects("admin", policy_id=None) + for _subject_id, _subject_dict in subjects.items(): + if _subject_dict["name"] == self.__subject: + self.__subject = _subject_id + break + else: + raise exceptions.SubjectUnknown("Cannot find subject {}".format(self.__subject)) + objects = self.PolicyManager.get_objects("admin", policy_id=None) + for _object_id, _object_dict in objects.items(): + if _object_dict["name"] == self.__object: + self.__object = _object_id + break + else: + raise exceptions.ObjectUnknown("Cannot find object {}".format(self.__object)) + actions = self.PolicyManager.get_actions("admin", policy_id=None) + for _action_id, _action_dict in actions.items(): + if _action_dict["name"] == self.__action: + self.__action = _action_id + break + else: + raise exceptions.ActionUnknown("Cannot find action {}".format(self.__action)) + self.__current_request = dict(self.initial_request) + + def __init_pdp_set(self): + for header in self.__headers: + self.__pdp_set[header] = dict() + self.__pdp_set[header]["meta_rules"] = self.__meta_rules[header] + self.__pdp_set[header]["target"] = self.__add_target() + # TODO (asteroide): the following information must be retrieve somewhere + self.__pdp_set[header]["instruction"] = list() + self.__pdp_set[header]["effect"] = "grant" + self.__pdp_set["effect"] = "grant" + + def __add_target(self): + result = dict() + _subject = self.__current_request["subject"] + _object = self.__current_request["object"] + _action = self.__current_request["action"] + categories = self.ModelManager.get_subject_categories("admin") + # TODO (asteroide): end the dev of that part + # for category in categories: + # result[category] = list() + # assignments = call("moon_secpolicy_{}".format(self.__intra_extension_id), + # method="get_subject_assignments", + # ctx={"id": self.__intra_extension_id, + # "sid": _subject, + # "scid": category, + # "user_id": "admin"}, + # args={})["subject_assignments"] + # result[category].extend(assignments[_subject][category]) + # categories = call("moon_secpolicy_{}".format(self.__intra_extension_id), + # method="get_object_categories", + # ctx={"id": self.__intra_extension_id, + # "user_id": "admin"}, + # args={})["object_categories"] + # for category in categories: + # result[category] = list() + # assignments = call("moon_secpolicy_{}".format(self.__intra_extension_id), + # method="get_object_assignments", + # ctx={"id": self.__intra_extension_id, + # "sid": _object, + # "scid": category, + # "user_id": "admin"}, + # args={})["object_assignments"] + # result[category].extend(assignments[_object][category]) + # categories = call("moon_secpolicy_{}".format(self.__intra_extension_id), + # method="get_action_categories", + # ctx={"id": self.__intra_extension_id, + # "user_id": "admin"}, + # args={})["action_categories"] + # for category in categories: + # result[category] = list() + # assignments = call("moon_secpolicy_{}".format(self.__intra_extension_id), + # method="get_action_assignments", + # ctx={"id": self.__intra_extension_id, + # "sid": _action, + # "scid": category, + # "user_id": "admin"}, + # args={})["action_assignments"] + # result[category].extend(assignments[_action][category]) + return result + + def __repr__(self): + return """PDP ID: {id} +current_request: {current_request} +request_id: {request_id} +index: {index} +headers: {headers} +pdp_set: {pdp_set} + """.format( + id=self.__pdp_id, + current_request=self.__current_request, + request_id=self.__request_id, + headers=self.__headers, + pdp_set=self.__pdp_set, + index=self.__index + ) + + def to_dict(self): + return { + "initial_request": copy.deepcopy(self.initial_request), + "current_request": copy.deepcopy(self.__current_request), + "headers": copy.deepcopy(self.__headers), + "index": copy.deepcopy(self.__index), + "pdp_set": copy.deepcopy(self.__pdp_set), + "request_id": copy.deepcopy(self.__request_id), + } + + @property + def initial_request(self): + return { + "subject": self.__subject, + "object": self.__object, + "action": self.__action, + } + + @initial_request.setter + def initial_request(self, value): + raise Exception("You are not allowed to update the initial_request") + + @initial_request.deleter + def initial_request(self): + raise Exception("You are not allowed to delete the initial_request") + + @property + def current_request(self): + if not self.__current_request: + self.__current_request = copy.deepcopy(self.initial_request) + return self.__current_request + + @current_request.setter + def current_request(self, value): + self.__current_request = copy.deepcopy(value) + # Note (asteroide): if the current request is modified, we must update the PDP Set. + self.__init_pdp_set() + + @current_request.deleter + def current_request(self): + self.__current_request = {} + self.__pdp_set = {} + + @property + def headers(self): + return self.__headers + + @headers.setter + def headers(self, headers): + self.__headers = headers + + @headers.deleter + def headers(self): + self.__headers = list() + + @property + def index(self): + return self.__index + + @index.setter + def index(self, index): + self.__index += 1 + + @index.deleter + def index(self): + self.__index = 0 + + @property + def pdp_set(self): + return self.__pdp_set + + @pdp_set.setter + def pdp_set(self, value): + raise Exception("You are not allowed to modify the pdp_set") + + @pdp_set.deleter + def pdp_set(self): + self.__pdp_set = {} diff --git a/moonv4/moon_utilities/requirements.txt b/moonv4/moon_utilities/requirements.txt new file mode 100644 index 00000000..c569e00b --- /dev/null +++ b/moonv4/moon_utilities/requirements.txt @@ -0,0 +1,6 @@ +kombu !=4.0.1,!=4.0.0 +oslo.messaging +oslo.config +oslo.log +vine +werkzeug \ No newline at end of file diff --git a/moonv4/moon_utilities/setup.py b/moonv4/moon_utilities/setup.py new file mode 100644 index 00000000..9bd1db40 --- /dev/null +++ b/moonv4/moon_utilities/setup.py @@ -0,0 +1,41 @@ +# Copyright 2015 Open Platform for NFV Project, Inc. and its contributors +# This software is distributed under the terms and conditions of the 'Apache-2.0' +# license which can be found in the file 'LICENSE' in this package distribution +# or at 'http://www.apache.org/licenses/LICENSE-2.0'. + +from setuptools import setup, find_packages +import moon_utilities + + +setup( + + name='moon_utilities', + + version=moon_utilities.__version__, + + packages=find_packages(), + + author="Thomas Duval", + + author_email="thomas.duval@orange.com", + + description="Some utilities for all the Moon components", + + long_description=open('README.rst').read(), + + # install_requires= , + + include_package_data=True, + + url='https://git.opnfv.org/cgit/moon', + + classifiers=[ + "Programming Language :: Python", + "Development Status :: 1 - Planning", + "License :: OSI Approved", + "Natural Language :: French", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + ], + +) -- cgit 1.2.3-korg