X-Git-Url: https://osm.etsi.org/gitweb/?p=osm%2FNBI.git;a=blobdiff_plain;f=osm_nbi%2Fauthconn_keystone.py;h=c8d68111949a98e33d6f175b0b7b508dd50999cf;hp=54442c8c9d617f699def4ecf91dea056254cb3da;hb=4015b4734a923c29c04bf9b30f5a06604dd2f0a4;hpb=5c01e193a17fcf730406e39fe7d019e1dee5c64d diff --git a/osm_nbi/authconn_keystone.py b/osm_nbi/authconn_keystone.py index 54442c8..c8d6811 100644 --- a/osm_nbi/authconn_keystone.py +++ b/osm_nbi/authconn_keystone.py @@ -23,7 +23,7 @@ AuthconnKeystone implements implements the connector for Openstack Keystone and leverages the RBAC model, to bring it for OSM. """ -import time + __author__ = "Eduardo Sousa " __date__ = "$27-jul-2018 23:59:59$" @@ -32,12 +32,14 @@ from authconn import Authconn, AuthException, AuthconnOperationException import logging import requests +import time from keystoneauth1 import session from keystoneauth1.identity import v3 from keystoneauth1.exceptions.base import ClientException from keystoneauth1.exceptions.http import Conflict from keystoneclient.v3 import client from http import HTTPStatus +from validation import is_valid_uuid class AuthconnKeystone(Authconn): @@ -95,9 +97,10 @@ class AuthconnKeystone(Authconn): project_domain_name=self.project_domain_name) return token["auth_token"], project_names - except ClientException: - self.logger.exception("Error during user authentication using keystone. Method: basic") - raise AuthException("Error during user authentication using Keystone", http_code=HTTPStatus.UNAUTHORIZED) + except ClientException as e: + self.logger.exception("Error during user authentication using keystone. Method: basic: {}".format(e)) + raise AuthException("Error during user authentication using Keystone: {}".format(e), + http_code=HTTPStatus.UNAUTHORIZED) def authenticate_with_token(self, token, project=None): """ @@ -122,9 +125,10 @@ class AuthconnKeystone(Authconn): project_domain_name=self.project_domain_name) return new_token["auth_token"], project_names - except ClientException: - self.logger.exception("Error during user authentication using keystone. Method: bearer") - raise AuthException("Error during user authentication using Keystone", http_code=HTTPStatus.UNAUTHORIZED) + except ClientException as e: + self.logger.exception("Error during user authentication using keystone. Method: bearer: {}".format(e)) + raise AuthException("Error during user authentication using Keystone: {}".format(e), + http_code=HTTPStatus.UNAUTHORIZED) def validate_token(self, token): """ @@ -141,9 +145,10 @@ class AuthconnKeystone(Authconn): token_info = self.keystone.tokens.validate(token=token) return token_info - except ClientException: - self.logger.exception("Error during token validation using keystone") - raise AuthException("Error during token validation using Keystone", http_code=HTTPStatus.UNAUTHORIZED) + except ClientException as e: + self.logger.exception("Error during token validation using keystone: {}".format(e)) + raise AuthException("Error during token validation using Keystone: {}".format(e), + http_code=HTTPStatus.UNAUTHORIZED) def revoke_token(self, token): """ @@ -156,9 +161,10 @@ class AuthconnKeystone(Authconn): self.keystone.tokens.revoke_token(token=token) return True - except ClientException: - self.logger.exception("Error during token revocation using keystone") - raise AuthException("Error during token revocation using Keystone", http_code=HTTPStatus.UNAUTHORIZED) + except ClientException as e: + self.logger.exception("Error during token revocation using keystone: {}".format(e)) + raise AuthException("Error during token revocation using Keystone: {}".format(e), + http_code=HTTPStatus.UNAUTHORIZED) def get_user_project_list(self, token): """ @@ -173,9 +179,10 @@ class AuthconnKeystone(Authconn): project_names = [project.name for project in projects] return project_names - except ClientException: - self.logger.exception("Error during user project listing using keystone") - raise AuthException("Error during user project listing using Keystone", http_code=HTTPStatus.UNAUTHORIZED) + except ClientException as e: + self.logger.exception("Error during user project listing using keystone: {}".format(e)) + raise AuthException("Error during user project listing using Keystone: {}".format(e), + http_code=HTTPStatus.UNAUTHORIZED) def get_user_role_list(self, token): """ @@ -192,9 +199,10 @@ class AuthconnKeystone(Authconn): roles = [role.name for role in roles_info] return roles - except ClientException: - self.logger.exception("Error during user role listing using keystone") - raise AuthException("Error during user role listing using Keystone", http_code=HTTPStatus.UNAUTHORIZED) + except ClientException as e: + self.logger.exception("Error during user role listing using keystone: {}".format(e)) + raise AuthException("Error during user role listing using Keystone: {}".format(e), + http_code=HTTPStatus.UNAUTHORIZED) def create_user(self, user, password): """ @@ -208,9 +216,9 @@ class AuthconnKeystone(Authconn): try: new_user = self.keystone.users.create(user, password=password, domain=self.user_domain_name) return {"username": new_user.name, "_id": new_user.id} - except ClientException: - self.logger.exception("Error during user creation using keystone") - raise AuthconnOperationException("Error during user creation using Keystone") + except ClientException as e: + self.logger.exception("Error during user creation using keystone: {}".format(e)) + raise AuthconnOperationException("Error during user creation using Keystone: {}".format(e)) def change_password(self, user, new_password): """ @@ -223,9 +231,9 @@ class AuthconnKeystone(Authconn): try: user_obj = list(filter(lambda x: x.name == user, self.keystone.users.list()))[0] self.keystone.users.update(user_obj, password=new_password) - except ClientException: - self.logger.exception("Error during user password update using keystone") - raise AuthconnOperationException("Error during user password update using Keystone") + except ClientException as e: + self.logger.exception("Error during user password update using keystone: {}".format(e)) + raise AuthconnOperationException("Error during user password update using Keystone: {}".format(e)) def delete_user(self, user_id): """ @@ -243,51 +251,62 @@ class AuthconnKeystone(Authconn): raise ClientException("User was not deleted") return True - except ClientException: - self.logger.exception("Error during user deletion using keystone") - raise AuthconnOperationException("Error during user deletion using Keystone") + except ClientException as e: + self.logger.exception("Error during user deletion using keystone: {}".format(e)) + raise AuthconnOperationException("Error during user deletion using Keystone: {}".format(e)) - def get_user_list(self): + def get_user_list(self, filter_q={}): """ Get user list. + :param filter_q: dictionary to filter user list. :return: returns a list of users. """ try: users = self.keystone.users.list() users = [{ "username": user.name, - "_id": user.id + "_id": user.id, + "id": user.id } for user in users if user.name != self.admin_username] + allowed_fields = ["_id", "id", "username"] + for key in filter_q.keys(): + if key not in allowed_fields: + continue + + users = [user for user in users + if filter_q[key] == user[key]] + for user in users: projects = self.keystone.projects.list(user=user["_id"]) projects = [{ "name": project.name, - "_id": project.id + "_id": project.id, + "id": project.id } for project in projects] for project in projects: roles = self.keystone.roles.list(user=user["_id"], project=project["_id"]) roles = [{ "name": role.name, - "_id": role.id + "_id": role.id, + "id": role.id } for role in roles] project["roles"] = roles user["projects"] = projects return users - except ClientException: - self.logger.exception("Error during user listing using keystone") - raise AuthconnOperationException("Error during user listing using Keystone") + except ClientException as e: + self.logger.exception("Error during user listing using keystone: {}".format(e)) + raise AuthconnOperationException("Error during user listing using Keystone: {}".format(e)) def get_role_list(self): """ Get role list. - :return: returns the list of roles for the user in that project. If - the token is unscoped it returns None. + :return: returns the list of roles. """ try: roles_list = self.keystone.roles.list() @@ -298,9 +317,10 @@ class AuthconnKeystone(Authconn): } for role in roles_list if role.name != "service"] return roles - except ClientException: - self.logger.exception("Error during user role listing using keystone") - raise AuthException("Error during user role listing using Keystone", http_code=HTTPStatus.UNAUTHORIZED) + except ClientException as e: + self.logger.exception("Error during user role listing using keystone: {}".format(e)) + raise AuthException("Error during user role listing using Keystone: {}".format(e), + http_code=HTTPStatus.UNAUTHORIZED) def create_role(self, role): """ @@ -314,9 +334,9 @@ class AuthconnKeystone(Authconn): return {"name": result.name, "_id": result.id} except Conflict as ex: self.logger.info("Duplicate entry: %s", str(ex)) - except ClientException: - self.logger.exception("Error during role creation using keystone") - raise AuthconnOperationException("Error during role creation using Keystone") + except ClientException as e: + self.logger.exception("Error during role creation using keystone: {}".format(e)) + raise AuthconnOperationException("Error during role creation using Keystone: {}".format(e)) def delete_role(self, role_id): """ @@ -334,14 +354,15 @@ class AuthconnKeystone(Authconn): raise ClientException("Role was not deleted") return True - except ClientException: - self.logger.exception("Error during role deletion using keystone") - raise AuthconnOperationException("Error during role deletion using Keystone") + except ClientException as e: + self.logger.exception("Error during role deletion using keystone: {}".format(e)) + raise AuthconnOperationException("Error during role deletion using Keystone: {}".format(e)) - def get_project_list(self): + def get_project_list(self, filter_q={}): """ Get all the projects. + :param filter_q: dictionary to filter project list. :return: list of projects """ try: @@ -351,24 +372,34 @@ class AuthconnKeystone(Authconn): "_id": project.id } for project in projects if project.name != self.admin_project] + allowed_fields = ["_id", "name"] + for key in filter_q.keys(): + if key not in allowed_fields: + continue + + projects = [project for project in projects + if filter_q[key] == project[key]] + return projects - except ClientException: - self.logger.exception("Error during user project listing using keystone") - raise AuthException("Error during user project listing using Keystone", http_code=HTTPStatus.UNAUTHORIZED) + except ClientException as e: + self.logger.exception("Error during user project listing using keystone: {}".format(e)) + raise AuthException("Error during user project listing using Keystone: {}".format(e), + http_code=HTTPStatus.UNAUTHORIZED) def create_project(self, project): """ Create a project. :param project: project name. + :return: the internal id of the created project :raises AuthconnOperationException: if project creation failed. """ try: result = self.keystone.projects.create(project, self.project_domain_name) - return {"name": result.name, "_id": result.id} - except ClientException: - self.logger.exception("Error during project creation using keystone") - raise AuthconnOperationException("Error during project creation using Keystone") + return result.id + except ClientException as e: + self.logger.exception("Error during project creation using keystone: {}".format(e)) + raise AuthconnOperationException("Error during project creation using Keystone: {}".format(e)) def delete_project(self, project_id): """ @@ -386,9 +417,22 @@ class AuthconnKeystone(Authconn): raise ClientException("Project was not deleted") return True - except ClientException: - self.logger.exception("Error during project deletion using keystone") - raise AuthconnOperationException("Error during project deletion using Keystone") + except ClientException as e: + self.logger.exception("Error during project deletion using keystone: {}".format(e)) + raise AuthconnOperationException("Error during project deletion using Keystone: {}".format(e)) + + def update_project(self, project_id, new_name): + """ + Change the name of a project + :param project_id: project to be changed + :param new_name: new name + :return: None + """ + try: + self.keystone.projects.update(project_id, name=new_name) + except ClientException as e: + self.logger.exception("Error during project update using keystone: {}".format(e)) + raise AuthconnOperationException("Error during project deletion using Keystone: {}".format(e)) def assign_role_to_user(self, user, project, role): """ @@ -400,14 +444,25 @@ class AuthconnKeystone(Authconn): :raises AuthconnOperationException: if role assignment failed. """ try: - user_obj = list(filter(lambda x: x.name == user, self.keystone.users.list()))[0] - project_obj = list(filter(lambda x: x.name == project, self.keystone.projects.list()))[0] - role_obj = list(filter(lambda x: x.name == role, self.keystone.roles.list()))[0] + if is_valid_uuid(user): + user_obj = self.keystone.users.get(user) + else: + user_obj = self.keystone.users.list(name=user)[0] + + if is_valid_uuid(project): + project_obj = self.keystone.projects.get(project) + else: + project_obj = self.keystone.projects.list(name=project)[0] + + if is_valid_uuid(role): + role_obj = self.keystone.roles.get(role) + else: + role_obj = self.keystone.roles.list(name=role)[0] self.keystone.roles.grant(role_obj, user=user_obj, project=project_obj) - except ClientException: - self.logger.exception("Error during user role assignment using keystone") - raise AuthconnOperationException("Error during user role assignment using Keystone") + except ClientException as e: + self.logger.exception("Error during user role assignment using keystone: {}".format(e)) + raise AuthconnOperationException("Error during user role assignment using Keystone: {}".format(e)) def remove_role_from_user(self, user, project, role): """ @@ -424,6 +479,6 @@ class AuthconnKeystone(Authconn): role_obj = list(filter(lambda x: x.name == role, self.keystone.roles.list()))[0] self.keystone.roles.revoke(role_obj, user=user_obj, project=project_obj) - except ClientException: - self.logger.exception("Error during user role revocation using keystone") - raise AuthconnOperationException("Error during user role revocation using Keystone") + except ClientException as e: + self.logger.exception("Error during user role revocation using keystone: {}".format(e)) + raise AuthconnOperationException("Error during user role revocation using Keystone: {}".format(e))