X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FNBI.git;a=blobdiff_plain;f=osm_nbi%2Fauth.py;h=d91618919f95f809abbcc7f6f1be1478aa09f83f;hp=9171c9494beacaaf38408982a57e48bb80eaf3f2;hb=c4650365704d7827e53280ca16f9bdb70bf9fcbb;hpb=c061f56a0218c562315f563b001a72fbdfa550c6;ds=sidebyside diff --git a/osm_nbi/auth.py b/osm_nbi/auth.py index 9171c94..d916189 100644 --- a/osm_nbi/auth.py +++ b/osm_nbi/auth.py @@ -55,6 +55,7 @@ class Authenticator: Authorization. Initially it should support Openstack Keystone as a backend through a plugin model where more backends can be added and a RBAC model to manage permissions on operations. + This class must be threading safe """ periodin_db_pruning = 60 * 30 # for the internal backend only. every 30 minutes expired tokens will be pruned @@ -155,16 +156,15 @@ class Authenticator: # 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) for resource, operation in resources_to_operations_yaml["resources_to_operations"].items(): - operation_key = operation.replace(".", ":") - if operation_key not in operations: - operations.append(operation_key) - self.resources_to_operations_mapping[resource] = operation_key + if operation not in operations: + operations.append(operation) + self.resources_to_operations_mapping[resource] = operation records = self.db.get_list("roles_operations") @@ -193,19 +193,18 @@ class Authenticator: if not isinstance(is_allowed, bool): continue - if operation == ".": + if operation == ":": root = is_allowed continue - if len(operation) != 1 and operation[-1] == ".": - self.logger.warning("Invalid operation {0} terminated in '.'. " + if len(operation) != 1 and operation[-1] == ":": + self.logger.warning("Invalid operation {0} terminated in ':'. " "Operation will be discarded" .format(operation)) continue - operation_key = operation.replace(".", ":") - if operation_key not in role_ops.keys(): - role_ops[operation_key] = is_allowed + if operation not in role_ops.keys(): + role_ops[operation] = is_allowed else: self.logger.info("In role {0}, the operation {1} with the value {2} was discarded due to " "repetition.".format(role_with_operations["role"], operation, is_allowed)) @@ -230,7 +229,12 @@ class Authenticator: if self.config["authentication"]["backend"] != "internal" and \ role_with_operations["role"] != "anonymous": - keystone_id = self.backend.create_role(role_with_operations["role"]) + keystone_id = [role for role in self.backend.get_role_list() + if role["name"] == role_with_operations["role"]] + if keystone_id: + keystone_id = keystone_id[0] + else: + 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) @@ -480,7 +484,8 @@ class Authenticator: now = time() session = self.tokens_cache.get(token_id) if session and session["expires"] < now: - del self.tokens_cache[token_id] + # delete token. MUST be done with care, as another thread maybe already delete it. Do not use del + self.tokens_cache.pop(token_id, None) session = None if session: return session @@ -501,7 +506,7 @@ class Authenticator: if self.config["global"].get("test.user_not_authorized"): return {"id": "fake-token-id-for-test", "project_id": self.config["global"].get("test.project_not_authorized", "admin"), - "username": self.config["global"]["test.user_not_authorized"]} + "username": self.config["global"]["test.user_not_authorized"], "admin": True} else: raise