Fix Bug 774 - NBI+Keystone: Trying to obtain a token with user+password+project gives...
[osm/NBI.git] / osm_nbi / authconn.py
1 # -*- coding: utf-8 -*-
2
3 # Copyright 2018 Whitestack, LLC
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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
15 # under the License.
16 #
17 # For those usages not covered by the Apache License, Version 2.0 please
18 # contact: esousa@whitestack.com or glavado@whitestack.com
19 ##
20
21 """
22 Authconn implements an Abstract class for the Auth backend connector
23 plugins with the definition of the methods to be implemented.
24 """
25
26 __author__ = "Eduardo Sousa <esousa@whitestack.com>"
27 __date__ = "$27-jul-2018 23:59:59$"
28
29 from http import HTTPStatus
30
31
32 class AuthException(Exception):
33 """
34 Authentication error, because token, user password not recognized
35 """
36 def __init__(self, message, http_code=HTTPStatus.UNAUTHORIZED):
37 super(AuthException, self).__init__(message)
38 self.http_code = http_code
39
40
41 class AuthExceptionUnauthorized(AuthException):
42 """
43 Authentication error, because not having rights to make this operation
44 """
45 pass
46
47
48 class AuthconnException(Exception):
49 """
50 Common and base class Exception for all authconn exceptions.
51 """
52 def __init__(self, message, http_code=HTTPStatus.UNAUTHORIZED):
53 super(AuthconnException, self).__init__(message)
54 self.http_code = http_code
55
56
57 class AuthconnConnectionException(AuthconnException):
58 """
59 Connectivity error with Auth backend.
60 """
61 def __init__(self, message, http_code=HTTPStatus.BAD_GATEWAY):
62 super(AuthconnConnectionException, self).__init__(message, http_code)
63
64
65 class AuthconnNotSupportedException(AuthconnException):
66 """
67 The request is not supported by the Auth backend.
68 """
69 def __init__(self, message, http_code=HTTPStatus.NOT_IMPLEMENTED):
70 super(AuthconnNotSupportedException, self).__init__(message, http_code)
71
72
73 class AuthconnNotImplementedException(AuthconnException):
74 """
75 The method is not implemented by the Auth backend.
76 """
77 def __init__(self, message, http_code=HTTPStatus.NOT_IMPLEMENTED):
78 super(AuthconnNotImplementedException, self).__init__(message, http_code)
79
80
81 class AuthconnOperationException(AuthconnException):
82 """
83 The operation executed failed.
84 """
85 def __init__(self, message, http_code=HTTPStatus.INTERNAL_SERVER_ERROR):
86 super(AuthconnOperationException, self).__init__(message, http_code)
87
88
89 class AuthconnNotFoundException(AuthconnException):
90 """
91 The operation executed failed because element not found.
92 """
93 def __init__(self, message, http_code=HTTPStatus.NOT_FOUND):
94 super().__init__(message, http_code)
95
96
97 class AuthconnConflictException(AuthconnException):
98 """
99 The operation has conflicts.
100 """
101 def __init__(self, message, http_code=HTTPStatus.CONFLICT):
102 super().__init__(message, http_code)
103
104
105 class Authconn:
106 """
107 Abstract base class for all the Auth backend connector plugins.
108 Each Auth backend connector plugin must be a subclass of
109 Authconn class.
110 """
111 def __init__(self, config):
112 """
113 Constructor of the Authconn class.
114
115 Note: each subclass
116
117 :param config: configuration dictionary containing all the
118 necessary configuration parameters.
119 """
120 self.config = config
121
122 def authenticate(self, user, password, project=None, token=None):
123 """
124 Authenticate a user using username/password or token, plus project
125 :param user: user: name, id or None
126 :param password: password or None
127 :param project: name, id, or None. If None first found project will be used to get an scope token
128 :param token: previous token to obtain authorization
129 :return: the scoped token info or raises an exception. The token is a dictionary with:
130 _id: token string id,
131 username: username,
132 project_id: scoped_token project_id,
133 project_name: scoped_token project_name,
134 expires: epoch time when it expires,
135
136 """
137 raise AuthconnNotImplementedException("Should have implemented this")
138
139 # def authenticate_with_token(self, token, project=None):
140 # """
141 # Authenticate a user using a token. Can be used to revalidate the token
142 # or to get a scoped token.
143 #
144 # :param token: a valid token.
145 # :param project: (optional) project for a scoped token.
146 # :return: return a revalidated token, scoped if a project was passed or
147 # the previous token was already scoped.
148 # """
149 # raise AuthconnNotImplementedException("Should have implemented this")
150
151 def validate_token(self, token):
152 """
153 Check if the token is valid.
154
155 :param token: token to validate
156 :return: dictionary with information associated with the token. If the
157 token is not valid, returns None.
158 """
159 raise AuthconnNotImplementedException("Should have implemented this")
160
161 def revoke_token(self, token):
162 """
163 Invalidate a token.
164
165 :param token: token to be revoked
166 """
167 raise AuthconnNotImplementedException("Should have implemented this")
168
169 def get_user_project_list(self, token):
170 """
171 Get all the projects associated with a user.
172
173 :param token: valid token
174 :return: list of projects
175 """
176 raise AuthconnNotImplementedException("Should have implemented this")
177
178 def get_user_role_list(self, token):
179 """
180 Get role list for a scoped project.
181
182 :param token: scoped token.
183 :return: returns the list of roles for the user in that project. If
184 the token is unscoped it returns None.
185 """
186 raise AuthconnNotImplementedException("Should have implemented this")
187
188 def create_user(self, user, password):
189 """
190 Create a user.
191
192 :param user: username.
193 :param password: password.
194 :raises AuthconnOperationException: if user creation failed.
195 """
196 raise AuthconnNotImplementedException("Should have implemented this")
197
198 def update_user(self, user, new_name=None, new_password=None):
199 """
200 Change the user name and/or password.
201
202 :param user: username or user_id
203 :param new_name: new name
204 :param new_password: new password.
205 :raises AuthconnOperationException: if change failed.
206 """
207 raise AuthconnNotImplementedException("Should have implemented this")
208
209 def delete_user(self, user_id):
210 """
211 Delete user.
212
213 :param user_id: user identifier.
214 :raises AuthconnOperationException: if user deletion failed.
215 """
216 raise AuthconnNotImplementedException("Should have implemented this")
217
218 def get_user_list(self, filter_q=None):
219 """
220 Get user list.
221
222 :param filter_q: dictionary to filter user list by name (username is also admited) and/or _id
223 :return: returns a list of users.
224 """
225
226 def create_role(self, role):
227 """
228 Create a role.
229
230 :param role: role name.
231 :raises AuthconnOperationException: if role creation failed.
232 """
233 raise AuthconnNotImplementedException("Should have implemented this")
234
235 def delete_role(self, role_id):
236 """
237 Delete a role.
238
239 :param role_id: role identifier.
240 :raises AuthconnOperationException: if user deletion failed.
241 """
242 raise AuthconnNotImplementedException("Should have implemented this")
243
244 def get_role_list(self, filter_q=None):
245 """
246 Get all the roles.
247
248 :param filter_q: dictionary to filter role list by _id and/or name.
249 :return: list of roles
250 """
251 raise AuthconnNotImplementedException("Should have implemented this")
252
253 def update_role(self, role, new_name):
254 """
255 Change the name of a role
256 :param role: role name or id to be changed
257 :param new_name: new name
258 :return: None
259 """
260 raise AuthconnNotImplementedException("Should have implemented this")
261
262 def create_project(self, project):
263 """
264 Create a project.
265
266 :param project: project name.
267 :return: the internal id of the created project
268 :raises AuthconnOperationException: if project creation failed.
269 """
270 raise AuthconnNotImplementedException("Should have implemented this")
271
272 def delete_project(self, project_id):
273 """
274 Delete a project.
275
276 :param project_id: project identifier.
277 :raises AuthconnOperationException: if project deletion failed.
278 """
279 raise AuthconnNotImplementedException("Should have implemented this")
280
281 def get_project_list(self, filter_q=None):
282 """
283 Get all the projects.
284
285 :param filter_q: dictionary to filter project list, by "name" and/or "_id"
286 :return: list of projects
287 """
288 raise AuthconnNotImplementedException("Should have implemented this")
289
290 def update_project(self, project_id, new_name):
291 """
292 Change the name of a project
293 :param project_id: project to be changed
294 :param new_name: new name
295 :return: None
296 """
297 raise AuthconnNotImplementedException("Should have implemented this")
298
299 def assign_role_to_user(self, user, project, role):
300 """
301 Assigning a role to a user in a project.
302
303 :param user: username.
304 :param project: project name.
305 :param role: role name.
306 :raises AuthconnOperationException: if role assignment failed.
307 """
308 raise AuthconnNotImplementedException("Should have implemented this")
309
310 def remove_role_from_user(self, user, project, role):
311 """
312 Remove a role from a user in a project.
313
314 :param user: username.
315 :param project: project name.
316 :param role: role name.
317 :raises AuthconnOperationException: if role assignment revocation failed.
318 """
319 raise AuthconnNotImplementedException("Should have implemented this")