1 .. -*- coding: utf-8 -*- |
|
2 |
|
3 The security model |
|
4 ------------------ |
|
5 |
|
6 The security model of `cubicWeb` is based on `Access Control List`. |
|
7 The main principles are: |
|
8 |
|
9 * users and groups of users |
|
10 * a user belongs to at least one group of user |
|
11 * permissions (read, update, create, delete) |
|
12 * permissions are assigned to groups (and not to users) |
|
13 |
|
14 For *CubicWeb* in particular: |
|
15 |
|
16 * we associate rights at the enttities/relations schema level |
|
17 * for each entity, we distinguish four kind of permissions: read, |
|
18 add, update and delete |
|
19 * for each relation, we distinguish three king of permissions: read, |
|
20 add and delete (we can not modify a relation) |
|
21 * the basic groups are: Administrators, Users and Guests |
|
22 * by default, users belongs to the group Users |
|
23 * there is a virtual group called `Owners users` to which we |
|
24 can associate only deletion and update permissions |
|
25 * we can not add users to the `Owners users` group, they are |
|
26 implicetely added to it according to the context of the objects |
|
27 they own |
|
28 * the permissions of this group are only be checked on update/deletion |
|
29 actions if all the other groups the user belongs does not provide |
|
30 those permissions |
|
31 |
|
32 |
|
33 Permissions definition |
|
34 `````````````````````` |
|
35 |
|
36 Setting permissions is done with the attribute `permissions` of entities and |
|
37 relation types. It defines a dictionary where the keys are the access types |
|
38 (action), and the values are the authorized groups or expressions. |
|
39 |
|
40 For an entity type, the possible actions are `read`, `add`, `update` and |
|
41 `delete`. |
|
42 |
|
43 For a relation type, the possible actions are `read`, `add`, and `delete`. |
|
44 |
|
45 For each access type, a tuple indicates the name of the authorized groups and/or |
|
46 one or multiple RQL expressions to satisfy to grant access. The access is |
|
47 provided once the user is in the listed groups or one of the RQL condition is |
|
48 satisfied. |
|
49 |
|
50 The standard groups are : |
|
51 |
|
52 * `guests` |
|
53 |
|
54 * `users` |
|
55 |
|
56 * `managers` |
|
57 |
|
58 * `owners` : virtual group corresponding to the entity's owner. |
|
59 This can only be used for the actions `update` and `delete` of an entity |
|
60 type. |
|
61 |
|
62 It is also possible to use specific groups if they are defined in the precreate |
|
63 of the cube (``migration/precreate.py``). |
|
64 |
|
65 |
|
66 Use of RQL expression for writing rights |
|
67 ```````````````````````````````````````` |
|
68 |
|
69 It is possible to define RQL expression to provide update permission |
|
70 (`add`, `delete` and `update`) on relation and entity types. |
|
71 |
|
72 RQL expression for entity type permission : |
|
73 |
|
74 * you have to use the class `ERQLExpression` |
|
75 |
|
76 * the used expression corresponds to the WHERE statement of an RQL query |
|
77 |
|
78 * in this expression, the variables X and U are pre-defined references |
|
79 respectively on the current entity (on which the action is verified) and |
|
80 on the user who send the request |
|
81 |
|
82 * it is possible to use, in this expression, a special relation |
|
83 "has_<ACTION>_permission" where the subject is the user and the |
|
84 object is a any variable, meaning that the user needs to have |
|
85 permission to execute the action <ACTION> on the entities related |
|
86 to this variable |
|
87 |
|
88 For RQL expressions on a relation type, the principles are the same except |
|
89 for the following : |
|
90 |
|
91 * you have to use the class `RRQLExpression` in the case of a non-final relation |
|
92 |
|
93 * in the expression, the variables S, O and U are pre-defined references |
|
94 to respectively the subject and the object of the current relation (on |
|
95 which the action is being verified) and the user who executed the query |
|
96 |
|
97 * we can also define rights on attributes of an entity (non-final |
|
98 relation), knowing that : |
|
99 |
|
100 - to define RQL expression, we have to use the class |
|
101 `ERQLExpression` in which X represents the entity the attribute |
|
102 belongs to |
|
103 |
|
104 - the permissions `add` and `delete` are equivalent. Only `add`/`read` |
|
105 are actually taken in consideration. |
|
106 |
|
107 In addition to that the entity type `EPermission` from the standard library |
|
108 allows to build very complex and dynamic security architecture. The schema of |
|
109 this entity type is as follow : :: |
|
110 |
|
111 class CWPermission(EntityType): |
|
112 """entity type that may be used to construct some advanced security configuration |
|
113 """ |
|
114 permissions = META_ETYPE_PERMS |
|
115 |
|
116 name = String(required=True, indexed=True, internationalizable=True, maxsize=100, |
|
117 description=_('name or identifier of the permission')) |
|
118 label = String(required=True, internationalizable=True, maxsize=100, |
|
119 description=_('distinct label to distinguate between other permission entity of the same name')) |
|
120 require_group = SubjectRelation('CWGroup', |
|
121 description=_('groups to which the permission is granted')) |
|
122 |
|
123 # explicitly add X require_permission CWPermission for each entity that should have |
|
124 # configurable security |
|
125 class require_permission(RelationType): |
|
126 """link a permission to the entity. This permission should be used in the |
|
127 security definition of the entity's type to be useful. |
|
128 """ |
|
129 permissions = { |
|
130 'read': ('managers', 'users', 'guests'), |
|
131 'add': ('managers',), |
|
132 'delete': ('managers',), |
|
133 } |
|
134 |
|
135 class require_group(RelationType): |
|
136 """used to grant a permission to a group""" |
|
137 permissions = { |
|
138 'read': ('managers', 'users', 'guests'), |
|
139 'add': ('managers',), |
|
140 'delete': ('managers',), |
|
141 } |
|
142 |
|
143 |
|
144 Example of configuration :: |
|
145 |
|
146 |
|
147 ... |
|
148 |
|
149 class Version(EntityType): |
|
150 """a version is defining the content of a particular project's release""" |
|
151 |
|
152 permissions = {'read': ('managers', 'users', 'guests',), |
|
153 'update': ('managers', 'logilab', 'owners',), |
|
154 'delete': ('managers', ), |
|
155 'add': ('managers', 'logilab', |
|
156 ERQLExpression('X version_of PROJ, U in_group G,' |
|
157 'PROJ require_permission P, P name "add_version",' |
|
158 'P require_group G'),)} |
|
159 |
|
160 ... |
|
161 |
|
162 class version_of(RelationType): |
|
163 """link a version to its project. A version is necessarily linked to one and only one project. |
|
164 """ |
|
165 permissions = {'read': ('managers', 'users', 'guests',), |
|
166 'delete': ('managers', ), |
|
167 'add': ('managers', 'logilab', |
|
168 RRQLExpression('O require_permission P, P name "add_version",' |
|
169 'U in_group G, P require_group G'),) |
|
170 } |
|
171 inlined = True |
|
172 |
|
173 This configuration indicates that an entity `CWPermission` named |
|
174 "add_version" can be associated to a project and provides rights to create |
|
175 new versions on this project to specific groups. It is important to notice that : |
|
176 |
|
177 * in such case, we have to protect both the entity type "Version" and the relation |
|
178 associating a version to a project ("version_of") |
|
179 |
|
180 * because of the genericity of the entity type `CWPermission`, we have to execute |
|
181 a unification with the groups and/or the states if necessary in the expression |
|
182 ("U in_group G, P require_group G" in the above example) |
|
183 |
|
184 Use of RQL expression for reading rights |
|
185 ```````````````````````````````````````` |
|
186 |
|
187 The principles are the same but with the following restrictions : |
|
188 |
|
189 * we can not use `RRQLExpression` on relation types for reading |
|
190 |
|
191 * special relations "has_<ACTION>_permission" can not be used |
|
192 |
|
193 |
|
194 Note on the use of RQL expression for `add` permission |
|
195 `````````````````````````````````````````````````````` |
|
196 Potentially, the use of an RQL expression to add an entity or a relation |
|
197 can cause problems for the user interface, because if the expression uses |
|
198 the entity or the relation to create, then we are not able to verify the |
|
199 permissions before we actually add the entity (please note that this is |
|
200 not a problem for the RQL server at all, because the permissions checks are |
|
201 done after the creation). In such case, the permission check methods |
|
202 (check_perm, has_perm) can indicate that the user is not allowed to create |
|
203 this entity but can obtain the permission. |
|
204 |
|
205 To compensate this problem, it is usually necessary, for such case, |
|
206 to use an action that reflects the schema permissions but which enables |
|
207 to check properly the permissions so that it would show up if necessary. |
|
208 |
|