Example #1
0
async def get_agents_in_group(request,
                              group_id,
                              pretty=False,
                              wait_for_complete=False,
                              offset=0,
                              limit=database_limit,
                              select=None,
                              sort=None,
                              search=None,
                              status=None,
                              q=None):
    """Get the list of agents that belongs to the specified group.

    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param group_id: Group ID.
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param select: Select which fields to return (separated by comma)
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :param status: Filters by agent status. Use commas to enter multiple statuses.
    :param q: Query to filter results by. For example q="status=active"
    :return: AllItemsResponseAgents
    """
    f_kwargs = {
        'group_list': [group_id],
        'offset': offset,
        'limit': limit,
        'sort': parse_api_param(sort, 'sort'),
        'search': parse_api_param(search, 'search'),
        'select': select,
        'filters': {
            'status': status,
        },
        'q': q
    }

    dapi = DistributedAPI(
        f=agent.get_agents_in_group,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])

    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
Example #2
0
def test_DistributedAPI(install_type_mock, kwargs):
    """Test constructor from DistributedAPI class.

    Parameters
    ----------
    kwargs : dict
        Dict with some kwargs to pass when instancing the class.
    """
    dapi = DistributedAPI(f=agent.get_agents_summary_status,
                          logger=logger,
                          **kwargs)
    assert isinstance(dapi, DistributedAPI)
Example #3
0
async def put_upgrade_agents(request,
                             agents_list=None,
                             pretty=False,
                             wait_for_complete=False,
                             wpk_repo=None,
                             version=None,
                             use_http=False,
                             force=False):
    """Upgrade agents using a WPK file from online repository.

    Parameters
    ----------
    pretty : bool
        Show results in human-readable format.
    wait_for_complete : bool
        Disable timeout response.
    agents_list : list
        List of agent IDs. All possible values from 000 onwards.
    wpk_repo : str
        WPK repository.
    version : str
        Wazuh version to upgrade to.
    use_http : bool
        Use protocol http. If it's false use https. By default the value is set to false.
    force : bool
        Force upgrade.

    Returns
    -------
    ApiResponse
        Upgrade message after trying to upgrade the agents.
    """
    f_kwargs = {
        'agent_list': agents_list,
        'wpk_repo': wpk_repo,
        'version': version,
        'use_http': use_http,
        'force': force
    }

    dapi = DistributedAPI(
        f=agent.upgrade_agents,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='distributed_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
Example #4
0
async def get_cluster_nodes(request,
                            pretty=False,
                            wait_for_complete=False,
                            offset=0,
                            limit=None,
                            sort=None,
                            search=None,
                            select=None,
                            nodes_list=None,
                            q=None):
    """Get information about all nodes in the cluster or a list of them

    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :param select: Select which fields to return (separated by comma)
    :param nodes_list: List of node ids
    :param q: Query to filter results by.
    """
    # Get type parameter from query
    type_ = request.query.get('type', 'all')

    f_kwargs = {
        'filter_node': nodes_list,
        'offset': offset,
        'limit': limit,
        'sort': parse_api_param(sort, 'sort'),
        'search': parse_api_param(search, 'search'),
        'select': select,
        'filter_type': type_,
        'q': q
    }

    nodes = raise_if_exc(await get_system_nodes())
    dapi = DistributedAPI(
        f=cluster.get_nodes_info,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=True,
        wait_for_complete=wait_for_complete,
        logger=logger,
        local_client_arg='lc',
        rbac_permissions=request['token_info']['rbac_policies'],
        nodes=nodes)
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
Example #5
0
async def get_rules_requirement(request,
                                requirement=None,
                                pretty=False,
                                wait_for_complete=False,
                                offset=0,
                                limit=None,
                                sort=None,
                                search=None):
    """Get all specified requirements

    :param requirement: Get the specified requirement in all rules in the system.
    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :return: Data object
    """
    f_kwargs = {
        'requirement':
        requirement.replace('-', '_'),
        'offset':
        offset,
        'limit':
        limit,
        'sort_by':
        parse_api_param(sort, 'sort')['fields'] if sort is not None else [''],
        'sort_ascending':
        True if sort is None or parse_api_param(sort, 'sort')['order'] == 'asc'
        else False,
        'search_text':
        parse_api_param(search, 'search')['value']
        if search is not None else None,
        'complementary_search':
        parse_api_param(search, 'search')['negation']
        if search is not None else None
    }

    dapi = DistributedAPI(
        f=rule_framework.get_requirement,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_any',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
Example #6
0
async def get_ports_info(request, agent_id, pretty=False, wait_for_complete=False, offset=0, limit=None, select=None,
                         sort=None, search=None, pid=None, protocol=None, tx_queue=None, state=None, process=None,
                         q=None):
    """ Get ports info of an agent

    :param agent_id: Agent ID
    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param select: Select which fields to return (separated by comma)
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :param pid: Filters by pid
    :param protocol: Filters by protocol
    :param tx_queue: Filters by tx_queue
    :param state: Filters by state
    :param process: Filters by process
    :param q: Query to filter results by.
    :return: Data
    """
    filters = {'pid': pid,
               'protocol': protocol,
               'tx_queue': tx_queue,
               'state': state,
               'process': process}
    # Add nested fields to kwargs filters
    nested = ['local.ip', 'local.port', 'remote.ip']
    for field in nested:
        filters[field] = request.query.get(field, None)

    f_kwargs = {'agent_list': [agent_id],
                'offset': offset,
                'limit': limit,
                'select': select,
                'sort': parse_api_param(sort, 'sort'),
                'search': parse_api_param(search, 'search'),
                'filters': filters,
                'element_type': 'ports',
                'q': q}

    dapi = DistributedAPI(f=syscollector.get_item_agent,
                          f_kwargs=remove_nones_to_dict(f_kwargs),
                          request_type='distributed_master',
                          is_async=False,
                          wait_for_complete=wait_for_complete,
                          logger=logger,
                          rbac_permissions=request['token_info']['rbac_policies']
                          )
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data, status=200, dumps=prettify if pretty else dumps)
Example #7
0
def test_DistributedAPI_local_request(mock_local_request):
    """Test `local_request` method from class DistributedAPI and check the behaviour when an error raise."""
    dapi_kwargs = {'f': manager.status, 'logger': logger}
    raise_if_exc_routine(dapi_kwargs=dapi_kwargs)

    dapi_kwargs = {'f': cluster.get_nodes_info, 'logger': logger, 'local_client_arg': 'lc'}
    raise_if_exc_routine(dapi_kwargs=dapi_kwargs)

    dapi_kwargs['is_async'] = True
    raise_if_exc_routine(dapi_kwargs=dapi_kwargs)

    with patch('asyncio.wait_for', new=AsyncMock(side_effect=TimeoutError('Testing'))):
        dapi = DistributedAPI(f=manager.status, logger=logger)
        try:
            raise_if_exc(loop.run_until_complete(dapi.distribute_function()))
        except ProblemException as e:
            assert e.ext['dapi_errors'][list(e.ext['dapi_errors'].keys())[0]]['error'] == \
                   'Timeout executing API request'

    with patch('asyncio.wait_for', new=AsyncMock(side_effect=WazuhError(1001))):
        dapi_kwargs = {'f': manager.status, 'logger': logger}
        raise_if_exc_routine(dapi_kwargs=dapi_kwargs, expected_error=1001)

        dapi_kwargs['debug'] = True
        raise_if_exc_routine(dapi_kwargs=dapi_kwargs, expected_error=1001)

    with patch('asyncio.wait_for', new=AsyncMock(side_effect=WazuhInternalError(1001))):
        dapi_kwargs = {'f': manager.status, 'logger': logger}
        raise_if_exc_routine(dapi_kwargs=dapi_kwargs, expected_error=1001)

        dapi = DistributedAPI(f=manager.status, logger=logger, debug=True)
        try:
            raise_if_exc(loop.run_until_complete(dapi.distribute_function()))
        except WazuhInternalError as e:
            assert e.code == 1001

    with patch('asyncio.wait_for', new=AsyncMock(side_effect=KeyError('Testing'))):
        dapi_kwargs = {'f': manager.status, 'logger': logger}
        raise_if_exc_routine(dapi_kwargs=dapi_kwargs, expected_error=1000)

        dapi = DistributedAPI(f=manager.status, logger=logger, debug=True)
        try:
            raise_if_exc(loop.run_until_complete(dapi.distribute_function()))
        except Exception as e:
            assert type(e) == KeyError
Example #8
0
def test_DistributedAPI_local_request_errors():
    """Check the behaviour when the local_request function raised an error."""
    with patch(
            'wazuh.core.cluster.dapi.dapi.DistributedAPI.execute_local_request',
            new=AsyncMock(side_effect=WazuhInternalError(1001))):
        dapi_kwargs = {'f': agent.get_agents_summary_status, 'logger': logger}
        raise_if_exc_routine(dapi_kwargs=dapi_kwargs, expected_error=1001)

        dapi_kwargs['debug'] = True
        dapi = DistributedAPI(f=agent.get_agents_summary_status,
                              logger=logger,
                              debug=True)
        try:
            raise_if_exc(loop.run_until_complete(dapi.distribute_function()))
        except WazuhInternalError as e:
            assert e.code == 1001

    with patch(
            'wazuh.core.cluster.dapi.dapi.DistributedAPI.execute_local_request',
            new=AsyncMock(side_effect=KeyError('Testing'))):
        dapi_kwargs = {'f': agent.get_agents_summary_status, 'logger': logger}
        raise_if_exc_routine(dapi_kwargs=dapi_kwargs,
                             expected_error=1000)  # Specify KeyError

        dapi = DistributedAPI(f=agent.get_agents_summary_status,
                              logger=logger,
                              debug=True)
        try:
            raise_if_exc(loop.run_until_complete(dapi.distribute_function()))
        except KeyError as e:
            assert 'KeyError' in repr(e)
Example #9
0
async def restart_agents_by_group(request, group_id, pretty=False, wait_for_complete=False):
    """Restart all agents from a group.

    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param group_id: Group ID.
    :return: AllItemsResponseAgents
    """
    f_kwargs = {'group_list': [group_id], 'select': ['id']}

    dapi = DistributedAPI(f=agent.get_agents_in_group,
                          f_kwargs=remove_nones_to_dict(f_kwargs),
                          request_type='local_master',
                          is_async=False,
                          wait_for_complete=wait_for_complete,
                          logger=logger,
                          rbac_permissions=request['token_info']['rbac_policies']
                          )

    agents = raise_if_exc(await dapi.distribute_function())
    agent_list = [a['id'] for a in agents.affected_items]

    if not agent_list:
        data = AffectedItemsWazuhResult(none_msg='Restart command was not sent to any agent')
        return web.json_response(data=data, status=200, dumps=prettify if pretty else dumps)

    f_kwargs = {'agent_list': agent_list}

    dapi = DistributedAPI(f=agent.restart_agents,
                          f_kwargs=remove_nones_to_dict(f_kwargs),
                          request_type='distributed_master',
                          is_async=False,
                          wait_for_complete=wait_for_complete,
                          logger=logger,
                          rbac_permissions=request['token_info']['rbac_policies']
                          )

    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data, status=200, dumps=prettify if pretty else dumps)
async def get_hotfixes_info(request,
                            pretty=False,
                            wait_for_complete=False,
                            list_agents='*',
                            offset=0,
                            limit=None,
                            sort=None,
                            search=None,
                            select=None,
                            hotfix=None):
    """ Get hotfixes info from all agents or a list of them.

    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param list_agents: List of agent's IDs.
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/. at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :param select: Select which fields to return (separated by comma)
    :param hotfix: Filters by hotfix in Windows agents
    :return:AllItemsResponseSyscollectorHotfixes
    """

    filters = {'hotfix': hotfix}

    f_kwargs = {
        'agent_list': list_agents,
        'offset': offset,
        'limit': limit,
        'select': select,
        'sort': parse_api_param(sort, 'sort'),
        'search': parse_api_param(search, 'search'),
        'filters': filters,
        'element_type': 'hotfixes'
    }

    dapi = DistributedAPI(
        f=syscollector.get_item_agent,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='distributed_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        broadcasting=list_agents == '*',
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
Example #11
0
async def get_network_interface_info(request, pretty=False, wait_for_complete=False, agents_list='*', offset=0,
                                     limit=None, select=None, sort=None, search=None, adapter=None, state=None,
                                     mtu=None):
    """ Get all network interfaces from all agents or a list of them.

    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param agents_list: List of agent's IDs.
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param select: Select which fields to return (separated by comma)
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :param adapter: Filters by adapter
    :param state: Filters by state
    :param mtu: Filters by mtu
    :return: AllItemsResponseSyscollectorInterface
    """
    filters = {
        'adapter': adapter,
        'type': request.query.get('type', None),
        'state': state,
        'mtu': mtu
    }
    # Add nested fields to kwargs filters
    nested = ['tx.packets', 'rx.packets', 'tx.bytes', 'rx.bytes', 'tx.errors', 'rx.errors', 'tx.dropped', 'rx.dropped']
    for field in nested:
        filters[field] = request.query.get(field, None)

    f_kwargs = {'agent_list': agents_list,
                'offset': offset,
                'limit': limit,
                'select': select,
                'sort': parse_api_param(sort, 'sort'),
                'search': parse_api_param(search, 'search'),
                'filters': filters,
                'element_type': 'netiface'
                }

    dapi = DistributedAPI(f=syscollector.get_item_agent,
                          f_kwargs=remove_nones_to_dict(f_kwargs),
                          request_type='distributed_master',
                          is_async=False,
                          wait_for_complete=wait_for_complete,
                          logger=logger,
                          broadcasting=agents_list == '*',
                          rbac_permissions=request['token_info']['rbac_policies']
                          )
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data, status=200, dumps=prettify if pretty else dumps)
Example #12
0
async def put_file(request,
                   body,
                   filename=None,
                   overwrite=False,
                   pretty=False,
                   wait_for_complete=False):
    """Upload a rule file.
    
    Parameters
    ----------
    body : dict
        Body request with the file content to be uploaded.
    filename : str, optional
        Name of the file. Default `None`
    overwrite : bool, optional
        If set to false, an exception will be raised when updating contents of an already existing file. Default `False`
    pretty : bool, optional
        Show results in human-readable format. Default `False`
    wait_for_complete : bool, optional
        Disable timeout response. Default `False`

    Returns
    -------
    web.json_response
    """
    # Parse body to utf-8
    Body.validate_content_type(
        request, expected_content_type='application/octet-stream')
    parsed_body = Body.decode_body(body,
                                   unicode_error=1911,
                                   attribute_error=1912)

    f_kwargs = {
        'filename': filename,
        'overwrite': overwrite,
        'content': parsed_body
    }

    dapi = DistributedAPI(
        f=rule_framework.upload_rule_file,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
Example #13
0
def decode_token(token):
    """Decode a jwt formatted token and add processed policies. Raise an Unauthorized exception in case validation fails.

    Parameters
    ----------
    token : str
        JWT formatted token

    Returns
    -------
    Dict payload ot the token
    """
    try:
        # Decode JWT token with local secret
        payload = jwt.decode(token,
                             generate_secret(),
                             algorithms=[JWT_ALGORITHM],
                             audience='Wazuh API REST')

        # Check token and add processed policies in the Master node
        dapi = DistributedAPI(f=check_token,
                              f_kwargs={
                                  'username': payload['sub'],
                                  'roles': payload['rbac_roles'],
                                  'token_nbf_time': payload['nbf'],
                                  'run_as': payload['run_as']
                              },
                              request_type='local_master',
                              is_async=False,
                              wait_for_complete=True,
                              logger=logging.getLogger('wazuh'))
        data = raise_if_exc(
            pool.submit(asyncio.run,
                        dapi.distribute_function()).result()).to_dict()

        if not data['result']['valid']:
            raise Unauthorized
        payload['rbac_policies'] = data['result']['policies']
        payload['rbac_policies']['rbac_mode'] = payload.pop('rbac_mode')

        # Detect local changes
        dapi = DistributedAPI(f=get_security_conf,
                              request_type='local_master',
                              is_async=False,
                              wait_for_complete=True,
                              logger=logging.getLogger('wazuh'))
        result = raise_if_exc(
            pool.submit(asyncio.run, dapi.distribute_function()).result())

        current_rbac_mode = result['rbac_mode']
        current_expiration_time = result['auth_token_exp_timeout']
        if payload['rbac_policies']['rbac_mode'] != current_rbac_mode \
                or (payload['exp'] - payload['nbf']) != current_expiration_time:
            raise Unauthorized

        return payload
    except JWTError as e:
        raise Unauthorized from e
Example #14
0
async def get_attack(request,
                     pretty=False,
                     wait_for_complete=False,
                     offset=0,
                     limit=database_limit,
                     phase_name=None,
                     platform_name=None,
                     q=None,
                     search=None,
                     select=None,
                     sort=None):
    """Get information from MITRE ATT&CK database

    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param phase_name: Filters by phase
    :param platform_name: Filters by platform
    :param search: Search if the string is contained in the db
    :param offset: First item to return
    :param limit: Maximum number of items to return
    :param sort: Sort the items. Format: {'fields': ['field1', 'field2'], 'order': 'asc|desc'}
    :param select: Select fields to return. Format: {"fields":["field1","field2"]}.
    :param q: Query to filter by
    :return: Data
    """
    f_kwargs = {
        'id_': request.query.get('id', None),
        'phase_name': phase_name,
        'platform_name': platform_name,
        'select': select,
        'search': parse_api_param(search, 'search'),
        'offset': offset,
        'limit': limit,
        'sort': parse_api_param(sort, 'sort'),
        'q': q
    }

    dapi = DistributedAPI(
        f=mitre.get_attack,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
Example #15
0
async def get_agent_fields(request,
                           pretty=False,
                           wait_for_complete=False,
                           fields=None,
                           offset=0,
                           limit=database_limit,
                           select=None,
                           sort=None,
                           search=None,
                           q=None):
    """Get distinct fields in agents.

    Returns all the different combinations that agents have for the selected fields. It also indicates the total number
    of agents that have each combination.

    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param fields: List of fields affecting the operation.
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param select: Select which fields to return (separated by comma)
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :param q: Query to filter results by. For example q="status=active"
    :return: ListMetadata
    """
    f_kwargs = {
        'offset': offset,
        'limit': limit,
        'select': select,
        'sort': parse_api_param(sort, 'sort'),
        'search': parse_api_param(search, 'search'),
        'fields': fields,
        'q': q
    }

    dapi = DistributedAPI(
        f=agent.get_distinct_agents,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
Example #16
0
async def get_configuration(request,
                            pretty=False,
                            wait_for_complete=False,
                            section=None,
                            field=None,
                            raw: bool = False):
    """Get manager's or local_node's configuration (ossec.conf)

    Parameters
    ----------
    pretty : bool, optional
        Show results in human-readable format. It only works when `raw` is False (JSON format). Default `True`
    wait_for_complete : bool, optional
        Disable response timeout or not. Default `False`
    section : str
        Indicates the wazuh configuration section
    field : str
        Indicates a section child, e.g, fields for rule section are include, decoder_dir, etc.
    raw : bool, optional
        Whether to return the file content in raw or JSON format. Default `True`

    Returns
    -------
    web.json_response or ConnexionResponse
        Depending on the `raw` parameter, it will return an object or other:
            raw=True            -> ConnexionResponse (application/xml)
            raw=False (default) -> web.json_response (application/json)
        If any exception was raised, it will return a web.json_response with details.
    """
    f_kwargs = {'section': section, 'field': field, 'raw': raw}

    dapi = DistributedAPI(
        f=manager.read_ossec_conf,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_any',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    if isinstance(data, AffectedItemsWazuhResult):
        response = web.json_response(data=data,
                                     status=200,
                                     dumps=prettify if pretty else dumps)
    else:
        response = ConnexionResponse(body=data["message"],
                                     mimetype='application/xml',
                                     content_type='application/xml')
    return response
Example #17
0
def generate_token(user_id=None, data=None, run_as=False):
    """Generate an encoded jwt token. This method should be called once a user is properly logged on.

    Parameters
    ----------
    user_id : str
        Unique username
    data : dict
        Roles permissions for the user
    run_as : bool
        Indicate if the user has logged in with run_as or not

    Returns
    -------
    JWT encode token
    """
    dapi = DistributedAPI(f=get_security_conf,
                          request_type='local_master',
                          is_async=False,
                          wait_for_complete=False,
                          logger=logging.getLogger('wazuh-api'))
    result = raise_if_exc(
        pool.submit(asyncio.run, dapi.distribute_function()).result()).dikt
    timestamp = int(time())

    payload = {
        "iss": JWT_ISSUER,
        "aud": "Wazuh API REST",
        "nbf": int(timestamp),
        "exp": int(timestamp + result['auth_token_exp_timeout']),
        "sub": str(user_id),
        "run_as": run_as,
        "rbac_roles": data['roles'],
        "rbac_mode": result['rbac_mode']
    }

    return jwt.encode(payload, generate_keypair()[0], algorithm=JWT_ALGORITHM)
Example #18
0
async def get_network_address_info(request, pretty=False, wait_for_complete=False, agents_list='*', offset=0,
                                   limit=None, select=None, sort=None, search=None, iface_name=None, proto=None,
                                   address=None, broadcast=None, netmask=None):
    """ Get the IPv4 and IPv6 addresses associated to all network interfaces

    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param agents_list: List of agent's IDs.
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param select: Select which fields to return (separated by comma)
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :param iface_name: Filters by interface name
    :param proto: Filters by IP protocol
    :param address: IP address associated with the network interface
    :param broadcast: Filters by broadcast direction
    :param netmask: Filters by netmask
    :return: AllItemsResponseSyscollectorNetwork
    """
    f_kwargs = {'agent_list': agents_list,
                'offset': offset,
                'limit': limit,
                'select': select,
                'sort': parse_api_param(sort, 'sort'),
                'search': parse_api_param(search, 'search'),
                'filters': {
                    'iface_name': iface_name,
                    'proto': proto,
                    'address': address,
                    'broadcast': broadcast,
                    'netmask': netmask
                },
                'element_type': 'netaddr'
                }

    dapi = DistributedAPI(f=syscollector.get_item_agent,
                          f_kwargs=remove_nones_to_dict(f_kwargs),
                          request_type='distributed_master',
                          is_async=False,
                          wait_for_complete=wait_for_complete,
                          logger=logger,
                          broadcasting=agents_list == '*',
                          rbac_permissions=request['token_info']['rbac_policies']
                          )
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data, status=200, dumps=prettify if pretty else dumps)
Example #19
0
async def security_revoke_tokens():
    """Revokes all tokens on all nodes after a change in security configuration."""
    nodes = await get_system_nodes()
    if isinstance(nodes, Exception):
        nodes = None

    dapi = DistributedAPI(f=revoke_tokens,
                          request_type='distributed_master'
                          if nodes is not None else 'local_any',
                          is_async=False,
                          wait_for_complete=True,
                          broadcasting=nodes is not None,
                          logger=logger,
                          nodes=nodes)
    raise_if_exc(await dapi.distribute_function())
Example #20
0
def generate_token(user_id=None, rbac_policies=None):
    """Generate an encoded jwt token. This method should be called once a user is properly logged on.

    Parameters
    ----------
    user_id : str
        Unique username
    rbac_policies : dict
        Permissions for the user

    Returns
    -------
    JWT encode token
    """
    dapi = DistributedAPI(f=get_security_conf,
                          request_type='local_master',
                          is_async=False,
                          wait_for_complete=True,
                          logger=logging.getLogger('wazuh'))
    result = raise_if_exc(
        pool.submit(asyncio.run, dapi.distribute_function()).result()).dikt
    timestamp = int(time())
    roles = rbac_policies['roles']
    rbac_policies = rbac_policies['policies']
    rbac_policies['rbac_mode'] = result['rbac_mode']
    payload = {
        "iss": JWT_ISSUER,
        "aud": "Wazuh API REST",
        "nbf": int(timestamp),
        "exp": int(timestamp + result['auth_token_exp_timeout']),
        "sub": str(user_id),
        "rbac_roles": roles,
        "rbac_policies": rbac_policies
    }

    return jwt.encode(payload, generate_secret(), algorithm=JWT_ALGORITHM)
Example #21
0
async def get_packages_info(request, pretty=False, wait_for_complete=False, agents_list='*', offset=0, limit=None,
                            select=None,
                            sort=None, search=None, vendor=None, name=None, architecture=None, version=None):
    """ Get packages info from all agents or a list of them.

    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param agents_list: List of agent's IDs.
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param select: Select which fields to return (separated by comma)
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :param vendor: Filters by vendor
    :param name: Filters by name
    :param architecture: Filters by architecture
    :param version: Filters by format
    :return: AllItemsResponseSyscollectorPackages
    """
    f_kwargs = {'agent_list': agents_list,
                'offset': offset,
                'limit': limit,
                'select': select,
                'sort': parse_api_param(sort, 'sort'),
                'search': parse_api_param(search, 'search'),
                'filters': {
                    'vendor': vendor,
                    'name': name,
                    'architecture': architecture,
                    'format': request.query.get('format', None),
                    'version': version
                },
                'element_type': 'packages'
                }

    dapi = DistributedAPI(f=syscollector.get_item_agent,
                          f_kwargs=remove_nones_to_dict(f_kwargs),
                          request_type='distributed_master',
                          is_async=False,
                          wait_for_complete=wait_for_complete,
                          logger=logger,
                          broadcasting=agents_list == '*',
                          rbac_permissions=request['token_info']['rbac_policies']
                          )
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data, status=200, dumps=prettify if pretty else dumps)
Example #22
0
async def get_decoders(request, decoder_names: list = None, pretty: bool = False, wait_for_complete: bool = False,
                       offset: int = 0, limit: int = None, select: list = None, sort: str = None, search: str = None,
                       q: str = None, filename: str = None, relative_dirname: str = None, status: str = None):
    """Get all decoders

    Returns information about all decoders included in ossec.conf. This information include decoder's route,
    decoder's name, decoder's file among others

    :param decoder_names: Filters by decoder name.
    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param select: List of selected fields to return
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :param q: Query to filter results by. For example q="status=active"
    :param filename: List of filenames to filter by.
    :param relative_dirname: Filters by relative dirname.
    :param status: Filters by list status.
    :return: Data object
    """
    f_kwargs = {'names': decoder_names,
                'offset': offset,
                'limit': limit,
                'select': select,
                'sort_by': parse_api_param(sort, 'sort')['fields'] if sort is not None else ['filename', 'position'],
                'sort_ascending': True if sort is None or parse_api_param(sort, 'sort')['order'] == 'asc' else False,
                'search_text': parse_api_param(search, 'search')['value'] if search is not None else None,
                'complementary_search': parse_api_param(search, 'search')['negation'] if search is not None else None,
                'q': q,
                'filename': filename,
                'status': status,
                'relative_dirname': relative_dirname}

    dapi = DistributedAPI(f=decoder_framework.get_decoders,
                          f_kwargs=remove_nones_to_dict(f_kwargs),
                          request_type='local_any',
                          is_async=False,
                          wait_for_complete=wait_for_complete,
                          logger=logger,
                          rbac_permissions=request['token_info']['rbac_policies']
                          )
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data, status=200, dumps=prettify if pretty else dumps)
Example #23
0
async def get_file(request,
                   pretty: bool = False,
                   wait_for_complete: bool = False,
                   filename: str = None,
                   raw: bool = False):
    """Get rule file content.

    Parameters
    ----------
    pretty : bool, optional
        Show results in human-readable format. It only works when `raw` is False (JSON format). Default `True`
    wait_for_complete : bool, optional
        Disable response timeout or not. Default `False`
    filename : str
        Filename to download.
    raw : bool, optional
        Whether to return the file content in raw or JSON format. Default `False`

    Returns
    -------
    web.json_response or ConnexionResponse
        Depending on the `raw` parameter, it will return an object or other:
            raw=True            -> ConnexionResponse (application/xml)
            raw=False (default) -> web.json_response (application/json)
        If any exception was raised, it will return a web.json_response with details.
    """
    f_kwargs = {'filename': filename, 'raw': raw}

    dapi = DistributedAPI(
        f=rule_framework.get_rule_file,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())
    if isinstance(data, AffectedItemsWazuhResult):
        response = web.json_response(data=data,
                                     status=200,
                                     dumps=prettify if pretty else dumps)
    else:
        response = ConnexionResponse(body=data["message"],
                                     mimetype='application/xml',
                                     content_type='application/xml')

    return response
Example #24
0
async def get_file(request,
                   pretty: bool = False,
                   wait_for_complete: bool = False,
                   filename: str = None,
                   raw: bool = False):
    """"Get content of one CDB list file, in raw or dict format.

    Parameters
    ----------
    pretty : bool
        Show results in human-readable format.
    wait_for_complete : bool
        Disable timeout response.
    filename : str
        Name of filename to get data from.
    raw : bool, optional
        Respond in raw format.

    Returns
    -------
    web.json_response, ConnexionResponse
        Depending on the `raw` parameter, it will return an object or other:
            raw=True            -> ConnexionResponse (text/plain)
            raw=False (default) -> web.json_response (application/json)
        If any exception was raised, it will return a web.json_response with details.
    """
    f_kwargs = {'filename': filename, 'raw': raw}

    dapi = DistributedAPI(
        f=cdb_list.get_list_file,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())
    if isinstance(data, AffectedItemsWazuhResult):
        response = web.json_response(data=data,
                                     status=200,
                                     dumps=prettify if pretty else dumps)
    else:
        response = ConnexionResponse(body=data["message"],
                                     mimetype='text/plain',
                                     content_type='text/plain')

    return response
Example #25
0
async def get_policies(request, policy_ids: list = None, pretty: bool = False, wait_for_complete: bool = False,
                       offset: int = 0, limit: int = None, search: str = None, select: str = None, sort: str = None):
    """Returns information from all system policies.

    Parameters
    ----------
    request : connexion.request
    policy_ids : list, optional
        List of policies
    pretty : bool, optional
        Show results in human-readable format
    wait_for_complete : bool, optional
        Disable timeout response
    offset : int, optional
        First item to return
    limit : int, optional
        Maximum number of items to return
    search : str, optional
        Looks for elements with the specified string
    select : str
        Select which fields to return (separated by comma)
    sort : str, optional
        Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
        ascending or descending order

    Returns
    -------
    Policies information
    """
    f_kwargs = {'policy_ids': policy_ids, 'offset': offset, 'limit': limit, 'select': select,
                'sort_by': parse_api_param(sort, 'sort')['fields'] if sort is not None else ['id'],
                'sort_ascending': True if sort is None or parse_api_param(sort, 'sort')['order'] == 'asc' else False,
                'search_text': parse_api_param(search, 'search')['value'] if search is not None else None,
                'complementary_search': parse_api_param(search, 'search')['negation'] if search is not None else None
                }

    dapi = DistributedAPI(f=security.get_policies,
                          f_kwargs=remove_nones_to_dict(f_kwargs),
                          request_type='local_master',
                          is_async=False,
                          wait_for_complete=wait_for_complete,
                          logger=logger,
                          rbac_permissions=request['token_info']['rbac_policies']
                          )
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data, status=200, dumps=prettify if pretty else dumps)
async def update_policy(request,
                        policy_id: int,
                        pretty: bool = False,
                        wait_for_complete: bool = False):
    """Update the information of one specified policy.

    Parameters
    ----------
    request : connexion.request
    policy_id : int
        Specific policy id in the system to be updated
    pretty : bool, optional
        Show results in human-readable format
    wait_for_complete : bool, optional
        Disable timeout response

    Returns
    -------
    Policy information updated
    """
    # get body parameters
    policy_added_model = dict()
    try:
        policy_added_model = await request.json()
    except JSONDecodeError as e:
        raise_if_exc(APIError(code=2005, details=e.msg))

    f_kwargs = {
        'policy_id': policy_id,
        'name': policy_added_model.get('name', None),
        'policy': policy_added_model.get('policy', None)
    }

    dapi = DistributedAPI(
        f=security.update_policy,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
Example #27
0
async def get_list_group(request,
                         pretty=False,
                         wait_for_complete=False,
                         groups_list=None,
                         offset=0,
                         limit=None,
                         sort=None,
                         search=None):
    """Get groups.

    Returns a list containing basic information about each agent group such as number of agents belonging to the group
    and the checksums of the configuration and shared files.

    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    :param groups_list: Array of group's IDs.
    :param offset: First element to return in the collection
    :param limit: Maximum number of elements to return
    :param sort: Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in
    ascending or descending order.
    :param search: Looks for elements with the specified string
    :return: AllItemsResponseGroups
    """
    hash_ = request.query.get(
        'hash', 'md5')  # Select algorithm to generate the returned checksums.
    f_kwargs = {
        'offset': offset,
        'limit': limit,
        'group_list': groups_list,
        'sort': parse_api_param(sort, 'sort'),
        'search': parse_api_param(search, 'search'),
        'hash_algorithm': hash_
    }
    dapi = DistributedAPI(
        f=agent.get_agent_groups,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
Example #28
0
async def put_files_node(request,
                         body,
                         node_id,
                         path,
                         overwrite=False,
                         pretty=False,
                         wait_for_complete=False):
    """Upload file contents in a specified cluster node.

    :param body: Body request with the content of the file to be uploaded
    :param node_id: Cluster node name
    :param path: Filepath to upload the new file
    :param overwrite: If set to false, an exception will be raised when uploading an already existing filename.
    :param pretty: Show results in human-readable format
    :param wait_for_complete: Disable timeout response
    """

    # parse body to utf-8
    Body.validate_content_type(
        request, expected_content_type='application/octet-stream')
    parsed_body = Body.decode_body(body,
                                   unicode_error=1911,
                                   attribute_error=1912)

    f_kwargs = {
        'node_id': node_id,
        'path': path,
        'overwrite': overwrite,
        'content': parsed_body
    }

    nodes = raise_if_exc(await get_system_nodes())
    dapi = DistributedAPI(
        f=manager.upload_file,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='distributed_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'],
        nodes=nodes)
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
async def set_role_policy(request,
                          role_id,
                          policy_ids,
                          position=None,
                          pretty=False,
                          wait_for_complete=False):
    """Add a list of policies to one specified role.

    Parameters
    ----------
    role_id : int
        Role ID
    policy_ids : list of int
        List of policy IDs
    position : int
        Position where the new role will be inserted
    pretty : bool
        Show results in human-readable format
    wait_for_complete : bool
        Disable timeout response

    Returns
    -------
    dict
        Role information
    """
    f_kwargs = {
        'role_id': role_id,
        'policy_ids': policy_ids,
        'position': position
    }

    dapi = DistributedAPI(
        f=security.set_role_policy,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)
async def set_user_role(request,
                        username: str,
                        role_ids: list,
                        position: int = None,
                        pretty: bool = False,
                        wait_for_complete: bool = False):
    """Add a list of roles to one specified user.

    Parameters
    ----------
    request : connexion.request
    username : str
        User's username
    role_ids : list of int
        List of role ids
    position : int, optional
        Position where the new role will be inserted
    pretty : bool, optional
        Show results in human-readable format
    wait_for_complete : bool, optional
        Disable timeout response

    Returns
    -------
    Dict
        User-Role information
    """
    f_kwargs = {
        'user_id': username,
        'role_ids': role_ids,
        'position': position
    }
    dapi = DistributedAPI(
        f=security.set_user_role,
        f_kwargs=remove_nones_to_dict(f_kwargs),
        request_type='local_master',
        is_async=False,
        wait_for_complete=wait_for_complete,
        logger=logger,
        rbac_permissions=request['token_info']['rbac_policies'])
    data = raise_if_exc(await dapi.distribute_function())

    return web.json_response(data=data,
                             status=200,
                             dumps=prettify if pretty else dumps)