From 42a989a6b9b6388947da6fc273728a24c19fa686 Mon Sep 17 00:00:00 2001 From: Alex Shatov Date: Tue, 12 Sep 2017 13:00:25 -0400 Subject: 1.0.0 and policy API to deployment-handler * policy API to deployment-handler /policy * removed pycrypto of config - the same way as other apps * simple upload of config to consul - curl * preparation for policy-handler blueprint Change-Id: I424a1ded0795562ea36b5409304cbb8b5a7e8a24 Issue-Id: DCAEGEN2-62 Signed-off-by: Alex Shatov --- policyhandler/config.py | 40 ++--------------------- policyhandler/deploy_handler.py | 22 ++++++------- policyhandler/onap/crypto.py | 72 ----------------------------------------- policyhandler/policy_engine.py | 22 +++++++------ policyhandler/policy_handler.py | 25 +------------- 5 files changed, 26 insertions(+), 155 deletions(-) delete mode 100644 policyhandler/onap/crypto.py (limited to 'policyhandler') diff --git a/policyhandler/config.py b/policyhandler/config.py index ea10167..9a4980a 100644 --- a/policyhandler/config.py +++ b/policyhandler/config.py @@ -26,7 +26,6 @@ import base64 import logging from .discovery import DiscoveryClient -from .onap.crypto import Cipher logging.basicConfig( filename='logs/policy_handler.log', \ @@ -38,14 +37,10 @@ class Config(object): """main config of the application""" CONFIG_FILE_PATH = "etc/config.json" LOGGER_CONFIG_FILE_PATH = "etc/common_logger.config" - UPLOAD_CONFIG_FILE_PATH = "etc_upload/config.json" SERVICE_NAME_POLICY_HANDLER = "policy_handler" FIELD_SYSTEM = "system" - FIELD_CONFIG_PWD = "config_pwd" FIELD_WSERVICE_PORT = "wservice_port" FIELD_POLICY_ENGINE = "policy_engine" - CRYPTED_FIELDS = ["ClientAuth", "Authorization", "config_pwd"] - config_pwd = "donottell150&$" wservice_port = 25577 _logger = logging.getLogger("policy_handler.config") config = None @@ -63,32 +58,6 @@ class Config(object): new_config = copy.deepcopy(new_config) Config.config.update(new_config) - @staticmethod - def decrypt_secret_value(field_name, field_value): - """decrypt the value of the secret field""" - if field_name in Config.CRYPTED_FIELDS and isinstance(field_value, basestring): - return Cipher.decrypt(Config.config_pwd, field_value) - return field_value - - @staticmethod - def encrypt_secret_value(field_name, field_value): - """encrypt the value of the secret field""" - if field_name in Config.CRYPTED_FIELDS and isinstance(field_value, basestring): - return Cipher.encrypt(Config.config_pwd, field_value) - return field_value - - @staticmethod - def update_tree_leaves(tree_element, func_on_leaf): - """traverse through json tree and apply function func_on_leaf to each leaf""" - if not tree_element: - return - - for field_name in tree_element: - field_value = func_on_leaf(field_name, tree_element[field_name]) - tree_element[field_name] = field_value - if isinstance(field_value, dict): - Config.update_tree_leaves(field_value, func_on_leaf) - @staticmethod def get_system_name(): """find the name of the policy-handler system @@ -112,9 +81,8 @@ class Config(object): Config._logger.debug("loaded config from discovery(%s): %s", \ discovery_key, json.dumps(new_config)) - Config.update_tree_leaves(new_config, Config.decrypt_secret_value) Config._logger.debug("config before merge from discovery: %s", json.dumps(Config.config)) - Config.merge(new_config) + Config.merge(new_config.get(Config.SERVICE_NAME_POLICY_HANDLER)) Config._logger.debug("merged config from discovery: %s", json.dumps(Config.config)) @staticmethod @@ -124,11 +92,8 @@ class Config(object): Config._logger.error("unexpected config: %s", Config.config) return - latest_config = copy.deepcopy(Config.config) - Config.update_tree_leaves(latest_config, Config.encrypt_secret_value) - discovery_key = Config.get_system_name() - latest_config = json.dumps(latest_config) + latest_config = json.dumps({Config.SERVICE_NAME_POLICY_HANDLER:Config.config}) DiscoveryClient.put_kv(discovery_key, latest_config) Config._logger.debug("uploaded config to discovery(%s): %s", \ discovery_key, latest_config) @@ -153,7 +118,6 @@ class Config(object): if logging_config: logging.config.dictConfig(logging_config) - Config.config_pwd = loaded_config.get(Config.FIELD_CONFIG_PWD, Config.config_pwd) Config.wservice_port = loaded_config.get(Config.FIELD_WSERVICE_PORT, Config.wservice_port) Config.merge(loaded_config.get(Config.SERVICE_NAME_POLICY_HANDLER)) return True diff --git a/policyhandler/deploy_handler.py b/policyhandler/deploy_handler.py index 02807f8..7d9c513 100644 --- a/policyhandler/deploy_handler.py +++ b/policyhandler/deploy_handler.py @@ -30,11 +30,10 @@ from .onap.audit import REQUEST_X_ECOMP_REQUESTID, Audit, AuditHttpCode class DeployHandler(object): """ deploy-handler """ _logger = logging.getLogger("policy_handler.deploy_handler") - _policy_update = '/policy_update' _lazy_inited = False _config = None _url = None - _path = None + _url_path = None _target_entity = None @staticmethod @@ -45,7 +44,7 @@ class DeployHandler(object): DeployHandler._lazy_inited = True DeployHandler._target_entity = Config.config["deploy_handler"] DeployHandler._url = DiscoveryClient.get_service_url(DeployHandler._target_entity) - DeployHandler._path = DeployHandler._url + DeployHandler._policy_update + DeployHandler._url_path = DeployHandler._url + '/policy' DeployHandler._logger.info("DeployHandler url(%s)", DeployHandler._url) @staticmethod @@ -53,24 +52,24 @@ class DeployHandler(object): """ post policy_updated message to deploy-handler """ DeployHandler._lazy_init() msg = {"latest_policies":latest_policies} - sub_aud = Audit(aud_parent=audit, targetEntity=DeployHandler._target_entity, \ - targetServiceName=DeployHandler._path) + sub_aud = Audit(aud_parent=audit, targetEntity=DeployHandler._target_entity, + targetServiceName=DeployHandler._url_path) headers = {REQUEST_X_ECOMP_REQUESTID : sub_aud.request_id} msg_str = json.dumps(msg) headers_str = json.dumps(headers) - log_line = "post to deployment-handler {0} msg={1} headers={2}".format(\ - DeployHandler._path, msg_str, headers_str) + log_line = "post to deployment-handler {0} msg={1} headers={2}".format( + DeployHandler._url_path, msg_str, headers_str) sub_aud.metrics_start(log_line) DeployHandler._logger.info(log_line) res = None try: - res = requests.post(DeployHandler._path, json=msg, headers=headers) + res = requests.post(DeployHandler._url_path, json=msg, headers=headers) except requests.exceptions.RequestException as ex: error_msg = "failed to post to deployment-handler {0} {1} msg={2} headers={3}" \ - .format(DeployHandler._path, str(ex), msg_str, headers_str) + .format(DeployHandler._url_path, str(ex), msg_str, headers_str) DeployHandler._logger.exception(error_msg) sub_aud.set_http_status_code(AuditHttpCode.SERVICE_UNAVAILABLE_ERROR.value) audit.set_http_status_code(AuditHttpCode.SERVICE_UNAVAILABLE_ERROR.value) @@ -80,9 +79,10 @@ class DeployHandler(object): sub_aud.set_http_status_code(res.status_code) audit.set_http_status_code(res.status_code) - sub_aud.metrics( \ + sub_aud.metrics( "response from deployment-handler to post {0}: {1} msg={2} text={3} headers={4}" \ - .format(DeployHandler._path, res.status_code, msg_str, res.text, res.request.headers)) + .format(DeployHandler._url_path, res.status_code, msg_str, res.text, + res.request.headers)) if res.status_code == requests.codes.ok: return res.json() diff --git a/policyhandler/onap/crypto.py b/policyhandler/onap/crypto.py deleted file mode 100644 index e2d58db..0000000 --- a/policyhandler/onap/crypto.py +++ /dev/null @@ -1,72 +0,0 @@ -"""ONAP specific encryption-decryption for passwords""" - -# org.onap.dcae -# ================================================================================ -# Copyright (c) 2017 AT&T Intellectual Property. All rights reserved. -# ================================================================================ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============LICENSE_END========================================================= -# -# ECOMP is a trademark and service mark of AT&T Intellectual Property. - -import base64 -from Crypto.Cipher import AES -from Crypto.Protocol.KDF import PBKDF2 -from Crypto import Random - -class Cipher(object): - """class for AES-256 encryption and decryption of text using the salted password""" - KEY_SIZE = 32 # AES-256 - KDF_ITERATIONS = 16384 - AES_MODE = AES.MODE_CFB - - @staticmethod - def encrypt(password, plain_text): - """ - encrypt the :plain_text: into :cipher_text: using the password - - :cipher_text: formatted as pbkdf2_salt + init_vector + encrypt(:plain_text:) - then cipher_text is encoded as base64 to make it textable (non-binary) - - :pbkdf2_salt: has the fixed length of 32 (AES-256) - :init_vector: has the fixed length of AES.block_size - """ - pbkdf2_salt = Random.new().read(Cipher.KEY_SIZE) - init_vector = Random.new().read(AES.block_size) - derived_key = PBKDF2(password, pbkdf2_salt, Cipher.KEY_SIZE, Cipher.KDF_ITERATIONS) - - cipher = AES.new(derived_key, Cipher.AES_MODE, init_vector) - cipher_text = base64.b64encode(pbkdf2_salt + init_vector + cipher.encrypt(plain_text)) - return cipher_text - - @staticmethod - def decrypt(password, cipher_text): - """ - decrypt the :cipher_text: into :plain_text: using the password - - :cipher_text: is expected to be encoded as base64 to make it textable (non-binary) - inside of that it is expected to be formatted as - pbkdf2_salt + init_vector + encrypt(:plain_text:) - - :pbkdf2_salt: has the fixed length of 32 (AES-256) - :init_vector: has the fixed length of AES.block_size - """ - cipher_text = base64.b64decode(cipher_text) - pbkdf2_salt = cipher_text[: Cipher.KEY_SIZE] - init_vector = cipher_text[Cipher.KEY_SIZE : Cipher.KEY_SIZE + AES.block_size] - cipher_text = cipher_text[Cipher.KEY_SIZE + AES.block_size :] - derived_key = PBKDF2(password, pbkdf2_salt, Cipher.KEY_SIZE, Cipher.KDF_ITERATIONS) - - cipher = AES.new(derived_key, Cipher.AES_MODE, init_vector) - plain_text = cipher.decrypt(cipher_text).decode('utf-8') - return plain_text diff --git a/policyhandler/policy_engine.py b/policyhandler/policy_engine.py index 838ccc7..68e81cf 100644 --- a/policyhandler/policy_engine.py +++ b/policyhandler/policy_engine.py @@ -32,7 +32,7 @@ class PolicyNotificationHandler(NotificationHandler): _logger = logging.getLogger("policy_handler.policy_notification") def __init__(self, policy_updater): - scope_prefixes = [scope_prefix.replace(".", "[.]") \ + scope_prefixes = [scope_prefix.replace(".", "[.]") for scope_prefix in Config.config["scope_prefixes"]] self._policy_scopes = re.compile("(" + "|".join(scope_prefixes) + ")") PolicyNotificationHandler._logger.info("_policy_scopes %s", self._policy_scopes.pattern) @@ -43,13 +43,13 @@ class PolicyNotificationHandler(NotificationHandler): if not notification or not notification._loadedPolicies: return - policy_names = [loaded._policyName \ - for loaded in notification._loadedPolicies \ - if self._policy_scopes.match(loaded._policyName)] + policy_names = [loaded._policyName + for loaded in notification._loadedPolicies + if self._policy_scopes.match(loaded._policyName)] if not policy_names: - PolicyNotificationHandler._logger.info("no policy updated for scopes %s", \ - self._policy_scopes.pattern) + PolicyNotificationHandler._logger.info("no policy updated for scopes %s", + self._policy_scopes.pattern) return audit = Audit(req_message="notificationReceived from PDP") @@ -89,11 +89,13 @@ class PolicyEngineClient(object): sub_aud = Audit(aud_parent=audit) sub_aud.metrics_start("create client to PDP") PolicyEngineConfig.save_to_file() - PolicyEngineClient._policy_engine = PolicyEngine(PolicyEngineConfig.PATH_TO_PROPERTIES, \ - scheme=NotificationScheme.AUTO_ALL_NOTIFICATIONS.name,\ - handler=PolicyEngineClient._pdp_notification_handler) + PolicyEngineClient._policy_engine = PolicyEngine( + PolicyEngineConfig.PATH_TO_PROPERTIES, + scheme=NotificationScheme.AUTO_ALL_NOTIFICATIONS.name, + handler=PolicyEngineClient._pdp_notification_handler + ) sub_aud.metrics("created client to PDP") - seed_scope = Config.config["scope_prefixes"][0] + ".*" + seed_scope = ".*" PolicyEngineClient._policy_engine.getConfig(policyName=seed_scope) sub_aud.metrics("seeded client by PDP.getConfig for policyName={0}".format(seed_scope)) diff --git a/policyhandler/policy_handler.py b/policyhandler/policy_handler.py index 10633cd..50d59bc 100644 --- a/policyhandler/policy_handler.py +++ b/policyhandler/policy_handler.py @@ -60,28 +60,5 @@ def run_policy_handler(): PolicyEngineClient.run() PolicyWeb.run() -def upload_config_to_discovery(): - """read the config from file and upload it to discovery""" - logger = logging.getLogger("policy_handler") - sys.stdout = LogWriter(logger.info) - sys.stderr = LogWriter(logger.error) - - Config.load_from_file() - - if not Config.load_from_file(Config.UPLOAD_CONFIG_FILE_PATH): - logger.info("not found config %s", Config.UPLOAD_CONFIG_FILE_PATH) - return - - logger.info("========== upload_config_to_discovery ==========") - Config.upload_to_discovery() - - logger.info("========== upload_config_to_discovery - get it back ==========") - Config.config = None - Config.load_from_file() - Config.discover() - logger.info("========== upload_config_to_discovery - done ==========") - return True - if __name__ == "__main__": - if not upload_config_to_discovery(): - run_policy_handler() + run_policy_handler() -- cgit 1.2.3-korg