def wrapper(*args, **kwargs): original_kwargs = dict(kwargs) target_params, req_permissions, add_denied = \ _get_required_permissions(actions=actions, resources=resources, **kwargs) allow = _match_permissions(req_permissions=req_permissions, rbac_mode=rbac.get()['rbac_mode']) skip_execution = False for res_id, target_param in target_params.items(): try: if target_param in original_kwargs and not isinstance( original_kwargs[target_param], list): if original_kwargs[target_param] is not None: original_kwargs[target_param] = [ original_kwargs[target_param] ] # We don't have any permissions over the required resources if len(allow[res_id]) == 0 and \ original_kwargs.get(target_param, None) is not None and \ len(original_kwargs[target_param]) != 0: raise Exception if target_param != '*': # No resourceless and not static if target_param in original_kwargs and original_kwargs[ target_param] is not None: kwargs[target_param] = list( filter(lambda x: x in allow[res_id], original_kwargs[target_param])) else: kwargs[target_param] = list(allow[res_id]) elif len(allow[res_id]) == 0: raise Exception except Exception: if add_denied: denied = _get_denied(original_kwargs, allow, target_param, res_id, resources=resources) raise WazuhPermissionError( 4000, extra_message=f'Resource type: {res_id}', ids=denied, title="Permission Denied") else: if target_param != '*': kwargs[target_param] = list() else: skip_execution = True result = func(*args, **kwargs) if not skip_execution else None if post_proc_func is None: return result else: return post_proc_func(result, original=original_kwargs, allowed=allow, target=target_params, add_denied=add_denied, **post_proc_kwargs)
def _match_permissions(req_permissions: dict = None, rbac_mode: str = 'white'): """Try to match function required permissions against user permissions to allow or deny execution :param req_permissions: Required permissions to allow function execution :return: Dictionary with final permissions """ allow_match = defaultdict(set) for req_action, req_resources in req_permissions.items(): is_combination = any('&' in req_resource for req_resource in req_resources) rbac_mode == 'black' and _black_expansion(req_resources, allow_match) if not is_combination or len(req_resources) == 0: _single_processor(req_resources, rbac.get().get(req_action, dict()), allow_match) else: _combination_processor(req_resources, rbac.get().get(req_action, dict()), allow_match) return allow_match