diff --git a/pyproject.toml b/pyproject.toml
index ea0e7ee..85665b3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -28,6 +28,7 @@ system_tests_launcher = [
'ansible>=4.10.0',
'pytest-testinfra>=6.7.0',
'pytest==7.3.1',
+ 'pywinrm>=0.2.2',
'ansible_runner>=2.3.2'
]
unit_testing = [
diff --git a/src/wazuh_qa_framework/generic_modules/tools/configuration.py b/src/wazuh_qa_framework/generic_modules/tools/configuration.py
new file mode 100644
index 0000000..e789a10
--- /dev/null
+++ b/src/wazuh_qa_framework/generic_modules/tools/configuration.py
@@ -0,0 +1,249 @@
+import xml.etree.ElementTree as ET
+import yaml
+from typing import List
+
+
+unlimited_sections = ['localfile', 'command', 'active-response']
+xml_configuration_files = ['ossec.conf', 'agent.conf']
+
+
+# customize _serialize_xml to avoid lexicographical order in XML attributes
+def _serialize_xml(write, elem, qnames, namespaces,
+ short_empty_elements, **kwargs):
+ tag = elem.tag
+ text = elem.text
+ if tag is ET.Comment:
+ write("" % text)
+ elif tag is ET.ProcessingInstruction:
+ write("%s?>" % text)
+ else:
+ tag = qnames[tag]
+ if tag is None:
+ if text:
+ write(ET._escape_cdata(text))
+ for e in elem:
+ _serialize_xml(write, e, qnames, None,
+ short_empty_elements=short_empty_elements)
+ else:
+ write("<" + tag)
+ items = list(elem.items())
+ if items or namespaces:
+ if namespaces:
+ for v, k in sorted(namespaces.items(),
+ key=lambda x: x[1]): # sort on prefix
+ if k:
+ k = ":" + k
+ write(" xmlns%s=\"%s\"" % (
+ k,
+ ET._escape_attrib(v)
+ ))
+ for k, v in items: # avoid lexicographical order for XML attributes
+ if isinstance(k, ET.QName):
+ k = k.text
+ if isinstance(v, ET.QName):
+ v = qnames[v.text]
+ else:
+ v = ET._escape_attrib(v)
+ write(" %s=\"%s\"" % (qnames[k], v))
+ if text or len(elem) or not short_empty_elements:
+ write(">")
+ if text:
+ write(ET._escape_cdata(text))
+ for e in elem:
+ _serialize_xml(write, e, qnames, None,
+ short_empty_elements=short_empty_elements)
+ write("" + tag + ">")
+ else:
+ write(" />")
+ if elem.tail:
+ write(ET._escape_cdata(elem.tail))
+
+
+def set_section_wazuh_conf(sections, template=None):
+ """
+ Set a configuration in a section of Wazuh. It replaces the content if it exists.
+
+ Args:
+ sections (list): List of dicts with section and new elements
+ section (str, optional): Section of Wazuh configuration to replace. Default `'syscheck'`
+ new_elements (list, optional) : List with dictionaries for settings elements in the section. Default `None`
+ template (list of string, optional): File content template
+
+ Returns:
+ List of str: List of str with the custom Wazuh configuration.
+ """
+
+ def create_elements(section: ET.Element, elements: List):
+ """
+ Insert new elements in a Wazuh configuration section.
+
+ Args:
+ section (ET.Element): Section where the element will be inserted.
+ elements (list): List with the new elements to be inserted.
+ Returns:
+ ET.ElementTree: Modified Wazuh configuration.
+ """
+ tag = None
+ for element in elements:
+ for tag_name, properties in element.items():
+ tag = ET.SubElement(section, tag_name)
+ new_elements = properties.get('elements')
+ attributes = properties.get('attributes')
+ if attributes is not None:
+ for attribute in attributes:
+ if isinstance(attribute, dict): # noqa: E501
+ for attr_name, attr_value in attribute.items():
+ tag.attrib[attr_name] = str(attr_value)
+ if new_elements:
+ create_elements(tag, new_elements)
+ else:
+ tag.text = str(properties.get('value'))
+ attributes = properties.get('attributes')
+ if attributes:
+ for attribute in attributes:
+ if attribute is not None and isinstance(attribute, dict): # noqa: E501
+ for attr_name, attr_value in attribute.items():
+ tag.attrib[attr_name] = str(attr_value)
+ tag.tail = "\n "
+ tag.tail = "\n "
+
+ def purge_multiple_root_elements(str_list: List[str], root_delimeter: str = "") -> List[str]:
+ """
+ Remove from the list all the lines located after the root element ends.
+
+ This operation is needed before attempting to convert the list to ElementTree because if the ossec.conf had more
+ than one `` element as root the conversion would fail.
+
+ Args:
+ str_list (list or str): The content of the ossec.conf file in a list of str.
+ root_delimeter (str, optional: The expected string to identify when the first root element ends,
+ by default ""
+
+ Returns:
+ list of str : The first N lines of the specified str_list until the root_delimeter is found. The rest of
+ the list will be ignored.
+ """
+ line_counter = 0
+ for line in str_list:
+ line_counter += 1
+ if root_delimeter in line:
+ return str_list[0:line_counter]
+ else:
+ return str_list
+
+ def to_element_tree(str_list: List[str], root_delimeter: str = "") -> ET.ElementTree:
+ """
+ Turn a list of str into an ElementTree object.
+
+ As ElementTree does not support xml with more than one root element this function will parse the list first with
+ `purge_multiple_root_elements` to ensure there is only one root element.
+
+ Args:
+ str_list (list of str): A list of strings with every line of the ossec conf.
+
+ Returns:
+ ElementTree: A ElementTree object with the data of the `str_list`
+ """
+ str_list = purge_multiple_root_elements(str_list, root_delimeter)
+ return ET.ElementTree(ET.fromstringlist(str_list))
+
+ def to_str_list(elementTree: ET.ElementTree) -> List[str]:
+ """
+ Turn an ElementTree object into a list of str.
+
+ Args:
+ elementTree (ElementTree): A ElementTree object with all the data of the ossec.conf.
+
+ Returns:
+ (list of str): A list of str containing all the lines of the ossec.conf.
+ """
+ return ET.tostringlist(elementTree.getroot(), encoding="unicode")
+
+ def find_module_config(wazuh_conf: ET.ElementTree, section: str, attributes: List[dict]) -> ET.ElementTree:
+ r"""
+ Check if a certain configuration section exists in ossec.conf and returns the corresponding block if exists.
+ (This extra function has been necessary to implement it to configure the wodle blocks, since they have the same
+ section but different attributes).
+
+ Args:
+ wazuh_conf (ElementTree): An ElementTree object with all the data of the ossec.conf
+ section (str): Name of the tag or configuration section to search for. For example: vulnerability_detector
+ attributes (list of dict): List with section attributes. Needed to check if the section exists with all the
+ searched attributes and values. For example (wodle section) [{'name': 'syscollector'}]
+ Returns:
+ ElementTree: An ElementTree object with the section data found in ossec.conf. None if nothing was found.
+ """
+ if attributes is None:
+ return wazuh_conf.find(section)
+ else:
+ attributes_query = ''.join([f"[@{attribute}='{value}']" for index, _ in enumerate(attributes)
+ for attribute, value in attributes[index].items()])
+ query = f"{section}{attributes_query}"
+
+ try:
+ return wazuh_conf.find(query)
+ except AttributeError:
+ return None
+
+ # Generate a ElementTree representation of the previous list to work with its sections
+ root_delimeter = '' if '' in template else ''
+ wazuh_conf = to_element_tree(template, root_delimeter)
+ for section in sections:
+ attributes = section.get('attributes')
+ section_conf = find_module_config(wazuh_conf, section['section'], attributes)
+ # Create section if it does not exist, clean otherwise
+ if not section_conf:
+ section_conf = ET.SubElement(wazuh_conf.getroot(), section['section'])
+ section_conf.text = '\n '
+ section_conf.tail = '\n\n '
+ else:
+ # Add section if there is no limit
+ if section_conf.tag in unlimited_sections:
+ section_conf = ET.SubElement(wazuh_conf.getroot(), section['section'])
+ section_conf.text = '\n '
+ section_conf.tail = '\n\n '
+ else:
+ prev_text = section_conf.text
+ prev_tail = section_conf.tail
+ section_conf.clear()
+ section_conf.text = prev_text
+ section_conf.tail = prev_tail
+
+ # Insert section attributes
+ if attributes:
+ for attribute in attributes:
+ if attribute is not None and isinstance(attribute, dict): # noqa: E501
+ for attr_name, attr_value in attribute.items():
+ section_conf.attrib[attr_name] = str(attr_value)
+
+ # Insert elements
+ new_elements = section.get('elements', list())
+ if new_elements:
+ create_elements(section_conf, new_elements)
+
+ return to_str_list(wazuh_conf)
+
+
+def configure_local_internal_options(new_conf):
+ local_internal_configuration_string = ''
+ for option_name, option_value in new_conf.items():
+ local_internal_configuration_string += f"{str(option_name)}={str(option_value)}\n"
+ return local_internal_configuration_string
+
+
+def configure_ossec_conf(new_conf, template):
+ new_configuration = ''.join(set_section_wazuh_conf(new_conf, template))
+ return new_configuration
+
+
+def configure_api_yaml(new_conf):
+ new_configuration = yaml.dump(new_conf)
+ return new_configuration
+
+
+conf_functions = {
+ 'local_internal_options.conf': configure_local_internal_options,
+ 'ossec.conf': configure_ossec_conf,
+ 'agent.conf': configure_ossec_conf,
+ 'api.yaml': configure_api_yaml
+}
diff --git a/src/wazuh_qa_framework/system/wazuh_handler.py b/src/wazuh_qa_framework/system/wazuh_handler.py
index 3fab9da..4cd620e 100644
--- a/src/wazuh_qa_framework/system/wazuh_handler.py
+++ b/src/wazuh_qa_framework/system/wazuh_handler.py
@@ -3,20 +3,26 @@
# This program is free software; you can redistribute it and/or modify it under the terms of GPLv2
import os
-import re
+import yaml
from multiprocessing.pool import ThreadPool
from wazuh_qa_framework.generic_modules.logging.base_logger import BaseLogger
+from wazuh_qa_framework.generic_modules.tools.configuration import conf_functions, xml_configuration_files
from wazuh_qa_framework.global_variables.daemons import WAZUH_ANGENT_WINDOWS_SERVICE_NAME
from wazuh_qa_framework.system.host_manager import HostManager
DEFAULT_INSTALL_PATH = {
'linux': '/var/ossec',
- 'windows': 'C:\\Program Files\\ossec-agent',
+ 'windows': 'C:/Program Files (x86)/ossec-agent',
'darwin': '/Library/Ossec'
}
+DEFAULT_TEMPORAL_DIRECTORY = {
+ 'linux': '/tmp',
+ 'windows': 'C:/Users/qa/AppData/Local/Temp'
+}
+
def get_configuration_directory_path(custom_installation_path=None, os_host='linux'):
installation_path = custom_installation_path if custom_installation_path else DEFAULT_INSTALL_PATH[os_host]
@@ -40,7 +46,7 @@ def get_api_directory(custom_installation_path=None):
def get_api_configuration_directory(custom_installation_path=None):
installation_path = custom_installation_path if custom_installation_path else DEFAULT_INSTALL_PATH['linux']
- return os.path.join(get_api_directory(custom_installation_path), 'configuration')
+ return os.path.join(get_api_directory(installation_path), 'configuration')
def get_alert_directory_path(custom_installation_path=None):
@@ -68,10 +74,10 @@ def get_group_configuration_directory(custom_installation_path=None, os_host='li
installation_path = custom_installation_path if custom_installation_path else DEFAULT_INSTALL_PATH[os_host]
group_configuration_path = None
if component == 'manager':
- group_configuration_path = os.path.join(get_shared_directory_path(custom_installation_path, os_host),
+ group_configuration_path = os.path.join(get_shared_directory_path(installation_path, os_host),
group)
else:
- group_configuration_path = os.path.join(get_shared_directory_path(custom_installation_path, os_host))
+ group_configuration_path = os.path.join(get_shared_directory_path(installation_path, os_host))
return group_configuration_path
@@ -132,7 +138,7 @@ def get_wazuh_file_path(custom_installation_path=None, os_host='linux', file_nam
'files': ['agent.conf'],
'path_calculator': lambda filename: os.path.join(get_group_configuration_directory(installation_path,
os_host,
- group_name=group,
+ group=group,
component=component),
filename)
}
@@ -340,108 +346,212 @@ def get_ruleset_directory_path(self, host):
return ruleset_directory_path
- def configure_host(self, host, configuration_host):
+ def configure_host(self, host, configuration_file, configuration_values):
"""Configure ossec.conf, agent.conf, api.conf and local_internal_options of specified host of the environment
Configuration should fit the format expected for each configuration file:
- ossec and agent.conf configuration should be provided as a list of configuration sections section.
- local_internal_options configuration should be provided as a map
- api.yaml should be provided as a map
- Example:
- local_internal_options:
- remoted.debug: 2
- wazuh_modulesd.debug: 2
- ossec.conf:
- - 'section': 'client',
- 'elements':
- - 'server':
- 'elements':
- - 'address':
- 'value': 121.1.3.1
- agent.conf:
- - 'group': 'default',
- - configuration:
- - 'section': 'client',
- 'elements':
- - 'server':
- 'elements':
- - 'address':
- 'value': 121.1.3.1
+ Examples:
+ - [('manager1', 'local_internal_options.conf', {'remoted.debug': '2'})]
+ - [('manager1', 'ossec.conf', [{'section': 'client', 'elements': [{'server': {'elements': [{'address':
+ {'value': '121.1.3.1'}}]}}]}])]
+ - [('manager1', 'agent.conf', {'group': 'default', 'configuration':
+ [{'section': 'client', 'elements': [{'server': {'elements': [{'address': {'value': '121.1.3.1'}}]}}]}]})]
+ - [('manager1', 'api.yaml', {'logs': {'level': 'debug'}})]
Args:
host (str): Hostname
- configuration_host (Map): Map with new hosts configuration
+ configuration_file (str): File name to be configured
+ configuration_values (dict): Dictionary with the new configuration
"""
- pass
+ self.logger.debug(f"Configuring {configuration_file} in {host}")
+
+ if configuration_file not in conf_functions:
+ raise Exception(f"Invalid operation for {configuration_file} configuration file. Please select one \
+ of the following: {conf_functions.keys()}")
+
+ # Get group folder and new configuration for agent.conf
+ group = configuration_values.get('group', 'default') if configuration_file == 'agent.conf' else None
+ configuration_values = (configuration_values['configuration'] if configuration_file == 'agent.conf'
+ else configuration_values)
+
+ # Get configuration file path
+ host_configuration_file_path = self.get_file_fullpath(host, configuration_file, group)
+
+ parameters = {'new_conf': configuration_values}
+
+ # Get template for ossec.conf and agent.conf
+ if configuration_file in xml_configuration_files:
+ current_configuration = self.get_file_content(host, host_configuration_file_path, become=True)
+ parameters.update({'template': current_configuration})
+
+ # Set new configuration
+ new_configuration = conf_functions[configuration_file](**parameters)
+ self.modify_file_content(host, host_configuration_file_path, new_configuration,
+ not self.is_windows(host), self.is_windows(host))
+
+ self.logger.debug(f"{configuration_file} in {host} configured successfully")
def configure_environment(self, configuration_hosts, parallel=True):
"""Configure multiple hosts at the same time.
Example:
- wazuh-agent1:
- local_internal_options:
- remoted.debug: 2
- wazuh_modulesd.debug: 2
+ wazuh-manager1:
+ local_internal_options.conf:
+ remoted.debug: '2'
ossec.conf:
- - 'section': 'client',
- 'elements':
- - 'server':
- 'elements':
- - 'address':
- 'value': 121.1.3.1
- api.yml:
- ....
- wazuh-agent2:
+ - section: client
+ elements:
+ - server:
+ elements:
+ - address:
+ value: 121.1.3.1
+ agent.conf:
+ group: default
+ configuration:
+ - section: client
+ elements:
+ - server:
+ elements:
+ - address:
+ value: 121.1.3.1
+ api.yaml:
+ logs:
+ level: debug
+ wazuh-agent1:
ossec.conf:
...
Args:
configuration_host (Map): Map with new hosts configuration
parallel(Boolean): Enable parallel tasks
"""
- pass
+ self.logger.info('Configuring environment')
+ if parallel:
+ host_configuration_map = []
+ for host, configuration in configuration_hosts.items():
+ for configuration_file, configuration_values in configuration.items():
+ host_configuration_map.append((host, configuration_file, configuration_values))
+ self.pool.starmap(self.configure_host, host_configuration_map)
+ else:
+ for host, configurations in configuration_hosts.items():
+ for configuration_file, configuration_values in configurations.items():
+ self.configure_host(host, configuration_file, configuration_values)
+ self.logger.info('Environment configured successfully')
- def change_agents_configure_manager(self, agent_list, manager, use_manager_name=True):
+ def change_agents_configured_manager(self, agent_list, manager, use_manager_name=True):
"""Change configured manager of specified agent
Args:
- agent (str): Agent name.
+ agent_list (list): List of agents that configuration will be changed.
manager (str): Manager name in the environment/Manager or IP.
use_manager_name (Boolean): Replace manager name with manager IP. Default True
"""
- pass
+ self.logger.debug('Changing configured manager')
+ if type(agent_list) != list:
+ raise TypeError('Expected a list of agents')
+
+ new_configuration = {}
+ new_manager = manager if use_manager_name else self.get_host_ansible_ip(manager)
+
+ server_block = {'server': {'elements': [{'address': {'value': new_manager}}]}}
+ configuration = [{'section': 'client', 'elements': [server_block]}]
+
+ for agent in agent_list:
+ new_configuration[agent] = {
+ 'ossec.conf': configuration
+ }
+
+ self.configure_environment(new_configuration)
+ self.logger.debug('Changed configured manager successfully')
- def backup_host_configuration(self, configuration_list):
- """Backup specified files in
+ def backup_host_configuration(self, host, file, group=None):
+ """Backup specified files in host
Args:
- configuration_list (dict): Host configuration files to backup
+ host (str): Hostname to backup
+ file (str): File to backup
Returns:
dict: Host backup filepaths
"""
+ self.logger.debug(f"Creating {file} backup on {host}")
+ backup_paths = {host: {}}
+ host_configuration_file_path = self.get_file_fullpath(host, file, group)
+ temporal_folder = DEFAULT_TEMPORAL_DIRECTORY[self.get_ansible_host_os(host)]
+ backup_file = os.path.join(temporal_folder, file + '.backup')
+ backup_paths[host][host_configuration_file_path] = backup_file
- def backup_environment_configuration(self, configuration_list, parallel=True):
+ self.copy_file(host, host_configuration_file_path, backup_file, remote_src=True,
+ become=not self.is_windows(host))
+
+ self.logger.debug(f"Created {file} backup on {host} successfully")
+ return backup_paths
+
+ def backup_environment_configuration(self, configuration_hosts, parallel=True):
"""Backup specified files in all hosts
Args:
- configuration_list (dict): Host configuration files to backup
+ configuration_hosts(dict): Host configuration files to backup
Returns:
dict: Host backup filepaths
"""
- pass
+ self.logger.info('Creating backup')
+ backup_configuration = []
+ if parallel:
+ host_configuration_map = []
+ for host, configuration in configuration_hosts.items():
+ for file in configuration['files']:
+ group = configuration['group'] if file == 'agent.conf' else None
+ host_configuration_map.append((host, file, group))
+ backup_configuration = self.pool.starmap(self.backup_host_configuration, host_configuration_map)
- def restore_host_backup_configuration(self, backup_configuration):
+ else:
+ for host, configuration in configuration_hosts.items():
+ for file in configuration['files']:
+ group = configuration['group'] if file == 'agent.conf' else None
+ backup_map = (self.backup_host_configuration(host, file, group))
+ backup_configuration.append(backup_map)
+
+ final_backup_configuration = {}
+ for backup_conf_host in backup_configuration:
+ for host, file in backup_conf_host.items():
+ if host in final_backup_configuration:
+ final_backup_configuration[host].update(file)
+ else:
+ final_backup_configuration[host] = file
+
+ self.logger.info('Created backup successfully')
+ return final_backup_configuration
+
+ def restore_host_backup_configuration(self, host, dest_file, backup_file):
"""Restore backup configuration
Args:
- backup_configuration (dict): Backup configuration filepaths
+ host (str): Hostname to restore
+ dest_file (str): File to restore
"""
- pass
+ self.logger.debug(f"Restoring {dest_file} backup on {host}")
+ self.copy_file(host=host, dest_path=dest_file,
+ src_path=backup_file, remote_src=True, become=not self.is_windows(host))
+ self.logger.debug(f"Restored {dest_file} backup on {host} succesfully")
- def restore_environment_backup_configuration(self, backup_configuration, parallel=True):
+ def restore_environment_backup_configuration(self, backup_configurations, parallel=True):
"""Restore environment backup configuration
Args:
- backup_configuration (dict): Backup configuration filepaths
+ backup_configurations (dict): Backup configuration filepaths
"""
- pass
+ self.logger.info('Restoring backup')
+ if parallel:
+ host_configuration_map = []
+ for host, files in backup_configurations.items():
+ for dest_file, backup_file in files.items():
+ host_configuration_map.append((host, dest_file, backup_file))
+ self.pool.starmap(self.restore_host_backup_configuration, host_configuration_map)
+ else:
+ for host, files in backup_configurations.items():
+ for dest_file, backup_file in files.items():
+ self.restore_host_backup_configuration(host, dest_file, backup_file)
+ self.logger.info('Restored backup successfully')
def log_search(self, host, pattern, timeout, file, escape=False, output_file='log_search_output.json'):
"""Search log in specified host file
@@ -517,13 +627,13 @@ def restart_agent(self, host):
Args:
host (str): Hostname
"""
- self.logger.debug(f'Restarting agent {host}')
+ self.logger.debug(f"Restarting agent {host}")
service_name = WAZUH_ANGENT_WINDOWS_SERVICE_NAME if self.is_windows(host) else 'wazuh-agent'
if self.is_agent(host):
self.control_service(host, service_name, 'restarted')
- self.logger.debug(f'Agent {host} restarted successfully')
+ self.logger.debug(f"Agent {host} restarted successfully")
else:
- raise ValueError(f'Host {host} is not an agent')
+ raise ValueError(f"Host {host} is not an agent")
def restart_agents(self, agent_list=None, parallel=True):
"""Restart list of agents
@@ -532,13 +642,13 @@ def restart_agents(self, agent_list=None, parallel=True):
agent_list (list, optional): Agent list. Defaults to None.
parallel (bool, optional): Parallel execution. Defaults to True.
"""
- self.logger.info(f'Restarting agents: {agent_list}')
+ self.logger.info(f"Restarting agents: {agent_list}")
if parallel:
- agent_restart_tasks = self.pool.map(self.restart_agent, agent_list)
+ self.pool.map(self.restart_agent, agent_list)
else:
for agent in agent_list:
self.restart_agent(agent)
- self.logger.info(f'Agents restarted successfully: {agent_list}')
+ self.logger.info(f"Agents restarted successfully: {agent_list}")
def restart_manager(self, host):
"""Restart manager
@@ -546,12 +656,12 @@ def restart_manager(self, host):
Args:
host (str): Hostname
"""
- self.logger.debug(f'Restarting manager {host}')
+ self.logger.debug(f"Restarting manager {host}")
if self.is_manager(host):
self.control_service(host, 'wazuh-manager', 'restarted', become=True)
- self.logger.debug(f'Manager {host} restarted successfully')
+ self.logger.debug(f"Manager {host} restarted successfully")
else:
- ValueError(f'Host {host} is not a manager')
+ ValueError(f"Host {host} is not a manager")
def restart_managers(self, manager_list, parallel=True):
"""Restart managers
@@ -560,13 +670,13 @@ def restart_managers(self, manager_list, parallel=True):
manager_list (list): Managers list
parallel (bool, optional): Parallel execution. Defaults to True.
"""
- self.logger.info(f'Restarting managers: {manager_list}')
+ self.logger.info(f"Restarting managers: {manager_list}")
if parallel:
self.pool.map(self.restart_manager, manager_list)
else:
for manager in manager_list:
self.restart_manager(manager)
- self.logger.info(f'Managers restarted successfully: {manager_list}')
+ self.logger.info(f"Managers restarted successfully: {manager_list}")
def stop_agent(self, host):
"""Stop agent
@@ -574,13 +684,13 @@ def stop_agent(self, host):
Args:
host (str): Hostname
"""
- self.logger.debug(f'Stopping agent {host}')
- service_name = WAZUH_ANGENT_WINDOWS_SERVICE_NAME if is_windows(host) else 'wazuh-agent'
+ self.logger.debug(f"Stopping agent {host}")
+ service_name = WAZUH_ANGENT_WINDOWS_SERVICE_NAME if self.is_windows(host) else 'wazuh-agent'
if self.is_agent(host):
self.control_service(host, service_name, 'stopped')
- self.logger.debug(f'Agent {host} stopped successfully')
+ self.logger.debug(f"Agent {host} stopped successfully")
else:
- raise ValueError(f'Host {host} is not an agent')
+ raise ValueError(f"Host {host} is not an agent")
def stop_agents(self, agent_list=None, parallel=True):
"""Stop agents
@@ -589,13 +699,13 @@ def stop_agents(self, agent_list=None, parallel=True):
agent_list(list, optional): Agents list. Defaults to None
parallel (bool, optional): Parallel execution. Defaults to True.
"""
- self.logger.info(f'Stopping agents: {agent_list}')
+ self.logger.info(f"Stopping agents: {agent_list}")
if parallel:
self.pool.map(self.stop_agent, agent_list)
else:
for agent in agent_list:
self.restart_agent(agent)
- self.logger.info(f'Agents stopped successfully: {agent_list}')
+ self.logger.info(f"Agents stopped successfully: {agent_list}")
def stop_manager(self, host):
"""Stop manager
@@ -603,12 +713,12 @@ def stop_manager(self, host):
Args:
host (str): Hostname
"""
- self.logger.debug(f'Stopping manager {host}')
+ self.logger.debug(f"Stopping manager {host}")
if self.is_manager(host):
self.control_service(host, 'wazuh-manager', 'stopped', become=True)
- self.logger.debug(f'Manager {host} stopped successfully')
+ self.logger.debug(f"Manager {host} stopped successfully")
else:
- raise ValueError(f'Host {host} is not a manager')
+ raise ValueError(f"Host {host} is not a manager")
def stop_managers(self, manager_list, parallel=True):
"""Stop managers
@@ -617,13 +727,13 @@ def stop_managers(self, manager_list, parallel=True):
manager_list (list): Managers list
parallel (bool, optional): Parallel execution. Defaults to True.
"""
- self.logger.info(f'Stopping managers: {manager_list}')
+ self.logger.info(f"Stopping managers: {manager_list}")
if parallel:
self.pool.map(self.stop_manager, manager_list)
else:
for manager in manager_list:
self.restart_manager(manager)
- self.logger.info(f'Stopping managers: {manager_list}')
+ self.logger.info(f"Stopping managers: {manager_list}")
def start_agent(self, host):
"""Start agent
@@ -631,13 +741,13 @@ def start_agent(self, host):
Args:
host (str): Hostname
"""
- self.logger.debug(f'Starting agent {host}')
- service_name = WAZUH_ANGENT_WINDOWS_SERVICE_NAME if is_windows(host) else 'wazuh-agent'
+ self.logger.debug(f"Starting agent {host}")
+ service_name = WAZUH_ANGENT_WINDOWS_SERVICE_NAME if self.is_windows(host) else 'wazuh-agent'
if self.is_agent(host):
self.control_service(host, service_name, 'started')
- self.logger.debug(f'Agent {host} started successfully')
+ self.logger.debug(f"Agent {host} started successfully")
else:
- raise ValueError(f'Host {host} is not an agent')
+ raise ValueError(f"Host {host} is not an agent")
def start_agents(self, agent_list, parallel=True):
"""Start agents
@@ -646,13 +756,13 @@ def start_agents(self, agent_list, parallel=True):
agent_list (list): Agents list
parallel (bool, optional): Parallel execution. Defaults to True.
"""
- self.logger.info(f'Starting agents: {agent_list}')
+ self.logger.info(f"Starting agents: {agent_list}")
if parallel:
self.pool.map(self.start_agent, agent_list)
else:
for agent in agent_list:
self.start_agent(agent)
- self.logger.info(f'Agents started successfully: {agent_list}')
+ self.logger.info(f"Agents started successfully: {agent_list}")
def start_manager(self, host):
"""Start manager
@@ -660,12 +770,12 @@ def start_manager(self, host):
Args:
host (str): Hostname
"""
- self.logger.debug(f'Starting manager {host}')
+ self.logger.debug(f"Starting manager {host}")
if self.is_manager(host):
self.control_service(host, 'wazuh-manager', 'started', become=True)
- self.logger.debug(f'Manager {host} started successfully')
+ self.logger.debug(f"Manager {host} started successfully")
else:
- raise ValueError(f'Host {host} is not a manager')
+ raise ValueError(f"Host {host} is not a manager")
def start_managers(self, manager_list, parallel=True):
"""Start managers
@@ -674,13 +784,13 @@ def start_managers(self, manager_list, parallel=True):
manager_list (list): Managers list
parallel (bool, optional): Parallel execution. Defaults to True.
"""
- self.logger.info(f'Starting managers: {manager_list}')
+ self.logger.info(f"Starting managers: {manager_list}")
if parallel:
self.pool.map(self.start_manager, manager_list)
else:
for manager in manager_list:
self.start_manager(manager)
- self.logger.info(f'Managers started successfully: {manager_list}')
+ self.logger.info(f"Managers started successfully: {manager_list}")
def restart_environment(self, parallel=True):
"""Restart all agents and manager in the environment
@@ -727,11 +837,11 @@ def stop_environment(self, parallel=True):
self.pool.map(self.stop_agent, agent_list)
else:
self.logger.info(message='Stopping environment: Managers')
- for manager in get_managers():
+ for manager in self.get_managers():
self.stop_manager(manager)
self.logger.info(message='Stopping environment: Agents')
- for agent in get_agents():
+ for agent in self.get_agents():
self.stop_agent(agent)
self.logger.info('Stopping environment')
@@ -754,11 +864,11 @@ def start_environment(self, parallel=True):
self.pool.map(self.start_agent, agent_list)
else:
self.logger.info(message='Starting environment: Managers')
- for manager in get_managers():
+ for manager in self.get_managers():
self.start_manager(manager)
self.logger.info(message='Starting environment: Agents')
- for agent in get_agents():
+ for agent in self.get_agents():
self.start_agent(agent)
self.logger.info('Environment started successfully')