Project

General

Profile

CdmAuthorisationAndAccessControl » History » Version 39

Andreas Kohlbecker, 04/25/2013 08:44 AM

1 1 Andreas Kohlbecker
2 3 Andreas Kohlbecker
# Cdm authorisation and access control
3 2 Andreas Kohlbecker
4
5 25 Andreas Kohlbecker
6
----
7
8
_Another page on this topic is found in the BDI wiki: http://wiki.bgbm.org/bdinotes/index.php/EDIT_Security_
9
10
11
----
12
13
14
15 2 Andreas Kohlbecker
It is evident that the cdm library needs authorisation and access control. There are library methods which need to protected from unauthorised execution and there is also the data which is exposed by the library. Not all data should be visible to every user so a [[HibernateSpringAndRowlevelSecurity|row level access control]] is needed.
16
17
18
19 4 Andreas Kohlbecker
## Questions
20 2 Andreas Kohlbecker
21 4 Andreas Kohlbecker
22 7 Andreas Kohlbecker
1. Do we need a access control in the web service (cdmlib-remote) or is it sufficient to protect the service layer. As long web service controllers are not using DAO (cdmlib-persistence) methods directly it should not be necessary.
23 4 Andreas Kohlbecker
24
25
26 3 Andreas Kohlbecker
## Use cases
27 4 Andreas Kohlbecker
28
29 12 Andreas Kohlbecker
 A. a specific **classification sub tree** is **publicly visible** that is it is _published_
30 1 Andreas Kohlbecker
31 12 Andreas Kohlbecker
 B. a specific **classification sub tree** must not be **publicly visible** in the data portal and thus must be also hidden in the web service responses
32 1 Andreas Kohlbecker
33 12 Andreas Kohlbecker
 C. a specific **classification sub tree** is only visible for users which have a specific **role** but the user is not granted to **edit** anything in/below it
34 8 Andreas Kohlbecker
35 19 Andreas Kohlbecker
 D. A user is only granted to **edit Descriptions** 
36 1 Andreas Kohlbecker
37 19 Andreas Kohlbecker
 E. A user is only granted to **edit DescriptionElements** of a specific _Feature_ 
38 1 Andreas Kohlbecker
39 19 Andreas Kohlbecker
 F. A user is only granted to **edit structured Descriptions** 
40 1 Andreas Kohlbecker
41 19 Andreas Kohlbecker
 G. Combinations of B, C and D, E must be possible
42 1 Andreas Kohlbecker
43 19 Andreas Kohlbecker
 H. Only users with the **roles** *Admin* or **Usermanager** or the user in question it self (if currently authenticated) are allowed to execute **change password** 
44 1 Andreas Kohlbecker
45 19 Andreas Kohlbecker
 I. Only users with the **roles** *Admin* or **Usermanager** are allowed to create or **edit** new users
46 12 Andreas Kohlbecker
47 19 Andreas Kohlbecker
48 1 Andreas Kohlbecker
~~~
49
<code class="rst">
50
Tabular summary of above use cases translated into roles:
51
52 19 Andreas Kohlbecker
===========  =========================  ======================================  ===============  =============================
53
\                                                                               what to protect
54
-----------  -------------------------  --------------------------------------  ----------------------------------------------
55
Usecase      Role                       authority string                        Entity            ServiceMethod
56
===========  =========================  ======================================  ===============  =============================
57
A.           Anonymous                  TaxonNode.READ{uuid}                     ...
58
B.           TaxGroupX_User             TaxonNode.READ{uuid}                     ...
59
C.           TaxGroupX_Editor           TaxonNode.UPDATE{uuid}                   ...
60
D.           DescriptionEditor		Description.UPDATE			 ...					
61
E.           DescriptionEditor		DescriptioElement(Ecology).UPDATE        ...					
62
H.           Admin, Usermanager                                                                  UserService.changePassword()
63
===========  =========================  ======================================  ===============  =============================
64 1 Andreas Kohlbecker
65
*Anonymous* means not authenticated  
66
67
~~~
68 17 Andreas Kohlbecker
69
 **Special cases:** 
70
71 18 Andreas Kohlbecker
* **@TaxonNames@** can potentially be shared between different taxa, thus a situation may occur where a user has grants to edit taxon A but not for taxon B, but both taxa are sharing the same name. How will we handle this situation, should the name be cloned when the user starts editing taxon A, so that taxon A has another name entity than taxon B after the user saved the latest changes?
72 12 Andreas Kohlbecker
73
* The same problem as described above for TaxonNames also accounts for *@References@*, but in this case the problem is more severe since references are very often part of multiple taxon names. 
74 19 Andreas Kohlbecker
75
76
77
78
## Implementation details
79
80
81 20 Andreas Kohlbecker
_only a brief note for now, compiled by a lot of copy paste from the java doc:_
82 19 Andreas Kohlbecker
83
84 1 Andreas Kohlbecker
85 20 Andreas Kohlbecker
86
### Roles and CdmAuthorities
87
88
89
90
#### Roles
91
92
only one hard coded role: `ROLE_ADMIN` 
93
94
95
96
#### CdmAuthority
97
98
99 21 Andreas Kohlbecker
A `CdmAuthority` consists basically of two parts which are separated by a dot character '.'.
100 20 Andreas Kohlbecker
101
102 21 Andreas Kohlbecker
* permissionClass: an `CdmPermissionClass` instance with represents a cdm type or a part of the cdm type hierarchy. The className is always represented as an upper case string.
103 20 Andreas Kohlbecker
104 21 Andreas Kohlbecker
* property: The `CdmAuthority` only applies to instances which satisfy the specified property. Interpretation is up to type specific voters.
105 20 Andreas Kohlbecker
106 21 Andreas Kohlbecker
* operation: a string which specifies a `Operation` on that set of cdm types
107 20 Andreas Kohlbecker
108
* targetUuid: The operation may be restricted to a specific cdm entity by adding the entity uuid to the operation. The uuid string is enclosed in curly brackets '{' , '}' and appended to the end of the operation.
109
110
Examples for permissionStrings:
111
112
~~~
113
 TAXONBASE.CREATE
114 1 Andreas Kohlbecker
 TAXONBASE.READ
115 20 Andreas Kohlbecker
 TAXONBASE.UPDATE
116
 TAXONBASE.DELETE
117 1 Andreas Kohlbecker
 DESCRIPTIONBASE.UPDATE
118 21 Andreas Kohlbecker
 DESCRIPTIONELEMENTBASE(Ecology).UPDATE
119 1 Andreas Kohlbecker
 TAXONNODE.UPDATE{20c8f083-5870-4cbd-bf56-c5b2b98ab6a7}
120
~~~
121 21 Andreas Kohlbecker
122 24 Andreas Kohlbecker
in contrast to CdmAuthorities there are more general role like the following listed below, all these roles are having the  role prefix `'ROLE_'` which is defined in the String Security RoleVoter class:
123
124
125
~~~
126
 ROLE_ADMIN
127
 ROLE_USER_MANAGER
128
~~~
129
130 21 Andreas Kohlbecker
131
### Authorisation control
132
133
134
Different approaches of authorisation control need to be used in order to implement all kinds of CRUD permissions:
135
136
137
* service layer: method `@PreAuthorize` annotations with Spring EL, e.g. UserService:
138
139
~~~
140
@PreAuthorize("#username == authentication.name or hasRole('ROLE_ADMIN')")
141
public void changePasswordForUser(String username, String newPassword) {
142
...
143
~~~
144
* UPDATE and CREATE of cdm instances is protected by a Hibernate interceptor, the `CdmSecurityHibernateInterceptor@. This interceptor implements the  @onSave()` and `onFlushDirty` methods and thus can control creation and updating of cdm objects. Hibernate calls these methods for any entity which needs to be persisted even if a save or update operations causes a cascading save of objects connected to the object graph which is being saved. **TODO** implement DELETE (#3079)
145
146
* READ permissions can not be implemented using the `CdmSecurityHibernateInterceptor@. Reasons: @onLoad()` is called just before an object is initialized, so the object has no uuid or anything else with would be needed to decide on principals authorisation. A row based access control mechanism is required, see [[HibernateSpringAndRowlevelSecurity]]
147
148
149 4 Andreas Kohlbecker
150
151 22 Andreas Kohlbecker
### Authorisation evaluation
152
153
154 27 Andreas Kohlbecker
One of the central classes for the evaluation of Roles and CdmAuthorities is the `CdmPermissionEvluator` with implements the `org.springframework.security.access.PermissionEvaluator@. The method @public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission)` will always return true if the authentication has the role `ROLE_ADMIN` otherwise decission making is delegated to a `AccessDecisionManager` which should be `org.springframework.security.access.vote.UnanimousBased@. This @AccessDecisionManager` polls all configured AccessDecisionVoters grants access if only grant (or abstain) votes were received. The `AccessDecisionManager` then asks the set of plugged in **@AccessDecisionVoter@s*. The cdm specific voters are found in the package eu.etaxonomy.cdm.persistence.hibernate.permission.voter. For actual configuration details please see the *persistence_security.xml** , here is an example: 
155 22 Andreas Kohlbecker
156
~~~
157
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
158
        <property name="decisionVoters">
159
            <list>
160
                <bean class="eu.etaxonomy.cdm.persistence.hibernate.permission.voter.GrantAlwaysVoter" />
161
                <bean class="eu.etaxonomy.cdm.persistence.hibernate.permission.voter.TaxonNodeVoter" />
162
                <bean class="eu.etaxonomy.cdm.persistence.hibernate.permission.voter.TaxonBaseVoter" />
163
                <bean class="eu.etaxonomy.cdm.persistence.hibernate.permission.voter.DescriptionBaseVoter" />
164
                <bean class="eu.etaxonomy.cdm.persistence.hibernate.permission.voter.DescriptionElementVoter" />
165
            </list>
166
        </property>
167
</bean>
168
169
<!--
170
    CdmPermissionEvaluator.hasPermissions() evaluates the CdmPermissions like TAXONNODE.UPDATE{20c8f083-5870-4cbd-bf56-c5b2b98ab6a7}
171
-->
172
<bean id="cdmPermissionEvaluator" class="eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionEvaluator">
173
    <property name="accessDecisionManager" ref="accessDecisionManager" />
174
</bean>
175
~~~
176
177 26 Andreas Kohlbecker
178
#### AccessDecisionVoters
179
180
181 34 Andreas Kohlbecker
As briefly described above, the AccessDecisionVoters are crucial for finding a decision on whether a user is allowed to perform an operation on a specific cdm object or class of cdm objects. The operations are the so called CRUD operations. This acronym refers to Create, Read, Update, Delete. 
182 26 Andreas Kohlbecker
183 35 Andreas Kohlbecker
184
A user can have one or multiple granted authorities, for more information on granted authorities please refer to the paragraph [[CdmAuthorisationAndAccessControl#CdmAuthority|CdmAuthority]] above. All voters will cast votes on all granted authorities a user has.
185
186
187 1 Andreas Kohlbecker
In the following we will just use the term voter as a short form for AccessDecisionVoter. 
188 33 Andreas Kohlbecker
189 1 Andreas Kohlbecker
190 35 Andreas Kohlbecker
Voters can cast three different vote:
191 27 Andreas Kohlbecker
192
193
* Allow
194
195
* Deny 
196
197
* Abstain
198
199
200 38 Andreas Kohlbecker
In order to make a access decision the AccessDecisionVoters are asked sequentially to cast their vote. If at least one voter casts _Deny_ the the whole operation will be denied. This behaviour is guaranteed by the `GrantAlwaysVoter` which will always cast an _Allow_.
201 1 Andreas Kohlbecker
202 27 Andreas Kohlbecker
203 35 Andreas Kohlbecker
All AccessDecisionVoters are responsible for a specific class of data entities and thus it will only cast an _Allow_ or _Deny_ vote when an operation on an object of this class is to be performed. If a voter is not responsible it will _Abstain_. Generally each of the voters will check if the user has a granted authority which matches the the operation and object. Voters can also perform additional checks. If a voter "feels" not responsible it casts an _Abstain_. As a consequence of this concept everything is allowed unless a voter is responsible for a specific object class. Only in this case there is the potential that an operation will be denied.  
204 27 Andreas Kohlbecker
205
206
List of existing AccessDecisionVoters in the order of their execution:
207 30 Andreas Kohlbecker
208 28 Andreas Kohlbecker
  
209 1 Andreas Kohlbecker
1. TaxonNodeVoter: 
210
211 36 Andreas Kohlbecker
  * responsible for TaxonNode
212 1 Andreas Kohlbecker
213 37 Andreas Kohlbecker
  * allows if voter is responsible for the object class in question and
214 1 Andreas Kohlbecker
215 37 Andreas Kohlbecker
    1. if the user has a granted authority for that specific object or for all objects of this class which matches the operation to be performed
216 1 Andreas Kohlbecker
217 39 Andreas Kohlbecker
    1. or if the user has a matching granted authority for any of the parent taxon nodes in the classification (e.g.: @TAXONNODE.UPDATE{20c8f083-5870-4cbd-bf56-c5b2b98ab6a7@})
218 1 Andreas Kohlbecker
219 37 Andreas Kohlbecker
  * denies otherwise
220 1 Andreas Kohlbecker
221 37 Andreas Kohlbecker
1. TaxonBaseVoter:  
222 1 Andreas Kohlbecker
223 37 Andreas Kohlbecker
  * responsible for Taxon, Synonym
224 1 Andreas Kohlbecker
225 38 Andreas Kohlbecker
  * allows if voter is responsible for the object class in question and
226 1 Andreas Kohlbecker
227 39 Andreas Kohlbecker
    1. if the user has a granted authority for that specific object or for all objects of this class which matches the operation to be performed (e.g.: @TAXONBASE.UPDATE@)
228 1 Andreas Kohlbecker
229 38 Andreas Kohlbecker
  * denies otherwise
230 37 Andreas Kohlbecker
231 38 Andreas Kohlbecker
1. DescriptionBaseVoter:  
232 37 Andreas Kohlbecker
233 38 Andreas Kohlbecker
  * responsible for TaxonDescription, SpecimenDescription
234 1 Andreas Kohlbecker
235 37 Andreas Kohlbecker
  * allows if voter is responsible for the object class in question and
236 1 Andreas Kohlbecker
237 39 Andreas Kohlbecker
    1. if the user has a granted authority for that specific object or for all objects of this class which matches the operation to be performed (e.g.: @DESCRIPTIONBASE.UPDATE@)
238 37 Andreas Kohlbecker
239 38 Andreas Kohlbecker
  * denies otherwise
240 37 Andreas Kohlbecker
241 38 Andreas Kohlbecker
1. DescriptionElementVoter:  
242 37 Andreas Kohlbecker
243 38 Andreas Kohlbecker
  * responsible for all types of DescriptionElements
244 37 Andreas Kohlbecker
245
  * allows if voter is responsible for the object class in question and
246
247 38 Andreas Kohlbecker
    1. if the user has a granted authority for that specific object or for all objects of this class which matches the operation to be performed
248 37 Andreas Kohlbecker
249 39 Andreas Kohlbecker
    1. if the the operation to be preformed is specific to the Feature of the Description Element and if the _Property_ of one of the users granted authorities matches this Feature. (e.g.: @DESCRIPTIONELEMENTBASE(Ecology).UPDATE@)
250 37 Andreas Kohlbecker
251 38 Andreas Kohlbecker
  * denies otherwise
252 26 Andreas Kohlbecker
253
254
255 1 Andreas Kohlbecker