X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FNBI.git;a=blobdiff_plain;f=osm_nbi%2Fauth.py;h=dc7c0ff860f79dfa5f57a74a680468cf8ef9a613;hp=e9a6b4e92b6a5617945bdf788a3582509954b2ba;hb=c844536bb27c39aa48988284c5a0d7b404930a8a;hpb=1f029d84b9597d3986a33dcd847b0d97d2bad077 diff --git a/osm_nbi/auth.py b/osm_nbi/auth.py index e9a6b4e..dc7c0ff 100644 --- a/osm_nbi/auth.py +++ b/osm_nbi/auth.py @@ -42,7 +42,7 @@ from time import time from os import path from base_topic import BaseTopic # To allow project names in project_id -from authconn import AuthException +from authconn import AuthException, AuthExceptionUnauthorized from authconn_keystone import AuthconnKeystone from osm_common import dbmongo from osm_common import dbmemory @@ -229,13 +229,14 @@ class Authenticator: def load_operation_to_allowed_roles(self): """ Fills the internal self.operation_to_allowed_roles based on database role content and self.operations + It works in a shadow copy and replace at the end to allow other threads working with the old copy :return: None """ permissions = {oper: [] for oper in self.operations} records = self.db.get_list("roles_operations") - ignore_fields = ["_id", "_admin", "name", "default", "admin"] + ignore_fields = ["_id", "_admin", "name", "default"] for record in records: record_permissions = {oper: record["permissions"].get("default", False) for oper in self.operations} operations_joined = [(oper, value) for oper, value in record["permissions"].items() @@ -253,8 +254,7 @@ class Authenticator: for allowed_op in allowed_operations: permissions[allowed_op].append(record["name"]) - for oper, role_list in permissions.items(): - self.operation_to_allowed_roles[oper] = role_list + self.operation_to_allowed_roles = permissions def authorize(self): token = None @@ -292,20 +292,18 @@ class Authenticator: if not token: raise AuthException("Needed a token or Authorization http header", http_code=HTTPStatus.UNAUTHORIZED) - try: - self.backend.validate_token(token) - self.check_permissions(self.tokens_cache[token], cherrypy.request.path_info, - cherrypy.request.method) - # TODO: check if this can be avoided. Backend may provide enough information - return deepcopy(self.tokens_cache[token]) - except AuthException: - self.del_token(token) - raise + token_info = self.backend.validate_token(token) + # TODO add to token info remote host, port + + self.check_permissions(token_info, cherrypy.request.path_info, + cherrypy.request.method) + return token_info except AuthException as e: - if cherrypy.session.get('Authorization'): - del cherrypy.session['Authorization'] - cherrypy.response.headers["WWW-Authenticate"] = 'Bearer realm="{}"'.format(e) - raise AuthException(str(e)) + if not isinstance(e, AuthExceptionUnauthorized): + if cherrypy.session.get('Authorization'): + del cherrypy.session['Authorization'] + cherrypy.response.headers["WWW-Authenticate"] = 'Bearer realm="{}"'.format(e) + raise def new_token(self, session, indata, remote): if self.config["authentication"]["backend"] == "internal": @@ -412,7 +410,14 @@ class Authenticator: operation = self.resources_to_operations_mapping[key] roles_required = self.operation_to_allowed_roles[operation] - roles_allowed = self.backend.get_user_role_list(session["_id"]) + roles_allowed = [role["name"] for role in session["roles"]] + + # fills session["admin"] if some roles allows it + session["admin"] = False + for role in roles_allowed: + if role in self.operation_to_allowed_roles["admin"]: + session["admin"] = True + break if "anonymous" in roles_required: return @@ -421,7 +426,7 @@ class Authenticator: if role in roles_required: return - raise AuthException("Access denied: lack of permissions.") + raise AuthExceptionUnauthorized("Access denied: lack of permissions.") def get_user_list(self): return self.backend.get_user_list()