1 | # Licensed to the StackStorm, Inc ('StackStorm') under one or more |
||
2 | # contributor license agreements. See the NOTICE file distributed with |
||
3 | # this work for additional information regarding copyright ownership. |
||
4 | # The ASF licenses this file to You under the Apache License, Version 2.0 |
||
5 | # (the "License"); you may not use this file except in compliance with |
||
6 | # the License. You may obtain a copy of the License at |
||
7 | # |
||
8 | # http://www.apache.org/licenses/LICENSE-2.0 |
||
9 | # |
||
10 | # Unless required by applicable law or agreed to in writing, software |
||
11 | # distributed under the License is distributed on an "AS IS" BASIS, |
||
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
13 | # See the License for the specific language governing permissions and |
||
14 | # limitations under the License. |
||
15 | |||
16 | """ |
||
17 | Module containing resolver classes which contain permission resolving logic for different resource |
||
18 | types. |
||
19 | """ |
||
20 | |||
21 | from __future__ import absolute_import |
||
22 | import sys |
||
23 | import logging as stdlib_logging |
||
24 | |||
25 | from st2common import log as logging |
||
26 | from st2common.models.db.pack import PackDB |
||
27 | from st2common.models.db.webhook import WebhookDB |
||
28 | from st2common.models.system.common import ResourceReference |
||
29 | from st2common.constants.triggers import WEBHOOK_TRIGGER_TYPE |
||
30 | from st2common.persistence.execution import ActionExecution |
||
31 | from st2common.rbac.types import PermissionType |
||
32 | from st2common.rbac.types import ResourceType |
||
33 | from st2common.rbac.types import SystemRole |
||
34 | from st2common.rbac.types import GLOBAL_PACK_PERMISSION_TYPES |
||
35 | from st2common.services.rbac import get_roles_for_user |
||
36 | from st2common.services.rbac import get_all_permission_grants_for_user |
||
37 | |||
38 | LOG = logging.getLogger(__name__) |
||
39 | |||
40 | __all__ = [ |
||
41 | 'RunnerPermissionsResolver', |
||
42 | 'PackPermissionsResolver', |
||
43 | 'SensorPermissionsResolver', |
||
44 | 'ActionPermissionsResolver', |
||
45 | 'ActionAliasPermissionsResolver', |
||
46 | 'RulePermissionsResolver', |
||
47 | 'RuleEnforcementPermissionsResolver', |
||
48 | 'KeyValuePermissionsResolver', |
||
49 | 'ExecutionPermissionsResolver', |
||
50 | 'WebhookPermissionsResolver', |
||
51 | 'TracePermissionsResolver', |
||
52 | 'TriggerPermissionsResolver', |
||
53 | 'StreamPermissionsResolver', |
||
54 | 'InquiryPermissionsResolver', |
||
55 | |||
56 | 'get_resolver_for_resource_type', |
||
57 | 'get_resolver_for_permission_type' |
||
58 | ] |
||
59 | |||
60 | # "Read" permission names which are granted to observer role by default |
||
61 | READ_PERMISSION_NAMES = [ |
||
62 | 'view', |
||
63 | 'list', |
||
64 | 'search' |
||
65 | ] |
||
66 | |||
67 | |||
68 | class PermissionsResolver(object): |
||
69 | """ |
||
70 | Base Permissions Resolver class. |
||
71 | |||
72 | Permission resolver classes implement permission resolving / checking logic for a particular |
||
73 | resource type. |
||
74 | """ |
||
75 | |||
76 | resource_type = None # Constant for the resource type this resolver refers to |
||
77 | |||
78 | def user_has_permission(self, user_db, permission_type): |
||
79 | """ |
||
80 | Method for checking user permissions which are not tied to a particular resource. |
||
81 | """ |
||
82 | raise NotImplementedError() |
||
83 | |||
84 | def user_has_resource_api_permission(self, user_db, resource_api, permission_type): |
||
85 | """ |
||
86 | Method for checking user permissions on a resource which is to be created (e.g. |
||
87 | create operation). |
||
88 | """ |
||
89 | raise NotImplementedError() |
||
90 | |||
91 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
92 | """ |
||
93 | Method for checking user permissions on an existing resource (e.g. get one, edit, delete |
||
94 | operations). |
||
95 | """ |
||
96 | raise NotImplementedError() |
||
97 | |||
98 | def _user_has_list_permission(self, user_db, permission_type): |
||
99 | """ |
||
100 | Common method for checking if a user has specific "list" resource permission (e.g. |
||
101 | rules_list, action_list, etc.). |
||
102 | """ |
||
103 | assert PermissionType.get_permission_name(permission_type) == 'list' |
||
104 | return self._user_has_global_permission(user_db=user_db, permission_type=permission_type) |
||
105 | |||
106 | def _user_has_global_permission(self, user_db, permission_type): |
||
107 | """ |
||
108 | Custom method for checking if user has a particular global permission which doesn't apply |
||
109 | to a specific resource but it's system-wide aka global permission. |
||
110 | """ |
||
111 | log_context = { |
||
112 | 'user_db': user_db, |
||
113 | 'permission_type': permission_type, |
||
114 | 'resolver': self.__class__.__name__ |
||
115 | } |
||
116 | self._log('Checking user permissions', extra=log_context) |
||
117 | |||
118 | # First check the system role permissions |
||
119 | has_system_role_permission = self._user_has_system_role_permission( |
||
120 | user_db=user_db, permission_type=permission_type) |
||
121 | |||
122 | if has_system_role_permission: |
||
123 | self._log('Found a matching grant via system role', extra=log_context) |
||
124 | return True |
||
125 | |||
126 | # Check custom roles |
||
127 | permission_types = [permission_type] |
||
128 | |||
129 | # Check direct grants |
||
130 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
131 | permission_types=permission_types) |
||
132 | if len(permission_grants) >= 1: |
||
133 | self._log('Found a direct grant', extra=log_context) |
||
134 | return True |
||
135 | |||
136 | self._log('No matching grants found', extra=log_context) |
||
137 | return False |
||
138 | |||
139 | def _user_has_system_role_permission(self, user_db, permission_type): |
||
140 | """ |
||
141 | Check the user system roles and return True if user has the required permission. |
||
142 | |||
143 | :rtype: ``bool`` |
||
144 | """ |
||
145 | permission_name = PermissionType.get_permission_name(permission_type) |
||
146 | |||
147 | user_role_dbs = get_roles_for_user(user_db=user_db) |
||
148 | user_role_names = [role_db.name for role_db in user_role_dbs] |
||
149 | |||
150 | if SystemRole.SYSTEM_ADMIN in user_role_names: |
||
151 | # System admin has all the permissions |
||
152 | return True |
||
153 | elif SystemRole.ADMIN in user_role_names: |
||
154 | # Admin has all the permissions |
||
155 | return True |
||
156 | elif SystemRole.OBSERVER in user_role_names and permission_name in READ_PERMISSION_NAMES: |
||
157 | # Observer role has "view" permission on all the resources |
||
158 | return True |
||
159 | |||
160 | return False |
||
161 | |||
162 | def _matches_permission_grant(self, resource_db, permission_grant, permission_type, |
||
163 | all_permission_type): |
||
164 | """ |
||
165 | :rtype: ``bool`` |
||
166 | """ |
||
167 | if permission_type in permission_grant.permission_types: |
||
168 | # Direct permission grant |
||
169 | return True |
||
170 | elif all_permission_type in permission_grant.permission_types: |
||
171 | # "ALL" permission grant |
||
172 | return True |
||
173 | |||
174 | return False |
||
175 | |||
176 | def _get_all_permission_type_for_resource(self, resource_db): |
||
177 | """ |
||
178 | Retrieve "ALL" permission type for the provided resource. |
||
179 | """ |
||
180 | resource_type = resource_db.get_resource_type() |
||
181 | permission_type = PermissionType.get_permission_type(resource_type=resource_type, |
||
182 | permission_name='all') |
||
183 | return permission_type |
||
184 | |||
185 | def _log(self, message, extra, level=stdlib_logging.DEBUG, **kwargs): |
||
186 | """ |
||
187 | Custom logger method which prefix message with the class and caller method name. |
||
188 | """ |
||
189 | class_name = self.__class__.__name__ |
||
190 | method_name = sys._getframe().f_back.f_code.co_name |
||
0 ignored issues
–
show
|
|||
191 | message_prefix = '%s.%s: ' % (class_name, method_name) |
||
192 | message = message_prefix + message |
||
193 | |||
194 | LOG.log(level, message, extra=extra, **kwargs) |
||
195 | |||
196 | |||
197 | class ContentPackResourcePermissionsResolver(PermissionsResolver): |
||
198 | """ |
||
199 | Base permissions resolver class which contains common functionality for resources which belong |
||
200 | to a pack (sensors, actions, action aliases, rules, ...). |
||
201 | """ |
||
202 | |||
203 | resource_type = None |
||
204 | |||
205 | # A list of resource-specific permission types which grant / imply "view" permission type |
||
206 | view_grant_permission_types = [] |
||
207 | |||
208 | def _user_has_resource_permission(self, user_db, pack_uid, resource_uid, permission_type): |
||
209 | log_context = { |
||
210 | 'user_db': user_db, |
||
211 | 'pack_uid': pack_uid, |
||
212 | 'resource_uid': resource_uid, |
||
213 | 'resource_type': self.resource_type, |
||
214 | 'permission_type': permission_type, |
||
215 | 'resolver': self.__class__.__name__ |
||
216 | } |
||
217 | self._log('Checking user resource permissions', extra=log_context) |
||
218 | |||
219 | # First check the system role permissions |
||
220 | self._log('Checking grants via system role permissions', extra=log_context) |
||
221 | has_system_role_permission = self._user_has_system_role_permission( |
||
222 | user_db=user_db, permission_type=permission_type) |
||
223 | |||
224 | if has_system_role_permission: |
||
225 | self._log('Found a matching grant via system role', extra=log_context) |
||
226 | return True |
||
227 | |||
228 | # Check custom roles |
||
229 | view_permission_type = PermissionType.get_permission_type(resource_type=self.resource_type, |
||
230 | permission_name='view') |
||
231 | all_permission_type = PermissionType.get_permission_type(resource_type=self.resource_type, |
||
232 | permission_name='all') |
||
233 | |||
234 | if permission_type == view_permission_type: |
||
235 | # Note: Some permissions such as "create", "modify", "delete" and "execute" also |
||
236 | # grant / imply "view" permission |
||
237 | permission_types = self.view_grant_permission_types[:] + [permission_type] |
||
238 | elif permission_type not in all_permission_type: |
||
239 | permission_types = [all_permission_type, permission_type] |
||
240 | else: |
||
241 | permission_types = [permission_type] |
||
242 | |||
243 | # Check direct grants on the specified resource |
||
244 | self._log('Checking direct grants on the specified resource', extra=log_context) |
||
245 | resource_types = [self.resource_type] |
||
246 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
247 | resource_uid=resource_uid, |
||
248 | resource_types=resource_types, |
||
249 | permission_types=permission_types) |
||
250 | if len(permission_grants) >= 1: |
||
251 | self._log('Found a direct grant on the action', extra=log_context) |
||
252 | return True |
||
253 | |||
254 | # Check grants on the parent pack |
||
255 | self._log('Checking grants on the parent resource', extra=log_context) |
||
256 | resource_types = [ResourceType.PACK] |
||
257 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
258 | resource_uid=pack_uid, |
||
259 | resource_types=resource_types, |
||
260 | permission_types=permission_types) |
||
261 | |||
262 | if len(permission_grants) >= 1: |
||
263 | self._log('Found a grant on the action parent pack', extra=log_context) |
||
264 | return True |
||
265 | |||
266 | self._log('No matching grants found', extra=log_context) |
||
267 | return False |
||
268 | |||
269 | |||
270 | class RunnerPermissionsResolver(PermissionsResolver): |
||
271 | """ |
||
272 | Permission resolver for "runner_type" resource type. |
||
273 | """ |
||
274 | resource_type = ResourceType.RUNNER |
||
275 | |||
276 | def user_has_permission(self, user_db, permission_type): |
||
277 | assert permission_type in [PermissionType.RUNNER_LIST] |
||
278 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
279 | |||
280 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
281 | log_context = { |
||
282 | 'user_db': user_db, |
||
283 | 'resource_db': resource_db, |
||
284 | 'permission_type': permission_type, |
||
285 | 'resolver': self.__class__.__name__ |
||
286 | } |
||
287 | self._log('Checking user resource permissions', extra=log_context) |
||
288 | |||
289 | # First check the system role permissions |
||
290 | has_system_role_permission = self._user_has_system_role_permission( |
||
291 | user_db=user_db, permission_type=permission_type) |
||
292 | |||
293 | if has_system_role_permission: |
||
294 | self._log('Found a matching grant via system role', extra=log_context) |
||
295 | return True |
||
296 | |||
297 | # Check custom roles |
||
298 | resource_uid = resource_db.get_uid() |
||
299 | resource_types = [ResourceType.RUNNER] |
||
300 | permission_types = [permission_type] |
||
301 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
302 | resource_uid=resource_uid, |
||
303 | resource_types=resource_types, |
||
304 | permission_types=permission_types) |
||
305 | |||
306 | if len(permission_grants) >= 1: |
||
307 | self._log('Found a direct grant on the runner type', extra=log_context) |
||
308 | return True |
||
309 | |||
310 | self._log('No matching grants found', extra=log_context) |
||
311 | return False |
||
312 | |||
313 | |||
314 | class PackPermissionsResolver(PermissionsResolver): |
||
315 | """ |
||
316 | Permission resolver for "pack" resource type. |
||
317 | """ |
||
318 | |||
319 | resource_type = ResourceType.PACK |
||
320 | |||
321 | def user_has_permission(self, user_db, permission_type): |
||
322 | assert permission_type in GLOBAL_PACK_PERMISSION_TYPES |
||
323 | |||
324 | if permission_type == PermissionType.PACK_LIST: |
||
325 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
326 | else: |
||
327 | return self._user_has_global_permission(user_db=user_db, |
||
328 | permission_type=permission_type) |
||
329 | |||
330 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
331 | log_context = { |
||
332 | 'user_db': user_db, |
||
333 | 'resource_db': resource_db, |
||
334 | 'permission_type': permission_type, |
||
335 | 'resolver': self.__class__.__name__ |
||
336 | } |
||
337 | self._log('Checking user resource permissions', extra=log_context) |
||
338 | |||
339 | # First check the system role permissions |
||
340 | has_system_role_permission = self._user_has_system_role_permission( |
||
341 | user_db=user_db, permission_type=permission_type) |
||
342 | |||
343 | if has_system_role_permission: |
||
344 | self._log('Found a matching grant via system role', extra=log_context) |
||
345 | return True |
||
346 | |||
347 | # Check custom roles |
||
348 | resource_uid = resource_db.get_uid() |
||
349 | resource_types = [ResourceType.PACK] |
||
350 | permission_types = [permission_type] |
||
351 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
352 | resource_uid=resource_uid, |
||
353 | resource_types=resource_types, |
||
354 | permission_types=permission_types) |
||
355 | |||
356 | if len(permission_grants) >= 1: |
||
357 | self._log('Found a direct grant on the pack', extra=log_context) |
||
358 | return True |
||
359 | |||
360 | self._log('No matching grants found', extra=log_context) |
||
361 | return False |
||
362 | |||
363 | |||
364 | class SensorPermissionsResolver(ContentPackResourcePermissionsResolver): |
||
365 | """ |
||
366 | Permission resolver for "sensor" resource type. |
||
367 | """ |
||
368 | |||
369 | resource_type = ResourceType.SENSOR |
||
370 | view_grant_permission_types = [ |
||
371 | PermissionType.SENSOR_ALL, |
||
372 | PermissionType.SENSOR_MODIFY |
||
373 | ] |
||
374 | |||
375 | def user_has_permission(self, user_db, permission_type): |
||
376 | assert permission_type in [PermissionType.SENSOR_LIST] |
||
377 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
378 | |||
379 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
380 | sensor_uid = resource_db.get_uid() |
||
381 | pack_uid = resource_db.get_pack_uid() |
||
382 | return self._user_has_resource_permission(user_db=user_db, pack_uid=pack_uid, |
||
383 | resource_uid=sensor_uid, |
||
384 | permission_type=permission_type) |
||
385 | |||
386 | |||
387 | class ActionPermissionsResolver(ContentPackResourcePermissionsResolver): |
||
388 | """ |
||
389 | Permission resolver for "action" resource type. |
||
390 | """ |
||
391 | |||
392 | resource_type = ResourceType.ACTION |
||
393 | view_grant_permission_types = [ |
||
394 | PermissionType.ACTION_ALL, |
||
395 | PermissionType.ACTION_CREATE, |
||
396 | PermissionType.ACTION_MODIFY, |
||
397 | PermissionType.ACTION_DELETE, |
||
398 | PermissionType.ACTION_EXECUTE, |
||
399 | ] |
||
400 | |||
401 | def user_has_permission(self, user_db, permission_type): |
||
402 | assert permission_type in [PermissionType.ACTION_LIST] |
||
403 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
404 | |||
405 | def user_has_resource_api_permission(self, user_db, resource_api, permission_type): |
||
406 | assert permission_type in [PermissionType.ACTION_CREATE] |
||
407 | |||
408 | action_uid = resource_api.get_uid() |
||
409 | pack_uid = resource_api.get_pack_uid() |
||
410 | return self._user_has_resource_permission(user_db=user_db, pack_uid=pack_uid, |
||
411 | resource_uid=action_uid, |
||
412 | permission_type=permission_type) |
||
413 | |||
414 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
415 | action_uid = resource_db.get_uid() |
||
416 | pack_uid = resource_db.get_pack_uid() |
||
417 | return self._user_has_resource_permission(user_db=user_db, pack_uid=pack_uid, |
||
418 | resource_uid=action_uid, |
||
419 | permission_type=permission_type) |
||
420 | |||
421 | |||
422 | class ActionAliasPermissionsResolver(ContentPackResourcePermissionsResolver): |
||
423 | """ |
||
424 | Permission resolver for "action_alias" resource type. |
||
425 | """ |
||
426 | |||
427 | resource_type = ResourceType.ACTION_ALIAS |
||
428 | view_grant_permission_types = [ |
||
429 | PermissionType.ACTION_ALIAS_ALL, |
||
430 | PermissionType.ACTION_ALIAS_CREATE, |
||
431 | PermissionType.ACTION_ALIAS_MODIFY, |
||
432 | PermissionType.ACTION_ALIAS_DELETE |
||
433 | ] |
||
434 | |||
435 | def user_has_permission(self, user_db, permission_type): |
||
436 | assert permission_type in [PermissionType.ACTION_ALIAS_LIST, |
||
437 | PermissionType.ACTION_ALIAS_MATCH, |
||
438 | PermissionType.ACTION_ALIAS_HELP] |
||
439 | |||
440 | if permission_type == PermissionType.ACTION_ALIAS_LIST: |
||
441 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
442 | elif permission_type in [PermissionType.ACTION_ALIAS_MATCH, |
||
443 | PermissionType.ACTION_ALIAS_HELP]: |
||
444 | return self._user_has_global_permission(user_db=user_db, |
||
445 | permission_type=permission_type) |
||
446 | else: |
||
447 | raise ValueError('Unsupported permission type: %s' % (permission_type)) |
||
448 | |||
449 | def user_has_resource_api_permission(self, user_db, resource_api, permission_type): |
||
450 | assert permission_type in [PermissionType.ACTION_ALIAS_CREATE] |
||
451 | |||
452 | action_alias_uid = resource_api.get_uid() |
||
453 | pack_uid = resource_api.get_pack_uid() |
||
454 | return self._user_has_resource_permission(user_db=user_db, pack_uid=pack_uid, |
||
455 | resource_uid=action_alias_uid, |
||
456 | permission_type=permission_type) |
||
457 | |||
458 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
459 | action_alias_uid = resource_db.get_uid() |
||
460 | pack_uid = resource_db.get_pack_uid() |
||
461 | return self._user_has_resource_permission(user_db=user_db, pack_uid=pack_uid, |
||
462 | resource_uid=action_alias_uid, |
||
463 | permission_type=permission_type) |
||
464 | |||
465 | |||
466 | class RulePermissionsResolver(ContentPackResourcePermissionsResolver): |
||
467 | """ |
||
468 | Permission resolver for "rule" resource type. |
||
469 | """ |
||
470 | |||
471 | resource_type = ResourceType.RULE |
||
472 | view_grant_permission_types = [ |
||
473 | PermissionType.RULE_ALL, |
||
474 | PermissionType.RULE_CREATE, |
||
475 | PermissionType.RULE_MODIFY, |
||
476 | PermissionType.RULE_DELETE |
||
477 | ] |
||
478 | |||
479 | def user_has_trigger_permission(self, user_db, trigger): |
||
480 | """ |
||
481 | Check if the user has access to the provided trigger. |
||
482 | |||
483 | This method is to be used during rule create and update where we check if the user has the |
||
484 | necessary trigger permissions. |
||
485 | |||
486 | Note: Right now we only support webhook triggers. |
||
487 | |||
488 | :param trigger: "trigger" attribute of the RuleAPI object. |
||
489 | :type trigger: ``dict`` |
||
490 | """ |
||
491 | log_context = { |
||
492 | 'user_db': user_db, |
||
493 | 'trigger': trigger, |
||
494 | 'resolver': self.__class__.__name__ |
||
495 | } |
||
496 | |||
497 | trigger_type = trigger['type'] |
||
498 | trigger_parameters = trigger.get('parameters', {}) |
||
499 | |||
500 | if trigger_type != WEBHOOK_TRIGGER_TYPE: |
||
501 | self._log('Not a webhook trigger type, ignoring trigger permission checking', |
||
502 | extra=log_context) |
||
503 | return True |
||
504 | |||
505 | resolver = get_resolver_for_resource_type(ResourceType.WEBHOOK) |
||
506 | webhook_db = WebhookDB(name=trigger_parameters['url']) |
||
507 | permission_type = PermissionType.WEBHOOK_CREATE |
||
508 | result = resolver.user_has_resource_db_permission(user_db=user_db, |
||
509 | resource_db=webhook_db, |
||
510 | permission_type=permission_type) |
||
511 | |||
512 | if result is True: |
||
513 | self._log('Found a matching trigger grant', extra=log_context) |
||
514 | return True |
||
515 | |||
516 | self._log('No matching trigger grants found', extra=log_context) |
||
517 | return False |
||
518 | |||
519 | def user_has_action_permission(self, user_db, action_ref): |
||
520 | """ |
||
521 | Check if the user has "execute" permission on the provided action. |
||
522 | """ |
||
523 | pass |
||
524 | |||
525 | def user_has_permission(self, user_db, permission_type): |
||
526 | assert permission_type in [PermissionType.RULE_LIST] |
||
527 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
528 | |||
529 | def user_has_resource_api_permission(self, user_db, resource_api, permission_type): |
||
530 | assert permission_type in [PermissionType.RULE_CREATE] |
||
531 | |||
532 | rule_uid = resource_api.get_uid() |
||
533 | pack_uid = resource_api.get_pack_uid() |
||
534 | return self._user_has_resource_permission(user_db=user_db, pack_uid=pack_uid, |
||
535 | resource_uid=rule_uid, |
||
536 | permission_type=permission_type) |
||
537 | |||
538 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
539 | rule_uid = resource_db.get_uid() |
||
540 | pack_uid = resource_db.get_pack_uid() |
||
541 | return self._user_has_resource_permission(user_db=user_db, pack_uid=pack_uid, |
||
542 | resource_uid=rule_uid, |
||
543 | permission_type=permission_type) |
||
544 | |||
545 | |||
546 | class RuleEnforcementPermissionsResolver(PermissionsResolver): |
||
547 | """ |
||
548 | Permission resolver for "rule enforcement" resource type. |
||
549 | """ |
||
550 | resource_type = ResourceType.RULE_ENFORCEMENT |
||
551 | |||
552 | def user_has_permission(self, user_db, permission_type): |
||
553 | assert permission_type in [PermissionType.RULE_ENFORCEMENT_LIST] |
||
554 | permission_type = PermissionType.RULE_LIST |
||
555 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
556 | |||
557 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
558 | log_context = { |
||
559 | 'user_db': user_db, |
||
560 | 'resource_db': resource_db, |
||
561 | 'permission_type': permission_type, |
||
562 | 'resolver': self.__class__.__name__ |
||
563 | } |
||
564 | self._log('Checking user resource permissions', extra=log_context) |
||
565 | |||
566 | # First check the system role permissions |
||
567 | has_system_role_permission = self._user_has_system_role_permission( |
||
568 | user_db=user_db, permission_type=permission_type) |
||
569 | |||
570 | if has_system_role_permission: |
||
571 | self._log('Found a matching grant via system role', extra=log_context) |
||
572 | return True |
||
573 | |||
574 | # Check custom roles |
||
575 | rule_spec = getattr(resource_db, 'rule', None) |
||
576 | rule_uid = rule_spec.uid |
||
577 | rule_id = rule_spec.id |
||
578 | rule_pack = ResourceReference.get_pack(rule_spec.ref) |
||
579 | |||
580 | if not rule_uid or not rule_id or not rule_pack: |
||
581 | LOG.error('Rule UID or ID or PACK not present in enforcement object. ' + |
||
582 | ('UID = %s, ID = %s, PACK = %s' % (rule_uid, rule_id, rule_pack)) + |
||
583 | 'Cannot assess access permissions without it. Defaulting to DENY.') |
||
584 | return False |
||
585 | |||
586 | # TODO: Add utility methods for constructing uids from parts |
||
587 | pack_db = PackDB(ref=rule_pack) |
||
588 | rule_pack_uid = pack_db.get_uid() |
||
589 | |||
590 | rule_permission_type = None |
||
591 | if permission_type == PermissionType.RULE_ENFORCEMENT_VIEW: |
||
592 | rule_permission_type = PermissionType.RULE_VIEW |
||
593 | elif permission_type == PermissionType.RULE_ENFORCEMENT_LIST: |
||
594 | rule_permission_type = PermissionType.RULE_LIST |
||
595 | else: |
||
596 | raise ValueError('Invalid permission type: %s' % (permission_type)) |
||
597 | |||
598 | permission_types = [PermissionType.RULE_ALL, rule_permission_type] |
||
599 | |||
600 | view_permission_type = PermissionType.get_permission_type(resource_type=ResourceType.RULE, |
||
601 | permission_name='view') |
||
602 | |||
603 | if rule_permission_type == view_permission_type: |
||
604 | permission_types = (RulePermissionsResolver.view_grant_permission_types[:] + |
||
605 | [rule_permission_type]) |
||
606 | |||
607 | # Check grants on the pack of the rule to which enforcement belongs to |
||
608 | resource_types = [ResourceType.PACK] |
||
609 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
610 | resource_uid=rule_pack_uid, |
||
611 | resource_types=resource_types, |
||
612 | permission_types=permission_types) |
||
613 | |||
614 | if len(permission_grants) >= 1: |
||
615 | self._log('Found a grant on the enforcement rule parent pack', extra=log_context) |
||
616 | return True |
||
617 | |||
618 | # Check grants on the rule the enforcement belongs to |
||
619 | resource_types = [ResourceType.RULE] |
||
620 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
621 | resource_uid=rule_uid, |
||
622 | resource_types=resource_types, |
||
623 | permission_types=permission_types) |
||
624 | |||
625 | if len(permission_grants) >= 1: |
||
626 | self._log('Found a grant on the enforcement\'s rule.', extra=log_context) |
||
627 | return True |
||
628 | |||
629 | self._log('No matching grants found', extra=log_context) |
||
630 | return False |
||
631 | |||
632 | |||
633 | class KeyValuePermissionsResolver(PermissionsResolver): |
||
634 | """ |
||
635 | Permission resolver for "key value pair" resource type. |
||
636 | """ |
||
637 | |||
638 | resource_type = ResourceType.KEY_VALUE_PAIR |
||
639 | |||
640 | def user_has_permission(self, user_db, permission_type): |
||
641 | # TODO: We don't support assigning permissions on key value pairs yet |
||
642 | return True |
||
643 | |||
644 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
645 | # TODO: We don't support assigning permissions on key value pairs yet |
||
646 | return True |
||
647 | |||
648 | |||
649 | class ExecutionPermissionsResolver(PermissionsResolver): |
||
650 | """ |
||
651 | Permission resolver for "execution" resource type. |
||
652 | """ |
||
653 | |||
654 | resource_type = ResourceType.EXECUTION |
||
655 | |||
656 | def user_has_permission(self, user_db, permission_type): |
||
657 | assert permission_type in [PermissionType.EXECUTION_LIST, |
||
658 | PermissionType.EXECUTION_VIEWS_FILTERS_LIST] |
||
659 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
660 | |||
661 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
662 | log_context = { |
||
663 | 'user_db': user_db, |
||
664 | 'resource_db': resource_db, |
||
665 | 'permission_type': permission_type, |
||
666 | 'resolver': self.__class__.__name__ |
||
667 | } |
||
668 | self._log('Checking user resource permissions', extra=log_context) |
||
669 | |||
670 | # First check the system role permissions |
||
671 | has_system_role_permission = self._user_has_system_role_permission( |
||
672 | user_db=user_db, permission_type=permission_type) |
||
673 | |||
674 | if has_system_role_permission: |
||
675 | self._log('Found a matching grant via system role', extra=log_context) |
||
676 | return True |
||
677 | |||
678 | # Check custom roles |
||
679 | action = resource_db['action'] |
||
680 | |||
681 | # TODO: Add utility methods for constructing uids from parts |
||
682 | pack_db = PackDB(ref=action['pack']) |
||
683 | |||
684 | action_uid = action['uid'] |
||
685 | action_pack_uid = pack_db.get_uid() |
||
686 | |||
687 | # Note: "action_execute" also grants / implies "execution_re_run" and "execution_stop" |
||
688 | if permission_type == PermissionType.EXECUTION_VIEW: |
||
689 | action_permission_type = PermissionType.ACTION_VIEW |
||
690 | elif permission_type in [PermissionType.EXECUTION_RE_RUN, |
||
691 | PermissionType.EXECUTION_STOP]: |
||
692 | action_permission_type = PermissionType.ACTION_EXECUTE |
||
693 | elif permission_type == PermissionType.EXECUTION_ALL: |
||
694 | action_permission_type = PermissionType.ACTION_ALL |
||
695 | elif permission_type == PermissionType.EXECUTION_VIEWS_FILTERS_LIST: |
||
696 | action_permission_type = PermissionType.EXECUTION_VIEWS_FILTERS_LIST |
||
697 | else: |
||
698 | raise ValueError('Invalid permission type: %s' % (permission_type)) |
||
699 | |||
700 | # Check grants on the pack of the action to which execution belongs to |
||
701 | resource_types = [ResourceType.PACK] |
||
702 | permission_types = [PermissionType.ACTION_ALL, action_permission_type] |
||
703 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
704 | resource_uid=action_pack_uid, |
||
705 | resource_types=resource_types, |
||
706 | permission_types=permission_types) |
||
707 | |||
708 | if len(permission_grants) >= 1: |
||
709 | self._log('Found a grant on the execution action parent pack', extra=log_context) |
||
710 | return True |
||
711 | |||
712 | # Check grants on the action the execution belongs to |
||
713 | resource_types = [ResourceType.ACTION] |
||
714 | permission_types = [PermissionType.ACTION_ALL, action_permission_type] |
||
715 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
716 | resource_uid=action_uid, |
||
717 | resource_types=resource_types, |
||
718 | permission_types=permission_types) |
||
719 | |||
720 | if len(permission_grants) >= 1: |
||
721 | self._log('Found a grant on the execution action', extra=log_context) |
||
722 | return True |
||
723 | |||
724 | self._log('No matching grants found', extra=log_context) |
||
725 | return False |
||
726 | |||
727 | |||
728 | class WebhookPermissionsResolver(PermissionsResolver): |
||
729 | |||
730 | resource_type = ResourceType.WEBHOOK |
||
731 | |||
732 | def user_has_permission(self, user_db, permission_type): |
||
733 | assert permission_type in [PermissionType.WEBHOOK_LIST] |
||
734 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
735 | |||
736 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
737 | log_context = { |
||
738 | 'user_db': user_db, |
||
739 | 'resource_db': resource_db, |
||
740 | 'permission_type': permission_type, |
||
741 | 'resolver': self.__class__.__name__ |
||
742 | } |
||
743 | self._log('Checking user resource permissions', extra=log_context) |
||
744 | |||
745 | # First check the system role permissions |
||
746 | has_system_role_permission = self._user_has_system_role_permission( |
||
747 | user_db=user_db, permission_type=permission_type) |
||
748 | |||
749 | if has_system_role_permission: |
||
750 | self._log('Found a matching grant via system role', extra=log_context) |
||
751 | return True |
||
752 | |||
753 | # Check custom roles |
||
754 | webhook_uid = resource_db.get_uid() |
||
755 | |||
756 | # Check direct grants on the webhook |
||
757 | resource_types = [ResourceType.WEBHOOK] |
||
758 | permission_types = [PermissionType.WEBHOOK_ALL, permission_type] |
||
759 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
760 | resource_uid=webhook_uid, |
||
761 | resource_types=resource_types, |
||
762 | permission_types=permission_types) |
||
763 | |||
764 | if len(permission_grants) >= 1: |
||
765 | self._log('Found a grant on the webhook', extra=log_context) |
||
766 | return True |
||
767 | |||
768 | self._log('No matching grants found', extra=log_context) |
||
769 | return False |
||
770 | |||
771 | |||
772 | class TimerPermissionsResolver(PermissionsResolver): |
||
773 | """ |
||
774 | Permission resolver for timers (timers are just a special type of triggers). |
||
775 | """ |
||
776 | |||
777 | resource_type = ResourceType.TIMER |
||
778 | |||
779 | def user_has_permission(self, user_db, permission_type): |
||
780 | assert permission_type in [PermissionType.TIMER_LIST] |
||
781 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
782 | |||
783 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
784 | log_context = { |
||
785 | 'user_db': user_db, |
||
786 | 'resource_db': resource_db, |
||
787 | 'permission_type': permission_type, |
||
788 | 'resolver': self.__class__.__name__ |
||
789 | } |
||
790 | self._log('Checking user resource permissions', extra=log_context) |
||
791 | |||
792 | # First check the system role permissions |
||
793 | has_system_role_permission = self._user_has_system_role_permission( |
||
794 | user_db=user_db, permission_type=permission_type) |
||
795 | |||
796 | if has_system_role_permission: |
||
797 | self._log('Found a matching grant via system role', extra=log_context) |
||
798 | return True |
||
799 | |||
800 | # Check custom roles |
||
801 | timer_uid = resource_db.get_uid() |
||
802 | |||
803 | # Check direct grants on the webhook |
||
804 | resource_types = [ResourceType.TIMER] |
||
805 | permission_types = [PermissionType.TIMER_ALL, permission_type] |
||
806 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
807 | resource_uid=timer_uid, |
||
808 | resource_types=resource_types, |
||
809 | permission_types=permission_types) |
||
810 | |||
811 | if len(permission_grants) >= 1: |
||
812 | self._log('Found a grant on the timer', extra=log_context) |
||
813 | return True |
||
814 | |||
815 | self._log('No matching grants found', extra=log_context) |
||
816 | return False |
||
817 | |||
818 | |||
819 | class ApiKeyPermissionResolver(PermissionsResolver): |
||
820 | """ |
||
821 | Permission resolver for "api key" resource type. |
||
822 | """ |
||
823 | |||
824 | resource_type = ResourceType.API_KEY |
||
825 | |||
826 | def user_has_permission(self, user_db, permission_type): |
||
827 | assert permission_type in [PermissionType.API_KEY_LIST] |
||
828 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
829 | |||
830 | def user_has_resource_api_permission(self, user_db, resource_api, permission_type): |
||
831 | assert permission_type in [PermissionType.API_KEY_CREATE] |
||
832 | return self._user_has_global_permission(user_db=user_db, permission_type=permission_type) |
||
833 | |||
834 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
835 | log_context = { |
||
836 | 'user_db': user_db, |
||
837 | 'resource_db': resource_db, |
||
838 | 'permission_type': permission_type, |
||
839 | 'resolver': self.__class__.__name__ |
||
840 | } |
||
841 | self._log('Checking user resource permissions', extra=log_context) |
||
842 | |||
843 | # First check the system role permissions |
||
844 | has_system_role_permission = self._user_has_system_role_permission( |
||
845 | user_db=user_db, permission_type=permission_type) |
||
846 | |||
847 | if has_system_role_permission: |
||
848 | self._log('Found a matching grant via system role', extra=log_context) |
||
849 | return True |
||
850 | |||
851 | # Check custom roles |
||
852 | api_key_uid = resource_db.get_uid() |
||
853 | |||
854 | # Check direct grants on the webhook |
||
855 | resource_types = [ResourceType.API_KEY] |
||
856 | permission_types = [PermissionType.API_KEY_ALL, permission_type] |
||
857 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
858 | resource_uid=api_key_uid, |
||
859 | resource_types=resource_types, |
||
860 | permission_types=permission_types) |
||
861 | |||
862 | if len(permission_grants) >= 1: |
||
863 | self._log('Found a grant on the api key', extra=log_context) |
||
864 | return True |
||
865 | |||
866 | self._log('No matching grants found', extra=log_context) |
||
867 | return False |
||
868 | |||
869 | |||
870 | class TracePermissionsResolver(PermissionsResolver): |
||
871 | """ |
||
872 | Permission resolver for "trace" resource type. |
||
873 | """ |
||
874 | |||
875 | resource_type = ResourceType.TRACE |
||
876 | |||
877 | def user_has_permission(self, user_db, permission_type): |
||
878 | assert permission_type in [PermissionType.TRACE_LIST] |
||
879 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
880 | |||
881 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
882 | log_context = { |
||
883 | 'user_db': user_db, |
||
884 | 'resource_db': resource_db, |
||
885 | 'permission_type': permission_type, |
||
886 | 'resolver': self.__class__.__name__ |
||
887 | } |
||
888 | self._log('Checking user resource permissions', extra=log_context) |
||
889 | |||
890 | # First check the system role permissions |
||
891 | has_system_role_permission = self._user_has_system_role_permission( |
||
892 | user_db=user_db, permission_type=permission_type) |
||
893 | |||
894 | if has_system_role_permission: |
||
895 | self._log('Found a matching grant via system role', extra=log_context) |
||
896 | return True |
||
897 | |||
898 | # Check custom roles |
||
899 | trace_uid = resource_db.get_uid() |
||
900 | |||
901 | # Check direct grants on the webhook |
||
902 | resource_types = [ResourceType.TRACE] |
||
903 | permission_types = [PermissionType.TRACE_ALL, permission_type] |
||
904 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
905 | resource_uid=trace_uid, |
||
906 | resource_types=resource_types, |
||
907 | permission_types=permission_types) |
||
908 | |||
909 | if len(permission_grants) >= 1: |
||
910 | self._log('Found a grant on the trace', extra=log_context) |
||
911 | return True |
||
912 | |||
913 | self._log('No matching grants found', extra=log_context) |
||
914 | return False |
||
915 | |||
916 | |||
917 | class TriggerPermissionsResolver(PermissionsResolver): |
||
918 | """ |
||
919 | Permission resolver for trigger and timers (timers are just a special type of triggers). |
||
920 | """ |
||
921 | |||
922 | resource_type = ResourceType.TRIGGER |
||
923 | |||
924 | def user_has_permission(self, user_db, permission_type): |
||
925 | assert permission_type in [PermissionType.TRIGGER_LIST] |
||
926 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
927 | |||
928 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
929 | log_context = { |
||
930 | 'user_db': user_db, |
||
931 | 'resource_db': resource_db, |
||
932 | 'permission_type': permission_type, |
||
933 | 'resolver': self.__class__.__name__ |
||
934 | } |
||
935 | self._log('Checking user resource permissions', extra=log_context) |
||
936 | |||
937 | # First check the system role permissions |
||
938 | has_system_role_permission = self._user_has_system_role_permission( |
||
939 | user_db=user_db, permission_type=permission_type) |
||
940 | |||
941 | if has_system_role_permission: |
||
942 | self._log('Found a matching grant via system role', extra=log_context) |
||
943 | return True |
||
944 | |||
945 | # Check custom roles |
||
946 | timer_uid = resource_db.get_uid() |
||
947 | |||
948 | # Check direct grants on the webhook |
||
949 | resource_types = [ResourceType.TRIGGER] |
||
950 | permission_types = [PermissionType.TRIGGER_ALL, permission_type] |
||
951 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
952 | resource_uid=timer_uid, |
||
953 | resource_types=resource_types, |
||
954 | permission_types=permission_types) |
||
955 | |||
956 | if len(permission_grants) >= 1: |
||
957 | self._log('Found a grant on the timer', extra=log_context) |
||
958 | return True |
||
959 | |||
960 | self._log('No matching grants found', extra=log_context) |
||
961 | return False |
||
962 | |||
963 | |||
964 | class PolicyTypePermissionsResolver(PermissionsResolver): |
||
965 | """ |
||
966 | Permission resolver for "policy type" resource. |
||
967 | """ |
||
968 | |||
969 | resource_type = ResourceType.POLICY_TYPE |
||
970 | |||
971 | def user_has_permission(self, user_db, permission_type): |
||
972 | assert permission_type in [PermissionType.POLICY_TYPE_LIST] |
||
973 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
974 | |||
975 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
976 | log_context = { |
||
977 | 'user_db': user_db, |
||
978 | 'resource_db': resource_db, |
||
979 | 'permission_type': permission_type, |
||
980 | 'resolver': self.__class__.__name__ |
||
981 | } |
||
982 | self._log('Checking user resource permissions', extra=log_context) |
||
983 | |||
984 | # First check the system role permissions |
||
985 | has_system_role_permission = self._user_has_system_role_permission( |
||
986 | user_db=user_db, permission_type=permission_type) |
||
987 | |||
988 | if has_system_role_permission: |
||
989 | self._log('Found a matching grant via system role', extra=log_context) |
||
990 | return True |
||
991 | |||
992 | # Check custom roles |
||
993 | policy_type_uid = resource_db.get_uid() |
||
994 | |||
995 | # Check direct grants on the webhook |
||
996 | resource_types = [ResourceType.POLICY_TYPE] |
||
997 | permission_types = [PermissionType.POLICY_TYPE_ALL, permission_type] |
||
998 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
999 | resource_uid=policy_type_uid, |
||
1000 | resource_types=resource_types, |
||
1001 | permission_types=permission_types) |
||
1002 | |||
1003 | if len(permission_grants) >= 1: |
||
1004 | self._log('Found a grant on the policy type', extra=log_context) |
||
1005 | return True |
||
1006 | |||
1007 | self._log('No matching grants found', extra=log_context) |
||
1008 | return False |
||
1009 | |||
1010 | |||
1011 | class PolicyPermissionsResolver(ContentPackResourcePermissionsResolver): |
||
1012 | """ |
||
1013 | Permission resolver for "policy" resource type. |
||
1014 | """ |
||
1015 | |||
1016 | resource_type = ResourceType.POLICY |
||
1017 | view_grant_permission_types = [ |
||
1018 | PermissionType.POLICY_ALL, |
||
1019 | PermissionType.POLICY_CREATE, |
||
1020 | PermissionType.POLICY_MODIFY, |
||
1021 | PermissionType.POLICY_DELETE |
||
1022 | ] |
||
1023 | |||
1024 | def user_has_permission(self, user_db, permission_type): |
||
1025 | assert permission_type in [PermissionType.POLICY_LIST] |
||
1026 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
1027 | |||
1028 | def user_has_resource_api_permission(self, user_db, resource_api, permission_type): |
||
1029 | assert permission_type in [PermissionType.POLICY_CREATE] |
||
1030 | |||
1031 | policy_uid = resource_api.get_uid() |
||
1032 | pack_uid = resource_api.get_pack_uid() |
||
1033 | return self._user_has_resource_permission(user_db=user_db, pack_uid=pack_uid, |
||
1034 | resource_uid=policy_uid, |
||
1035 | permission_type=permission_type) |
||
1036 | |||
1037 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
1038 | policy_uid = resource_db.get_uid() |
||
1039 | pack_uid = resource_db.get_pack_uid() |
||
1040 | return self._user_has_resource_permission(user_db=user_db, pack_uid=pack_uid, |
||
1041 | resource_uid=policy_uid, |
||
1042 | permission_type=permission_type) |
||
1043 | |||
1044 | |||
1045 | class StreamPermissionsResolver(PermissionsResolver): |
||
1046 | resource_type = ResourceType.STREAM |
||
1047 | view_grant_permission_types = [] |
||
1048 | |||
1049 | def user_has_permission(self, user_db, permission_type): |
||
1050 | assert permission_type in [PermissionType.STREAM_VIEW] |
||
1051 | return self._user_has_global_permission(user_db=user_db, permission_type=permission_type) |
||
1052 | |||
1053 | |||
1054 | class InquiryPermissionsResolver(PermissionsResolver): |
||
1055 | resource_type = ResourceType.INQUIRY |
||
1056 | view_grant_permission_types = [ |
||
1057 | PermissionType.INQUIRY_LIST, |
||
1058 | PermissionType.INQUIRY_VIEW, |
||
1059 | PermissionType.INQUIRY_RESPOND, |
||
1060 | PermissionType.INQUIRY_ALL |
||
1061 | ] |
||
1062 | |||
1063 | def user_has_permission(self, user_db, permission_type): |
||
1064 | assert permission_type in [PermissionType.INQUIRY_LIST, PermissionType.INQUIRY_ALL] |
||
1065 | return self._user_has_list_permission(user_db=user_db, permission_type=permission_type) |
||
1066 | |||
1067 | def user_has_resource_db_permission(self, user_db, resource_db, permission_type): |
||
1068 | """ |
||
1069 | Method for checking user permissions on an existing resource (e.g. get one, edit, delete |
||
1070 | operations). |
||
1071 | |||
1072 | NOTE: |
||
1073 | Because we're borrowing the ActionExecutionDB model, the resource_db parameter is |
||
1074 | effectively ignored. All other filters are passed to get_all_permission_grants_for_user. |
||
1075 | Since all Inquiry permission types are global, this will still correctly return a list of |
||
1076 | grants. |
||
1077 | """ |
||
1078 | |||
1079 | permission_types = [ |
||
1080 | PermissionType.INQUIRY_VIEW, |
||
1081 | PermissionType.INQUIRY_RESPOND, |
||
1082 | PermissionType.INQUIRY_ALL |
||
1083 | ] |
||
1084 | |||
1085 | assert permission_type in permission_types |
||
1086 | |||
1087 | log_context = { |
||
1088 | 'user_db': user_db, |
||
1089 | 'resource_db': resource_db, |
||
1090 | 'permission_type': permission_type, |
||
1091 | 'resolver': self.__class__.__name__ |
||
1092 | } |
||
1093 | self._log('Checking user resource permissions', extra=log_context) |
||
1094 | |||
1095 | # First check the system role permissions |
||
1096 | has_system_role_permission = self._user_has_system_role_permission( |
||
1097 | user_db=user_db, permission_type=permission_type) |
||
1098 | |||
1099 | if has_system_role_permission: |
||
1100 | self._log('Found a matching grant via system role', extra=log_context) |
||
1101 | return True |
||
1102 | |||
1103 | # Check for explicit Inquiry grants first |
||
1104 | resource_types = [ResourceType.INQUIRY] |
||
1105 | permission_grants = get_all_permission_grants_for_user(user_db=user_db, |
||
1106 | resource_types=resource_types, |
||
1107 | permission_types=permission_types) |
||
1108 | |||
1109 | if len(permission_grants) >= 1: |
||
1110 | self._log('Found a grant on the inquiry', extra=log_context) |
||
1111 | return True |
||
1112 | |||
1113 | # If the inquiry has a parent (is in a workflow) we want to |
||
1114 | # check permissions of the parent action and pack, and inherit |
||
1115 | # if applicable |
||
1116 | if resource_db.parent: |
||
1117 | |||
1118 | # Retrieve objects for parent workflow action and pack |
||
1119 | wf_exc = ActionExecution.get(id=resource_db.parent) |
||
1120 | wf_action = wf_exc['action'] |
||
1121 | # TODO: Add utility methods for constructing uids from parts |
||
1122 | wf_pack_db = PackDB(ref=wf_action['pack']) |
||
1123 | wf_action_uid = wf_action['uid'] |
||
1124 | wf_action_pack_uid = wf_pack_db.get_uid() |
||
1125 | |||
1126 | # Check grants on the pack of the workflow that the Inquiry was generated from |
||
1127 | resource_types = [ResourceType.PACK] |
||
1128 | permission_types = [PermissionType.ACTION_ALL, PermissionType.ACTION_EXECUTE] |
||
1129 | permission_grants = get_all_permission_grants_for_user( |
||
1130 | user_db=user_db, |
||
1131 | resource_uid=wf_action_pack_uid, |
||
1132 | resource_types=resource_types, |
||
1133 | permission_types=permission_types |
||
1134 | ) |
||
1135 | |||
1136 | if len(permission_grants) >= 1: |
||
1137 | log_context['wf_action_pack_uid'] = wf_action_pack_uid |
||
1138 | self._log( |
||
1139 | 'Found a grant on the parent pack for an inquiry workflow', |
||
1140 | extra=log_context |
||
1141 | ) |
||
1142 | return True |
||
1143 | |||
1144 | # Check grants on the workflow that the Inquiry was generated from |
||
1145 | resource_types = [ResourceType.ACTION] |
||
1146 | permission_types = [PermissionType.ACTION_ALL, PermissionType.ACTION_EXECUTE] |
||
1147 | permission_grants = get_all_permission_grants_for_user( |
||
1148 | user_db=user_db, |
||
1149 | resource_uid=wf_action_uid, |
||
1150 | resource_types=resource_types, |
||
1151 | permission_types=permission_types |
||
1152 | ) |
||
1153 | |||
1154 | if len(permission_grants) >= 1: |
||
1155 | log_context['wf_action_uid'] = wf_action_uid |
||
1156 | self._log('Found a grant on the inquiry workflow', extra=log_context) |
||
1157 | return True |
||
1158 | |||
1159 | self._log('No matching grants found', extra=log_context) |
||
1160 | return False |
||
1161 | |||
1162 | |||
1163 | def get_resolver_for_resource_type(resource_type): |
||
1164 | """ |
||
1165 | Return resolver instance for the provided resource type. |
||
1166 | |||
1167 | :rtype: Instance of :class:`PermissionsResolver` |
||
1168 | """ |
||
1169 | if resource_type == ResourceType.RUNNER: |
||
1170 | resolver_cls = RunnerPermissionsResolver |
||
1171 | elif resource_type == ResourceType.PACK: |
||
1172 | resolver_cls = PackPermissionsResolver |
||
1173 | elif resource_type == ResourceType.SENSOR: |
||
1174 | resolver_cls = SensorPermissionsResolver |
||
1175 | elif resource_type == ResourceType.ACTION: |
||
1176 | resolver_cls = ActionPermissionsResolver |
||
1177 | elif resource_type == ResourceType.ACTION_ALIAS: |
||
1178 | resolver_cls = ActionAliasPermissionsResolver |
||
1179 | elif resource_type == ResourceType.RULE: |
||
1180 | resolver_cls = RulePermissionsResolver |
||
1181 | elif resource_type == ResourceType.EXECUTION: |
||
1182 | resolver_cls = ExecutionPermissionsResolver |
||
1183 | elif resource_type == ResourceType.KEY_VALUE_PAIR: |
||
1184 | resolver_cls = KeyValuePermissionsResolver |
||
1185 | elif resource_type == ResourceType.WEBHOOK: |
||
1186 | resolver_cls = WebhookPermissionsResolver |
||
1187 | elif resource_type == ResourceType.TIMER: |
||
1188 | resolver_cls = TimerPermissionsResolver |
||
1189 | elif resource_type == ResourceType.API_KEY: |
||
1190 | resolver_cls = ApiKeyPermissionResolver |
||
1191 | elif resource_type == ResourceType.RULE_ENFORCEMENT: |
||
1192 | resolver_cls = RuleEnforcementPermissionsResolver |
||
1193 | elif resource_type == ResourceType.TRACE: |
||
1194 | resolver_cls = TracePermissionsResolver |
||
1195 | elif resource_type == ResourceType.TRIGGER: |
||
1196 | resolver_cls = TriggerPermissionsResolver |
||
1197 | elif resource_type == ResourceType.POLICY_TYPE: |
||
1198 | resolver_cls = PolicyTypePermissionsResolver |
||
1199 | elif resource_type == ResourceType.POLICY: |
||
1200 | resolver_cls = PolicyPermissionsResolver |
||
1201 | elif resource_type == ResourceType.STREAM: |
||
1202 | resolver_cls = StreamPermissionsResolver |
||
1203 | elif resource_type == ResourceType.INQUIRY: |
||
1204 | resolver_cls = InquiryPermissionsResolver |
||
1205 | else: |
||
1206 | raise ValueError('Unsupported resource: %s' % (resource_type)) |
||
1207 | |||
1208 | resolver_instance = resolver_cls() |
||
1209 | return resolver_instance |
||
1210 | |||
1211 | |||
1212 | def get_resolver_for_permission_type(permission_type): |
||
1213 | """ |
||
1214 | Return resolver instance for the provided permission type. |
||
1215 | |||
1216 | :rtype: Instance of :class:`PermissionsResolver` |
||
1217 | """ |
||
1218 | resource_type = PermissionType.get_resource_type(permission_type=permission_type) |
||
1219 | resolver_instance = get_resolver_for_resource_type(resource_type=resource_type) |
||
1220 | return resolver_instance |
||
1221 |
Prefixing a member variable
_
is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class: