Пример #1
0
def test_create_wazuh_socket_message(origin, command, parameters):
    """Test create_wazuh_socket_message function."""
    response_message = create_wazuh_socket_message(origin, command, parameters)
    assert response_message['version'] == SOCKET_COMMUNICATION_PROTOCOL_VERSION
    assert response_message.get('origin') == origin
    assert response_message.get('command') == command
    assert response_message.get('parameters') == parameters
Пример #2
0
def send_logtest_msg(command: str = None, parameters: dict = None):
    """Connect and send a message to the logtest socket.

    Parameters
    ----------
    command: str
        Command to send to the logtest socket.
    parameters : dict
        Dict of parameters that will be sent to the logtest socket.

    Returns
    -------
    dict
        Response from the logtest socket.
    """
    full_message = create_wazuh_socket_message(origin={
        'name': 'Logtest',
        'module': 'api/framework'
    },
                                               command=command,
                                               parameters=parameters)
    logtest_socket = WazuhSocketJSON(LOGTEST_SOCKET)
    logtest_socket.send(full_message)
    response = logtest_socket.receive(raw=True)
    logtest_socket.close()

    return response
Пример #3
0
def send_logtest_msg(command: str = None, parameters: dict = None):
    """Connect and send a message to the logtest socket.

    Parameters
    ----------
    command: str
        Command to send to the logtest socket.
    parameters : dict
        Dict of parameters that will be sent to the logtest socket.

    Returns
    -------
    dict
        Response from the logtest socket.
    """
    full_message = create_wazuh_socket_message(origin={
        'name': 'Logtest',
        'module': origin_module.get()
    },
                                               command=command,
                                               parameters=parameters)
    logtest_socket = WazuhSocketJSON(LOGTEST_SOCKET)
    logtest_socket.send(full_message)
    response = logtest_socket.receive(raw=True)
    logtest_socket.close()
    try:
        response['data']['output']['timestamp'] = datetime.strptime(
            response['data']['output']['timestamp'],
            "%Y-%m-%dT%H:%M:%S.%f+0000").strftime(decimals_date_format)
    except KeyError:
        pass

    return response
Пример #4
0
def manager_restart() -> WazuhResult:
    """Restart Wazuh manager.

    Send JSON message with the 'restart-wazuh' command to common.EXECQ socket.

    Raises
    ------
    WazuhInternalError(1901)
        If the socket path doesn't exist.
    WazuhInternalError(1902)
        If there is a socket connection error.
    WazuhInternalError(1014)
        If there is a socket communication error.

    Returns
    -------
    WazuhResult
        Confirmation message.
    """
    lock_file = open(execq_lockfile, 'a+')
    fcntl.lockf(lock_file, fcntl.LOCK_EX)
    try:
        # execq socket path
        socket_path = common.EXECQ
        # json msg for restarting Wazuh manager
        msg = json.dumps(
            create_wazuh_socket_message(
                origin={'module': common.origin_module.get()},
                command=common.RESTART_WAZUH_COMMAND,
                parameters={
                    'extra_args': [],
                    'alert': {}
                }))
        # initialize socket
        if exists(socket_path):
            try:
                conn = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
                conn.connect(socket_path)
            except socket.error:
                raise WazuhInternalError(1902)
        else:
            raise WazuhInternalError(1901)

        try:
            conn.send(msg.encode())
            conn.close()
        except socket.error as e:
            raise WazuhInternalError(1014, extra_message=str(e))
    finally:
        fcntl.lockf(lock_file, fcntl.LOCK_UN)
        lock_file.close()
        read_config.cache_clear()

    return WazuhResult({'message': 'Restart request sent'})
Пример #5
0
def create_json_message(command: str = '',
                        arguments: list = None,
                        alert: dict = None) -> str:
    """Create the JSON message that will be sent. Function used when Wazuh agent version is >= 4.2.0.

    Parameters
    ----------
    command : str
        Command running in the agent. If this value starts by !, then it refers to a script name instead of a command
        name.
    arguments : list
        Command arguments.
    alert : dict
        Alert data that will be sent with the AR command.

    Raises
    ------
    WazuhError(1650)
        If the command is not specified.

    Returns
    -------
    str
        Message that will be sent to the socket.
    """
    if not command:
        raise WazuhError(1650)

    cluster_enabled = not read_cluster_config()['disabled']
    node_name = get_node().get('node') if cluster_enabled else None

    msg_queue = json.dumps(
        create_wazuh_socket_message(origin={
            'name': node_name,
            'module': common.origin_module.get()
        },
                                    command=command,
                                    parameters={
                                        'extra_args':
                                        arguments if arguments else [],
                                        'alert':
                                        alert if alert else {}
                                    }))

    return msg_queue
Пример #6
0
def send_logtest_msg_mock(**kwargs):
    socket_response = create_wazuh_socket_message(
        command=kwargs['command'], parameters=kwargs['parameters'])
    socket_response['error'] = 0
    return socket_response
Пример #7
0
def validate_ossec_conf():
    """Check if Wazuh configuration is OK.

    Raises
    ------
    WazuhInternalError(1014)
        If there is a socket communication error.
    WazuhInternalError(1013)
        If it is unable to connect to socket.
    WazuhInternalError(1901)
        If 'execq' socket cannot be created.
    WazuhInternalError(1904)
        If there is bad data received from 'execq'.

    Returns
    -------
    str
        Status of the configuration.
    """
    lock_file = open(execq_lockfile, 'a+')
    fcntl.lockf(lock_file, fcntl.LOCK_EX)

    try:
        # Sockets path
        api_socket_relative_path = join('queue', 'alerts', 'execa')
        api_socket_path = join(common.wazuh_path, api_socket_relative_path)
        execq_socket_path = common.EXECQ
        # Message for checking Wazuh configuration
        execq_msg = json.dumps(
            create_wazuh_socket_message(origin={'module': 'api/framework'},
                                        command=common.CHECK_CONFIG_COMMAND,
                                        parameters={
                                            "extra_args": [],
                                            "alert": {}
                                        }))

        # Remove api_socket if exists
        try:
            remove(api_socket_path)
        except OSError as e:
            if exists(api_socket_path):
                extra_msg = f'Socket: WAZUH_PATH/{api_socket_relative_path}. Error: {e.strerror}'
                raise WazuhInternalError(1014, extra_message=extra_msg)

        # up API socket
        try:
            api_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
            api_socket.bind(api_socket_path)
            # Timeout
            api_socket.settimeout(10)
        except OSError as e:
            extra_msg = f'Socket: WAZUH_PATH/{api_socket_relative_path}. Error: {e.strerror}'
            raise WazuhInternalError(1013, extra_message=extra_msg)

        # Connect to execq socket
        if exists(execq_socket_path):
            try:
                execq_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
                execq_socket.connect(execq_socket_path)
            except OSError as e:
                extra_msg = f'Socket: WAZUH_PATH/queue/alerts/execq. Error {e.strerror}'
                raise WazuhInternalError(1013, extra_message=extra_msg)
        else:
            raise WazuhInternalError(1901)

        # Send msg to execq socket
        try:
            execq_socket.send(execq_msg.encode())
            execq_socket.close()
        except socket.error as e:
            raise WazuhInternalError(1014, extra_message=str(e))
        finally:
            execq_socket.close()

        # If api_socket receives a message, configuration is OK
        try:
            buffer = bytearray()
            # Receive data
            datagram = api_socket.recv(4096)
            buffer.extend(datagram)
        except socket.timeout as e:
            raise WazuhInternalError(1014, extra_message=str(e))
        finally:
            api_socket.close()
            # Remove api_socket
            if exists(api_socket_path):
                remove(api_socket_path)

        try:
            response = parse_execd_output(buffer.decode('utf-8').rstrip('\0'))
        except (KeyError, json.decoder.JSONDecodeError) as e:
            raise WazuhInternalError(1904, extra_message=str(e))
    finally:
        fcntl.lockf(lock_file, fcntl.LOCK_UN)
        lock_file.close()

    return response
Пример #8
0
class WazuhQueue:
    """
    WazuhQueue Object.
    """

    # Messages
    HC_SK_RESTART = "syscheck restart"  # syscheck restart
    HC_FORCE_RECONNECT = "force_reconnect"  # force reconnect command
    RESTART_AGENTS = "restart-ossec0"  # Agents, not manager (000)
    RESTART_AGENTS_JSON = json.dumps(create_wazuh_socket_message(origin={'module': origin_module.get()},
                                                                 command="restart-wazuh0",
                                                                 parameters={"extra_args": [],
                                                                             "alert": {}}))  # Agents, not manager (000)

    # Types
    AR_TYPE = "ar-message"

    # Sizes
    OS_MAXSTR = 6144  # OS_SIZE_6144
    MAX_MSG_SIZE = OS_MAXSTR + 256

    def __init__(self, path):
        self.path = path
        self._connect()

    def _connect(self):
        try:
            self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
            self.socket.connect(self.path)
            length_send_buffer = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
            if length_send_buffer < WazuhQueue.MAX_MSG_SIZE:
                self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, WazuhQueue.MAX_MSG_SIZE)
        except Exception:
            raise WazuhInternalError(1010, self.path)

    def _send(self, msg):
        try:
            sent = self.socket.send(msg)

            if sent == 0:
                raise WazuhInternalError(1011, self.path)
        except Exception:
            raise WazuhInternalError(1011, self.path)

    def close(self):
        self.socket.close()

    def send_msg_to_agent(self, msg: str = '', agent_id: str = '', msg_type: str = '') -> str:
        """Send message to agent.

        Active-response
          Agents: /var/ossec/queue/alerts/ar
            - Existing command:
              - (msg_to_agent) [] NNS 001 restart-ossec0 arg1 arg2 arg3
              - (msg_to_agent) [] ANN (null) restart-ossec0 arg1 arg2 arg3
            - Custom command:
              - (msg_to_agent) [] NNS 001 !test.sh arg1 arg2 arg3
              - (msg_to_agent) [] ANN (null) !test.sh arg1 arg2 arg3
          Agents with version >= 4.2.0:
            - Existing and custom commands:
              - (msg_to_agent) [] NNS 001 {JSON message}
          Manager: /var/ossec/queue/alerts/execq
            - Existing or custom command:
              - {JSON message}

        Parameters
        ----------
        msg : str
            Message to be sent to the agent.
        agent_id : str
            ID of the agent we want to send the message to.
        msg_type : str
            Message type.

        Raises
        ------
        WazuhInternalError(1012)
            If the message was invalid to queue.
        WazuhError(1014)
            If there was an error communicating with socket.

        Returns
        -------
        str
            Message confirming the message has been sent.
        """
        # Variables to check if msg is a non active-response message or a restart message
        msg_is_no_ar = msg in [WazuhQueue.HC_SK_RESTART, WazuhQueue.HC_FORCE_RECONNECT]
        msg_is_restart = msg in [WazuhQueue.RESTART_AGENTS, WazuhQueue.RESTART_AGENTS_JSON]

        # Create flag and string used to specify the agent ID
        if agent_id:
            flag = 'NNS' if not msg_is_no_ar else 'N!S'
            str_agent_id = agent_id
        else:
            flag = 'ANN' if not msg_is_no_ar else 'A!N'
            str_agent_id = '(null)'

        # AR
        if msg_type == WazuhQueue.AR_TYPE:
            socket_msg = create_wazuh_queue_socket_msg(flag, str_agent_id, msg) if agent_id != '000' else msg
            # Return message
            ret_msg = "Command sent."

        # NO-AR: Restart syscheck and reconnect
        # Restart agents
        else:
            # If msg is not a non active-response command and not a restart command, raises WazuhInternalError
            if not msg_is_no_ar and not msg_is_restart:
                raise WazuhInternalError(1012, msg)
            socket_msg = create_wazuh_queue_socket_msg(flag, str_agent_id, msg, is_restart=msg_is_restart)
            # Return message
            if msg == WazuhQueue.HC_SK_RESTART:
                ret_msg = "Restarting Syscheck on agent" if agent_id else "Restarting Syscheck on all agents"
            elif msg == WazuhQueue.HC_FORCE_RECONNECT:
                ret_msg = "Reconnecting agent" if agent_id else "Reconnecting all agents"
            else:  # msg == WazuhQueue.RESTART_AGENTS or msg == WazuhQueue.RESTART_AGENTS_JSON
                ret_msg = "Restarting agent" if agent_id else "Restarting all agents"

        try:
            # Send message
            self._send(socket_msg.encode())
        except:
            raise WazuhError(1014, extra_message=f": WazuhQueue socket with path {self.path}")

        return ret_msg
Пример #9
0
def core_upgrade_agents(agents_chunk,
                        command='upgrade_result',
                        wpk_repo=None,
                        version=None,
                        force=False,
                        use_http=False,
                        file_path=None,
                        installer=None,
                        get_result=False):
    """Send command to upgrade module / task module

    Parameters
    ----------
    agents_chunk : list
        List of agents ID's.
    command : str
        Command sent to the socket.
    wpk_repo : str
        URL for WPK download.
    version : str
        Version to upgrade to.
    force : bool
        force the update even if it is a downgrade.
    use_http : bool
        False for HTTPS protocol, True for HTTP protocol.
    file_path : str
        Path to the installation file.
    installer : str
        Selected installer.
    get_result : bool
        Get the result of an update (True -> Task module), Create new upgrade task (False -> Upgrade module)

    Returns
    -------
    Message received from the socket (Task module or Upgrade module)
    """
    msg = create_wazuh_socket_message(
        origin={'module': 'api'},
        command=command,
        parameters={
            'agents': agents_chunk,
            'version': version,
            'force_upgrade': force,
            'use_http': use_http,
            'wpk_repo': wpk_repo,
            'file_path': file_path,
            'installer': installer
        } if not get_result else {'agents': agents_chunk})

    msg['parameters'] = {
        k: v
        for k, v in msg['parameters'].items() if v is not None
    }

    # Send upgrading command
    s = WazuhSocket(common.UPGRADE_SOCKET)
    s.send(dumps(msg).encode())

    # Receive upgrade information from socket
    data = loads(s.receive().decode())
    s.close()
    [
        agent_info.update(
            (k,
             datetime.strptime(v, "%Y/%m/%d %H:%M:%S").strftime(date_format))
            for k, v in agent_info.items()
            if k in {'create_time', 'update_time'})
        for agent_info in data['data']
    ]

    return data
Пример #10
0
class WazuhQueue:
    """
    WazuhQueue Object.
    """

    # Messages
    HC_SK_RESTART = "syscheck restart"  # syscheck restart
    RESTART_AGENTS = "restart-ossec0"  # Agents, not manager (000)
    RESTART_AGENTS_JSON = json.dumps(create_wazuh_socket_message(origin={'module': 'api/framework'},
                                                                 command="restart-wazuh0",
                                                                 parameters={"extra_args": [],
                                                                             "alert": {}}))  # Agents, not manager (000)

    # Types
    AR_TYPE = "ar-message"

    # Sizes
    OS_MAXSTR = 6144  # OS_SIZE_6144
    MAX_MSG_SIZE = OS_MAXSTR + 256

    def __init__(self, path):
        self.path = path
        self._connect()

    def _connect(self):
        try:
            self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
            self.socket.connect(self.path)
            length_send_buffer = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
            if length_send_buffer < WazuhQueue.MAX_MSG_SIZE:
                self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, WazuhQueue.MAX_MSG_SIZE)
        except Exception:
            raise WazuhInternalError(1010, self.path)

    def _send(self, msg):
        try:
            sent = self.socket.send(msg)

            if sent == 0:
                raise WazuhInternalError(1011, self.path)
        except Exception:
            raise WazuhInternalError(1011, self.path)

    def close(self):
        self.socket.close()

    def send_msg_to_agent(self, msg: Union[str, dict] = '', agent_id: str = '', msg_type: str = '') -> str:
        """Send message to agent.

        Active-response
          Agents: /var/ossec/queue/alerts/ar
            - Existing command:
              - (msg_to_agent) [] NNS 001 restart-ossec0 arg1 arg2 arg3
              - (msg_to_agent) [] ANN (null) restart-ossec0 arg1 arg2 arg3
            - Custom command:
              - (msg_to_agent) [] NNS 001 !test.sh arg1 arg2 arg3
              - (msg_to_agent) [] ANN (null) !test.sh arg1 arg2 arg3
          Agents with version >= 4.2.0:
            - Existing and custom commands:
              - (msg_to_agent) [] NNS 001 {JSON message}
          Manager: /var/ossec/queue/alerts/execq
            - Existing or custom command:
              - {JSON message}

        Parameters
        ----------
        msg : str
            Message to be sent to the agent.
        agent_id : str
            ID of the agent we want to send the message to.
        msg_type : str
            Message type.

        Raises
        ------
        WazuhError(1652)
            If it was unable to run the command.
        WazuhInternalError(1012)
            If the message was invalid to queue.
        WazuhError(1601)
            If it was unable to run the syscheck scan on the agent because it is a non active agent.
        WazuhError(1702)
            If it was unable to restart the agent.

        Returns
        -------
        str
            Message confirming the message has been sent.
        """

        # Build message
        ALL_AGENTS_C = 'A'
        NONE_C = 'N'
        SPECIFIC_AGENT_C = 'S'
        NO_AR_C = '!'

        if agent_id:
            str_all_agents = NONE_C
            str_agent = SPECIFIC_AGENT_C
            str_agent_id = agent_id
        else:
            str_all_agents = ALL_AGENTS_C
            str_agent = NONE_C
            str_agent_id = "(null)"

        # AR
        if msg_type == WazuhQueue.AR_TYPE:

            if agent_id != "000":
                # Example restart 'msg': restart-ossec0 - null (from_the_server) (no_rule_id)
                socket_msg = "{0} {1}{2}{3} {4} {5}".format("(msg_to_agent) []", str_all_agents, NONE_C, str_agent,
                                                            str_agent_id, msg)
            elif agent_id == "000":
                socket_msg = msg

            # Send message
            try:
                self._send(socket_msg.encode())
            except Exception:
                raise WazuhError(1652)

            return "Command sent."

        # Legacy: Restart syscheck, restart agents
        else:
            if msg == WazuhQueue.HC_SK_RESTART:
                socket_msg = "{0} {1}{2}{3} {4} {5}".format("(msg_to_agent) []", str_all_agents, NO_AR_C, str_agent,
                                                            str_agent_id, WazuhQueue.HC_SK_RESTART)
            elif msg == WazuhQueue.RESTART_AGENTS or msg == WazuhQueue.RESTART_AGENTS_JSON:
                socket_msg = "{0} {1}{2}{3} {4} {5} - {6} (from_the_server) (no_rule_id)".format("(msg_to_agent) []",
                                                                                                 str_all_agents, NONE_C,
                                                                                                 str_agent,
                                                                                                 str_agent_id,
                                                                                                 msg, "null")
            else:
                raise WazuhInternalError(1012, msg)

            # Send message
            try:
                self._send(socket_msg.encode())
            except:
                if msg == WazuhQueue.HC_SK_RESTART:
                    if agent_id:
                        raise WazuhError(1601, "on agent")
                    else:
                        raise WazuhError(1601, "on all agents")
                elif msg == WazuhQueue.RESTART_AGENTS:
                    raise WazuhError(1702)

            # Return message
            if msg == WazuhQueue.HC_SK_RESTART:
                return "Restarting Syscheck on agent" if agent_id else "Restarting Syscheck on all agents"
            elif msg == WazuhQueue.RESTART_AGENTS:
                return "Restarting agent" if agent_id else "Restarting all agents"