Exemple #1
0
async def prevent_bruteforce_attack(request, block_time=300, attempts=5):
    """This function checks that the IPs that are requesting an API token do not do so repeatedly"""
    global ip_stats, ip_block
    if request.path == '/security/user/authenticate' and request.method == 'GET':
        try:
            if time() - block_time >= ip_stats[request.remote]['timestamp']:
                ip_stats.pop(request.remote)
                ip_block.remove(request.remote)
        except (KeyError, ValueError):
            pass

        if request.remote in ip_block:
            logger.warning(
                f'IP blocked due to exceeded number of logins attempts: {request.remote}'
            )
            raise_if_exc(WazuhPermissionError(6000))

        if request.remote not in ip_stats.keys():
            ip_stats[request.remote] = dict()
            ip_stats[request.remote]['attempts'] = 1
            ip_stats[request.remote]['timestamp'] = time()
        else:
            ip_stats[request.remote]['attempts'] += 1

        if ip_stats[request.remote]['attempts'] >= attempts:
            ip_block.add(request.remote)
Exemple #2
0
def list_handler(result: AffectedItemsWazuhResult,
                 original: dict = None,
                 allowed: dict = None,
                 target: dict = None,
                 add_denied: bool = False,
                 **post_proc_kwargs):
    """ Post processor for framework list responses with affected items and optional denied items

    :param result: Dict with affected_items, failed_items and str_priority
    :param original: Original input call parameter values
    :param allowed: Allowed input call parameter values
    :param target: Name of the input parameters used to calculate resource access
    :param add_denied: Flag to add denied permissions to answer
    :return: AffectedItemsWazuhResult
    """
    if add_denied:
        for res_id, target_param in target.items():
            denied = _get_denied(original, allowed, target_param, res_id)
            if res_id in integer_resources:
                denied = {int(i) if i.isdigit() else i for i in denied}
            for denied_item in denied:
                result.add_failed_item(
                    id_=denied_item,
                    error=WazuhPermissionError(
                        4000,
                        extra_message=f'Resource type: {res_id}',
                        ids=denied))
    else:
        if 'default_result_kwargs' in post_proc_kwargs and result is None:
            return AffectedItemsWazuhResult(
                **post_proc_kwargs['default_result_kwargs'])
        if 'exclude_codes' in post_proc_kwargs:
            result.remove_failed_items(post_proc_kwargs['exclude_codes'])

    return result
async def revoke_all_tokens(request, pretty: bool = False):
    """Revoke all tokens

    Parameters
    ----------
    pretty : bool, optional
        Show results in human-readable format

    Returns
    -------
    dict
        Status message
    """
    f_kwargs = {}

    nodes = await get_system_nodes()
    if isinstance(nodes, Exception):
        nodes = None

    dapi = DistributedAPI(f=security.wrapper_revoke_tokens,
                          f_kwargs=remove_nones_to_dict(f_kwargs),
                          request_type='distributed_master' if nodes is not None else 'local_any',
                          is_async=False,
                          broadcasting=nodes is not None,
                          wait_for_complete=True,
                          logger=logger,
                          rbac_permissions=request['token_info']['rbac_policies'],
                          nodes=nodes
                          )
    data = raise_if_exc(await dapi.distribute_function())
    if type(data) == AffectedItemsWazuhResult and len(data.affected_items) == 0:
        raise_if_exc(WazuhPermissionError(4000, data.message))

    return web.json_response(data=data, status=200, dumps=prettify if pretty else dumps)
Exemple #4
0
        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)
Exemple #5
0
async def unlock_ip(request, block_time):
    """This function blocks/unblocks the IPs that are requesting an API token"""
    global ip_block, ip_stats
    try:
        if time() - block_time >= ip_stats[request.remote]['timestamp']:
            ip_stats.pop(request.remote)
            ip_block.remove(request.remote)
    except (KeyError, ValueError):
        pass

    if request.remote in ip_block:
        logger.warning(f'IP blocked due to exceeded number of logins attempts: {request.remote}')
        raise_if_exc(WazuhPermissionError(6000))
Exemple #6
0
def list_handler(result: AffectedItemsWazuhResult,
                 original: dict = None,
                 allowed: dict = None,
                 target: dict = None,
                 add_denied: bool = False,
                 **post_proc_kwargs):
    """Post processor for framework list responses with affected items and optional denied items.

    Parameters
    ----------
    result : AffectedItemsWazuhResult
        Dict with affected_items, failed_items and str_priority.
    original : dict
        Original input call parameter values.
    allowed : dict
        Allowed input call parameter values.
    target : dict
        Name of the input parameters used to calculate resource access.
    add_denied : bool
        Flag to add denied permissions to answer.
    post_proc_kwargs : dict
        Additional kwargs used in post-processing.

    Returns
    -------
    AffectedItemsWazuhResult
    """
    if add_denied:
        for res_id, target_param in target.items():
            denied = _get_denied(original, allowed, target_param, res_id)
            if res_id in integer_resources:
                denied = {int(i) if i.isdigit() else i for i in denied}
            for denied_item in denied:
                result.add_failed_item(
                    id_=denied_item,
                    error=WazuhPermissionError(
                        4000,
                        extra_message=f'Resource type: {res_id}',
                        ids=denied))
    if not add_denied or post_proc_kwargs.get('force'):
        # Apply post processing exclusion/default values if the main resource was not explicit or
        # `force` parameter exists in `post_proc_kwargs` and is True
        if 'default_result_kwargs' in post_proc_kwargs and result is None:
            return AffectedItemsWazuhResult(
                **post_proc_kwargs['default_result_kwargs'])
        if 'exclude_codes' in post_proc_kwargs:
            result.remove_failed_items(post_proc_kwargs['exclude_codes'])

    return result
Exemple #7
0
def get_permissions(user_id=None, auth_context=None):
    with AuthenticationManager() as auth:
        if not auth.user_allow_run_as(user_id) and auth_context:
            raise WazuhPermissionError(code=6004)
        elif auth.user_allow_run_as(user_id):
            permissions, roles = optimize_resources(auth_context=auth_context, user_id=user_id)
        else:
            permissions, roles = optimize_resources(user_id=user_id)

        result = {
            'policies': permissions,
            'roles': roles
        }

        return WazuhResult(result)
Exemple #8
0
def get_permissions(user_id=None, auth_context=None):
    """Obtain the permissions of a user using auth_context or user_id

    :param auth_context: Authorization context of the current user
    :param user_id: Username of the current user
    """
    with AuthenticationManager() as auth:
        if not auth.user_allow_run_as(user_id) and auth_context:
            raise WazuhPermissionError(6004)
        elif auth.user_allow_run_as(user_id):
            roles = get_roles(auth_context=auth_context, user_id=user_id)
        else:
            roles = get_roles(user_id=user_id)

        result = {'roles': roles}

        return WazuhResult(result)
Exemple #9
0
def get_agent_by_name(name=None, select=None):
    """Gets an agent by its name.

    :param name: Agent_name.
    :param select: Select fields to return. Format: {"fields":["field1","field2"]}.
    :return: AffectedItemsWazuhResult.
    """
    db_query = WazuhDBQueryAgents(filters={'name': name})
    data = db_query.run()
    try:
        agent = data['items'][0]['id']
        return get_agents(agent_list=[agent], select=select)
    except IndexError:
        raise WazuhResourceNotFound(1754)
    except Exception as e:
        if e.code == 4000:
            raise WazuhPermissionError(4000)
        raise e
Exemple #10
0
    (WazuhPermissionError, 4000, ['remediation', 'code'], 403, ProblemException),
    (WazuhResourceNotFound, 1710, ['remediation', 'code'], 404, ProblemException),
    (WazuhInternalError, 1000, ['remediation', 'code'], 500, ProblemException)
])
def test_create_problem(exception_type, code, extra_fields, returned_code, returned_exception):
    """Check that _create_problem returns exception with expected data"""
    with pytest.raises(returned_exception) as exc_info:
        util._create_problem(exception_type(code))

    if returned_exception == ProblemException:
        assert exc_info.value.status == returned_code
    if extra_fields:
        assert all(x in exc_info.value.ext.keys() for x in extra_fields)
        assert None not in exc_info.value.ext.values()


@pytest.mark.parametrize('obj, code', [
    ((WazuhError(6001), ['value0', 'value1']), 429),
    ((WazuhInternalError(1000), ['value0', 'value1']), None),
    ((WazuhPermissionError(4000), ['value0', 'value1']), None),
    ((WazuhResourceNotFound(1710), ['value0', 'value1']), None)
])
@patch('api.util._create_problem')
def test_raise_if_exc(mock_create_problem, obj, code):
    """Check that raise_if_exc calls _create_problem when an exception is given"""
    result = util.raise_if_exc(obj)
    if isinstance(obj, Exception):
        mock_create_problem.assert_called_once_with(obj, code)
    else:
        assert result == obj
Exemple #11
0
async def test_middlewares_unlock_ip_ko(time_mock):
    """Test if `unlock_ip` raises an exception if the IP is still blocked."""
    with patch("api.middlewares.raise_if_exc") as raise_mock:
        await unlock_ip(DummyRequest({'remote': "ip"}), 5)
        raise_mock.assert_called_once_with(WazuhPermissionError(6000))