X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FNBI.git;a=blobdiff_plain;f=osm_nbi%2Fauth.py;h=9171c9494beacaaf38408982a57e48bb80eaf3f2;hp=18986a3ab4d7e64a00280519a495fb37d510ea40;hb=e4a07d5db1e38e6a52788d5788c6cc3396e1052d;hpb=cc02e9ae712026b0c07389f66304fc9c1fde86e1;ds=sidebyside diff --git a/osm_nbi/auth.py b/osm_nbi/auth.py index 18986a3..9171c94 100644 --- a/osm_nbi/auth.py +++ b/osm_nbi/auth.py @@ -25,7 +25,6 @@ Authenticator is responsible for authenticating the users, create the tokens unscoped and scoped, retrieve the role list inside the projects that they are inserted """ -from os import path __author__ = "Eduardo Sousa ; Alfonso Tierno " __date__ = "$27-jul-2018 23:59:59$" @@ -40,7 +39,8 @@ from hashlib import sha256 from http import HTTPStatus from random import choice as random_choice from time import time -from uuid import uuid4 +from os import path +from base_topic import BaseTopic # To allow project names in project_id from authconn import AuthException from authconn_keystone import AuthconnKeystone @@ -108,8 +108,11 @@ class Authenticator: if "resources_to_operations" in config["rbac"]: self.resources_to_operations_file = config["rbac"]["resources_to_operations"] else: - for config_file in (__file__[:__file__.rfind("auth.py")] + "resources_to_operations.yml", - "./resources_to_operations.yml"): + possible_paths = ( + __file__[:__file__.rfind("auth.py")] + "resources_to_operations.yml", + "./resources_to_operations.yml" + ) + for config_file in possible_paths: if path.isfile(config_file): self.resources_to_operations_file = config_file break @@ -119,8 +122,11 @@ class Authenticator: if "roles_to_operations" in config["rbac"]: self.roles_to_operations_file = config["rbac"]["roles_to_operations"] else: - for config_file in (__file__[:__file__.rfind("auth.py")] + "roles_to_operations.yml", - "./roles_to_operations.yml"): + possible_paths = ( + __file__[:__file__.rfind("auth.py")] + "roles_to_operations.yml", + "./roles_to_operations.yml" + ) + for config_file in possible_paths: if path.isfile(config_file): self.roles_to_operations_file = config_file break @@ -147,6 +153,9 @@ class Authenticator: # Always reads operation to resource mapping from file (this is static, no need to store it in MongoDB) # Operations encoding: " " # Note: it is faster to rewrite the value than to check if it is already there or not + if self.config["authentication"]["backend"] == "internal": + return + operations = [] with open(self.resources_to_operations_file, "r") as stream: resources_to_operations_yaml = yaml.load(stream) @@ -208,28 +217,29 @@ class Authenticator: now = time() operation_to_roles_item = { - "_id": str(uuid4()), "_admin": { "created": now, "modified": now, }, - "role": role_with_operations["role"], + "name": role_with_operations["role"], "root": root } for operation, value in role_ops.items(): operation_to_roles_item[operation] = value + if self.config["authentication"]["backend"] != "internal" and \ + role_with_operations["role"] != "anonymous": + keystone_id = self.backend.create_role(role_with_operations["role"]) + operation_to_roles_item["_id"] = keystone_id["_id"] + self.db.create("roles_operations", operation_to_roles_item) permissions = {oper: [] for oper in operations} records = self.db.get_list("roles_operations") - ignore_fields = ["_id", "_admin", "role", "root"] - roles = [] + ignore_fields = ["_id", "_admin", "name", "root"] for record in records: - - roles.append(record["role"]) record_permissions = {oper: record["root"] for oper in operations} operations_joined = [(oper, value) for oper, value in record.items() if oper not in ignore_fields] operations_joined.sort(key=lambda x: x[0].count(":")) @@ -243,17 +253,12 @@ class Authenticator: allowed_operations = [k for k, v in record_permissions.items() if v is True] for allowed_op in allowed_operations: - permissions[allowed_op].append(record["role"]) + permissions[allowed_op].append(record["name"]) for oper, role_list in permissions.items(): self.operation_to_allowed_roles[oper] = role_list if self.config["authentication"]["backend"] != "internal": - for role in roles: - if role == "anonymous": - continue - self.backend.create_role(role) - self.backend.assign_role_to_user("admin", "admin", "system_admin") def authorize(self): @@ -402,7 +407,7 @@ class Authenticator: operation = self.resources_to_operations_mapping[key] roles_required = self.operation_to_allowed_roles[operation] - roles_allowed = self.backend.get_role_list(session["id"]) + roles_allowed = self.backend.get_user_role_list(session["id"]) if "anonymous" in roles_required: return @@ -413,6 +418,9 @@ class Authenticator: raise AuthException("Access denied: lack of permissions.") + def get_user_list(self): + return self.backend.get_user_list() + def _normalize_url(self, url, method): # Removing query strings normalized_url = url if '?' not in url else url[:url.find("?")] @@ -524,17 +532,21 @@ class Authenticator: token_id = ''.join(random_choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for _ in range(0, 32)) - if indata.get("project_id"): - project_id = indata.get("project_id") - if project_id not in user_content["projects"]: - raise AuthException("project {} not allowed for this user" - .format(project_id), http_code=HTTPStatus.UNAUTHORIZED) + project_id = indata.get("project_id") + if project_id: + if project_id != "admin": + # To allow project names in project_id + proj = self.db.get_one("projects", {BaseTopic.id_field("projects", project_id): project_id}) + if proj["_id"] not in user_content["projects"] and proj["name"] not in user_content["projects"]: + raise AuthException("project {} not allowed for this user" + .format(project_id), http_code=HTTPStatus.UNAUTHORIZED) else: project_id = user_content["projects"][0] if project_id == "admin": session_admin = True else: - project = self.db.get_one("projects", {"_id": project_id}) + # To allow project names in project_id + project = self.db.get_one("projects", {BaseTopic.id_field("projects", project_id): project_id}) session_admin = project.get("admin", False) new_session = {"issued_at": now, "expires": now + 3600, "_id": token_id, "id": token_id, "project_id": project_id, "username": user_content["username"],