]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/services/access_control.py
import ceph 14.2.5
[ceph.git] / ceph / src / pybind / mgr / dashboard / services / access_control.py
CommitLineData
11fdf7f2
TL
1# -*- coding: utf-8 -*-
2# pylint: disable=too-many-arguments,too-many-return-statements
3# pylint: disable=too-many-branches, too-many-locals, too-many-statements
4from __future__ import absolute_import
5
6import errno
7import json
8import threading
9import time
10
11import bcrypt
12
13from mgr_module import CLIReadCommand, CLIWriteCommand
14
15from .. import mgr, logger
16from ..security import Scope, Permission
17from ..exceptions import RoleAlreadyExists, RoleDoesNotExist, ScopeNotValid, \
18 PermissionNotValid, RoleIsAssociatedWithUser, \
19 UserAlreadyExists, UserDoesNotExist, ScopeNotInRole, \
20 RoleNotInUser
21
22
23# password hashing algorithm
24def password_hash(password, salt_password=None):
25 if not password:
26 return None
27 if not salt_password:
28 salt_password = bcrypt.gensalt()
29 else:
30 salt_password = salt_password.encode('utf8')
31 return bcrypt.hashpw(password.encode('utf8'), salt_password).decode('utf8')
32
33
34_P = Permission # short alias
35
36
37class Role(object):
38 def __init__(self, name, description=None, scope_permissions=None):
39 self.name = name
40 self.description = description
41 if scope_permissions is None:
42 self.scopes_permissions = {}
43 else:
44 self.scopes_permissions = scope_permissions
45
46 def __hash__(self):
47 return hash(self.name)
48
49 def __eq__(self, other):
50 return self.name == other.name
51
52 def set_scope_permissions(self, scope, permissions):
53 if not Scope.valid_scope(scope):
54 raise ScopeNotValid(scope)
55 for perm in permissions:
56 if not Permission.valid_permission(perm):
57 raise PermissionNotValid(perm)
58
59 permissions.sort()
60 self.scopes_permissions[scope] = permissions
61
62 def del_scope_permissions(self, scope):
63 if scope not in self.scopes_permissions:
64 raise ScopeNotInRole(scope, self.name)
65 del self.scopes_permissions[scope]
66
67 def reset_scope_permissions(self):
68 self.scopes_permissions = {}
69
70 def authorize(self, scope, permissions):
71 if scope in self.scopes_permissions:
72 role_perms = self.scopes_permissions[scope]
73 for perm in permissions:
74 if perm not in role_perms:
75 return False
76 return True
77 return False
78
79 def to_dict(self):
80 return {
81 'name': self.name,
82 'description': self.description,
83 'scopes_permissions': self.scopes_permissions
84 }
85
86 @classmethod
87 def from_dict(cls, r_dict):
88 return Role(r_dict['name'], r_dict['description'],
89 r_dict['scopes_permissions'])
90
91
92# static pre-defined system roles
93# this roles cannot be deleted nor updated
94
95# admin role provides all permissions for all scopes
96ADMIN_ROLE = Role('administrator', 'Administrator', {
97 scope_name: Permission.all_permissions()
98 for scope_name in Scope.all_scopes()
99})
100
101
102# read-only role provides read-only permission for all scopes
103READ_ONLY_ROLE = Role('read-only', 'Read-Only', {
104 scope_name: [_P.READ] for scope_name in Scope.all_scopes()
105 if scope_name != Scope.DASHBOARD_SETTINGS
106})
107
108
109# block manager role provides all permission for block related scopes
110BLOCK_MGR_ROLE = Role('block-manager', 'Block Manager', {
111 Scope.RBD_IMAGE: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
112 Scope.POOL: [_P.READ],
113 Scope.ISCSI: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
114 Scope.RBD_MIRRORING: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
eafe8130 115 Scope.GRAFANA: [_P.READ],
11fdf7f2
TL
116})
117
118
119# RadosGW manager role provides all permissions for block related scopes
120RGW_MGR_ROLE = Role('rgw-manager', 'RGW Manager', {
121 Scope.RGW: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
122 Scope.CONFIG_OPT: [_P.READ],
eafe8130 123 Scope.GRAFANA: [_P.READ],
11fdf7f2
TL
124})
125
126
127# Cluster manager role provides all permission for OSDs, Monitors, and
128# Config options
129CLUSTER_MGR_ROLE = Role('cluster-manager', 'Cluster Manager', {
130 Scope.HOSTS: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
131 Scope.OSD: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
132 Scope.MONITOR: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
133 Scope.MANAGER: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
134 Scope.CONFIG_OPT: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
135 Scope.LOG: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
eafe8130 136 Scope.GRAFANA: [_P.READ],
11fdf7f2
TL
137})
138
139
140# Pool manager role provides all permissions for pool related scopes
141POOL_MGR_ROLE = Role('pool-manager', 'Pool Manager', {
142 Scope.POOL: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
143 Scope.CONFIG_OPT: [_P.READ],
eafe8130 144 Scope.GRAFANA: [_P.READ],
11fdf7f2
TL
145})
146
147# Pool manager role provides all permissions for CephFS related scopes
148CEPHFS_MGR_ROLE = Role('cephfs-manager', 'CephFS Manager', {
149 Scope.CEPHFS: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
150 Scope.CONFIG_OPT: [_P.READ],
eafe8130 151 Scope.GRAFANA: [_P.READ],
11fdf7f2
TL
152})
153
154GANESHA_MGR_ROLE = Role('ganesha-manager', 'NFS Ganesha Manager', {
155 Scope.NFS_GANESHA: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
156 Scope.CEPHFS: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
157 Scope.RGW: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
158 Scope.CONFIG_OPT: [_P.READ],
eafe8130 159 Scope.GRAFANA: [_P.READ],
11fdf7f2
TL
160})
161
162
163SYSTEM_ROLES = {
164 ADMIN_ROLE.name: ADMIN_ROLE,
165 READ_ONLY_ROLE.name: READ_ONLY_ROLE,
166 BLOCK_MGR_ROLE.name: BLOCK_MGR_ROLE,
167 RGW_MGR_ROLE.name: RGW_MGR_ROLE,
168 CLUSTER_MGR_ROLE.name: CLUSTER_MGR_ROLE,
169 POOL_MGR_ROLE.name: POOL_MGR_ROLE,
170 CEPHFS_MGR_ROLE.name: CEPHFS_MGR_ROLE,
171 GANESHA_MGR_ROLE.name: GANESHA_MGR_ROLE,
172}
173
174
175class User(object):
176 def __init__(self, username, password, name=None, email=None, roles=None,
177 lastUpdate=None):
178 self.username = username
179 self.password = password
180 self.name = name
181 self.email = email
182 if roles is None:
183 self.roles = set()
184 else:
185 self.roles = roles
186 if lastUpdate is None:
187 self.refreshLastUpdate()
188 else:
189 self.lastUpdate = lastUpdate
190
191 def refreshLastUpdate(self):
81eedcae 192 self.lastUpdate = int(time.time())
11fdf7f2
TL
193
194 def set_password(self, password):
195 self.password = password_hash(password)
196 self.refreshLastUpdate()
197
198 def set_roles(self, roles):
199 self.roles = set(roles)
200 self.refreshLastUpdate()
201
202 def add_roles(self, roles):
203 self.roles = self.roles.union(set(roles))
204 self.refreshLastUpdate()
205
206 def del_roles(self, roles):
207 for role in roles:
208 if role not in self.roles:
209 raise RoleNotInUser(role.name, self.username)
210 self.roles.difference_update(set(roles))
211 self.refreshLastUpdate()
212
213 def authorize(self, scope, permissions):
214 for role in self.roles:
215 if role.authorize(scope, permissions):
216 return True
217 return False
218
219 def permissions_dict(self):
220 perms = {}
221 for role in self.roles:
222 for scope, perms_list in role.scopes_permissions.items():
223 if scope in perms:
224 perms_tmp = set(perms[scope]).union(set(perms_list))
225 perms[scope] = list(perms_tmp)
226 else:
227 perms[scope] = perms_list
228
229 return perms
230
231 def to_dict(self):
232 return {
233 'username': self.username,
234 'password': self.password,
235 'roles': sorted([r.name for r in self.roles]),
236 'name': self.name,
237 'email': self.email,
238 'lastUpdate': self.lastUpdate
239 }
240
241 @classmethod
242 def from_dict(cls, u_dict, roles):
243 return User(u_dict['username'], u_dict['password'], u_dict['name'],
244 u_dict['email'], {roles[r] for r in u_dict['roles']},
245 u_dict['lastUpdate'])
246
247
248class AccessControlDB(object):
249 VERSION = 1
250 ACDB_CONFIG_KEY = "accessdb_v"
251
252 def __init__(self, version, users, roles):
253 self.users = users
254 self.version = version
255 self.roles = roles
256 self.lock = threading.RLock()
257
258 def create_role(self, name, description=None):
259 with self.lock:
260 if name in SYSTEM_ROLES or name in self.roles:
261 raise RoleAlreadyExists(name)
262 role = Role(name, description)
263 self.roles[name] = role
264 return role
265
266 def get_role(self, name):
267 with self.lock:
268 if name not in self.roles:
269 raise RoleDoesNotExist(name)
270 return self.roles[name]
271
272 def delete_role(self, name):
273 with self.lock:
274 if name not in self.roles:
275 raise RoleDoesNotExist(name)
276 role = self.roles[name]
277
278 # check if role is not associated with a user
279 for username, user in self.users.items():
280 if role in user.roles:
281 raise RoleIsAssociatedWithUser(name, username)
282
283 del self.roles[name]
284
285 def create_user(self, username, password, name, email):
286 logger.debug("AC: creating user: username=%s", username)
287 with self.lock:
288 if username in self.users:
289 raise UserAlreadyExists(username)
290 user = User(username, password_hash(password), name, email)
291 self.users[username] = user
292 return user
293
294 def get_user(self, username):
295 with self.lock:
296 if username not in self.users:
297 raise UserDoesNotExist(username)
298 return self.users[username]
299
300 def delete_user(self, username):
301 with self.lock:
302 if username not in self.users:
303 raise UserDoesNotExist(username)
304 del self.users[username]
305
306 def update_users_with_roles(self, role):
307 with self.lock:
308 if not role:
309 return
310 for _, user in self.users.items():
311 if role in user.roles:
312 user.refreshLastUpdate()
313
314 def save(self):
315 with self.lock:
316 db = {
317 'users': {un: u.to_dict() for un, u in self.users.items()},
318 'roles': {rn: r.to_dict() for rn, r in self.roles.items()},
319 'version': self.version
320 }
321 mgr.set_store(self.accessdb_config_key(), json.dumps(db))
322
323 @classmethod
324 def accessdb_config_key(cls, version=None):
325 if version is None:
326 version = cls.VERSION
327 return "{}{}".format(cls.ACDB_CONFIG_KEY, version)
328
329 def check_and_update_db(self):
330 logger.debug("AC: Checking for previews DB versions")
331 if self.VERSION == 1: # current version
332 # check if there is username/password from previous version
333 username = mgr.get_module_option('username', None)
334 password = mgr.get_module_option('password', None)
335 if username and password:
336 logger.debug("AC: Found single user credentials: user=%s",
337 username)
338 # found user credentials
339 user = self.create_user(username, "", None, None)
340 # password is already hashed, so setting manually
341 user.password = password
342 user.add_roles([ADMIN_ROLE])
343 self.save()
344 else:
345 raise NotImplementedError()
346
347 @classmethod
348 def load(cls):
349 logger.info("AC: Loading user roles DB version=%s", cls.VERSION)
350
351 json_db = mgr.get_store(cls.accessdb_config_key())
352 if json_db is None:
353 logger.debug("AC: No DB v%s found, creating new...", cls.VERSION)
354 db = cls(cls.VERSION, {}, {})
355 # check if we can update from a previous version database
356 db.check_and_update_db()
357 return db
358
359 db = json.loads(json_db)
360 roles = {rn: Role.from_dict(r)
361 for rn, r in db.get('roles', {}).items()}
362 users = {un: User.from_dict(u, dict(roles, **SYSTEM_ROLES))
363 for un, u in db.get('users', {}).items()}
364 return cls(db['version'], users, roles)
365
366
367def load_access_control_db():
368 mgr.ACCESS_CTRL_DB = AccessControlDB.load()
369
370
371# CLI dashboard access control scope commands
372
373@CLIWriteCommand('dashboard set-login-credentials',
374 'name=username,type=CephString '
375 'name=password,type=CephString',
376 'Set the login credentials')
377def set_login_credentials_cmd(_, username, password):
378 try:
379 user = mgr.ACCESS_CTRL_DB.get_user(username)
380 user.set_password(password)
381 except UserDoesNotExist:
382 user = mgr.ACCESS_CTRL_DB.create_user(username, password, None, None)
383 user.set_roles([ADMIN_ROLE])
384
385 mgr.ACCESS_CTRL_DB.save()
386
387 return 0, '''\
388******************************************************************
389*** WARNING: this command is deprecated. ***
390*** Please use the ac-user-* related commands to manage users. ***
391******************************************************************
392Username and password updated''', ''
393
394
395@CLIReadCommand('dashboard ac-role-show',
396 'name=rolename,type=CephString,req=false',
397 'Show role info')
398def ac_role_show_cmd(_, rolename=None):
399 if not rolename:
400 roles = dict(mgr.ACCESS_CTRL_DB.roles)
401 roles.update(SYSTEM_ROLES)
402 roles_list = [name for name, _ in roles.items()]
403 return 0, json.dumps(roles_list), ''
404 try:
405 role = mgr.ACCESS_CTRL_DB.get_role(rolename)
406 except RoleDoesNotExist as ex:
407 if rolename not in SYSTEM_ROLES:
408 return -errno.ENOENT, '', str(ex)
409 role = SYSTEM_ROLES[rolename]
410 return 0, json.dumps(role.to_dict()), ''
411
412
413@CLIWriteCommand('dashboard ac-role-create',
414 'name=rolename,type=CephString '
415 'name=description,type=CephString,req=false',
416 'Create a new access control role')
417def ac_role_create_cmd(_, rolename, description=None):
418 try:
419 role = mgr.ACCESS_CTRL_DB.create_role(rolename, description)
420 mgr.ACCESS_CTRL_DB.save()
421 return 0, json.dumps(role.to_dict()), ''
422 except RoleAlreadyExists as ex:
423 return -errno.EEXIST, '', str(ex)
424
425
426@CLIWriteCommand('dashboard ac-role-delete',
427 'name=rolename,type=CephString',
428 'Delete an access control role')
429def ac_role_delete_cmd(_, rolename):
430 try:
431 mgr.ACCESS_CTRL_DB.delete_role(rolename)
432 mgr.ACCESS_CTRL_DB.save()
433 return 0, "Role '{}' deleted".format(rolename), ""
434 except RoleDoesNotExist as ex:
435 if rolename in SYSTEM_ROLES:
436 return -errno.EPERM, '', "Cannot delete system role '{}'" \
437 .format(rolename)
438 return -errno.ENOENT, '', str(ex)
439 except RoleIsAssociatedWithUser as ex:
440 return -errno.EPERM, '', str(ex)
441
442
443@CLIWriteCommand('dashboard ac-role-add-scope-perms',
444 'name=rolename,type=CephString '
445 'name=scopename,type=CephString '
446 'name=permissions,type=CephString,n=N',
447 'Add the scope permissions for a role')
448def ac_role_add_scope_perms_cmd(_, rolename, scopename, permissions):
449 try:
450 role = mgr.ACCESS_CTRL_DB.get_role(rolename)
451 perms_array = [perm.strip() for perm in permissions]
452 role.set_scope_permissions(scopename, perms_array)
453 mgr.ACCESS_CTRL_DB.update_users_with_roles(role)
454 mgr.ACCESS_CTRL_DB.save()
455 return 0, json.dumps(role.to_dict()), ''
456 except RoleDoesNotExist as ex:
457 if rolename in SYSTEM_ROLES:
458 return -errno.EPERM, '', "Cannot update system role '{}'" \
459 .format(rolename)
460 return -errno.ENOENT, '', str(ex)
461 except ScopeNotValid as ex:
462 return -errno.EINVAL, '', str(ex) + "\n Possible values: {}" \
463 .format(Scope.all_scopes())
464 except PermissionNotValid as ex:
465 return -errno.EINVAL, '', str(ex) + \
466 "\n Possible values: {}" \
467 .format(Permission.all_permissions())
468
469
470@CLIWriteCommand('dashboard ac-role-del-scope-perms',
471 'name=rolename,type=CephString '
472 'name=scopename,type=CephString',
473 'Delete the scope permissions for a role')
474def ac_role_del_scope_perms_cmd(_, rolename, scopename):
475 try:
476 role = mgr.ACCESS_CTRL_DB.get_role(rolename)
477 role.del_scope_permissions(scopename)
478 mgr.ACCESS_CTRL_DB.update_users_with_roles(role)
479 mgr.ACCESS_CTRL_DB.save()
480 return 0, json.dumps(role.to_dict()), ''
481 except RoleDoesNotExist as ex:
482 if rolename in SYSTEM_ROLES:
483 return -errno.EPERM, '', "Cannot update system role '{}'" \
484 .format(rolename)
485 return -errno.ENOENT, '', str(ex)
486 except ScopeNotInRole as ex:
487 return -errno.ENOENT, '', str(ex)
488
489
490@CLIReadCommand('dashboard ac-user-show',
491 'name=username,type=CephString,req=false',
492 'Show user info')
493def ac_user_show_cmd(_, username=None):
494 if not username:
495 users = mgr.ACCESS_CTRL_DB.users
496 users_list = [name for name, _ in users.items()]
497 return 0, json.dumps(users_list), ''
498 try:
499 user = mgr.ACCESS_CTRL_DB.get_user(username)
500 return 0, json.dumps(user.to_dict()), ''
501 except UserDoesNotExist as ex:
502 return -errno.ENOENT, '', str(ex)
503
504
505@CLIWriteCommand('dashboard ac-user-create',
506 'name=username,type=CephString '
507 'name=password,type=CephString,req=false '
508 'name=rolename,type=CephString,req=false '
509 'name=name,type=CephString,req=false '
510 'name=email,type=CephString,req=false',
511 'Create a user')
512def ac_user_create_cmd(_, username, password=None, rolename=None, name=None,
513 email=None):
514 try:
515 role = mgr.ACCESS_CTRL_DB.get_role(rolename) if rolename else None
516 except RoleDoesNotExist as ex:
517 if rolename not in SYSTEM_ROLES:
518 return -errno.ENOENT, '', str(ex)
519 role = SYSTEM_ROLES[rolename]
520
521 try:
522 user = mgr.ACCESS_CTRL_DB.create_user(username, password, name, email)
523 except UserAlreadyExists as ex:
524 return -errno.EEXIST, '', str(ex)
525
526 if role:
527 user.set_roles([role])
528 mgr.ACCESS_CTRL_DB.save()
529 return 0, json.dumps(user.to_dict()), ''
530
531
532@CLIWriteCommand('dashboard ac-user-delete',
533 'name=username,type=CephString',
534 'Delete user')
535def ac_user_delete_cmd(_, username):
536 try:
537 mgr.ACCESS_CTRL_DB.delete_user(username)
538 mgr.ACCESS_CTRL_DB.save()
539 return 0, "User '{}' deleted".format(username), ""
540 except UserDoesNotExist as ex:
541 return -errno.ENOENT, '', str(ex)
542
543
544@CLIWriteCommand('dashboard ac-user-set-roles',
545 'name=username,type=CephString '
546 'name=roles,type=CephString,n=N',
547 'Set user roles')
548def ac_user_set_roles_cmd(_, username, roles):
549 rolesname = roles
550 roles = []
551 for rolename in rolesname:
552 try:
553 roles.append(mgr.ACCESS_CTRL_DB.get_role(rolename))
554 except RoleDoesNotExist as ex:
555 if rolename not in SYSTEM_ROLES:
556 return -errno.ENOENT, '', str(ex)
557 roles.append(SYSTEM_ROLES[rolename])
558 try:
559 user = mgr.ACCESS_CTRL_DB.get_user(username)
560 user.set_roles(roles)
561 mgr.ACCESS_CTRL_DB.save()
562 return 0, json.dumps(user.to_dict()), ''
563 except UserDoesNotExist as ex:
564 return -errno.ENOENT, '', str(ex)
565
566
567@CLIWriteCommand('dashboard ac-user-add-roles',
568 'name=username,type=CephString '
569 'name=roles,type=CephString,n=N',
570 'Add roles to user')
571def ac_user_add_roles_cmd(_, username, roles):
572 rolesname = roles
573 roles = []
574 for rolename in rolesname:
575 try:
576 roles.append(mgr.ACCESS_CTRL_DB.get_role(rolename))
577 except RoleDoesNotExist as ex:
578 if rolename not in SYSTEM_ROLES:
579 return -errno.ENOENT, '', str(ex)
580 roles.append(SYSTEM_ROLES[rolename])
581 try:
582 user = mgr.ACCESS_CTRL_DB.get_user(username)
583 user.add_roles(roles)
584 mgr.ACCESS_CTRL_DB.save()
585 return 0, json.dumps(user.to_dict()), ''
586 except UserDoesNotExist as ex:
587 return -errno.ENOENT, '', str(ex)
588
589
590@CLIWriteCommand('dashboard ac-user-del-roles',
591 'name=username,type=CephString '
592 'name=roles,type=CephString,n=N',
593 'Delete roles from user')
594def ac_user_del_roles_cmd(_, username, roles):
595 rolesname = roles
596 roles = []
597 for rolename in rolesname:
598 try:
599 roles.append(mgr.ACCESS_CTRL_DB.get_role(rolename))
600 except RoleDoesNotExist as ex:
601 if rolename not in SYSTEM_ROLES:
602 return -errno.ENOENT, '', str(ex)
603 roles.append(SYSTEM_ROLES[rolename])
604 try:
605 user = mgr.ACCESS_CTRL_DB.get_user(username)
606 user.del_roles(roles)
607 mgr.ACCESS_CTRL_DB.save()
608 return 0, json.dumps(user.to_dict()), ''
609 except UserDoesNotExist as ex:
610 return -errno.ENOENT, '', str(ex)
611 except RoleNotInUser as ex:
612 return -errno.ENOENT, '', str(ex)
613
614
615@CLIWriteCommand('dashboard ac-user-set-password',
616 'name=username,type=CephString '
617 'name=password,type=CephString',
618 'Set user password')
619def ac_user_set_password(_, username, password):
620 try:
621 user = mgr.ACCESS_CTRL_DB.get_user(username)
622 user.set_password(password)
623
624 mgr.ACCESS_CTRL_DB.save()
625 return 0, json.dumps(user.to_dict()), ''
626 except UserDoesNotExist as ex:
627 return -errno.ENOENT, '', str(ex)
628
629
630@CLIWriteCommand('dashboard ac-user-set-info',
631 'name=username,type=CephString '
632 'name=name,type=CephString '
633 'name=email,type=CephString',
634 'Set user info')
635def ac_user_set_info(_, username, name, email):
636 try:
637 user = mgr.ACCESS_CTRL_DB.get_user(username)
638 if name:
639 user.name = name
640 if email:
641 user.email = email
642 mgr.ACCESS_CTRL_DB.save()
643 return 0, json.dumps(user.to_dict()), ''
644 except UserDoesNotExist as ex:
645 return -errno.ENOENT, '', str(ex)
646
647
648class LocalAuthenticator(object):
649 def __init__(self):
650 load_access_control_db()
651
652 def get_user(self, username):
653 return mgr.ACCESS_CTRL_DB.get_user(username)
654
655 def authenticate(self, username, password):
656 try:
657 user = mgr.ACCESS_CTRL_DB.get_user(username)
658 if user.password:
659 pass_hash = password_hash(password, user.password)
660 if pass_hash == user.password:
661 return user.permissions_dict()
662 except UserDoesNotExist:
663 logger.debug("User '%s' does not exist", username)
664 return None
665
666 def authorize(self, username, scope, permissions):
667 user = mgr.ACCESS_CTRL_DB.get_user(username)
668 return user.authorize(scope, permissions)