def test_WazuhSocket_receive(mock_recv, mock_unpack, mock_conn): """Tests WazuhSocket.receive function works""" queue = WazuhSocket('test_path') response = queue.receive() assert isinstance(response, MagicMock) mock_conn.assert_called_once_with('test_path')
def test_WazuhSocket_send(mock_send, mock_conn): """Tests WazuhSocket.send function works""" queue = WazuhSocket('test_path') response = queue.send(b"\x00\x01") assert isinstance(response, MagicMock) mock_conn.assert_called_once_with('test_path')
def test_WazuhSocket_receive_ko(mock_recv, mock_conn): """Tests WazuhSocket.receive function exception works""" queue = WazuhSocket('test_path') with pytest.raises(WazuhException, match=".* 1014 .*"): queue.receive() mock_conn.assert_called_once_with('test_path')
def test_WazuhSocket_close(mock_close, mock_conn): """Tests WazuhSocket.close function works""" queue = WazuhSocket('test_path') queue.close() mock_conn.assert_called_once_with('test_path') mock_close.assert_called_once_with()
def get_daemons_stats_from_socket(agent_id, daemon): """Get a daemon stats from an agent or manager. Parameters ---------- agent_id: string Id of the agent to get stats from. daemon: string Name of the service to get stats from. Returns ------- Dict Object with daemon's stats. """ if not agent_id or not daemon: raise WazuhError(1307) sockets_path = os.path.join(common.wazuh_path, "queue", "sockets") if str(agent_id).zfill(3) == '000': # Some daemons do not exist in agent 000 if daemon in {'agent'}: raise WazuhError(1310) dest_socket = os.path.join(sockets_path, daemon) command = "getstate" else: dest_socket = os.path.join(sockets_path, "request") command = f"{str(agent_id).zfill(3)} {daemon} getstate" # Socket connection try: s = WazuhSocket(dest_socket) except Exception: raise WazuhInternalError(1121) # Send message s.send(command.encode()) # Receive response try: rec_msg = s.receive().decode() except ValueError: raise WazuhInternalError(1118, extra_message="Data could not be received") s.close() # Format response try: data = json.loads(rec_msg)['data'] data.update((k, datetime.strptime( data[k], "%Y-%m-%d %H:%M:%S").strftime(common.date_format)) for k, v in data.items() if k in {'last_keepalive', 'last_ack'}) return data except Exception: rec_msg = rec_msg.split(" ", 1)[1] raise WazuhError(1117, extra_message=rec_msg)
def get_active_configuration(agent_id, component, configuration): """ Reads agent loaded configuration in memory """ if not component or not configuration: raise WazuhError(1307) components = {"agent", "agentless", "analysis", "auth", "com", "csyslog", "integrator", "logcollector", "mail", "monitor", "request", "syscheck", "wmodules"} # checks if the component is correct if component not in components: raise WazuhError(1101, f'Valid components: {", ".join(components)}') sockets_path = os_path.join(common.wazuh_path, "queue", "sockets") if agent_id == '000': dest_socket = os_path.join(sockets_path, component) command = f"getconfig {configuration}" else: dest_socket = os_path.join(sockets_path, "request") command = f"{str(agent_id).zfill(3)} {component} getconfig {configuration}" # Socket connection try: s = WazuhSocket(dest_socket) except Exception: raise WazuhInternalError(1121) # Send message s.send(command.encode()) # Receive response try: # Receive data length rec_msg_ok, rec_msg = s.receive().decode().split(" ", 1) except ValueError: raise WazuhInternalError(1118, extra_message="Data could not be received") s.close() if rec_msg_ok.startswith('ok'): msg = json.loads(rec_msg) # Include password if auth->use_password enabled and authd.pass file exists if msg.get('auth', {}).get('use_password') == 'yes': try: with open(os_path.join(common.wazuh_path, "etc", "authd.pass"), 'r') as f: msg['authd.pass'] = f.read().rstrip() except IOError: pass return msg else: raise WazuhError(1117 if "No such file or directory" in rec_msg or "Cannot send request" in rec_msg else 1116, extra_message='{0}:{1}'.format(component, configuration))
def send_to_tasks_socket(command): """Send command to task module Parameters ---------- command : dict Command to be sent to task module Returns ------- Message received from the socket """ try: s = WazuhSocket(common.TASKS_SOCKET) except Exception: raise WazuhInternalError(1121) s.send(dumps(command).encode()) data = loads(s.receive().decode()) s.close() return data
def test_WazuhSocket_send_ko(mock_conn, msg, effect, send_effect, expected_exception): """Tests WazuhSocket.send function exceptions works""" queue = WazuhSocket('test_path') if effect == 'return_value': with patch('wazuh.core.wazuh_socket.socket.socket.send', return_value=send_effect): with pytest.raises(WazuhException, match=f'.* {expected_exception} .*'): queue.send(msg) else: with patch('wazuh.core.wazuh_socket.socket.socket.send', side_effect=send_effect): with pytest.raises(WazuhException, match=f'.* {expected_exception} .*'): queue.send(msg) mock_conn.assert_called_once_with('test_path')
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(wcom_lockfile, 'a+') fcntl.lockf(lock_file, fcntl.LOCK_EX) try: # Socket path wcom_socket_path = common.WCOM_SOCKET # Message for checking Wazuh configuration wcom_msg = common.CHECK_CONFIG_COMMAND # Connect to wcom socket if exists(wcom_socket_path): try: wcom_socket = WazuhSocket(wcom_socket_path) except WazuhException as e: extra_msg = f'Socket: WAZUH_PATH/queue/sockets/com. Error {e.message}' raise WazuhInternalError(1013, extra_message=extra_msg) else: raise WazuhInternalError(1901) # Send msg to wcom socket try: wcom_socket.send(wcom_msg.encode()) buffer = bytearray() datagram = wcom_socket.receive() buffer.extend(datagram) wcom_socket.close() except (socket.error, socket.timeout) as e: raise WazuhInternalError(1014, extra_message=str(e)) finally: wcom_socket.close() 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
def test_WazuhSocket_protected_connect_ko(mock_conn): """Tests WazuhSocket._connect function exceptions works""" with pytest.raises(WazuhException, match=".* 1013 .*"): WazuhSocket('test_path')
def test_WazuhSocket_protected_connect(mock_conn): """Tests WazuhSocket._connect function works""" WazuhSocket('test_path') mock_conn.assert_called_with('test_path')
def test_WazuhSocket__init__(mock_conn): """Tests WazuhSocket.__init__ function works""" WazuhSocket('test_path') mock_conn.assert_called_once_with()
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