diff options
Diffstat (limited to 'osdf')
-rw-r--r-- | osdf/adapters/aaf/__init__.py | 0 | ||||
-rw-r--r-- | osdf/adapters/aaf/aaf_authentication.py | 99 | ||||
-rw-r--r-- | osdf/optimizers/routeopt/simple_route_opt.py | 65 | ||||
-rw-r--r-- | osdf/webapp/appcontroller.py | 12 |
4 files changed, 137 insertions, 39 deletions
diff --git a/osdf/adapters/aaf/__init__.py b/osdf/adapters/aaf/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/osdf/adapters/aaf/__init__.py diff --git a/osdf/adapters/aaf/aaf_authentication.py b/osdf/adapters/aaf/aaf_authentication.py new file mode 100644 index 0000000..26a3992 --- /dev/null +++ b/osdf/adapters/aaf/aaf_authentication.py @@ -0,0 +1,99 @@ +# ------------------------------------------------------------------------- +# Copyright (c) 2015-2017 AT&T Intellectual Property +# +# 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. +# +# ------------------------------------------------------------------------- +# + +import base64 +import re +from datetime import datetime, timedelta +from flask import request + +from osdf.config.base import osdf_config +from osdf.logging.osdf_logging import error_log, debug_log +from osdf.utils.interfaces import RestClient + +AUTHZ_PERMS_USER = '{}/authz/perms/user/{}' + +EXPIRE_TIME = 'expire_time' + +perm_cache = {} +deploy_config = osdf_config.deployment + + +def clear_cache(): + perm_cache.clear() + + +def authenticate(uid, passwd): + try: + perms = get_aaf_permissions(uid, passwd) + return has_valid_role(perms) + except Exception as exp: + error_log.error("Error Authenticating the user {} : {}: ".format(uid, exp)) + pass + return False + + +""" +Check whether the user has valid permissions +return True if the user has valid permissions +else return false +""" + + +def has_valid_role(perms): + aaf_user_roles = deploy_config['aaf_user_roles'] + + for roles in aaf_user_roles: + path_perm = roles.split(':') + uri = path_perm[0] + role = path_perm[1].split('|')[0] + if re.search(uri, request.path) and perms: + roles = perms.get('roles') + if roles: + perm_list = roles.get('perm') + for p in perm_list: + if role == p['type']: + return True + return False + +""" +Make the remote aaf api call if user is not in the cache. + +Return the perms +""" +def get_aaf_permissions(uid, passwd): + key = base64.b64encode(bytes("{}_{}".format(uid, passwd), "ascii")) + time_delta = timedelta(hours=deploy_config.get('aaf_cache_expiry_hrs', 3)) + + perms = perm_cache.get(key) + + if perms and datetime.now() < perms.get(EXPIRE_TIME): + debug_log.debug("Returning cached value") + return perms + debug_log.debug("Invoking AAF authentication API") + perms = {EXPIRE_TIME: datetime.now() + time_delta, 'roles': remote_api(passwd, uid)} + perm_cache[key] = perms + return perms + + +def remote_api(passwd, uid): + headers = {"Accept": "application/Users+xml;q=1.0;charset=utf-8;version=2.0,text/xml;q=1.0;version=2.0", + "Accept": "application/Users+json;q=1.0;charset=utf-8;version=2.0,application/json;q=1.0;version=2.0,*/*;q=1.0"} + url = AUTHZ_PERMS_USER.format(deploy_config['aaf_url'], uid) + rc = RestClient(userid=uid, passwd=passwd, headers=headers, url=url, log_func=debug_log.debug, + req_id='aaf_user_id', service='aaf_authentication_service') + return rc.request(method='GET', asjson=True) diff --git a/osdf/optimizers/routeopt/simple_route_opt.py b/osdf/optimizers/routeopt/simple_route_opt.py index 9560996..d1cf13f 100644 --- a/osdf/optimizers/routeopt/simple_route_opt.py +++ b/osdf/optimizers/routeopt/simple_route_opt.py @@ -42,9 +42,9 @@ class RouteOpt: :param logical_link: :return: """ - for relationship in logical_link["logical-links"]["relationsihp-list"]["relationship"]: + for relationship in logical_link["logical-links"]["relationship-list"]["relationship"]: if relationship["related-to"] == "p-interface": - if "external" in relationship["related-link"]: + if "ext-aai-network" in relationship["related-link"]: return True return False @@ -58,20 +58,6 @@ class RouteOpt: src_access_node_id = request["srcPort"]["src-access-node-id"] dst_access_node_id = request["dstPort"]["dst-access-node-id"] - # for the case of request for same domain, return the same node with destination update - if src_access_node_id == dst_access_node_id: - return { - [ - { - "access-topology-id": request["srcPort"]["src-access-topology-id"], - "access-client-id": request["srcPort"]["access-client-id"], - "access-provider-id": request["srcPort"]["access-provider-id"], - "access-node-id": request["srcPort"]["access-node-id"], - "src-access-ltp-id": request["srcPort"]["src-access-ltp-id"], - "dst-access-ltp-id": request["dstPort"]["dst-access-ltp-id"] - } - ] - } ingress_p_interface = None egress_p_interface = None @@ -84,33 +70,34 @@ class RouteOpt: if not self.isCrossONAPLink(logical_link): # link is in local ONAP - for relationship in logical_link["logical-links"]["relationsihp-list"]["relationship"]: + for relationship in logical_link["logical-links"]["relationship-list"]["relationship"]: if relationship["related-to"] == "p-interface": if src_access_node_id in relationship["related-link"]: ingress_p_interface = relationship["related-link"].split("/")[-1] if dst_access_node_id in relationship["related-link"]: egress_p_interface = relationship["related-link"].split("/")[-1] - return { - [ - { - "access-topology-id": request["srcPort"]["src-access-topology-id"], - "access-client-id": request["srcPort"]["access-client-id"], - "access-provider-id": request["srcPort"]["access-provider-id"], - "access-node-id": request["srcPort"]["access-node-id"], - "src-access-ltp-id": request["srcPort"]["src-access-ltp-id"], - "dst-access-ltp-id": ingress_p_interface - }, - { - "access-topology-id": request["dstPort"]["access-topology-id"], - "access-client-id": request["dstPort"]["access-client-id"], - "access-provider-id": request["dstPort"]["access-provider-id"], - "access-node-id": request["dstPort"]["access-node-id"], - "src-access-ltp-id": egress_p_interface, - "dst-access-ltp-id": request["dstPort"]["dst-access-ltp-id"] - } - ] - } + data = '{'\ + '"vpns":['\ + '{'\ + '"access-topology-id": "' + request["srcPort"]["src-access-topology-id"] + '",'\ + '"access-client-id": "' + request["srcPort"]["src-access-client-id"] + '",'\ + '"access-provider-id": "' + request["srcPort"]["src-access-provider-id"]+ '",'\ + '"access-node-id": "' + request["srcPort"]["src-access-node-id"]+ '",'\ + '"src-access-ltp-id": "' + request["srcPort"]["src-access-ltp-id"]+ '",'\ + '"dst-access-ltp-id": "' + ingress_p_interface +'"'\ + '},'\ + '{' \ + '"access-topology-id": "' + request["dstPort"]["dst-access-topology-id"] + '",' \ + '"access-topology-id": "' + request["dstPort"]["dst-access-topology-id"]+ '",' \ + '"access-provider-id": "' + request["dstPort"]["dst-access-provider-id"]+ '",' \ + '"access-node-id": "' + request["dstPort"]["dst-access-node-id"]+ '",' \ + '"src-access-ltp-id": "' + egress_p_interface + '",' \ + '"dst-access-ltp-id": "' + request["dstPort"]["dst-access-ltp-id"] + '"' \ + '}'\ + ']'\ + '}' + return data @@ -125,7 +112,7 @@ class RouteOpt: auth=HTTPBasicAuth("", "")) if response.status_code == 200: - return response.json + return response.json() def get_logical_links(self): @@ -142,4 +129,4 @@ class RouteOpt: auth=HTTPBasicAuth("", "")) if response.status_code == 200: - return response.json + return response.json()
\ No newline at end of file diff --git a/osdf/webapp/appcontroller.py b/osdf/webapp/appcontroller.py index 49f84ff..a56a53d 100644 --- a/osdf/webapp/appcontroller.py +++ b/osdf/webapp/appcontroller.py @@ -22,6 +22,7 @@ from flask import Response import json import osdf from osdf.config.base import http_basic_auth_credentials +from osdf.adapters.aaf import aaf_authentication as aaf_auth auth_basic = HTTPBasicAuth() @@ -45,3 +46,14 @@ def auth_error(): response.headers.add('content-length', len(unauthorized_message)) response.status_code = 401 return response + + +@auth_basic.verify_password +def verify_pw(username, password): + is_aaf_enabled = osdf.deployment.get('is_aaf_enabled', False) + if is_aaf_enabled: + return aaf_auth.authenticate(username, password) + else: + pw = get_pw(username) + return pw == password + return False
\ No newline at end of file |