]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/controllers/role.py
import quincy beta 17.1.0
[ceph.git] / ceph / src / pybind / mgr / dashboard / controllers / role.py
1 # -*- coding: utf-8 -*-
2
3 import cherrypy
4
5 from .. import mgr
6 from ..exceptions import DashboardException, RoleAlreadyExists, \
7 RoleDoesNotExist, RoleIsAssociatedWithUser
8 from ..security import Permission
9 from ..security import Scope as SecurityScope
10 from ..services.access_control import SYSTEM_ROLES
11 from . import APIDoc, APIRouter, CreatePermission, EndpointDoc, RESTController, UIRouter
12
13 ROLE_SCHEMA = [{
14 "name": (str, "Role Name"),
15 "description": (str, "Role Descriptions"),
16 "scopes_permissions": ({
17 "cephfs": ([str], "")
18 }, ""),
19 "system": (bool, "")
20 }]
21
22
23 @APIRouter('/role', SecurityScope.USER)
24 @APIDoc("Role Management API", "Role")
25 class Role(RESTController):
26 @staticmethod
27 def _role_to_dict(role):
28 role_dict = role.to_dict()
29 role_dict['system'] = role_dict['name'] in SYSTEM_ROLES
30 return role_dict
31
32 @staticmethod
33 def _validate_permissions(scopes_permissions):
34 if scopes_permissions:
35 for scope, permissions in scopes_permissions.items():
36 if scope not in SecurityScope.all_scopes():
37 raise DashboardException(msg='Invalid scope',
38 code='invalid_scope',
39 component='role')
40 if any(permission not in Permission.all_permissions()
41 for permission in permissions):
42 raise DashboardException(msg='Invalid permission',
43 code='invalid_permission',
44 component='role')
45
46 @staticmethod
47 def _set_permissions(role, scopes_permissions):
48 role.reset_scope_permissions()
49 if scopes_permissions:
50 for scope, permissions in scopes_permissions.items():
51 if permissions:
52 role.set_scope_permissions(scope, permissions)
53
54 @EndpointDoc("Display Role list",
55 responses={200: ROLE_SCHEMA})
56 def list(self):
57 # type: () -> list
58 roles = dict(mgr.ACCESS_CTRL_DB.roles)
59 roles.update(SYSTEM_ROLES)
60 roles = sorted(roles.values(), key=lambda role: role.name)
61 return [Role._role_to_dict(r) for r in roles]
62
63 @staticmethod
64 def _get(name):
65 role = SYSTEM_ROLES.get(name)
66 if not role:
67 try:
68 role = mgr.ACCESS_CTRL_DB.get_role(name)
69 except RoleDoesNotExist:
70 raise cherrypy.HTTPError(404)
71 return Role._role_to_dict(role)
72
73 def get(self, name):
74 # type: (str) -> dict
75 return Role._get(name)
76
77 @staticmethod
78 def _create(name=None, description=None, scopes_permissions=None):
79 if not name:
80 raise DashboardException(msg='Name is required',
81 code='name_required',
82 component='role')
83 Role._validate_permissions(scopes_permissions)
84 try:
85 role = mgr.ACCESS_CTRL_DB.create_role(name, description)
86 except RoleAlreadyExists:
87 raise DashboardException(msg='Role already exists',
88 code='role_already_exists',
89 component='role')
90 Role._set_permissions(role, scopes_permissions)
91 mgr.ACCESS_CTRL_DB.save()
92 return Role._role_to_dict(role)
93
94 def create(self, name=None, description=None, scopes_permissions=None):
95 # type: (str, str, dict) -> dict
96 return Role._create(name, description, scopes_permissions)
97
98 def set(self, name, description=None, scopes_permissions=None):
99 # type: (str, str, dict) -> dict
100 try:
101 role = mgr.ACCESS_CTRL_DB.get_role(name)
102 except RoleDoesNotExist:
103 if name in SYSTEM_ROLES:
104 raise DashboardException(msg='Cannot update system role',
105 code='cannot_update_system_role',
106 component='role')
107 raise cherrypy.HTTPError(404)
108 Role._validate_permissions(scopes_permissions)
109 Role._set_permissions(role, scopes_permissions)
110 role.description = description
111 mgr.ACCESS_CTRL_DB.update_users_with_roles(role)
112 mgr.ACCESS_CTRL_DB.save()
113 return Role._role_to_dict(role)
114
115 def delete(self, name):
116 # type: (str) -> None
117 try:
118 mgr.ACCESS_CTRL_DB.delete_role(name)
119 except RoleDoesNotExist:
120 if name in SYSTEM_ROLES:
121 raise DashboardException(msg='Cannot delete system role',
122 code='cannot_delete_system_role',
123 component='role')
124 raise cherrypy.HTTPError(404)
125 except RoleIsAssociatedWithUser:
126 raise DashboardException(msg='Role is associated with user',
127 code='role_is_associated_with_user',
128 component='role')
129 mgr.ACCESS_CTRL_DB.save()
130
131 @RESTController.Resource('POST', status=201)
132 @CreatePermission
133 def clone(self, name, new_name):
134 # type: (str, str) -> dict
135 role = Role._get(name)
136 return Role._create(new_name, role.get('description'),
137 role.get('scopes_permissions'))
138
139
140 @UIRouter('/scope', SecurityScope.USER)
141 class Scope(RESTController):
142 def list(self):
143 return SecurityScope.all_scopes()