Skip to content

Commit

Permalink
Merge pull request #5264 from wazuh/enhancement/5229-macOS-tests-added
Browse files Browse the repository at this point in the history
macOs test added
  • Loading branch information
rauldpm authored Apr 26, 2024
2 parents 9b48f37 + 333a6b7 commit 74455bb
Show file tree
Hide file tree
Showing 15 changed files with 584 additions and 157 deletions.
10 changes: 8 additions & 2 deletions deployability/modules/generic/ansible.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Copyright (C) 2015, Wazuh Inc.
# Created by Wazuh, Inc. <info@wazuh.com>.
# 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
Expand All @@ -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:
Expand Down Expand Up @@ -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
169 changes: 105 additions & 64 deletions deployability/modules/testing/tests/helpers/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
])
Expand All @@ -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 /'
])
Expand All @@ -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/<address>MANAGER_IP<\/address>/<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/<address>MANAGER_IP<\/address>/<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/<address>MANAGER_IP<\/address>/<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>{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>{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>{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:
Expand Down Expand Up @@ -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():
Expand All @@ -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
Expand All @@ -275,20 +307,25 @@ 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.
Args:
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:
Expand All @@ -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:
"""
Expand Down
54 changes: 36 additions & 18 deletions deployability/modules/testing/tests/helpers/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading

0 comments on commit 74455bb

Please sign in to comment.