diff --git a/deployability/modules/generic/ansible.py b/deployability/modules/generic/ansible.py index 0829c84b3e..06ccb9072b 100755 --- a/deployability/modules/generic/ansible.py +++ b/deployability/modules/generic/ansible.py @@ -1,8 +1,10 @@ # Copyright (C) 2015, Wazuh Inc. # Created by Wazuh, Inc. . # This program is a free software; you can redistribute it and/or modify it under the terms of GPLv2 + import ansible_runner import jinja2 +from typing import Optional import yaml from pathlib import Path @@ -16,7 +18,8 @@ class Inventory(BaseModel): ansible_host: str | IPvAnyAddress ansible_user: str ansible_port: int - ansible_ssh_private_key_file: str + ansible_ssh_private_key_file: Optional[str] = None + ansible_password: Optional[str] = None class Ansible: @@ -118,10 +121,13 @@ def generate_inventory(self) -> dict: self.ansible_data.ansible_host: { 'ansible_port': self.ansible_data.ansible_port, 'ansible_user': self.ansible_data.ansible_user, - 'ansible_ssh_private_key_file': self.ansible_data.ansible_ssh_private_key_file + **({'ansible_ssh_private_key_file': self.ansible_data.ansible_ssh_private_key_file} + if hasattr(self.ansible_data, 'ansible_ssh_private_key_file') + else {'ansible_password': self.ansible_data.ansible_password}) } } } } + return inventory_data diff --git a/deployability/modules/testing/tests/helpers/agent.py b/deployability/modules/testing/tests/helpers/agent.py index 3815bbd4ea..857174117d 100644 --- a/deployability/modules/testing/tests/helpers/agent.py +++ b/deployability/modules/testing/tests/helpers/agent.py @@ -23,24 +23,25 @@ def install_agent(inventory_path, agent_name, wazuh_version, wazuh_revision, liv release = 'pre-release' os_type = HostInformation.get_os_type(inventory_path) + architecture = HostInformation.get_architecture(inventory_path) commands = [] if 'linux' in os_type: distribution = HostInformation.get_linux_distribution(inventory_path) architecture = HostInformation.get_architecture(inventory_path) - if distribution == 'rpm' and 'x86_64' in architecture: + if distribution == 'rpm' and 'amd64' in architecture: commands.extend([ f"curl -o wazuh-agent-{wazuh_version}-1.x86_64.rpm https://{s3_url}.wazuh.com/{release}/yum/wazuh-agent-{wazuh_version}-1.x86_64.rpm && sudo WAZUH_MANAGER='MANAGER_IP' WAZUH_AGENT_NAME='{agent_name}' rpm -ihv wazuh-agent-{wazuh_version}-1.x86_64.rpm" ]) - elif distribution == 'rpm' and 'aarch64' in architecture: + elif distribution == 'rpm' and 'arm64' in architecture: commands.extend([ f"curl -o wazuh-agent-{wazuh_version}-1aarch64.rpm https://{s3_url}.wazuh.com/{release}/yum/wazuh-agent-{wazuh_version}-1.aarch64.rpm && sudo WAZUH_MANAGER='MANAGER_IP' WAZUH_AGENT_NAME='{agent_name}' rpm -ihv wazuh-agent-{wazuh_version}-1.aarch64.rpm" ]) - elif distribution == 'deb' and 'x86_64' in architecture: + elif distribution == 'deb' and 'amd64' in architecture: commands.extend([ f"wget https://{s3_url}.wazuh.com/{release}/apt/pool/main/w/wazuh-agent/wazuh-agent_{wazuh_version}-1_amd64.deb && sudo WAZUH_MANAGER='MANAGER_IP' WAZUH_AGENT_NAME='{agent_name}' dpkg -i ./wazuh-agent_{wazuh_version}-1_amd64.deb" ]) - elif distribution == 'deb' and 'aarch64' in architecture: + elif distribution == 'deb' and 'arm64' in architecture: commands.extend([ f"wget https://{s3_url}.wazuh.com/{release}/apt/pool/main/w/wazuh-agent/wazuh-agent_{wazuh_version}-1_arm64.deb && sudo WAZUH_MANAGER='MANAGER_IP' WAZUH_AGENT_NAME='{agent_name}' dpkg -i ./wazuh-agent_{wazuh_version}-1arm64.deb" ]) @@ -64,11 +65,11 @@ def install_agent(inventory_path, agent_name, wazuh_version, wazuh_revision, liv "NET STATUS WazuhSvc" ]) elif 'macos' in os_type: - if 'intel' in architecture: + if 'amd64' in architecture: commands.extend([ f'curl -so wazuh-agent.pkg https://{s3_url}.wazuh.com/{release}/macos/wazuh-agent-{wazuh_version}-1.intel64.pkg && echo "WAZUH_MANAGER=\'MANAGER_IP\' && WAZUH_AGENT_NAME=\'{agent_name}\'" > /tmp/wazuh_envs && sudo installer -pkg ./wazuh-agent.pkg -target /' ]) - elif 'apple' in architecture: + elif 'arm64' in architecture: commands.extend([ f'curl -so wazuh-agent.pkg https://{s3_url}.wazuh.com/{release}/macos/wazuh-agent-{wazuh_version}-1.arm64.pkg && echo "WAZUH_MANAGER=\'MANAGER_IP\' && WAZUH_AGENT_NAME=\'{agent_name}\'" > /tmp/wazuh_envs && sudo installer -pkg ./wazuh-agent.pkg -target /' ]) @@ -92,30 +93,54 @@ def install_agents(inventories_paths=[], wazuh_versions=[], wazuh_revisions=[], def register_agent(inventory_path, manager_path): with open(manager_path, 'r') as yaml_file: - manager_path = yaml.safe_load(yaml_file) - host = manager_path.get('ansible_host') + manager_path_yaml = yaml.safe_load(yaml_file) + manager_host = manager_path_yaml.get('ansible_host') - internal_ip = HostInformation.get_internal_ip_from_aws_dns(host) if 'amazonaws' in host else host + with open(inventory_path, 'r') as yaml_file: + inventory_path_yaml = yaml.safe_load(yaml_file) + agent_host = inventory_path_yaml.get('ansible_host') - commands = [ - f"sed -i 's/
MANAGER_IP<\/address>/
{internal_ip}<\/address>/g' {WAZUH_CONF}", - "systemctl restart wazuh-agent" - ] + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + host_ip = HostInformation.get_internal_ip_from_aws_dns(manager_host) if 'amazonaws' in manager_host else manager_host + commands = [ + f"sed -i 's/
MANAGER_IP<\/address>/
{host_ip}<\/address>/g' {WAZUH_CONF}", + "systemctl restart wazuh-agent" + ] + Executor.execute_commands(inventory_path, commands) + assert host_ip in Executor.execute_command(inventory_path, f'cat {WAZUH_CONF}'), logger.error(f'Error configuring the Manager IP ({host_ip}) in: {HostInformation.get_os_name_and_version_from_inventory(inventory_path)} agent') - Executor.execute_commands(inventory_path, commands) - assert internal_ip in Executor.execute_command(inventory_path, f'cat {WAZUH_CONF}'), logger.error(f'Error configuring the Manager IP ({internal_ip}) in: {HostInformation.get_os_name_and_version_from_inventory(inventory_path)} agent') + elif os_type == 'macos': + if 'amazonaws' in manager_host and 'amazonaws' in agent_host: + host_ip = HostInformation.get_internal_ip_from_aws_dns(manager_host) + else: + host_ip = HostInformation.get_public_ip_from_aws_dns(manager_host) + commands = [ + f"sed -i '.bak' 's/
MANAGER_IP<\/address>/
{host_ip}<\/address>/g' /Library/Ossec/etc/ossec.conf", + "/Library/Ossec/bin/wazuh-control restart" + ] + Executor.execute_commands(inventory_path, commands) + assert host_ip in Executor.execute_command(inventory_path, f'cat /Library/Ossec/etc/ossec.conf'), logger.error(f'Error configuring the Manager IP ({host_ip}) in: {HostInformation.get_os_name_and_version_from_inventory(inventory_path)} agent') @staticmethod def set_protocol_agent_connection(inventory_path, protocol): - commands = [ - f"sed -i 's/[^<]*<\/protocol>/{protocol}<\/protocol>/g' {WAZUH_CONF}", - "systemctl restart wazuh-agent" - ] - - Executor.execute_commands(inventory_path, commands) - assert protocol in Executor.execute_command(inventory_path, f'cat {WAZUH_CONF}'), logger.error(f'Error configuring the protocol ({protocol}) in: {HostInformation.get_os_name_and_version_from_inventory(inventory_path)} agent') - + os_type = HostInformation.get_os_type(inventory_path) + if 'linux' in os_type: + commands = [ + f"sed -i 's/[^<]*<\/protocol>/{protocol}<\/protocol>/g' {WAZUH_CONF}", + "systemctl restart wazuh-agent" + ] + Executor.execute_commands(inventory_path, commands) + assert protocol in Executor.execute_command(inventory_path, f'cat {WAZUH_CONF}'), logger.error(f'Error configuring the protocol ({protocol}) in: {HostInformation.get_os_name_and_version_from_inventory(inventory_path)} agent') + elif 'macos' in os_type: + commands = [ + f"sed -i '' 's/[^<]*<\/protocol>/{protocol}<\/protocol>/g' /Library/Ossec/etc/ossec.conf", + "/Library/Ossec/bin/wazuh-control restart" + ] + Executor.execute_commands(inventory_path, commands) + assert protocol in Executor.execute_command(inventory_path, f'cat /Library/Ossec/etc/ossec.conf'), logger.error(f'Error configuring the protocol ({protocol}) in: {HostInformation.get_os_name_and_version_from_inventory(inventory_path)} agent') + @staticmethod def uninstall_agent(inventory_path, wazuh_version=None, wazuh_revision=None) -> None: @@ -199,43 +224,50 @@ def perform_action_and_scan(agent_params, action_callback) -> dict: """ result = CheckFiles.perform_action_and_scan(agent_params, action_callback) os_name = HostInformation.get_os_name_from_inventory(agent_params) + os_type = HostInformation.get_os_type(agent_params) logger.info(f'Applying filters in checkfiles in {HostInformation.get_os_name_and_version_from_inventory(agent_params)}') - if 'debian' in os_name: - filter_data = { - '/boot': {'added': [], 'removed': [], 'modified': ['grubenv']}, - '/usr/bin': { - 'added': [ - 'unattended-upgrade', 'gapplication', 'add-apt-repository', 'gpg-wks-server', 'pkexec', 'gpgsplit', - 'watchgnupg', 'pinentry-curses', 'gpg-zip', 'gsettings', 'gpg-agent', 'gresource', 'gdbus', - 'gpg-connect-agent', 'gpgconf', 'gpgparsemail', 'lspgpot', 'pkaction', 'pkttyagent', 'pkmon', - 'dirmngr', 'kbxutil', 'migrate-pubring-from-classic-gpg', 'gpgcompose', 'pkcheck', 'gpgsm', 'gio', - 'pkcon', 'gpgtar', 'dirmngr-client', 'gpg', 'filebeat', 'gawk', 'curl', 'update-mime-database', - 'dh_installxmlcatalogs', 'appstreamcli', 'lspgpot', 'symcryptrun' - ], - 'removed': [], - 'modified': [] - }, - '/root': {'added': ['trustdb.gpg', 'lesshst'], 'removed': [], 'modified': []}, - '/usr/sbin': { - 'added': [ - 'update-catalog', 'applygnupgdefaults', 'addgnupghome', 'install-sgmlcatalog', 'update-xmlcatalog' - ], - 'removed': [], - 'modified': [] + if os_type == 'linux': + if 'debian' in os_name: + filter_data = { + '/boot': {'added': [], 'removed': [], 'modified': ['grubenv']}, + '/usr/bin': { + 'added': [ + 'unattended-upgrade', 'gapplication', 'add-apt-repository', 'gpg-wks-server', 'pkexec', 'gpgsplit', + 'watchgnupg', 'pinentry-curses', 'gpg-zip', 'gsettings', 'gpg-agent', 'gresource', 'gdbus', + 'gpg-connect-agent', 'gpgconf', 'gpgparsemail', 'lspgpot', 'pkaction', 'pkttyagent', 'pkmon', + 'dirmngr', 'kbxutil', 'migrate-pubring-from-classic-gpg', 'gpgcompose', 'pkcheck', 'gpgsm', 'gio', + 'pkcon', 'gpgtar', 'dirmngr-client', 'gpg', 'filebeat', 'gawk', 'curl', 'update-mime-database', + 'dh_installxmlcatalogs', 'appstreamcli', 'lspgpot', 'symcryptrun' + ], + 'removed': [], + 'modified': [] + }, + '/root': {'added': ['trustdb.gpg', 'lesshst'], 'removed': [], 'modified': []}, + '/usr/sbin': { + 'added': [ + 'update-catalog', 'applygnupgdefaults', 'addgnupghome', 'install-sgmlcatalog', 'update-xmlcatalog' + ], + 'removed': [], + 'modified': [] + } + } + else: + filter_data = { + '/boot': { + 'added': ['grub2', 'loader', 'vmlinuz', 'System.map', 'config-', 'initramfs'], + 'removed': [], + 'modified': ['grubenv'] + }, + '/usr/bin': {'added': ['filebeat'], 'removed': [], 'modified': []}, + '/root': {'added': ['trustdb.gpg', 'lesshst'], 'removed': [], 'modified': []}, + '/usr/sbin': {'added': [], 'removed': [], 'modified': []} + } + elif os_type == 'macos': + filter_data = { + '/usr/bin': {'added': [], 'removed': [], 'modified': []}, + '/usr/sbin': {'added': [], 'removed': [], 'modified': []} } - } - else: - filter_data = { - '/boot': { - 'added': ['grub2', 'loader', 'vmlinuz', 'System.map', 'config-', 'initramfs'], - 'removed': [], - 'modified': ['grubenv'] - }, - '/usr/bin': {'added': ['filebeat'], 'removed': [], 'modified': []}, - '/root': {'added': ['trustdb.gpg', 'lesshst'], 'removed': [], 'modified': []}, - '/usr/sbin': {'added': [], 'removed': [], 'modified': []} - } # Use of filters for directory, changes in result.items(): @@ -259,7 +291,7 @@ def perform_install_and_scan_for_agent(agent_params, agent_name, wazuh_params) - action_callback = lambda: WazuhAgent._install_agent_callback(wazuh_params, agent_name, agent_params) result = WazuhAgent.perform_action_and_scan(agent_params, action_callback) logger.info(f'Pre and post install checkfile comparison in {HostInformation.get_os_name_and_version_from_inventory(agent_params)}: {result}') - WazuhAgent.assert_results(result) + WazuhAgent.assert_results(result, agent_params) @staticmethod @@ -275,11 +307,11 @@ def perform_uninstall_and_scan_for_agent(agent_params, wazuh_params) -> None: action_callback = lambda: WazuhAgent._uninstall_agent_callback(wazuh_params, agent_params) result = WazuhAgent.perform_action_and_scan(agent_params, action_callback) logger.info(f'Pre and post uninstall checkfile comparison in {HostInformation.get_os_name_and_version_from_inventory(agent_params)}: {result}') - WazuhAgent.assert_results(result) + WazuhAgent.assert_results(result, agent_params) @staticmethod - def assert_results(result) -> None: + def assert_results(result, agent_params) -> None: """ Gets the status of an agent given its name. @@ -287,8 +319,13 @@ def assert_results(result) -> None: result (dict): result of comparison between pre and post action scan """ - categories = ['/root', '/usr/bin', '/usr/sbin', '/boot'] + os_type = HostInformation.get_os_type(agent_params) + if os_type == 'linux': + categories = ['/root', '/usr/bin', '/usr/sbin', '/boot'] + elif os_type == 'macos': + categories = ['/usr/bin', '/usr/sbin'] actions = ['added', 'modified', 'removed'] + # Testing the results for category in categories: for action in actions: @@ -306,17 +343,21 @@ def areAgent_processes_active(agent_params): """ return bool([int(numero) for numero in Executor.execute_command(agent_params, 'pgrep wazuh').splitlines()]) - def isAgent_port_open(agent_params): + def isAgent_port_open(inventory_path): """ Check if agent port is open Args: - agent_name (str): Agent name. + inventory_path (str): Agent inventory path. Returns: str: Os name. """ - return 'ESTAB' in Executor.execute_command(agent_params, 'ss -t -a -n | grep ":1514" | grep ESTAB') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return 'ESTAB' in Executor.execute_command(inventory_path, 'ss -t -a -n | grep ":1514" | grep ESTAB') + elif os_type == 'macos': + return 'ESTABLISHED' in Executor.execute_command(inventory_path, 'netstat -an | grep ".1514 " | grep ESTABLISHED') def get_agents_information(wazuh_api: WazuhAPI) -> list: """ diff --git a/deployability/modules/testing/tests/helpers/executor.py b/deployability/modules/testing/tests/helpers/executor.py index 6d204d6ba8..f77c924c05 100644 --- a/deployability/modules/testing/tests/helpers/executor.py +++ b/deployability/modules/testing/tests/helpers/executor.py @@ -3,6 +3,7 @@ # This program is a free software; you can redistribute it and/or modify it under the terms of GPLv2 import json +import paramiko import requests import subprocess import urllib3 @@ -19,24 +20,41 @@ def execute_command(inventory_path, command) -> str: with open(inventory_path, 'r') as yaml_file: inventory_data = yaml.safe_load(yaml_file) - host = inventory_data.get('ansible_host') - port = inventory_data.get('ansible_port') - private_key_path = inventory_data.get('ansible_ssh_private_key_file') - username = inventory_data.get('ansible_user') - - ssh_command = [ - "ssh", - "-i", private_key_path, - "-o", "StrictHostKeyChecking=no", - "-o", "UserKnownHostsFile=/dev/null", - "-p", str(port), - f"{username}@{host}", - "sudo", - command - ] - result = subprocess.run(ssh_command, stdout=subprocess.PIPE, text=True) - - return result.stdout + if 'ansible_ssh_private_key_file' in inventory_data: + host = inventory_data.get('ansible_host') + port = inventory_data.get('ansible_port') + private_key_path = inventory_data.get('ansible_ssh_private_key_file') + username = inventory_data.get('ansible_user') + + ssh_command = [ + "ssh", + "-i", private_key_path, + "-o", "StrictHostKeyChecking=no", + "-o", "UserKnownHostsFile=/dev/null", + "-p", str(port), + f"{username}@{host}", + "sudo", + command + ] + result = subprocess.run(ssh_command, stdout=subprocess.PIPE, text=True) + + return result.stdout + else: + host = inventory_data.get('ansible_host', None) + port = inventory_data.get('ansible_port', 22) + user = inventory_data.get('ansible_user', None) + password = inventory_data.get('ansible_password', None) + + ssh_client = paramiko.SSHClient() + ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh_client.connect(hostname=host, port=port, username=user, password=password) + stdin, stdout, stderr = ssh_client.exec_command(f"sudo {command}") + + result = ''.join(stdout.readlines()) + + ssh_client.close() + + return result @staticmethod diff --git a/deployability/modules/testing/tests/helpers/generic.py b/deployability/modules/testing/tests/helpers/generic.py index 7c989028bf..eaeee50211 100644 --- a/deployability/modules/testing/tests/helpers/generic.py +++ b/deployability/modules/testing/tests/helpers/generic.py @@ -14,8 +14,8 @@ from pathlib import Path from .constants import WAZUH_CONTROL, CLIENT_KEYS from .executor import Executor -from .utils import Utils from modules.testing.utils import logger +from .utils import Utils class HostInformation: @@ -32,7 +32,11 @@ def dir_exists(inventory_path, dir_path) -> str: Returns: bool: True or False """ - return 'true' in Executor.execute_command(inventory_path, f'test -d {dir_path} && echo "true" || echo "false"') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return 'true' in Executor.execute_command(inventory_path, f'test -d {dir_path} && echo "true" || echo "false"') + elif os_type == 'macos': + return 'true' in Executor.execute_command(inventory_path, f'stat {dir_path} >/dev/null 2>&1 && echo "true" || echo "false"') @staticmethod @@ -47,7 +51,11 @@ def file_exists(inventory_path, file_path) -> bool: Returns: bool: True or False """ - return 'true' in Executor.execute_command(inventory_path, f'test -f {file_path} && echo "true" || echo "false"') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return 'true' in Executor.execute_command(inventory_path, f'test -f {file_path} && echo "true" || echo "false"') + elif os_type == 'macos': + return 'true' in Executor.execute_command(inventory_path, f'stat {file_path} >/dev/null 2>&1 && echo "true" || echo "false"') @staticmethod @@ -61,8 +69,19 @@ def get_os_type(inventory_path) -> str: Returns: str: type of host (windows, linux, macos) """ - system = Executor.execute_command(inventory_path, 'uname') - return system.lower() + try: + with open(inventory_path.replace('inventory', 'track'), 'r') as file: + data = yaml.safe_load(file) + if 'platform' in data: + return data['platform'] + else: + raise KeyError("The 'platform' key was not found in the YAML file.") + except FileNotFoundError: + logger.error(f"The YAML file '{inventory_path}' was not found.") + except yaml.YAMLError as e: + logger.error(f"Error while loading the YAML file: {e}") + except Exception as e: + logger.error(f"An unexpected error occurred: {e}") @staticmethod @@ -74,9 +93,21 @@ def get_architecture(inventory_path) -> str: inventory_path: host's inventory path Returns: - str: architecture (aarch64, x86_64, intel, apple) + str: architecture (amd64, arm64, intel, apple) """ - return Executor.execute_command(inventory_path, 'uname -m') + try: + with open(inventory_path.replace('inventory', 'track'), 'r') as file: + data = yaml.safe_load(file) + if 'platform' in data: + return data['arch'] + else: + raise KeyError("The 'platform' key was not found in the YAML file.") + except FileNotFoundError: + logger.error(f"The YAML file '{inventory_path}' was not found.") + except yaml.YAMLError as e: + logger.error(f"Error while loading the YAML file: {e}") + except Exception as e: + logger.error(f"An unexpected error occurred: {e}") @staticmethod @@ -115,9 +146,9 @@ def get_os_name_from_inventory(inventory_path) -> str: str: linux os name (debian, ubuntu, opensuse, amazon, centos, redhat) """ if 'manager' in inventory_path: - os_name = re.search(r'/manager-linux-([^-]+)-', inventory_path).group(1) + os_name = re.search(r'/manager-[^-]+-([^-]+)-', inventory_path).group(1) elif 'agent' in inventory_path: - os_name = re.search(r'/agent-linux-([^-]+)-', inventory_path).group(1) + os_name = re.search(r'/agent-[^-]+-([^-]+)-', inventory_path).group(1) return os_name @@ -133,9 +164,9 @@ def get_os_name_and_version_from_inventory(inventory_path) -> tuple: tuple: linux os name and version (e.g., ('ubuntu', '22.04')) """ if 'manager' in inventory_path: - match = re.search(r'/manager-linux-([^-]+)-([^-]+)-', inventory_path) + match = re.search(r'/manager-[^-]+-([^-]+)-([^-]+)-', inventory_path) elif 'agent' in inventory_path: - match = re.search(r'/agent-linux-([^-]+)-([^-]+)-', inventory_path) + match = re.search(r'/agent-[^-]+-([^-]+)-([^-]+)-', inventory_path) if match: os_name = match.group(1) version = match.group(2) @@ -146,9 +177,9 @@ def get_os_name_and_version_from_inventory(inventory_path) -> tuple: @staticmethod def get_os_version_from_inventory(inventory_path) -> str: if 'manager' in inventory_path: - os_version = re.search(r".*?/manager-linux-.*?-(.*?)-.*?/inventory.yaml", inventory_path).group(1) + os_version = re.search(r".*?/manager-.*?-.*?-(.*?)-.*?/inventory.yaml", inventory_path).group(1) elif 'agent' in inventory_path: - os_version = re.search(r".*?/agent-linux-.*?-(.*?)-.*?/inventory.yaml", inventory_path).group(1) + os_version = re.search(r".*?/agent-.*?-.*?-(.*?)-.*?/inventory.yaml", inventory_path).group(1) return os_version else: return None @@ -168,7 +199,7 @@ def get_current_dir(inventory_path) -> str: return Executor.execute_command(inventory_path, 'pwd').replace("\n","") @staticmethod - def get_internal_ip_from_aws_dns(dns_name): + def get_internal_ip_from_aws_dns(dns_name) -> str: """ It returns the private AWS IP from dns_name @@ -186,6 +217,24 @@ def get_internal_ip_from_aws_dns(dns_name): else: return None + @staticmethod + def get_public_ip_from_aws_dns(dns_name) -> str: + """ + It returns the public AWS IP from dns_name + + Args: + dns_name (str): host's dns public dns name + + Returns: + str: public ip + """ + try: + ip_address = socket.gethostbyname(dns_name) + return ip_address + except socket.gaierror as e: + logger.error("Error obtaining IP address:", e) + return None + @staticmethod def get_client_keys(inventory_path) -> list[dict]: """ @@ -198,7 +247,11 @@ def get_client_keys(inventory_path) -> list[dict]: list: List of dictionaries with the client keys. """ clients = [] - client_key = Executor.execute_command(inventory_path, f'cat {CLIENT_KEYS}') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + client_key = Executor.execute_command(inventory_path, f'cat {CLIENT_KEYS}') + elif os_type == 'macos': + client_key = Executor.execute_command(inventory_path, f'cat /Library/Ossec/etc/client.keys') lines = client_key.split('\n')[:-1] for line in lines: _id, name, address, password = line.strip().split() @@ -237,14 +290,18 @@ def disable_firewall(inventory_path) -> None: inventory_path: host's inventory path """ - commands = ["sudo systemctl stop firewalld", "sudo systemctl disable firewalld"] - if GeneralComponentActions.isComponentActive(inventory_path, 'firewalld'): - Executor.execute_commands(inventory_path, commands) + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + commands = ["sudo systemctl stop firewalld", "sudo systemctl disable firewalld"] + if GeneralComponentActions.isComponentActive(inventory_path, 'firewalld'): + Executor.execute_commands(inventory_path, commands) + logger.info(f'Firewall disabled on {HostInformation.get_os_name_and_version_from_inventory(inventory_path)}') + else: + logger.info(f'No Firewall to disable on {HostInformation.get_os_name_and_version_from_inventory(inventory_path)}') + elif os_type == 'macos': logger.info(f'Firewall disabled on {HostInformation.get_os_name_and_version_from_inventory(inventory_path)}') - else: - logger.info(f'No Firewall to disable on {HostInformation.get_os_name_and_version_from_inventory(inventory_path)}') - + Executor.execute_command(inventory_path, 'sudo pfctl -d') def _extract_hosts(paths, is_aws): @@ -467,11 +524,13 @@ def _checkfiles(inventory_path, os_type, directory, filter= None, hash_algorithm Returns: Dict: dict of directories:hash """ - if 'linux' in os_type or 'macos' in os_type: + if 'linux' == os_type: command = f'sudo find {directory} -type f -exec sha256sum {{}} + {filter}' result = Executor.execute_command(inventory_path, command) - - elif 'windows' in os_type: + elif 'macos' == os_type: + command = f'sudo find {directory} -type f -exec shasum -a 256 {{}} \; {filter}' + result = Executor.execute_command(inventory_path, command) + elif 'windows' == os_type: command = 'dir /a-d /b /s | findstr /v /c:"\\.$" /c:"\\..$"| find /c ":"' else: logger.info(f'Unsupported operating system') @@ -514,9 +573,15 @@ def perform_action_and_scan(inventory_path, callback) -> dict: """ os_type = HostInformation.get_os_type(inventory_path) - directories = ['/boot', '/usr/bin', '/root', '/usr/sbin'] - filters_keywords = ['grep', 'tar', 'coreutils', 'sed', 'procps', 'gawk', 'lsof', 'curl', 'openssl', 'libcap', 'apt-transport-https', 'libcap2-bin', 'software-properties-common', 'gnupg', 'gpg'] - filters = f"| grep -v {filters_keywords[0]}" + if 'linux' in inventory_path: + directories = ['/boot', '/usr/bin', '/root', '/usr/sbin'] + filters_keywords = ['grep', 'tar', 'coreutils', 'sed', 'procps', 'gawk', 'lsof', 'curl', 'openssl', 'libcap', 'apt-transport-https', 'libcap2-bin', 'software-properties-common', 'gnupg', 'gpg'] + filters = f"| grep -v {filters_keywords[0]}" + + elif 'macos' in inventory_path: + directories = ['/usr/bin', '/usr/sbin'] + filters_keywords = ['grep'] + filters = f"| grep -v {filters_keywords[0]}" for filter_ in filters_keywords[1:]: filters+= f" | grep -v {filter_}" @@ -543,8 +608,11 @@ def get_component_status(inventory_path, host_role) -> str: str: Role status """ logger.info(f'Getting status of {HostInformation.get_os_name_and_version_from_inventory(inventory_path)}') - - return Executor.execute_command(inventory_path, f'systemctl status {host_role}') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return Executor.execute_command(inventory_path, f'systemctl status {host_role}') + elif os_type == 'macos': + return Executor.execute_command(inventory_path, f'/Library/Ossec/bin/wazuh-control status | grep {host_role}') @staticmethod @@ -556,9 +624,12 @@ def component_stop(inventory_path, host_role) -> None: inventory_path: host's inventory path host_role: role of the component """ - logger.info(f'Stopping {host_role} in {HostInformation.get_os_name_and_version_from_inventory(inventory_path)}') - Executor.execute_command(inventory_path, f'systemctl stop {host_role}') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return Executor.execute_command(inventory_path, f'systemctl stop {host_role}') + elif os_type == 'macos': + return Executor.execute_command(inventory_path, f'/Library/Ossec/bin/wazuh-control stop | grep {host_role}') @staticmethod @@ -572,7 +643,11 @@ def component_restart(inventory_path, host_role) -> None: """ logger.info(f'Restarting {host_role} in {HostInformation.get_os_name_and_version_from_inventory(inventory_path)}') - Executor.execute_command(inventory_path, f'systemctl restart {host_role}') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return Executor.execute_command(inventory_path, f'systemctl restart {host_role}') + elif os_type == 'macos': + return Executor.execute_command(inventory_path, f'/Library/Ossec/bin/wazuh-control restart | grep {host_role}') @staticmethod @@ -586,7 +661,11 @@ def component_start(inventory_path, host_role) -> None: """ logger.info(f'Starting {host_role} in {HostInformation.get_os_name_and_version_from_inventory(inventory_path)}') - Executor.execute_command(inventory_path, f'systemctl restart {host_role}') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return Executor.execute_command(inventory_path, f'systemctl start {host_role}') + elif os_type == 'macos': + return Executor.execute_command(inventory_path, f'/Library/Ossec/bin/wazuh-control start | grep {host_role}') @staticmethod @@ -600,7 +679,11 @@ def get_component_version(inventory_path) -> str: Returns: str: version """ - return Executor.execute_command(inventory_path, f'{WAZUH_CONTROL} info -v') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return Executor.execute_command(inventory_path, f'{WAZUH_CONTROL} info -v') + elif os_type == 'macos': + return Executor.execute_command(inventory_path, f'/Library/Ossec/bin/wazuh-control info -v') @staticmethod @@ -614,7 +697,11 @@ def get_component_revision(inventory_path) -> str: Returns: str: revision number """ - return Executor.execute_command(inventory_path, f'{WAZUH_CONTROL} info -r') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return Executor.execute_command(inventory_path, f'{WAZUH_CONTROL} info -r') + elif os_type == 'macos': + return Executor.execute_command(inventory_path, f'/Library/Ossec/bin/wazuh-control info -r') @staticmethod @@ -628,7 +715,11 @@ def hasAgentClientKeys(inventory_path) -> bool: Returns: bool: True/False """ - return 'true' in Executor.execute_command(inventory_path, f'[ -f {CLIENT_KEYS} ] && echo true || echo false') + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return HostInformation.file_exists(inventory_path, CLIENT_KEYS) + elif os_type == 'macos': + return HostInformation.file_exists(inventory_path, '/Library/Ossec/etc/client.keys') @staticmethod @@ -643,7 +734,12 @@ def isComponentActive(inventory_path, host_role) -> bool: Returns: bool: True/False """ - return 'active' == Executor.execute_command(inventory_path, f'systemctl is-active {host_role}').replace("\n", "") + os_type = HostInformation.get_os_type(inventory_path) + if os_type == 'linux': + return 'active' == Executor.execute_command(inventory_path, f'systemctl is-active {host_role}').replace("\n", "") + elif os_type == 'macos': + return f'com.{host_role.replace("-", ".")}' in Executor.execute_command(inventory_path, f'launchctl list | grep com.{host_role.replace("-", ".")}') + class Waits: diff --git a/deployability/modules/testing/tests/helpers/utils.py b/deployability/modules/testing/tests/helpers/utils.py index aea456c151..24dd874c54 100644 --- a/deployability/modules/testing/tests/helpers/utils.py +++ b/deployability/modules/testing/tests/helpers/utils.py @@ -26,9 +26,9 @@ def extract_ansible_host(file_path) -> str: @staticmethod def check_inventory_connection(inventory_path, attempts=10, sleep=30) -> bool: if 'manager' in inventory_path: - match = re.search(r'/manager-linux-([^-]+)-([^-]+)-', inventory_path) + match = re.search(r'/manager-[^-]+-([^-]+)-([^-]+)-', inventory_path) elif 'agent' in inventory_path: - match = re.search(r'/agent-linux-([^-]+)-([^-]+)-', inventory_path) + match = re.search(r'/agent-[^-]+-([^-]+)-([^-]+)-', inventory_path) if match: os_name = match.group(1)+ '-' + match.group(2) logger.info(f'Checking connection to {os_name}') @@ -40,30 +40,55 @@ def check_inventory_connection(inventory_path, attempts=10, sleep=30) -> bool: except yaml.YAMLError: raise ValueError(logger.error(f'Invalid inventory information in {os_name}')) - host = inventory_data.get('ansible_host') - port = inventory_data.get('ansible_port') - private_key_path = inventory_data.get('ansible_ssh_private_key_file') - username = inventory_data.get('ansible_user') - - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - private_key = paramiko.RSAKey.from_private_key_file(private_key_path) + + if 'ansible_ssh_private_key_file' in inventory_data: + host = inventory_data.get('ansible_host') + port = inventory_data.get('ansible_port') + private_key_path = inventory_data.get('ansible_ssh_private_key_file') + username = inventory_data.get('ansible_user') - for attempt in range(1, attempts + 1): ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) private_key = paramiko.RSAKey.from_private_key_file(private_key_path) - try: - ssh.connect(hostname=host, port=port, username=username, pkey=private_key) - logger.info(f'Connection established successfully in {os_name}') - ssh.close() - return True - except paramiko.AuthenticationException: - logger.error(f'Authentication error. Check SSH credentials in {os_name}') - return False - except Exception as e: - logger.warning(f'Error on attempt {attempt} of {attempts}: {e}') - time.sleep(sleep) + + for attempt in range(1, attempts + 1): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + private_key = paramiko.RSAKey.from_private_key_file(private_key_path) + try: + ssh.connect(hostname=host, port=port, username=username, pkey=private_key) + logger.info(f'Connection established successfully in {os_name}') + ssh.close() + return True + except paramiko.AuthenticationException: + logger.error(f'Authentication error. Check SSH credentials in {os_name}') + return False + except Exception as e: + logger.warning(f'Error on attempt {attempt} of {attempts}: {e}') + time.sleep(sleep) + else: + host = inventory_data.get('ansible_host', None) + port = inventory_data.get('ansible_port', 22) + user = inventory_data.get('ansible_user', None) + password = inventory_data.get('ansible_password', None) + + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + for attempt in range(1, attempts + 1): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + try: + ssh.connect(hostname=host, port=port, username=user, password=password) + logger.info(f'Connection established successfully in {os_name}') + ssh.close() + return True + except paramiko.AuthenticationException: + logger.error(f'Authentication error. Check SSH credentials in {os_name}') + return False + except Exception as e: + logger.warning(f'Error on attempt {attempt} of {attempts}: {e}') + time.sleep(sleep) logger.error(f'Connection attempts failed after {attempts} tries. Connection timeout in {os_name}') return False diff --git a/deployability/modules/testing/tests/test_agent/test_basic_info.py b/deployability/modules/testing/tests/test_agent/test_basic_info.py index 3b81a0765f..1caa6c8cce 100644 --- a/deployability/modules/testing/tests/test_agent/test_basic_info.py +++ b/deployability/modules/testing/tests/test_agent/test_basic_info.py @@ -67,11 +67,18 @@ def setup_test_environment(wazuh_params): def test_wazuh_os_version(wazuh_params): wazuh_api = WazuhAPI(wazuh_params['master']) for agent_names, agent_params in wazuh_params['agents'].items(): - assert HostInformation.dir_exists(agent_params, WAZUH_ROOT), logger.error(f'The {WAZUH_ROOT} is not present in {HostInformation.get_os_name_and_version_from_inventory(agent_params)}') + if HostInformation.get_os_type(agent_params) == 'linux': + assert HostInformation.dir_exists(agent_params, WAZUH_ROOT), logger.error(f'The {WAZUH_ROOT} is not present in {HostInformation.get_os_name_and_version_from_inventory(agent_params)}') + elif HostInformation.get_os_type(agent_params) == 'macos': + assert HostInformation.dir_exists(agent_params, '/Library/Ossec'), logger.error(f'The /Library/Ossec is not present in {HostInformation.get_os_name_and_version_from_inventory(agent_params)}') + expected_condition_func = lambda: 'active' == WazuhAgent.get_agent_status(wazuh_api, agent_names) Waits.dynamic_wait(expected_condition_func, cycles=20, waiting_time=30) assert HostInformation.get_os_version_from_inventory(agent_params) in WazuhAgent.get_agent_os_version_by_name(wazuh_api, agent_names), logger.error('There is a mismatch between the OS version and the OS version of the installed agent') - assert HostInformation.get_os_name_from_inventory(agent_params) in WazuhAgent.get_agent_os_name_by_name(wazuh_api, agent_names).replace(' ', ''), logger.error('There is a mismatch between the OS name and the OS name of the installed agent') + if HostInformation.get_os_type(agent_params) == 'linux': + assert HostInformation.get_os_name_from_inventory(agent_params) in WazuhAgent.get_agent_os_name_by_name(wazuh_api, agent_names).replace(' ', ''), logger.error('There is a mismatch between the OS name and the OS name of the installed agent') + elif HostInformation.get_os_type(agent_params) == 'macos': + assert 'macos' in WazuhAgent.get_agent_os_name_by_name(wazuh_api, agent_names).replace(' ', ''), logger.error('There is a mismatch between the OS name and the OS name of the installed agent') def test_wazuh_version(wazuh_params): diff --git a/deployability/modules/testing/tests/test_agent/test_connection.py b/deployability/modules/testing/tests/test_agent/test_connection.py index 4a7297596a..6d2377dc6f 100644 --- a/deployability/modules/testing/tests/test_agent/test_connection.py +++ b/deployability/modules/testing/tests/test_agent/test_connection.py @@ -73,7 +73,7 @@ def test_connection(wazuh_params): def test_status(wazuh_params): for agent in wazuh_params['agents'].values(): - assert 'active' in GeneralComponentActions.get_component_status(agent, 'wazuh-agent'), logger.error(f'The {HostInformation.get_os_name_and_version_from_inventory(agent)} is not active') + assert 'active' in GeneralComponentActions.get_component_status(agent, 'wazuh-agent') or 'is running' in GeneralComponentActions.get_component_status(agent, 'wazuh-agent'), logger.error(f'The {HostInformation.get_os_name_and_version_from_inventory(agent)} is not active') def test_service(wazuh_params): diff --git a/deployability/modules/testing/tests/test_agent/test_install.py b/deployability/modules/testing/tests/test_agent/test_install.py index 059d46273f..b06c00b668 100644 --- a/deployability/modules/testing/tests/test_agent/test_install.py +++ b/deployability/modules/testing/tests/test_agent/test_install.py @@ -85,11 +85,14 @@ def test_installation(wazuh_params): WazuhAgent.perform_install_and_scan_for_agent(agent_params, agent_names, wazuh_params) # Testing installation directory - for agent in wazuh_params['agents'].values(): - assert HostInformation.dir_exists(agent, WAZUH_ROOT), logger.error(f'The {WAZUH_ROOT} is not present in {HostInformation.get_os_name_and_version_from_inventory(agent)}') + for agent_names, agent_params in wazuh_params['agents'].items(): + if HostInformation.get_os_type(agent_params) == 'linux': + assert HostInformation.dir_exists(agent_params, WAZUH_ROOT), logger.error(f'The {WAZUH_ROOT} is not present in {HostInformation.get_os_name_and_version_from_inventory(agent_params)}') + elif HostInformation.get_os_type(agent_params) == 'macos': + assert HostInformation.dir_exists(agent_params, '/Library/Ossec'), logger.error(f'The /Library/Ossec is not present in {HostInformation.get_os_name_and_version_from_inventory(agent_params)}') def test_status(wazuh_params): for agent in wazuh_params['agents'].values(): agent_status = GeneralComponentActions.get_component_status(agent, 'wazuh-agent') - assert 'loaded' in agent_status, logger.error(f'The {HostInformation.get_os_name_and_version_from_inventory(agent)} status is not loaded') + assert 'loaded' in agent_status or 'not running' in agent_status, logger.error(f'The {HostInformation.get_os_name_and_version_from_inventory(agent)} status is not loaded') diff --git a/deployability/modules/testing/tests/test_agent/test_registration.py b/deployability/modules/testing/tests/test_agent/test_registration.py index dc756410d5..fa1a5d911f 100644 --- a/deployability/modules/testing/tests/test_agent/test_registration.py +++ b/deployability/modules/testing/tests/test_agent/test_registration.py @@ -68,7 +68,7 @@ def test_status(wazuh_params): for agent_names, agent_params in wazuh_params['agents'].items(): WazuhAgent.register_agent(agent_params, wazuh_params['master']) for agent in wazuh_params['agents'].values(): - assert 'active' in GeneralComponentActions.get_component_status(agent, 'wazuh-agent'), logger.error(f'The {HostInformation.get_os_name_and_version_from_inventory(agent)} is not active') + assert 'active' in GeneralComponentActions.get_component_status(agent, 'wazuh-agent') or 'is running' in GeneralComponentActions.get_component_status(agent, 'wazuh-agent'), logger.error(f'The {HostInformation.get_os_name_and_version_from_inventory(agent)} is not active') def test_connection(wazuh_params): @@ -81,7 +81,7 @@ def test_connection(wazuh_params): def test_service(wazuh_params): wazuh_api = WazuhAPI(wazuh_params['master']) for agent_names, agent_params in wazuh_params['agents'].items(): - assert GeneralComponentActions.isComponentActive(agent_params, 'wazuh-agent'), logger.error(f'{agent_names} is not active by API') + assert GeneralComponentActions.isComponentActive(agent_params, 'wazuh-agent'), logger.error(f'{agent_names} is not active by command') expected_condition_func = lambda: 'active' == WazuhAgent.get_agent_status(wazuh_api, agent_names) Waits.dynamic_wait(expected_condition_func, cycles=20, waiting_time=30) diff --git a/deployability/modules/testing/tests/test_agent/test_restart.py b/deployability/modules/testing/tests/test_agent/test_restart.py index 734e4791e3..6fee856ec0 100644 --- a/deployability/modules/testing/tests/test_agent/test_restart.py +++ b/deployability/modules/testing/tests/test_agent/test_restart.py @@ -69,7 +69,7 @@ def test_restart(wazuh_params): def test_status(wazuh_params): for agent_names, agent_params in wazuh_params['agents'].items(): - assert 'active' in GeneralComponentActions.get_component_status(agent_params, 'wazuh-agent'), logger.error(f'{agent_names} is not active by command') + assert 'active' in GeneralComponentActions.get_component_status(agent_params, 'wazuh-agent') or 'is running' in GeneralComponentActions.get_component_status(agent_params, 'wazuh-agent'), logger.error(f'{agent_names} is not active by command') def test_connection(wazuh_params): diff --git a/deployability/modules/testing/tests/test_agent/test_stop.py b/deployability/modules/testing/tests/test_agent/test_stop.py index a347bce95f..7d7eda4bfc 100644 --- a/deployability/modules/testing/tests/test_agent/test_stop.py +++ b/deployability/modules/testing/tests/test_agent/test_stop.py @@ -71,8 +71,7 @@ def test_service(wazuh_params): GeneralComponentActions.component_stop(agent_params, 'wazuh-agent') for agent_names, agent_params in wazuh_params['agents'].items(): - assert 'inactive' in GeneralComponentActions.get_component_status(agent_params, 'wazuh-agent'), logger.error(f'{agent_names} is still active by command') - assert not GeneralComponentActions.isComponentActive(agent_params, 'wazuh-agent'), logger.error(f'{agent_names} is still active by command') + assert 'inactive' in GeneralComponentActions.get_component_status(agent_params, 'wazuh-agent') or 'not running' in GeneralComponentActions.get_component_status(agent_params, 'wazuh-agent'), logger.error(f'{agent_names} is still active by command') expected_condition_func = lambda: 'disconnected' == WazuhAgent.get_agent_status(wazuh_api, agent_names) Waits.dynamic_wait(expected_condition_func, cycles=20, waiting_time=30) diff --git a/deployability/modules/testing/tests/test_agent/test_uninstall.py b/deployability/modules/testing/tests/test_agent/test_uninstall.py index 953e73bc5e..b61e952f34 100644 --- a/deployability/modules/testing/tests/test_agent/test_uninstall.py +++ b/deployability/modules/testing/tests/test_agent/test_uninstall.py @@ -66,12 +66,16 @@ def setup_test_environment(wazuh_params): def test_uninstall(wazuh_params): for agent_names, agent_params in wazuh_params['agents'].items(): assert GeneralComponentActions.isComponentActive(agent_params, 'wazuh-agent'), logger.error(f'{agent_names} is not Active before the installation') - assert HostInformation.dir_exists(agent_params, WAZUH_ROOT), logger.error(f'The {WAZUH_ROOT} is not present in the host {agent_names}') + if 'linux' in agent_params: + assert HostInformation.dir_exists(agent_params, WAZUH_ROOT), logger.error(f'The {WAZUH_ROOT} is not present in the host {agent_names}') + elif 'macos' in wazuh_params: + assert HostInformation.dir_exists(agent_params, '/Library/Ossec'), logger.error(f'The /Library/Ossec is not present in the host {agent_names}') - # Agent installation + # Agent uninstallation for agent_names, agent_params in wazuh_params['agents'].items(): WazuhAgent.perform_uninstall_and_scan_for_agent(agent_params,wazuh_params) + # Manager uninstallation status check for agent_names, agent_params in wazuh_params['agents'].items(): assert 'Disconnected' in WazuhManager.get_agent_control_info(wazuh_params['master']), logger.error(f'{agent_names} is still connected in the Manager') diff --git a/deployability/modules/workflow_engine/examples/agent/aws/test-agent-complete-macOs.yaml b/deployability/modules/workflow_engine/examples/agent/aws/test-agent-complete-macOs.yaml new file mode 100755 index 0000000000..2ae2d26e5f --- /dev/null +++ b/deployability/modules/workflow_engine/examples/agent/aws/test-agent-complete-macOs.yaml @@ -0,0 +1,115 @@ +version: 0.1 +description: This workflow is used to test agents' deployment for DDT1 PoC +variables: + agent-os: + # Run one at a time as there are limitations on the number of hosts (Inform @dev-devops-team about your usage, dedicated hosts) + - macos-sonoma-14.3-arm64 + #- macos-ventura-13.6.4-arm64 + #- macos-sonoma-14.3-amd64 + #- macos-ventura-13.6.4-amd64 + manager-os: linux-ubuntu-22.04-amd64 + infra-provider: aws + working-dir: /tmp/dtt1-poc + +tasks: + # Unique manager allocate task + - task: "allocate-manager-{manager-os}" + description: "Allocate resources for the manager." + do: + this: process + with: + path: python3 + args: + - modules/allocation/main.py + - action: create + - provider: "{infra-provider}" + - size: large + - composite-name: "{manager-os}" + - inventory-output: "{working-dir}/manager-{manager-os}/inventory.yaml" + - track-output: "{working-dir}/manager-{manager-os}/track.yaml" + - label-termination-date: "1d" + - label-team: "qa" + on-error: "abort-all" + cleanup: + this: process + with: + path: python3 + args: + - modules/allocation/main.py + - action: delete + - track-output: "{working-dir}/manager-{manager-os}/track.yaml" + + # Unique agent allocate task + - task: "allocate-agent-{agent}" + description: "Allocate resources for the agent." + do: + this: process + with: + path: python3 + args: + - modules/allocation/main.py + - action: create + - provider: "{infra-provider}" + - size: small + - composite-name: "{agent}" + - inventory-output: "{working-dir}/agent-{agent}/inventory.yaml" + - track-output: "{working-dir}/agent-{agent}/track.yaml" + - label-termination-date: "1d" + - label-team: "qa" + on-error: "abort-all" + foreach: + - variable: agent-os + as: agent + cleanup: + this: process + with: + path: python3 + args: + - modules/allocation/main.py + - action: delete + - track-output: "{working-dir}/agent-{agent}/track.yaml" + depends-on: + - "provision-manager-{manager-os}" + + # Unique manager provision task + - task: "provision-manager-{manager-os}" + description: "Provision the manager." + do: + this: process + with: + path: python3 + args: + - modules/provision/main.py + - inventory: "{working-dir}/manager-{manager-os}/inventory.yaml" + - install: + - component: wazuh-manager + type: assistant + version: 4.7.3 + live: True + depends-on: + - "allocate-manager-{manager-os}" + on-error: "abort-all" + + + # Generic agent test task + - task: "run-agent-{agent}-tests" + description: "Run tests install for the agent {agent}." + do: + this: process + with: + path: python3 + args: + - modules/testing/main.py + - targets: + - wazuh-1: "{working-dir}/manager-{manager-os}/inventory.yaml" + - agent: "{working-dir}/agent-{agent}/inventory.yaml" + - tests: "install,registration,basic_info,connection,restart,stop,uninstall" + - component: "agent" + - wazuh-version: "4.7.3" + - wazuh-revision: "40714" + - live: "True" + foreach: + - variable: agent-os + as: agent + depends-on: + - "allocate-agent-{agent}" diff --git a/deployability/modules/workflow_engine/examples/agent/aws/test-agent-suse.yaml b/deployability/modules/workflow_engine/examples/agent/aws/test-agent-suse.yaml index e97b123b8b..5f2c1e1047 100644 --- a/deployability/modules/workflow_engine/examples/agent/aws/test-agent-suse.yaml +++ b/deployability/modules/workflow_engine/examples/agent/aws/test-agent-suse.yaml @@ -122,7 +122,7 @@ tasks: - targets: - wazuh-1: "{working-dir}/manager-{manager-os}/inventory.yaml" - agent: "{working-dir}/agent-{agent}/inventory.yaml" - - tests: "install,registration,restart,stop,uninstall" + - tests: "install,registration,basic_info,connection,restart,stop,uninstall" - component: "agent" - wazuh-version: "4.7.3" - wazuh-revision: "40714" diff --git a/deployability/modules/workflow_engine/examples/agent/vagrant/test-agent-complete-macOs.yaml b/deployability/modules/workflow_engine/examples/agent/vagrant/test-agent-complete-macOs.yaml new file mode 100755 index 0000000000..d1e35d3e71 --- /dev/null +++ b/deployability/modules/workflow_engine/examples/agent/vagrant/test-agent-complete-macOs.yaml @@ -0,0 +1,113 @@ +version: 0.1 +description: This workflow is used to test agents' deployment for DDT1 PoC +variables: + agent-os: + # Run one at a time as there are limitations on the number of hosts + - macos-sonoma-14.0-arm64 + #- macos-ventura-13.4.1-arm64 + manager-os: linux-ubuntu-22.04-amd64 + infra-provider: vagrant + working-dir: /tmp/dtt1-poc + +tasks: + # Unique manager allocate task + - task: "allocate-manager-{manager-os}" + description: "Allocate resources for the manager." + do: + this: process + with: + path: python3 + args: + - modules/allocation/main.py + - action: create + - provider: "aws" + - size: large + - composite-name: "{manager-os}" + - inventory-output: "{working-dir}/manager-{manager-os}/inventory.yaml" + - track-output: "{working-dir}/manager-{manager-os}/track.yaml" + - label-termination-date: "1d" + - label-team: "qa" + on-error: "abort-all" + cleanup: + this: process + with: + path: python3 + args: + - modules/allocation/main.py + - action: delete + - track-output: "{working-dir}/manager-{manager-os}/track.yaml" + + # Unique agent allocate task + - task: "allocate-agent-{agent}" + description: "Allocate resources for the agent." + do: + this: process + with: + path: python3 + args: + - modules/allocation/main.py + - action: create + - provider: "{infra-provider}" + - size: small + - composite-name: "{agent}" + - inventory-output: "{working-dir}/agent-{agent}/inventory.yaml" + - track-output: "{working-dir}/agent-{agent}/track.yaml" + - label-termination-date: "1d" + - label-team: "qa" + on-error: "abort-all" + foreach: + - variable: agent-os + as: agent + cleanup: + this: process + with: + path: python3 + args: + - modules/allocation/main.py + - action: delete + - track-output: "{working-dir}/agent-{agent}/track.yaml" + depends-on: + - "provision-manager-{manager-os}" + + # Unique manager provision task + - task: "provision-manager-{manager-os}" + description: "Provision the manager." + do: + this: process + with: + path: python3 + args: + - modules/provision/main.py + - inventory: "{working-dir}/manager-{manager-os}/inventory.yaml" + - install: + - component: wazuh-manager + type: assistant + version: 4.7.3 + live: True + depends-on: + - "allocate-manager-{manager-os}" + on-error: "abort-all" + + + # Generic agent test task + - task: "run-agent-{agent}-tests" + description: "Run tests install for the agent {agent}." + do: + this: process + with: + path: python3 + args: + - modules/testing/main.py + - targets: + - wazuh-1: "{working-dir}/manager-{manager-os}/inventory.yaml" + - agent: "{working-dir}/agent-{agent}/inventory.yaml" + - tests: "install,registration,basic_info,connection,restart,stop,uninstall" + - component: "agent" + - wazuh-version: "4.7.3" + - wazuh-revision: "40714" + - live: "True" + foreach: + - variable: agent-os + as: agent + depends-on: + - "allocate-agent-{agent}"