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
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
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
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'})
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
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
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
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
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
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"