1 # -*- coding: utf-8 -*-
3 # Copyright 2018 Whitestack, LLC
5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
6 # not use this file except in compliance with the License. You may obtain
7 # a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
17 # For those usages not covered by the Apache License, Version 2.0 please
18 # contact: esousa@whitestack.com or glavado@whitestack.com
22 Authconn implements an Abstract class for the Auth backend connector
23 plugins with the definition of the methods to be implemented.
27 "Eduardo Sousa <esousa@whitestack.com>, "
28 "Pedro de la Cruz Ramos <pdelacruzramos@altran.com>"
30 __date__
= "$27-jul-2018 23:59:59$"
32 from http
import HTTPStatus
33 from osm_nbi
.base_topic
import BaseTopic
36 class AuthException(Exception):
38 Authentication error, because token, user password not recognized
41 def __init__(self
, message
, http_code
=HTTPStatus
.UNAUTHORIZED
):
42 super(AuthException
, self
).__init
__(message
)
43 self
.http_code
= http_code
46 class AuthExceptionUnauthorized(AuthException
):
48 Authentication error, because not having rights to make this operation
54 class AuthconnException(Exception):
56 Common and base class Exception for all authconn exceptions.
59 def __init__(self
, message
, http_code
=HTTPStatus
.UNAUTHORIZED
):
60 super(AuthconnException
, self
).__init
__(message
)
61 self
.http_code
= http_code
64 class AuthconnConnectionException(AuthconnException
):
66 Connectivity error with Auth backend.
69 def __init__(self
, message
, http_code
=HTTPStatus
.BAD_GATEWAY
):
70 super(AuthconnConnectionException
, self
).__init
__(message
, http_code
)
73 class AuthconnNotSupportedException(AuthconnException
):
75 The request is not supported by the Auth backend.
78 def __init__(self
, message
, http_code
=HTTPStatus
.NOT_IMPLEMENTED
):
79 super(AuthconnNotSupportedException
, self
).__init
__(message
, http_code
)
82 class AuthconnNotImplementedException(AuthconnException
):
84 The method is not implemented by the Auth backend.
87 def __init__(self
, message
, http_code
=HTTPStatus
.NOT_IMPLEMENTED
):
88 super(AuthconnNotImplementedException
, self
).__init
__(message
, http_code
)
91 class AuthconnOperationException(AuthconnException
):
93 The operation executed failed.
96 def __init__(self
, message
, http_code
=HTTPStatus
.INTERNAL_SERVER_ERROR
):
97 super(AuthconnOperationException
, self
).__init
__(message
, http_code
)
100 class AuthconnNotFoundException(AuthconnException
):
102 The operation executed failed because element not found.
105 def __init__(self
, message
, http_code
=HTTPStatus
.NOT_FOUND
):
106 super().__init
__(message
, http_code
)
109 class AuthconnConflictException(AuthconnException
):
111 The operation has conflicts.
114 def __init__(self
, message
, http_code
=HTTPStatus
.CONFLICT
):
115 super().__init
__(message
, http_code
)
120 Abstract base class for all the Auth backend connector plugins.
121 Each Auth backend connector plugin must be a subclass of
125 def __init__(self
, config
, db
, role_permissions
):
127 Constructor of the Authconn class.
128 :param config: configuration dictionary containing all the
129 necessary configuration parameters.
130 :param db: internal database classs
131 :param role_permissions: read only role permission list
134 self
.role_permissions
= role_permissions
136 def authenticate(self
, credentials
, token_info
=None):
138 Authenticate a user using username/password or token_info, plus project
139 :param credentials: dictionary that contains:
140 username: name, id or None
141 password: password or None
142 project_id: name, id, or None. If None first found project will be used to get an scope token
143 other items are allowed for specific auth backends
144 :param token_info: previous token_info to obtain authorization
145 :return: the scoped token info or raises an exception. The token is a dictionary with:
146 _id: token string id,
148 project_id: scoped_token project_id,
149 project_name: scoped_token project_name,
150 expires: epoch time when it expires,
153 raise AuthconnNotImplementedException("Should have implemented this")
155 def validate_token(self
, token
):
157 Check if the token is valid.
159 :param token: token to validate
160 :return: dictionary with information associated with the token. If the
161 token is not valid, returns None.
163 raise AuthconnNotImplementedException("Should have implemented this")
165 def revoke_token(self
, token
):
169 :param token: token to be revoked
171 raise AuthconnNotImplementedException("Should have implemented this")
173 def create_user(self
, user_info
):
177 :param user_info: full user info.
178 :raises AuthconnOperationException: if user creation failed.
180 raise AuthconnNotImplementedException("Should have implemented this")
182 def update_user(self
, user_info
):
184 Change the user name and/or password.
186 :param user_info: user info modifications
187 :raises AuthconnNotImplementedException: if function not implemented
189 raise AuthconnNotImplementedException("Should have implemented this")
191 def delete_user(self
, user_id
):
195 :param user_id: user identifier.
196 :raises AuthconnOperationException: if user deletion failed.
198 raise AuthconnNotImplementedException("Should have implemented this")
200 def get_user_list(self
, filter_q
=None):
204 :param filter_q: dictionary to filter user list by name (username is also admited) and/or _id
205 :return: returns a list of users.
207 return list() # Default return value so that the method get_user passes pylint
209 def get_user(self
, _id
, fail
=True):
212 :param _id: id or name
213 :param fail: True to raise exception on not found. False to return None on not found
214 :return: dictionary with the user information
216 filt
= {BaseTopic
.id_field("users", _id
): _id
}
217 users
= self
.get_user_list(filt
)
220 raise AuthconnNotFoundException(
221 "User with {} not found".format(filt
),
222 http_code
=HTTPStatus
.NOT_FOUND
,
228 def create_role(self
, role_info
):
232 :param role_info: full role info.
233 :raises AuthconnOperationException: if role creation failed.
235 raise AuthconnNotImplementedException("Should have implemented this")
237 def delete_role(self
, role_id
):
241 :param role_id: role identifier.
242 :raises AuthconnOperationException: if user deletion failed.
244 raise AuthconnNotImplementedException("Should have implemented this")
246 def get_role_list(self
, filter_q
=None):
250 :param filter_q: dictionary to filter role list by _id and/or name.
251 :return: list of roles
253 raise AuthconnNotImplementedException("Should have implemented this")
255 def get_role(self
, _id
, fail
=True):
258 :param _id: id or name
259 :param fail: True to raise exception on not found. False to return None on not found
260 :return: dictionary with the role information
262 filt
= {BaseTopic
.id_field("roles", _id
): _id
}
263 roles
= self
.get_role_list(filt
)
266 raise AuthconnNotFoundException("Role with {} not found".format(filt
))
271 def update_role(self
, role_info
):
273 Change the information of a role
274 :param role_info: full role info
277 raise AuthconnNotImplementedException("Should have implemented this")
279 def create_project(self
, project_info
):
283 :param project_info: full project info.
284 :return: the internal id of the created project
285 :raises AuthconnOperationException: if project creation failed.
287 raise AuthconnNotImplementedException("Should have implemented this")
289 def delete_project(self
, project_id
):
293 :param project_id: project identifier.
294 :raises AuthconnOperationException: if project deletion failed.
296 raise AuthconnNotImplementedException("Should have implemented this")
298 def get_project_list(self
, filter_q
=None):
300 Get all the projects.
302 :param filter_q: dictionary to filter project list, by "name" and/or "_id"
303 :return: list of projects
305 raise AuthconnNotImplementedException("Should have implemented this")
307 def get_project(self
, _id
, fail
=True):
310 :param _id: id or name
311 :param fail: True to raise exception on not found. False to return None on not found
312 :return: dictionary with the project information
314 filt
= {BaseTopic
.id_field("projects", _id
): _id
}
315 projs
= self
.get_project_list(filt
)
318 raise AuthconnNotFoundException(
319 "project with {} not found".format(filt
)
325 def update_project(self
, project_id
, project_info
):
327 Change the information of a project
328 :param project_id: project to be changed
329 :param project_info: full project info
332 raise AuthconnNotImplementedException("Should have implemented this")