From fd13dc95dfc33c883c602e4c67e4fea1f5628fe2 Mon Sep 17 00:00:00 2001 From: Julian Morales Date: Thu, 17 Jun 2021 12:37:09 -0700 Subject: [PATCH 01/16] Base test for macos file_status IT development --- .../data/wazuh_macos_file_status_basic.yaml | 23 +++++ .../test_macos_file_status_basic.py | 97 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml create mode 100644 tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml new file mode 100644 index 0000000000..52d730449b --- /dev/null +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml @@ -0,0 +1,23 @@ +- tags: + - test_macos_file_status_basic + apply_to_modules: + - test_macos_file_status_basic + sections: + - section: client + elements: + - server: + elements: + - address: + value: '127.0.0.1' + - protocol: + value: 'tcp' + - section: localfile + elements: + - location: + value: 'macos' + - log_format: + value: 'macos' + - only-future-events: + value: ONLY_FUTURE_EVENTS + - query: + value: 'message CONTAINS "testing message"' diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py new file mode 100644 index 0000000000..88a8a78485 --- /dev/null +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -0,0 +1,97 @@ +# Copyright (C) 2015-2021, Wazuh Inc. +# Created by Wazuh, Inc. . +# This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 + +import os +import pytest +import json +import re + +import wazuh_testing.logcollector as logcollector +from wazuh_testing.tools.configuration import load_wazuh_configurations +from wazuh_testing.remote import check_agent_received_message +from wazuh_testing.tools import WAZUH_PATH + +# Marks +pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] + +# Configuration +test_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') +configurations_path = os.path.join(test_data_path, 'wazuh_macos_file_status_basic.yaml') +parameters = [{'ONLY_FUTURE_EVENTS': 'yes'}, {'ONLY_FUTURE_EVENTS': 'no'}] +metadata = [{'only-future-events': 'yes'}, {'only-future-events': 'no'}] + +# Configuration data +configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters, metadata=metadata) +configuration_ids = [f"{x['ONLY_FUTURE_EVENTS']}" for x in parameters] + + +file_status_path = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') + +# configurations = load_wazuh_configurations(configurations_path, __name__) + +macos_log_messages = [ + { + 'command': 'logger', + 'message': "Logger testing message - file status", + } +] + + +# Fixtures +@pytest.fixture(scope="module", params=configurations, ids=configuration_ids) +def get_configuration(request): + """Get configurations from the module.""" + return request.param + + + +@pytest.fixture(scope="module") +def get_connection_configuration(): + """Get configurations from the module.""" + return logcollector.DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION + + +@pytest.mark.parametrize('macos_message', macos_log_messages) +def test_macos_file_status_basic(get_configuration, configure_environment, get_connection_configuration, + init_authd_remote_simulator, macos_message, restart_logcollector): + + """Check if logcollector gather correctly macOS unified logging system events. + + This test uses logger tool and a custom log to generate ULS events. The agent is connected to a authd simulator + and sended events are gather using remoted simulator tool. + + Raises: + TimeoutError: If the expected callback is not generated. + """ + + # Remove status file to check if agent behavior is as expected + os.remove(file_status_path) if os.path.exists(file_status_path) else None + + expected_macos_message = "" + log_command = macos_message['command'] + + macos_logcollector_monitored = logcollector.callback_monitoring_macos_logs + wazuh_log_monitor.start(timeout=30, callback=macos_logcollector_monitored, + error_message=logcollector.GENERIC_CALLBACK_ERROR_TARGET_SOCKET) + + logcollector.generate_macos_logger_log(macos_message['message']) + expected_macos_message = logcollector.format_macos_message_pattern(macos_message['command'], + macos_message['message']) + + check_agent_received_message(remoted_simulator.rcv_msg_queue, expected_macos_message, timeout=40) + + file_status_json = "" + + try: + with open(file_status_path) as json_status: + file_status_json = json.loads(json_status.read()) + except EnvironmentError: + assert False, "Error opening '{}'".format(file_status_path) + + # Check if json has a structure + assert file_status_json["macos"], "Error finding 'macos' key" + assert file_status_json["macos"]["timestamp"], "Error finding 'timestamp' key inside 'macos'" + assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}-\d{4}$', file_status_json["macos"]["timestamp"]), "Error of timestamp format" + assert file_status_json["macos"]["settings"], "Error finding 'settings' key inside 'macos'" + From d293247c08932d1f2682e7fe5a43f7ecf944b816 Mon Sep 17 00:00:00 2001 From: Mariano Koremblum Date: Fri, 18 Jun 2021 00:04:56 -0300 Subject: [PATCH 02/16] Logcollector macOS ULS feature file status IT improved --- .../data/wazuh_macos_file_status_basic.yaml | 7 +++-- .../test_macos/macos_utils.py | 26 ++++++++++++++++ .../test_macos_file_status_basic.py | 30 +++++++++---------- 3 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 tests/integration/test_logcollector/test_macos/macos_utils.py diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml index 52d730449b..13d41aa303 100644 --- a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml @@ -17,7 +17,10 @@ value: 'macos' - log_format: value: 'macos' - - only-future-events: - value: ONLY_FUTURE_EVENTS - query: value: 'message CONTAINS "testing message"' + attributes: + - level: 'default' + - type: 'log,trace' + - only-future-events: + value: ONLY_FUTURE_EVENTS diff --git a/tests/integration/test_logcollector/test_macos/macos_utils.py b/tests/integration/test_logcollector/test_macos/macos_utils.py new file mode 100644 index 0000000000..ac48364f86 --- /dev/null +++ b/tests/integration/test_logcollector/test_macos/macos_utils.py @@ -0,0 +1,26 @@ +# Copyright (C) 2015-2021, Wazuh Inc. +# Created by Wazuh, Inc. . +# This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 + +def compose_settings(__type="", __level="", __predicate="", __is_sierra=False): + + settings_str = "" + + if (__is_sierra): + settings_str = "/usr/bin/script -q /dev/null " + + settings_str = settings_str + "/usr/bin/log stream --style syslog " + + if (__type): + __type = __type.replace(" ", "") + for t in __type.split(","): + settings_str = settings_str + "--type " + t + " " + + if (__level): + __level = __level.replace(" ", "") + settings_str = settings_str + "--level " + __level + " " + + if(__predicate): + settings_str = settings_str + "--predicate " + __predicate + + return settings_str diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index 88a8a78485..6724c327d8 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -6,8 +6,9 @@ import pytest import json import re - +import time import wazuh_testing.logcollector as logcollector +import macos_utils from wazuh_testing.tools.configuration import load_wazuh_configurations from wazuh_testing.remote import check_agent_received_message from wazuh_testing.tools import WAZUH_PATH @@ -25,11 +26,8 @@ configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters, metadata=metadata) configuration_ids = [f"{x['ONLY_FUTURE_EVENTS']}" for x in parameters] - file_status_path = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') -# configurations = load_wazuh_configurations(configurations_path, __name__) - macos_log_messages = [ { 'command': 'logger', @@ -37,15 +35,12 @@ } ] - # Fixtures @pytest.fixture(scope="module", params=configurations, ids=configuration_ids) def get_configuration(request): """Get configurations from the module.""" return request.param - - @pytest.fixture(scope="module") def get_connection_configuration(): """Get configurations from the module.""" @@ -56,10 +51,10 @@ def get_connection_configuration(): def test_macos_file_status_basic(get_configuration, configure_environment, get_connection_configuration, init_authd_remote_simulator, macos_message, restart_logcollector): - """Check if logcollector gather correctly macOS unified logging system events. + """Checks if logcollector stores correctly "macos"-formatted localfile data. - This test uses logger tool and a custom log to generate ULS events. The agent is connected to a authd simulator - and sended events are gather using remoted simulator tool. + This test uses logger tool and a custom log to generate an ULS event. The agent is connected to the authd simulator + and sends an event to trigger the file_status.json update. Raises: TimeoutError: If the expected callback is not generated. @@ -68,21 +63,21 @@ def test_macos_file_status_basic(get_configuration, configure_environment, get_c # Remove status file to check if agent behavior is as expected os.remove(file_status_path) if os.path.exists(file_status_path) else None - expected_macos_message = "" log_command = macos_message['command'] - + macos_logcollector_monitored = logcollector.callback_monitoring_macos_logs wazuh_log_monitor.start(timeout=30, callback=macos_logcollector_monitored, error_message=logcollector.GENERIC_CALLBACK_ERROR_TARGET_SOCKET) logcollector.generate_macos_logger_log(macos_message['message']) - expected_macos_message = logcollector.format_macos_message_pattern(macos_message['command'], - macos_message['message']) + expected_message = logcollector.format_macos_message_pattern(macos_message['command'], macos_message['message']) - check_agent_received_message(remoted_simulator.rcv_msg_queue, expected_macos_message, timeout=40) + check_agent_received_message(remoted_simulator.rcv_msg_queue, expected_message, timeout=40) file_status_json = "" + time.sleep(5) + try: with open(file_status_path) as json_status: file_status_json = json.loads(json_status.read()) @@ -94,4 +89,7 @@ def test_macos_file_status_basic(get_configuration, configure_environment, get_c assert file_status_json["macos"]["timestamp"], "Error finding 'timestamp' key inside 'macos'" assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}-\d{4}$', file_status_json["macos"]["timestamp"]), "Error of timestamp format" assert file_status_json["macos"]["settings"], "Error finding 'settings' key inside 'macos'" - + conf_predicate = get_configuration['sections'][1]['elements'][2]['query']['value'] + conf_level = get_configuration['sections'][1]['elements'][2]['query']['attributes'][0]['level'] + conf_type = get_configuration['sections'][1]['elements'][2]['query']['attributes'][1]['type'] + assert file_status_json["macos"]["settings"] == macos_utils.compose_settings(conf_type, conf_level, conf_predicate) From f4b9a4ab978f3037b9ce97b51d66b9faf10bcf17 Mon Sep 17 00:00:00 2001 From: Julian Morales Date: Fri, 18 Jun 2021 10:42:51 -0700 Subject: [PATCH 03/16] file status updating time reduced --- .../test_macos/test_macos_file_status_basic.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index 6724c327d8..aa7df2ef89 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -9,6 +9,7 @@ import time import wazuh_testing.logcollector as logcollector import macos_utils +from wazuh_testing.fim import change_internal_options from wazuh_testing.tools.configuration import load_wazuh_configurations from wazuh_testing.remote import check_agent_received_message from wazuh_testing.tools import WAZUH_PATH @@ -35,6 +36,13 @@ } ] +file_status_update = 4 + +def extra_configuration_before_yield(): + # Set default values + os.remove(file_status_path) if os.path.exists(file_status_path) else None + change_internal_options('logcollector.vcheck_files', str(file_status_update)) + # Fixtures @pytest.fixture(scope="module", params=configurations, ids=configuration_ids) def get_configuration(request): @@ -76,7 +84,8 @@ def test_macos_file_status_basic(get_configuration, configure_environment, get_c file_status_json = "" - time.sleep(5) + # Waiting for file_status.json to be updated with macOS data by logcollector + time.sleep(file_status_update + 1) try: with open(file_status_path) as json_status: From 36a6fdea01b96c623ac00c5509075eb3fea95d25 Mon Sep 17 00:00:00 2001 From: Julian Morales Date: Fri, 18 Jun 2021 11:44:25 -0700 Subject: [PATCH 04/16] fixes code style in file_status --- .../test_macos/test_macos_file_status_basic.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index aa7df2ef89..9becd805e7 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -38,17 +38,20 @@ file_status_update = 4 + def extra_configuration_before_yield(): # Set default values os.remove(file_status_path) if os.path.exists(file_status_path) else None change_internal_options('logcollector.vcheck_files', str(file_status_update)) + # Fixtures @pytest.fixture(scope="module", params=configurations, ids=configuration_ids) def get_configuration(request): """Get configurations from the module.""" return request.param + @pytest.fixture(scope="module") def get_connection_configuration(): """Get configurations from the module.""" @@ -57,7 +60,7 @@ def get_connection_configuration(): @pytest.mark.parametrize('macos_message', macos_log_messages) def test_macos_file_status_basic(get_configuration, configure_environment, get_connection_configuration, - init_authd_remote_simulator, macos_message, restart_logcollector): + init_authd_remote_simulator, macos_message, restart_logcollector): """Checks if logcollector stores correctly "macos"-formatted localfile data. @@ -96,7 +99,8 @@ def test_macos_file_status_basic(get_configuration, configure_environment, get_c # Check if json has a structure assert file_status_json["macos"], "Error finding 'macos' key" assert file_status_json["macos"]["timestamp"], "Error finding 'timestamp' key inside 'macos'" - assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}-\d{4}$', file_status_json["macos"]["timestamp"]), "Error of timestamp format" + assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}-\d{4}$', + file_status_json["macos"]["timestamp"]), "Error of timestamp format" assert file_status_json["macos"]["settings"], "Error finding 'settings' key inside 'macos'" conf_predicate = get_configuration['sections'][1]['elements'][2]['query']['value'] conf_level = get_configuration['sections'][1]['elements'][2]['query']['attributes'][0]['level'] From a8681630912560fe5a58dc52b0e132cb6b97a46c Mon Sep 17 00:00:00 2001 From: Julian Morales Date: Sun, 20 Jun 2021 15:02:34 -0700 Subject: [PATCH 05/16] Adds the documentation of the file_status_basic IT. --- .../integration/test_logcollector/index.md | 9 +++++++ .../test_logcollector/test_macos/index.md | 3 +++ .../test_macos_file_status_basic.md | 27 +++++++++++++++++++ .../test_macos_file_status_basic.py | 4 ++- 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md diff --git a/docs/tests/integration/test_logcollector/index.md b/docs/tests/integration/test_logcollector/index.md index 6611505b3f..ab25bb6dc8 100644 --- a/docs/tests/integration/test_logcollector/index.md +++ b/docs/tests/integration/test_logcollector/index.md @@ -41,6 +41,15 @@ produced while the agent was stopped. For each location and exclude option specified in the configuration file, check if `logcollector` is analyzing or excluding the required files. +#### Test macos + +For the macos log format, test the basic operation: +- Collect logs from `log stream` +- Collect logs from `log show` (only future events) +- Correctly filters/generates the predicate of `log`. +- Updates and correctly generates `file_status.json` file +- Detects invalid configurations in the localfile + ### Tier 1 #### Test location custom sockets diff --git a/docs/tests/integration/test_logcollector/test_macos/index.md b/docs/tests/integration/test_logcollector/test_macos/index.md index 175da2afb9..8c76b547dd 100644 --- a/docs/tests/integration/test_logcollector/test_macos/index.md +++ b/docs/tests/integration/test_logcollector/test_macos/index.md @@ -18,6 +18,9 @@ Confirm that logcollector works correctly for unified logging system events in m ## List of tests +- **[Test macOS file status basic](test_macos_file_status_basic.md)**: Checks if `wazuh-logcollector` correctly generates +the `file_status.json` file used by `only future events`. + - **[Test macOS format basic](test_macos_format_basic.md)**: Check if `wazuh-logcollector` gather corrrectly generated unified logging system events. diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md new file mode 100644 index 0000000000..9b4681b5a2 --- /dev/null +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md @@ -0,0 +1,27 @@ +# Test macOS format basic +## Overview + +Checks if `wazuh-logcollector` correctly generates the `file_status.json` file used by `only future events`. + +## Objective + +- To confirm that the Wazuh macOS agent generates a valid status file (`file_status.json`) +that can be used at the next startup of Wazuh-Logcollector + +## General info + +|Tier | Total | Time spent | +| :--:| :--: | :--: | +| 0 | 2 | 65s | + + +## Expected behavior + +- Fail if `wazuh-logcollector` does not gather generated unified logging system event or does not send it to the manager +- Fail if `wazuh-logcollector` does not create the status file `status_file.json` +- Fail if `wazuh-logcollector` saves incorrectly formatted, or invalid data in the status file `status_file.json`. + + +## Code documentation + +::: tests.integration.test_logcollector.test_macos.test_macos_file_status_basic diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index 9becd805e7..e37ef61093 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -40,8 +40,10 @@ def extra_configuration_before_yield(): - # Set default values + """Delete old OFE data and change file status update interval.""" + # Remove old data from json_status os.remove(file_status_path) if os.path.exists(file_status_path) else None + # Set default values change_internal_options('logcollector.vcheck_files', str(file_status_update)) From 70c966e2befced430cadce8c8ff3108085b1f439 Mon Sep 17 00:00:00 2001 From: Julian Morales Date: Mon, 21 Jun 2021 09:31:18 -0700 Subject: [PATCH 06/16] Adds base macos bad predicate IT --- .../wazuh_macos_file_status_predicate.yaml | 26 ++++ .../test_macos_file_status_basic.py | 2 - .../test_macos_file_status_predicate.py | 112 ++++++++++++++++++ 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml create mode 100644 tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml new file mode 100644 index 0000000000..615dc0eb7f --- /dev/null +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml @@ -0,0 +1,26 @@ +- tags: + - test_macos_file_status_predicate + apply_to_modules: + - test_macos_file_status_predicate + sections: + - section: client + elements: + - server: + elements: + - address: + value: '127.0.0.1' + - protocol: + value: 'tcp' + - section: localfile + elements: + - location: + value: 'macos' + - log_format: + value: 'macos' + - query: + value: 'message =!= \"testing message"' + attributes: + - level: 'default' + - type: 'log,trace' + - only-future-events: + value: ONLY_FUTURE_EVENTS diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index e37ef61093..65e6a87ca2 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -76,8 +76,6 @@ def test_macos_file_status_basic(get_configuration, configure_environment, get_c # Remove status file to check if agent behavior is as expected os.remove(file_status_path) if os.path.exists(file_status_path) else None - log_command = macos_message['command'] - macos_logcollector_monitored = logcollector.callback_monitoring_macos_logs wazuh_log_monitor.start(timeout=30, callback=macos_logcollector_monitored, error_message=logcollector.GENERIC_CALLBACK_ERROR_TARGET_SOCKET) diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py new file mode 100644 index 0000000000..61ed132ca5 --- /dev/null +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py @@ -0,0 +1,112 @@ +# Copyright (C) 2015-2021, Wazuh Inc. +# Created by Wazuh, Inc. . +# This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 + +import os +import pytest +import json +import re +import time +import wazuh_testing.logcollector as logcollector +from wazuh_testing.fim import change_internal_options +from wazuh_testing.tools.configuration import load_wazuh_configurations +from wazuh_testing.tools import LOG_FILE_PATH, WAZUH_PATH +from wazuh_testing import global_parameters +from wazuh_testing.tools.monitoring import FileMonitor + + + +# Marks +pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] + +# Configuration +test_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') +configurations_path = os.path.join(test_data_path, 'wazuh_macos_file_status_predicate.yaml') +parameters = [{'ONLY_FUTURE_EVENTS': 'yes'}, {'ONLY_FUTURE_EVENTS': 'no'}] +metadata = [{'only-future-events': 'yes'}, {'only-future-events': 'no'}] + +# Configuration data +configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters, metadata=metadata) +configuration_ids = [f"{x['ONLY_FUTURE_EVENTS']}" for x in parameters] + +file_status_path = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') + +macos_log_messages = [ + { + 'command': 'logger', + 'message': "Logger testing message - file status", + } +] + +file_status_update = 4 + +wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) + + +def extra_configuration_before_yield(): + """Delete old OFE data and change file status update interval.""" + # Remove old data from json_status + os.remove(file_status_path) if os.path.exists(file_status_path) else None + # Set default values + change_internal_options('logcollector.vcheck_files', str(file_status_update)) + +def callback_log_bad_predicate(line): + match = re.match(r'.*Execution error \'log:', line) + if match: + return True + return None + +def callback_log_exit_log(line): + match = re.match(r'.*macOS \'log stream\' process exited, pid:', line) + if match: + return True + return None + +# Fixtures +@pytest.fixture(scope="module", params=configurations, ids=configuration_ids) +def get_configuration(request): + """Get configurations from the module.""" + return request.param + + +@pytest.fixture(scope="module") +def get_connection_configuration(): + """Get configurations from the module.""" + return logcollector.DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION + + +@pytest.mark.parametrize('macos_message', macos_log_messages) +def test_macos_file_status_predicate(get_configuration, configure_environment, get_connection_configuration, + init_authd_remote_simulator, macos_message, restart_logcollector): + + """Checks if logcollector stores correctly "macos"-formatted localfile data. + + This test uses logger tool and a custom log to generate an ULS event. The agent is connected to the authd simulator + and sends an event to trigger the file_status.json update. + + Raises: + TimeoutError: If the expected callback is not generated. + """ + + wazuh_log_monitor.start(timeout=global_parameters.default_timeout, + callback=callback_log_bad_predicate, + error_message="log 1: ") + + wazuh_log_monitor.start(timeout=global_parameters.default_timeout, + callback=callback_log_exit_log, + error_message="log 2: ") + + file_status_json = "" + + # Waiting for file_status.json to be updated with macOS data by logcollector + time.sleep(file_status_update + 5) + + try: + with open(file_status_path) as json_status: + file_status_json = json.loads(json_status.read()) + except EnvironmentError: + assert False, "Error opening '{}'".format(file_status_path) + + # Check if json has a structure + assert file_status_json["macos"], "Error finding 'macos' key" + From 06d09dc6db2c7bf04d97f6a76338c00a43753b76 Mon Sep 17 00:00:00 2001 From: Mariano Koremblum Date: Tue, 22 Jun 2021 02:44:18 -0300 Subject: [PATCH 07/16] test macos file status predicate improved and docu added --- .../test_logcollector/test_macos/index.md | 5 +- .../test_macos_file_status_basic.md | 2 +- .../test_macos_file_status_predicate.md | 27 +++++++++ .../wazuh_macos_file_status_predicate.yaml | 54 ++++++++++------- .../test_macos_file_status_predicate.py | 59 +++++++++---------- 5 files changed, 94 insertions(+), 53 deletions(-) create mode 100644 docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md diff --git a/docs/tests/integration/test_logcollector/test_macos/index.md b/docs/tests/integration/test_logcollector/test_macos/index.md index 8c76b547dd..7d52e5ced5 100644 --- a/docs/tests/integration/test_logcollector/test_macos/index.md +++ b/docs/tests/integration/test_logcollector/test_macos/index.md @@ -13,7 +13,7 @@ Confirm that logcollector works correctly for unified logging system events in m |Tier | Total | Time spent | | :--:| :--: | :--: | -| 0 | 4 | 3m18s | +| 0 | 4 | 3m50s | ## List of tests @@ -21,6 +21,9 @@ Confirm that logcollector works correctly for unified logging system events in m - **[Test macOS file status basic](test_macos_file_status_basic.md)**: Checks if `wazuh-logcollector` correctly generates the `file_status.json` file used by `only future events`. +- **[Test macOS file status predicate](test_macos_file_status_predicate.md)**: Checks that `wazuh-logcollector` does not +store "macos"-formatted localfile data in `file_status.json`, since its predicate is erroneous. + - **[Test macOS format basic](test_macos_format_basic.md)**: Check if `wazuh-logcollector` gather corrrectly generated unified logging system events. diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md index 9b4681b5a2..1a4ce7f41e 100644 --- a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md @@ -1,4 +1,4 @@ -# Test macOS format basic +# Test macOS file status basic ## Overview Checks if `wazuh-logcollector` correctly generates the `file_status.json` file used by `only future events`. diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md new file mode 100644 index 0000000000..6494400c24 --- /dev/null +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md @@ -0,0 +1,27 @@ +# Test macOS file status predicate +## Overview + +Checks that `wazuh-logcollector` does not store "macos"-formatted localfile data in `file_status.json`, +since its predicate is erroneous. + +## Objective + +- Confirm that, even when the Wazuh macOS agent generates a valid status file (`file_status.json`), there is no stored +data related to the "macos"-formatted localfile, even when a configuration block (with an erroneous predicate) is set. + +## General info + +|Tier | Total | Time spent | +| :--:| :--: | :--: | +| 0 | 2 | 30s | + + +## Expected behavior + +- Fail if `wazuh-logcollector` does not create the status file `status_file.json` +- Fail if `wazuh-logcollector` stores "macos"-formatted localfile data in the status file `status_file.json`. + + +## Code documentation + +::: tests.integration.test_logcollector.test_macos.test_macos_file_status_predicate diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml index 615dc0eb7f..0f50a20d99 100644 --- a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml @@ -1,26 +1,38 @@ - tags: - - test_macos_file_status_predicate + - test_macos_file_status_predicate apply_to_modules: - - test_macos_file_status_predicate + - test_macos_file_status_predicate sections: - - section: client - elements: + - section: client + elements: - server: elements: - - address: - value: '127.0.0.1' - - protocol: - value: 'tcp' - - section: localfile - elements: - - location: - value: 'macos' - - log_format: - value: 'macos' - - query: - value: 'message =!= \"testing message"' - attributes: - - level: 'default' - - type: 'log,trace' - - only-future-events: - value: ONLY_FUTURE_EVENTS + - address: + value: "127.0.0.1" + - protocol: + value: "tcp" + - section: localfile + attributes: + - name: "localfile_macos_block" + elements: + - location: + value: "macos" + - log_format: + value: "macos" + - query: + value: 'message =x= \"tresting merssage\"' + attributes: + - level: "default" + - type: "log,trace" + - only-future-events: + value: ONLY_FUTURE_EVENTS + - section: localfile + attributes: + - name: "localfile_dummy_block" + elements: + - location: + value: "/Library/Ossec/logs/active-responses.log" + - log_format: + value: "syslog" + - only-future-events: + value: "yes" diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py index 61ed132ca5..fd791b1e01 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py @@ -14,14 +14,13 @@ from wazuh_testing import global_parameters from wazuh_testing.tools.monitoring import FileMonitor - - # Marks pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] # Configuration test_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') configurations_path = os.path.join(test_data_path, 'wazuh_macos_file_status_predicate.yaml') + parameters = [{'ONLY_FUTURE_EVENTS': 'yes'}, {'ONLY_FUTURE_EVENTS': 'no'}] metadata = [{'only-future-events': 'yes'}, {'only-future-events': 'no'}] @@ -31,24 +30,23 @@ file_status_path = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') -macos_log_messages = [ - { - 'command': 'logger', - 'message': "Logger testing message - file status", - } -] +wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) -file_status_update = 4 +# Maximum waiting time in seconds to find the logs on ossec.log +wazuh_log_monitor_timeout = 30 -wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) +# Time in seconds to update the file_status.json +file_status_update = 4 +local_internal_options = {'logcollector.vcheck_files': str(file_status_update)} +@pytest.fixture(scope="module") +def get_local_internal_options(): + """Get configurations from the module.""" + return local_internal_options def extra_configuration_before_yield(): - """Delete old OFE data and change file status update interval.""" - # Remove old data from json_status + """Delete file status file.""" os.remove(file_status_path) if os.path.exists(file_status_path) else None - # Set default values - change_internal_options('logcollector.vcheck_files', str(file_status_update)) def callback_log_bad_predicate(line): match = re.match(r'.*Execution error \'log:', line) @@ -75,31 +73,32 @@ def get_connection_configuration(): return logcollector.DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION -@pytest.mark.parametrize('macos_message', macos_log_messages) -def test_macos_file_status_predicate(get_configuration, configure_environment, get_connection_configuration, - init_authd_remote_simulator, macos_message, restart_logcollector): +def test_macos_file_status_predicate(get_local_internal_options, get_configuration, configure_environment, + get_connection_configuration, init_authd_remote_simulator, restart_logcollector): - """Checks if logcollector stores correctly "macos"-formatted localfile data. + """Checks that logcollector does not store "macos"-formatted localfile data since its predicate is erroneous. - This test uses logger tool and a custom log to generate an ULS event. The agent is connected to the authd simulator - and sends an event to trigger the file_status.json update. + The agent is connected to the authd simulator and uses a dummy localfile (/Library/Ossec/logs/active-responses.log) + which triggers the creation of file_status.json Raises: - TimeoutError: If the expected callback is not generated. + TimeoutError: If the expected callbacks are not satisfied. """ - wazuh_log_monitor.start(timeout=global_parameters.default_timeout, + wazuh_log_monitor.start(timeout=wazuh_log_monitor_timeout, callback=callback_log_bad_predicate, - error_message="log 1: ") + error_message="Expected log that matches the regex " + "'.*Execution error \'log:' could not be found") - wazuh_log_monitor.start(timeout=global_parameters.default_timeout, + wazuh_log_monitor.start(timeout=wazuh_log_monitor_timeout, callback=callback_log_exit_log, - error_message="log 2: ") - + error_message="Expected log that matches the regex " + "'.*macOS \'log stream\' process exited, pid:' could not be found") + file_status_json = "" - # Waiting for file_status.json to be updated with macOS data by logcollector - time.sleep(file_status_update + 5) + # Waiting for file_status.json tocat be updated with macOS data by logcollector + time.sleep(file_status_update + 1) try: with open(file_status_path) as json_status: @@ -108,5 +107,5 @@ def test_macos_file_status_predicate(get_configuration, configure_environment, g assert False, "Error opening '{}'".format(file_status_path) # Check if json has a structure - assert file_status_json["macos"], "Error finding 'macos' key" - + if "macos" in file_status_json: + assert False, "Error, macos should not be present on the status file" From 852a2a5e730ffe0af2444c86eae82cfc6796c074 Mon Sep 17 00:00:00 2001 From: Nicolas Mariano Koremblum Date: Tue, 22 Jun 2021 10:50:25 -0700 Subject: [PATCH 08/16] logcollector macos-related tests and docu improved --- .../wazuh_testing/tools/monitoring.py | 17 +++++ .../test_logcollector/test_macos/index.md | 2 +- .../test_macos_file_status_basic.md | 2 +- .../test_macos_file_status_predicate.md | 3 +- .../data/wazuh_macos_file_status_basic.yaml | 66 ++++++++++++------ .../test_macos_file_status_basic.py | 67 +++++++++++-------- .../test_macos_file_status_predicate.py | 46 +++++++------ 7 files changed, 132 insertions(+), 71 deletions(-) diff --git a/deps/wazuh_testing/wazuh_testing/tools/monitoring.py b/deps/wazuh_testing/wazuh_testing/tools/monitoring.py index 531de12f5d..3f9054930d 100644 --- a/deps/wazuh_testing/wazuh_testing/tools/monitoring.py +++ b/deps/wazuh_testing/wazuh_testing/tools/monitoring.py @@ -1016,3 +1016,20 @@ def wait_mtime(path, time_step=5, timeout=-1): if last_mtime - tic >= timeout: logger.error(f"{len(open(path, 'r').readlines())} lines within the file.") raise TimeoutError("Reached timeout.") + + + +def wait_file(path, timeout=30): + """Wait until a file, defined by its path, is available. + + Raises: + FileNotFoundError: If the file is not available within the timeout defined interval of time. + """ + for _ in range(timeout): + if os.path.isfile(path): + break + else: + time.sleep(1) + + if not os.path.isfile(path): + raise FileNotFoundError \ No newline at end of file diff --git a/docs/tests/integration/test_logcollector/test_macos/index.md b/docs/tests/integration/test_logcollector/test_macos/index.md index 7d52e5ced5..f01f486cd2 100644 --- a/docs/tests/integration/test_logcollector/test_macos/index.md +++ b/docs/tests/integration/test_logcollector/test_macos/index.md @@ -13,7 +13,7 @@ Confirm that logcollector works correctly for unified logging system events in m |Tier | Total | Time spent | | :--:| :--: | :--: | -| 0 | 4 | 3m50s | +| 0 | 4 | 4m30s | ## List of tests diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md index 1a4ce7f41e..dce4862020 100644 --- a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md @@ -12,7 +12,7 @@ that can be used at the next startup of Wazuh-Logcollector |Tier | Total | Time spent | | :--:| :--: | :--: | -| 0 | 2 | 65s | +| 0 | 2 | 105s | ## Expected behavior diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md index 6494400c24..f55f3d5da5 100644 --- a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md @@ -2,7 +2,7 @@ ## Overview Checks that `wazuh-logcollector` does not store "macos"-formatted localfile data in `file_status.json`, -since its predicate is erroneous. +since its predicate is erroneous. Respective errors should be logged in the `ossec.log` file. ## Objective @@ -20,6 +20,7 @@ data related to the "macos"-formatted localfile, even when a configuration block - Fail if `wazuh-logcollector` does not create the status file `status_file.json` - Fail if `wazuh-logcollector` stores "macos"-formatted localfile data in the status file `status_file.json`. +- Fail if `wazuh-logcollector` does not log the errors related to `log stream` in the log file `ossec.log`. ## Code documentation diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml index 13d41aa303..bbeca222b7 100644 --- a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml @@ -1,26 +1,50 @@ - tags: - - test_macos_file_status_basic + - test_macos_file_status_basic apply_to_modules: - - test_macos_file_status_basic + - test_macos_file_status_basic sections: - - section: client - elements: + - section: client + elements: - server: elements: - - address: - value: '127.0.0.1' - - protocol: - value: 'tcp' - - section: localfile - elements: - - location: - value: 'macos' - - log_format: - value: 'macos' - - query: - value: 'message CONTAINS "testing message"' - attributes: - - level: 'default' - - type: 'log,trace' - - only-future-events: - value: ONLY_FUTURE_EVENTS + - address: + value: "127.0.0.1" + - protocol: + value: "tcp" + - section: localfile + elements: + - location: + value: 'macos' + - log_format: + value: 'macos' + - query: + value: 'message CONTAINS "testing message"' + attributes: + - level: 'default' + - type: 'log,trace' + - only-future-events: + value: ONLY_FUTURE_EVENTS + - section: rootcheck + elements: + - disabled: + value: 'yes' + - section: wodle + attributes: + - name: 'osquery' + elements: + - disabled: + value: 'yes' + - section: wodle + attributes: + - name: 'syscollector' + elements: + - disabled: + value: 'yes' + - section: syscheck + elements: + - disabled: + value: 'yes' + - section: sca + elements: + - enabled: + value: 'no' diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index 65e6a87ca2..8d3e098640 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -4,15 +4,19 @@ import os import pytest -import json import re -import time -import wazuh_testing.logcollector as logcollector import macos_utils -from wazuh_testing.fim import change_internal_options +import wazuh_testing.logcollector as logcollector + from wazuh_testing.tools.configuration import load_wazuh_configurations from wazuh_testing.remote import check_agent_received_message +from wazuh_testing.tools import LOG_FILE_PATH, WAZUH_PATH +from wazuh_testing.tools.monitoring import FileMonitor +from wazuh_testing.fim import change_internal_options +from wazuh_testing.tools.monitoring import wait_file +from wazuh_testing.tools.file import read_json from wazuh_testing.tools import WAZUH_PATH +from time import sleep # Marks pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] @@ -20,6 +24,7 @@ # Configuration test_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') configurations_path = os.path.join(test_data_path, 'wazuh_macos_file_status_basic.yaml') + parameters = [{'ONLY_FUTURE_EVENTS': 'yes'}, {'ONLY_FUTURE_EVENTS': 'no'}] metadata = [{'only-future-events': 'yes'}, {'only-future-events': 'no'}] @@ -36,15 +41,18 @@ } ] -file_status_update = 4 +wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) +# Time in seconds to update the file_status.json +file_status_update_time = 4 + +local_internal_options = {'logcollector.vcheck_files': str(file_status_update_time)} -def extra_configuration_before_yield(): - """Delete old OFE data and change file status update interval.""" - # Remove old data from json_status - os.remove(file_status_path) if os.path.exists(file_status_path) else None - # Set default values - change_internal_options('logcollector.vcheck_files', str(file_status_update)) + +@pytest.fixture(scope="module") +def get_local_internal_options(): + """Get configurations from the module.""" + return local_internal_options # Fixtures @@ -61,8 +69,9 @@ def get_connection_configuration(): @pytest.mark.parametrize('macos_message', macos_log_messages) -def test_macos_file_status_basic(get_configuration, configure_environment, get_connection_configuration, - init_authd_remote_simulator, macos_message, restart_logcollector): +def test_macos_file_status_basic(get_local_internal_options, configure_local_internal_options, get_configuration, configure_environment, + get_connection_configuration, init_authd_remote_simulator, macos_message, + restart_logcollector): """Checks if logcollector stores correctly "macos"-formatted localfile data. @@ -70,31 +79,36 @@ def test_macos_file_status_basic(get_configuration, configure_environment, get_c and sends an event to trigger the file_status.json update. Raises: - TimeoutError: If the expected callback is not generated. + TimeoutError: If the callbacks, that checks the expected logs, are not satisfied in the expected time. + FileNotFoundError: If the file_status.json is not available in the expected time. """ - # Remove status file to check if agent behavior is as expected + # Remove old data from json_status os.remove(file_status_path) if os.path.exists(file_status_path) else None macos_logcollector_monitored = logcollector.callback_monitoring_macos_logs - wazuh_log_monitor.start(timeout=30, callback=macos_logcollector_monitored, + wazuh_log_monitor.start(timeout=15, callback=macos_logcollector_monitored, error_message=logcollector.GENERIC_CALLBACK_ERROR_TARGET_SOCKET) + # Waits 20 seconds to give time to logcollector to start the module + sleep(20) + logcollector.generate_macos_logger_log(macos_message['message']) expected_message = logcollector.format_macos_message_pattern(macos_message['command'], macos_message['message']) - check_agent_received_message(remoted_simulator.rcv_msg_queue, expected_message, timeout=40) + check_agent_received_message(remoted_simulator.rcv_msg_queue, expected_message, timeout=15) - file_status_json = "" + # Waiting for file_status.json to be created, with a timeout equal to its update time + wait_file(file_status_path, file_status_update_time) - # Waiting for file_status.json to be updated with macOS data by logcollector - time.sleep(file_status_update + 1) + # Waits 10 seconds to give time to logcollector to update the file_status.json file + sleep(10) - try: - with open(file_status_path) as json_status: - file_status_json = json.loads(json_status.read()) - except EnvironmentError: - assert False, "Error opening '{}'".format(file_status_path) + file_status_json = read_json(file_status_path) + + conf_predicate = get_configuration['sections'][1]['elements'][2]['query']['value'] + conf_level = get_configuration['sections'][1]['elements'][2]['query']['attributes'][0]['level'] + conf_type = get_configuration['sections'][1]['elements'][2]['query']['attributes'][1]['type'] # Check if json has a structure assert file_status_json["macos"], "Error finding 'macos' key" @@ -102,7 +116,4 @@ def test_macos_file_status_basic(get_configuration, configure_environment, get_c assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}-\d{4}$', file_status_json["macos"]["timestamp"]), "Error of timestamp format" assert file_status_json["macos"]["settings"], "Error finding 'settings' key inside 'macos'" - conf_predicate = get_configuration['sections'][1]['elements'][2]['query']['value'] - conf_level = get_configuration['sections'][1]['elements'][2]['query']['attributes'][0]['level'] - conf_type = get_configuration['sections'][1]['elements'][2]['query']['attributes'][1]['type'] assert file_status_json["macos"]["settings"] == macos_utils.compose_settings(conf_type, conf_level, conf_predicate) diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py index fd791b1e01..ea1b798d1b 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py @@ -4,15 +4,16 @@ import os import pytest -import json import re -import time -import wazuh_testing.logcollector as logcollector -from wazuh_testing.fim import change_internal_options + +from wazuh_testing.logcollector import DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION from wazuh_testing.tools.configuration import load_wazuh_configurations from wazuh_testing.tools import LOG_FILE_PATH, WAZUH_PATH -from wazuh_testing import global_parameters from wazuh_testing.tools.monitoring import FileMonitor +from wazuh_testing.fim import change_internal_options +from wazuh_testing.tools.monitoring import wait_file +from wazuh_testing.tools.file import read_json +from wazuh_testing import global_parameters # Marks pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] @@ -36,30 +37,42 @@ wazuh_log_monitor_timeout = 30 # Time in seconds to update the file_status.json -file_status_update = 4 +file_status_update_time = 4 + +local_internal_options = {'logcollector.vcheck_files': str(file_status_update_time)} + + +@pytest.fixture(scope="module") +def get_local_internal_options(): + """Get configurations from the module.""" + return local_internal_options + -local_internal_options = {'logcollector.vcheck_files': str(file_status_update)} @pytest.fixture(scope="module") def get_local_internal_options(): """Get configurations from the module.""" return local_internal_options + def extra_configuration_before_yield(): """Delete file status file.""" os.remove(file_status_path) if os.path.exists(file_status_path) else None + def callback_log_bad_predicate(line): match = re.match(r'.*Execution error \'log:', line) if match: return True return None + def callback_log_exit_log(line): match = re.match(r'.*macOS \'log stream\' process exited, pid:', line) if match: return True return None + # Fixtures @pytest.fixture(scope="module", params=configurations, ids=configuration_ids) def get_configuration(request): @@ -70,10 +83,10 @@ def get_configuration(request): @pytest.fixture(scope="module") def get_connection_configuration(): """Get configurations from the module.""" - return logcollector.DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION + return DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION -def test_macos_file_status_predicate(get_local_internal_options, get_configuration, configure_environment, +def test_macos_file_status_predicate(get_local_internal_options, get_configuration, configure_environment, get_connection_configuration, init_authd_remote_simulator, restart_logcollector): """Checks that logcollector does not store "macos"-formatted localfile data since its predicate is erroneous. @@ -82,7 +95,8 @@ def test_macos_file_status_predicate(get_local_internal_options, get_configurati which triggers the creation of file_status.json Raises: - TimeoutError: If the expected callbacks are not satisfied. + TimeoutError: If the callbacks, that checks the expected logs, are not satisfied in the expected time. + FileNotFoundError: If the file_status.json is not available in the expected time. """ wazuh_log_monitor.start(timeout=wazuh_log_monitor_timeout, @@ -95,16 +109,10 @@ def test_macos_file_status_predicate(get_local_internal_options, get_configurati error_message="Expected log that matches the regex " "'.*macOS \'log stream\' process exited, pid:' could not be found") - file_status_json = "" - - # Waiting for file_status.json tocat be updated with macOS data by logcollector - time.sleep(file_status_update + 1) + # Waiting for file_status.json to be created, with a timeout equal to the double of the update time + wait_file(file_status_path, file_status_update_time*2) - try: - with open(file_status_path) as json_status: - file_status_json = json.loads(json_status.read()) - except EnvironmentError: - assert False, "Error opening '{}'".format(file_status_path) + file_status_json = read_json(file_status_path) # Check if json has a structure if "macos" in file_status_json: From af35a25245778026f301a448e1cdc16e18994388 Mon Sep 17 00:00:00 2001 From: Nicolas Mariano Koremblum Date: Wed, 23 Jun 2021 14:37:17 -0700 Subject: [PATCH 09/16] llogcollector macos localfile IT and docu added and some improvements to other ITs --- .../wazuh_testing/tools/monitoring.py | 3 +- .../test_logcollector/test_macos/index.md | 5 +- .../test_macos_file_status_when_no_macos.md | 29 ++++++ .../data/wazuh_macos_file_status_basic.yaml | 4 +- .../wazuh_macos_file_status_predicate.yaml | 24 ++--- ...wazuh_macos_file_status_when_no_macos.yaml | 13 +++ .../test_macos_file_status_basic.py | 30 +++--- .../test_macos_file_status_predicate.py | 28 +++--- .../test_macos_file_status_when_no_macos.py | 98 +++++++++++++++++++ 9 files changed, 186 insertions(+), 48 deletions(-) create mode 100644 docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.md create mode 100644 tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_when_no_macos.yaml create mode 100644 tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py diff --git a/deps/wazuh_testing/wazuh_testing/tools/monitoring.py b/deps/wazuh_testing/wazuh_testing/tools/monitoring.py index 3f9054930d..b46b671ce1 100644 --- a/deps/wazuh_testing/wazuh_testing/tools/monitoring.py +++ b/deps/wazuh_testing/wazuh_testing/tools/monitoring.py @@ -1018,7 +1018,6 @@ def wait_mtime(path, time_step=5, timeout=-1): raise TimeoutError("Reached timeout.") - def wait_file(path, timeout=30): """Wait until a file, defined by its path, is available. @@ -1032,4 +1031,4 @@ def wait_file(path, timeout=30): time.sleep(1) if not os.path.isfile(path): - raise FileNotFoundError \ No newline at end of file + raise FileNotFoundError diff --git a/docs/tests/integration/test_logcollector/test_macos/index.md b/docs/tests/integration/test_logcollector/test_macos/index.md index f01f486cd2..b01a976398 100644 --- a/docs/tests/integration/test_logcollector/test_macos/index.md +++ b/docs/tests/integration/test_logcollector/test_macos/index.md @@ -13,7 +13,7 @@ Confirm that logcollector works correctly for unified logging system events in m |Tier | Total | Time spent | | :--:| :--: | :--: | -| 0 | 4 | 4m30s | +| 0 | 4 | 5m20s | ## List of tests @@ -24,6 +24,9 @@ the `file_status.json` file used by `only future events`. - **[Test macOS file status predicate](test_macos_file_status_predicate.md)**: Checks that `wazuh-logcollector` does not store "macos"-formatted localfile data in `file_status.json`, since its predicate is erroneous. +- **[Test macOS file status when no macos](test_macos_file_status_when_no_macos.md)**: Checks that `wazuh-logcollector` +does not store and removes, if exists, previous "macos"-formatted localfile data in the file_status.json + - **[Test macOS format basic](test_macos_format_basic.md)**: Check if `wazuh-logcollector` gather corrrectly generated unified logging system events. diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.md new file mode 100644 index 0000000000..ab135394ba --- /dev/null +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.md @@ -0,0 +1,29 @@ +# Test macOS file status when no macos +## Overview + +Checks that `wazuh-logcollector` does not store and removes, if exists, previous +"macos"-formatted localfile data in the file_status.json + +## Objective + +- Confirm that, given a file_status.json that contains a valid combination of +"settings" and "timestamp" of "macos", when starting an agent that has no +"macos" localfile configured on its ossec.conf file, it should happen that, when +file_status.json is updated after a certain time, no "macos" status should +remain stored on the status file. + +## General info + +|Tier | Total | Time spent | +| :--:| :--: | :--: | +| 0 | 1 | 50s | + + +## Expected behavior + +- Fail if `wazuh-logcollector` stores "macos"-formatted localfile data in the status file `status_file.json`. + + +## Code documentation + +::: tests.integration.test_logcollector.test_macos.test_macos_file_status_when_no_macos diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml index bbeca222b7..96cc698d67 100644 --- a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml @@ -8,9 +8,9 @@ - server: elements: - address: - value: "127.0.0.1" + value: '127.0.0.1' - protocol: - value: "tcp" + value: 'tcp' - section: localfile elements: - location: diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml index 0f50a20d99..24882b06bd 100644 --- a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml @@ -8,31 +8,31 @@ - server: elements: - address: - value: "127.0.0.1" + value: '127.0.0.1' - protocol: - value: "tcp" + value: 'tcp' - section: localfile attributes: - - name: "localfile_macos_block" + - name: 'localfile_macos_block' elements: - location: - value: "macos" + value: 'macos' - log_format: - value: "macos" + value: 'macos' - query: - value: 'message =x= \"tresting merssage\"' + value: 'message =x= "tresting merssage"' attributes: - - level: "default" - - type: "log,trace" + - level: 'default' + - type: 'log,trace' - only-future-events: value: ONLY_FUTURE_EVENTS - section: localfile attributes: - - name: "localfile_dummy_block" + - name: 'localfile_dummy_block' elements: - location: - value: "/Library/Ossec/logs/active-responses.log" + value: '/Library/Ossec/logs/active-responses.log' - log_format: - value: "syslog" + value: 'syslog' - only-future-events: - value: "yes" + value: 'yes' diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_when_no_macos.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_when_no_macos.yaml new file mode 100644 index 0000000000..ec3fe601e4 --- /dev/null +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_when_no_macos.yaml @@ -0,0 +1,13 @@ +- tags: + - test_macos_file_status_when_no_macos + apply_to_modules: + - test_macos_file_status_when_no_macos + sections: + - section: client + elements: + - server: + elements: + - address: + value: '127.0.0.1' + - protocol: + value: 'tcp' diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index 8d3e098640..bc8f371296 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -12,10 +12,8 @@ from wazuh_testing.remote import check_agent_received_message from wazuh_testing.tools import LOG_FILE_PATH, WAZUH_PATH from wazuh_testing.tools.monitoring import FileMonitor -from wazuh_testing.fim import change_internal_options from wazuh_testing.tools.monitoring import wait_file from wazuh_testing.tools.file import read_json -from wazuh_testing.tools import WAZUH_PATH from time import sleep # Marks @@ -30,14 +28,14 @@ # Configuration data configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters, metadata=metadata) -configuration_ids = [f"{x['ONLY_FUTURE_EVENTS']}" for x in parameters] +configuration_ids = [f'{x["ONLY_FUTURE_EVENTS"]}' for x in parameters] file_status_path = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') macos_log_messages = [ { 'command': 'logger', - 'message': "Logger testing message - file status", + 'message': 'Logger testing message - file status', } ] @@ -49,29 +47,29 @@ local_internal_options = {'logcollector.vcheck_files': str(file_status_update_time)} -@pytest.fixture(scope="module") +@pytest.fixture(scope='module') def get_local_internal_options(): """Get configurations from the module.""" return local_internal_options # Fixtures -@pytest.fixture(scope="module", params=configurations, ids=configuration_ids) +@pytest.fixture(scope='module', params=configurations, ids=configuration_ids) def get_configuration(request): """Get configurations from the module.""" return request.param -@pytest.fixture(scope="module") +@pytest.fixture(scope='module') def get_connection_configuration(): """Get configurations from the module.""" return logcollector.DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION @pytest.mark.parametrize('macos_message', macos_log_messages) -def test_macos_file_status_basic(get_local_internal_options, configure_local_internal_options, get_configuration, configure_environment, - get_connection_configuration, init_authd_remote_simulator, macos_message, - restart_logcollector): +def test_macos_file_status_basic(get_local_internal_options, configure_local_internal_options, get_configuration, + configure_environment, get_connection_configuration, init_authd_remote_simulator, + macos_message, restart_logcollector): """Checks if logcollector stores correctly "macos"-formatted localfile data. @@ -111,9 +109,9 @@ def test_macos_file_status_basic(get_local_internal_options, configure_local_int conf_type = get_configuration['sections'][1]['elements'][2]['query']['attributes'][1]['type'] # Check if json has a structure - assert file_status_json["macos"], "Error finding 'macos' key" - assert file_status_json["macos"]["timestamp"], "Error finding 'timestamp' key inside 'macos'" - assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}-\d{4}$', - file_status_json["macos"]["timestamp"]), "Error of timestamp format" - assert file_status_json["macos"]["settings"], "Error finding 'settings' key inside 'macos'" - assert file_status_json["macos"]["settings"] == macos_utils.compose_settings(conf_type, conf_level, conf_predicate) + assert file_status_json['macos'], 'Error finding "macos" key' + assert file_status_json['macos']['timestamp'], 'Error finding "timestamp" key inside "macos"' + assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}-\d{4}$', + file_status_json['macos']['timestamp']), 'Error of timestamp format' + assert file_status_json['macos']['settings'], 'Error finding "settings" key inside "macos"' + assert file_status_json['macos']['settings'] == macos_utils.compose_settings(conf_type, conf_level, conf_predicate) diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py index ea1b798d1b..0490c345b1 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py @@ -10,10 +10,8 @@ from wazuh_testing.tools.configuration import load_wazuh_configurations from wazuh_testing.tools import LOG_FILE_PATH, WAZUH_PATH from wazuh_testing.tools.monitoring import FileMonitor -from wazuh_testing.fim import change_internal_options from wazuh_testing.tools.monitoring import wait_file from wazuh_testing.tools.file import read_json -from wazuh_testing import global_parameters # Marks pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] @@ -27,7 +25,7 @@ # Configuration data configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters, metadata=metadata) -configuration_ids = [f"{x['ONLY_FUTURE_EVENTS']}" for x in parameters] +configuration_ids = [f'{x["ONLY_FUTURE_EVENTS"]}' for x in parameters] file_status_path = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') @@ -42,13 +40,13 @@ local_internal_options = {'logcollector.vcheck_files': str(file_status_update_time)} -@pytest.fixture(scope="module") +@pytest.fixture(scope='module') def get_local_internal_options(): """Get configurations from the module.""" return local_internal_options -@pytest.fixture(scope="module") +@pytest.fixture(scope='module') def get_local_internal_options(): """Get configurations from the module.""" return local_internal_options @@ -74,13 +72,13 @@ def callback_log_exit_log(line): # Fixtures -@pytest.fixture(scope="module", params=configurations, ids=configuration_ids) +@pytest.fixture(scope='module', params=configurations, ids=configuration_ids) def get_configuration(request): """Get configurations from the module.""" return request.param -@pytest.fixture(scope="module") +@pytest.fixture(scope='module') def get_connection_configuration(): """Get configurations from the module.""" return DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION @@ -89,9 +87,9 @@ def get_connection_configuration(): def test_macos_file_status_predicate(get_local_internal_options, get_configuration, configure_environment, get_connection_configuration, init_authd_remote_simulator, restart_logcollector): - """Checks that logcollector does not store "macos"-formatted localfile data since its predicate is erroneous. + """Checks that logcollector does not store 'macos'-formatted localfile data since its predicate is erroneous. - The agent is connected to the authd simulator and uses a dummy localfile (/Library/Ossec/logs/active-responses.log) + The agent is connected to the authd simulator and uses a dummy localfile (/Library/Ossec/logs/active-responses.log) which triggers the creation of file_status.json Raises: @@ -101,13 +99,13 @@ def test_macos_file_status_predicate(get_local_internal_options, get_configurati wazuh_log_monitor.start(timeout=wazuh_log_monitor_timeout, callback=callback_log_bad_predicate, - error_message="Expected log that matches the regex " - "'.*Execution error \'log:' could not be found") + error_message='Expected log that matches the regex ' + '".*Execution error \'log:" could not be found') wazuh_log_monitor.start(timeout=wazuh_log_monitor_timeout, callback=callback_log_exit_log, - error_message="Expected log that matches the regex " - "'.*macOS \'log stream\' process exited, pid:' could not be found") + error_message='Expected log that matches the regex ' + '".*macOS \'log stream\' process exited, pid:" could not be found') # Waiting for file_status.json to be created, with a timeout equal to the double of the update time wait_file(file_status_path, file_status_update_time*2) @@ -115,5 +113,5 @@ def test_macos_file_status_predicate(get_local_internal_options, get_configurati file_status_json = read_json(file_status_path) # Check if json has a structure - if "macos" in file_status_json: - assert False, "Error, macos should not be present on the status file" + if 'macos' in file_status_json: + assert False, 'Error, macos should not be present on the status file' diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py new file mode 100644 index 0000000000..5388bfb7bf --- /dev/null +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py @@ -0,0 +1,98 @@ +# Copyright (C) 2015-2021, Wazuh Inc. +# Created by Wazuh, Inc. . +# This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 + +import os +import pytest +import wazuh_testing.logcollector as logcollector + +from wazuh_testing.tools.configuration import load_wazuh_configurations +from wazuh_testing.tools.file import read_json, write_json_file +from wazuh_testing.tools import LOG_FILE_PATH, WAZUH_PATH +from wazuh_testing.tools.monitoring import FileMonitor +from time import sleep + +# Marks +pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] + +# Configuration +test_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') +configurations_path = os.path.join(test_data_path, 'wazuh_macos_file_status_when_no_macos.yaml') + +# Configuration data +configurations = load_wazuh_configurations(configurations_path, __name__) + +file_status_path = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') + +wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) + +# Time in seconds to update the file_status.json +file_status_update_time = 4 + +local_internal_options = {'logcollector.vcheck_files': str(file_status_update_time)} + + +@pytest.fixture(scope='module') +def get_local_internal_options(): + """Get configurations from the module.""" + return local_internal_options + + +# Fixtures +@pytest.fixture(scope='module', params=configurations) +def get_configuration(request): + """Get configurations from the module.""" + return request.param + + +@pytest.fixture(scope='module') +def get_connection_configuration(): + """Get configurations from the module.""" + return logcollector.DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION + + +def test_macos_file_status_when_no_macos(get_local_internal_options, configure_local_internal_options, + get_configuration, configure_environment, get_connection_configuration, + init_authd_remote_simulator, restart_logcollector): + + """Checks that logcollector does not store and removes, if exists, previous "macos"-formatted localfile data in the + file_status.json + + Given a file_status.json that contains a valid combination of "settings" and "timestamp" of "macos", when starting + an agent that has no "macos" localfile configured on its ossec.conf file, it should happen that, when + file_status.json is updated after a certain time, no "macos" status should remain stored on the status file. + + Raises: + TimeoutError: If the callbacks, that checks the expected logs, are not satisfied in the expected time. + """ + + file_status_json = '' + # Check if json_status contains 'macos' data and if not insert it + if os.path.exists(file_status_path): + file_status_json = read_json(file_status_path) + if 'macos' not in file_status_json: + file_status_json['macos'] = {} + file_status_json['macos']['timestamp'] = '2021-10-22 04:59:46.796446-0700' + file_status_json['macos']['settings'] = 'message CONTAINS "testing"' + write_json_file(file_status_path, file_status_json) + else: + # If the file does not exist, then is created and then macos data is added + with open(file_status_path, 'w') as f: + pass + file_status_json['macos'] = {} + file_status_json['macos']['timestamp'] = '2021-10-22 04:59:46.796446-0700' + file_status_json['macos']['settings'] = 'message CONTAINS "testing"' + write_json_file(file_status_path, file_status_json) + + macos_logcollector_monitored = logcollector.callback_monitoring_macos_logs + wazuh_log_monitor.start(timeout=15, callback=macos_logcollector_monitored, + error_message=logcollector.GENERIC_CALLBACK_ERROR_TARGET_SOCKET) + + # Waits two times what it should take to logcollector to update the file status + sleep(file_status_update_time*2) + + file_status_json = read_json(file_status_path) + + # Check if json has a structure + if 'macos' in file_status_json: + assert False, 'Error, macos should not be present on the status file' From d8986daee4048597028602a0127eaca0c2cd8651 Mon Sep 17 00:00:00 2001 From: Juan Cabrera Date: Thu, 24 Jun 2021 12:49:39 +0200 Subject: [PATCH 10/16] Fixed test documentation --- .../test_macos/test_macos_file_status_basic.md | 2 +- .../test_macos/test_macos_file_status_predicate.md | 2 +- .../test_macos/test_macos_file_status_when_no_macos.md | 2 +- mkdocs.yml | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md index dce4862020..fe1b72497b 100644 --- a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md @@ -1,4 +1,4 @@ -# Test macOS file status basic +# Test macOS - File status basic ## Overview Checks if `wazuh-logcollector` correctly generates the `file_status.json` file used by `only future events`. diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md index f55f3d5da5..bff57b2f10 100644 --- a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md @@ -1,4 +1,4 @@ -# Test macOS file status predicate +# Test macOS - File status predicate ## Overview Checks that `wazuh-logcollector` does not store "macos"-formatted localfile data in `file_status.json`, diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.md index ab135394ba..ee20e945d7 100644 --- a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.md +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.md @@ -1,4 +1,4 @@ -# Test macOS file status when no macos +# Test macOS - File status when no macos ## Overview Checks that `wazuh-logcollector` does not store and removes, if exists, previous diff --git a/mkdocs.yml b/mkdocs.yml index 6ed8a4f1ac..180159e0c7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -481,6 +481,9 @@ nav: - Test location custom sockets: tests/integration/test_logcollector/test_location_custom_sockets/test_location_custom_sockets.md - Test macos: - Overview: tests/integration/test_logcollector/test_macos/index.md + - Test macos file status basic: tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md + - Test macos file status predicate: tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md + - Test macos file when no macos: tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.md - Test macos format basic: tests/integration/test_logcollector/test_macos/test_macos_format_basic.md - Test only future events macos format: tests/integration/test_logcollector/test_macos/test_macos_format_only_future_events.md - Test query macos format: tests/integration/test_logcollector/test_macos/test_macos_format_query.md From f63b67cccdc09bad0911687050bb4c3aab02762d Mon Sep 17 00:00:00 2001 From: Nicolas Mariano Koremblum Date: Thu, 24 Jun 2021 12:59:04 +0000 Subject: [PATCH 11/16] Some fixes added --- .../test_logcollector/test_macos/index.md | 13 ++++++------- .../test_macos/test_macos_file_status_basic.md | 5 ++--- .../test_macos/test_macos_file_status_predicate.md | 7 +++---- .../test_macos/test_macos_file_status_basic.py | 2 +- .../test_macos/test_macos_file_status_predicate.py | 6 ------ 5 files changed, 12 insertions(+), 21 deletions(-) diff --git a/docs/tests/integration/test_logcollector/test_macos/index.md b/docs/tests/integration/test_logcollector/test_macos/index.md index b01a976398..b306710938 100644 --- a/docs/tests/integration/test_logcollector/test_macos/index.md +++ b/docs/tests/integration/test_logcollector/test_macos/index.md @@ -1,8 +1,8 @@ # Test macOS -## Overview +## Overview -Wazuh macOS agent allows gathering unified logging system events. These tests ensure logcollector works correctly with +Wazuh macOS agent allows gathering unified logging system events. These tests ensure logcollector works correctly with this kind of log format. Also, these tests check that every option available for this log format work as expected. ## Objective @@ -15,19 +15,18 @@ Confirm that logcollector works correctly for unified logging system events in m | :--:| :--: | :--: | | 0 | 4 | 5m20s | - ## List of tests -- **[Test macOS file status basic](test_macos_file_status_basic.md)**: Checks if `wazuh-logcollector` correctly generates -the `file_status.json` file used by `only future events`. +- **[Test macOS file status basic](test_macos_file_status_basic.md)**: Checks if `wazuh-logcollector` correctly +generates the `file_status.json` file used by `only future events`. - **[Test macOS file status predicate](test_macos_file_status_predicate.md)**: Checks that `wazuh-logcollector` does not store "macos"-formatted localfile data in `file_status.json`, since its predicate is erroneous. -- **[Test macOS file status when no macos](test_macos_file_status_when_no_macos.md)**: Checks that `wazuh-logcollector` +- **[Test macOS file status when no macos](test_macos_file_status_when_no_macos.md)**: Checks that `wazuh-logcollector` does not store and removes, if exists, previous "macos"-formatted localfile data in the file_status.json -- **[Test macOS format basic](test_macos_format_basic.md)**: Check if `wazuh-logcollector` gather corrrectly generated +- **[Test macOS format basic](test_macos_format_basic.md)**: Check if `wazuh-logcollector` gather corrrectly generated unified logging system events. - **[Test macos format query](test_macos_format_query.md)**: Check if `query` option for `wazuh-logcollector` diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md index fe1b72497b..424c60d4c8 100644 --- a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.md @@ -1,5 +1,6 @@ # Test macOS - File status basic -## Overview + +## Overview Checks if `wazuh-logcollector` correctly generates the `file_status.json` file used by `only future events`. @@ -14,14 +15,12 @@ that can be used at the next startup of Wazuh-Logcollector | :--:| :--: | :--: | | 0 | 2 | 105s | - ## Expected behavior - Fail if `wazuh-logcollector` does not gather generated unified logging system event or does not send it to the manager - Fail if `wazuh-logcollector` does not create the status file `status_file.json` - Fail if `wazuh-logcollector` saves incorrectly formatted, or invalid data in the status file `status_file.json`. - ## Code documentation ::: tests.integration.test_logcollector.test_macos.test_macos_file_status_basic diff --git a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md index bff57b2f10..97634caf4a 100644 --- a/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md +++ b/docs/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.md @@ -1,7 +1,8 @@ # Test macOS - File status predicate -## Overview -Checks that `wazuh-logcollector` does not store "macos"-formatted localfile data in `file_status.json`, +## Overview + +Checks that `wazuh-logcollector` does not store "macos"-formatted localfile data in `file_status.json`, since its predicate is erroneous. Respective errors should be logged in the `ossec.log` file. ## Objective @@ -15,14 +16,12 @@ data related to the "macos"-formatted localfile, even when a configuration block | :--:| :--: | :--: | | 0 | 2 | 30s | - ## Expected behavior - Fail if `wazuh-logcollector` does not create the status file `status_file.json` - Fail if `wazuh-logcollector` stores "macos"-formatted localfile data in the status file `status_file.json`. - Fail if `wazuh-logcollector` does not log the errors related to `log stream` in the log file `ossec.log`. - ## Code documentation ::: tests.integration.test_logcollector.test_macos.test_macos_file_status_predicate diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index bc8f371296..2d2f2066e0 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -5,7 +5,7 @@ import os import pytest import re -import macos_utils +# import macos_utils import wazuh_testing.logcollector as logcollector from wazuh_testing.tools.configuration import load_wazuh_configurations diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py index 0490c345b1..d6723fabf8 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py @@ -40,12 +40,6 @@ local_internal_options = {'logcollector.vcheck_files': str(file_status_update_time)} -@pytest.fixture(scope='module') -def get_local_internal_options(): - """Get configurations from the module.""" - return local_internal_options - - @pytest.fixture(scope='module') def get_local_internal_options(): """Get configurations from the module.""" From 0590683188a2106f2c12b0cb1e84a6b569250bb4 Mon Sep 17 00:00:00 2001 From: Nicolas Mariano Koremblum Date: Thu, 24 Jun 2021 13:21:59 +0000 Subject: [PATCH 12/16] macos_utils.py moved --- .../wazuh_testing/tools/macos_log}/macos_utils.py | 5 ++++- .../test_macos/test_macos_file_status_basic.py | 4 ++-- .../test_macos/test_macos_file_status_predicate.py | 5 +++-- 3 files changed, 9 insertions(+), 5 deletions(-) rename {tests/integration/test_logcollector/test_macos => deps/wazuh_testing/wazuh_testing/tools/macos_log}/macos_utils.py (86%) diff --git a/tests/integration/test_logcollector/test_macos/macos_utils.py b/deps/wazuh_testing/wazuh_testing/tools/macos_log/macos_utils.py similarity index 86% rename from tests/integration/test_logcollector/test_macos/macos_utils.py rename to deps/wazuh_testing/wazuh_testing/tools/macos_log/macos_utils.py index ac48364f86..0c788b4c9d 100644 --- a/tests/integration/test_logcollector/test_macos/macos_utils.py +++ b/deps/wazuh_testing/wazuh_testing/tools/macos_log/macos_utils.py @@ -3,12 +3,15 @@ # This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 def compose_settings(__type="", __level="", __predicate="", __is_sierra=False): + """ + This function replicates how the command 'log' will be called from the Wazuh agent given the query parameters + """ settings_str = "" if (__is_sierra): settings_str = "/usr/bin/script -q /dev/null " - + settings_str = settings_str + "/usr/bin/log stream --style syslog " if (__type): diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index 2d2f2066e0..a33d5bb4e2 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -3,10 +3,10 @@ # This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 import os -import pytest import re -# import macos_utils +import pytest import wazuh_testing.logcollector as logcollector +import wazuh_testing.tools.macos_log.macos_utils as macos_utils from wazuh_testing.tools.configuration import load_wazuh_configurations from wazuh_testing.remote import check_agent_received_message diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py index d6723fabf8..9dc302d6f4 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py @@ -78,8 +78,9 @@ def get_connection_configuration(): return DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION -def test_macos_file_status_predicate(get_local_internal_options, get_configuration, configure_environment, - get_connection_configuration, init_authd_remote_simulator, restart_logcollector): +def test_macos_file_status_predicate(get_local_internal_options, configure_local_internal_options, get_configuration, + configure_environment, get_connection_configuration, init_authd_remote_simulator, + restart_logcollector): """Checks that logcollector does not store 'macos'-formatted localfile data since its predicate is erroneous. From 94a0888b7b8c7e04c6a0013a2964a7c818174ed2 Mon Sep 17 00:00:00 2001 From: Nicolas Mariano Koremblum Date: Mon, 28 Jun 2021 08:59:46 -0700 Subject: [PATCH 13/16] Some fixes added to macos ITs --- .../wazuh_testing/logcollector.py | 25 +++++++++ .../wazuh_testing/tools/__init__.py | 1 + .../tools/macos_log/macos_utils.py | 29 ---------- .../data/wazuh_macos_file_status_basic.yaml | 8 --- .../wazuh_macos_file_status_predicate.yaml | 8 --- .../test_macos_file_status_basic.py | 53 ++++++++++--------- .../test_macos_file_status_predicate.py | 15 ++---- .../test_macos_file_status_when_no_macos.py | 32 ++++------- 8 files changed, 68 insertions(+), 103 deletions(-) delete mode 100644 deps/wazuh_testing/wazuh_testing/tools/macos_log/macos_utils.py diff --git a/deps/wazuh_testing/wazuh_testing/logcollector.py b/deps/wazuh_testing/wazuh_testing/logcollector.py index d4f000d22c..66c05bb41d 100644 --- a/deps/wazuh_testing/wazuh_testing/logcollector.py +++ b/deps/wazuh_testing/wazuh_testing/logcollector.py @@ -765,3 +765,28 @@ def format_macos_message_pattern(process_name, message, type='log', subsystem=No assert macos_message is not None, 'Wrong type or process name selected for macos message pattern format.' return macos_message + +def compose_macos_log_command(type="", level="", predicate="", is_sierra=False): + """ + This function replicates how the command 'log' will be called from the Wazuh agent given the query parameters + """ + + settings_str = "" + + if (is_sierra): + settings_str = "/usr/bin/script -q /dev/null " + + settings_str += "/usr/bin/log stream --style syslog " + + if (type): + for t in type.split(","): + settings_str += "--type " + t + " " + + if (level): + level = level.replace(" ", "") + settings_str += "--level " + level + " " + + if(predicate): + settings_str += "--predicate " + predicate + + return settings_str diff --git a/deps/wazuh_testing/wazuh_testing/tools/__init__.py b/deps/wazuh_testing/wazuh_testing/tools/__init__.py index 811fb23fe2..9d56a4db5f 100644 --- a/deps/wazuh_testing/wazuh_testing/tools/__init__.py +++ b/deps/wazuh_testing/wazuh_testing/tools/__init__.py @@ -46,6 +46,7 @@ ARCHIVES_LOG_FILE_PATH = os.path.join(WAZUH_PATH, 'logs', 'archives', 'archives.log') AGENT_STATISTICS_FILE = os.path.join(WAZUH_PATH, 'var', 'run', 'wazuh-agentd.state') LOGCOLLECTOR_STATISTICS_FILE = os.path.join(WAZUH_PATH, 'var', 'run', 'wazuh-logcollector.state') + LOGCOLLECTOR_FILE_STATUS_PATH = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') REMOTE_STATISTICS_FILE = os.path.join(WAZUH_PATH, 'var', 'run', 'wazuh-remoted.state') ANALYSIS_STATISTICS_FILE = os.path.join(WAZUH_PATH, 'var', 'run', 'wazuh-analysisd.state') diff --git a/deps/wazuh_testing/wazuh_testing/tools/macos_log/macos_utils.py b/deps/wazuh_testing/wazuh_testing/tools/macos_log/macos_utils.py deleted file mode 100644 index 0c788b4c9d..0000000000 --- a/deps/wazuh_testing/wazuh_testing/tools/macos_log/macos_utils.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 2015-2021, Wazuh Inc. -# Created by Wazuh, Inc. . -# This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 - -def compose_settings(__type="", __level="", __predicate="", __is_sierra=False): - """ - This function replicates how the command 'log' will be called from the Wazuh agent given the query parameters - """ - - settings_str = "" - - if (__is_sierra): - settings_str = "/usr/bin/script -q /dev/null " - - settings_str = settings_str + "/usr/bin/log stream --style syslog " - - if (__type): - __type = __type.replace(" ", "") - for t in __type.split(","): - settings_str = settings_str + "--type " + t + " " - - if (__level): - __level = __level.replace(" ", "") - settings_str = settings_str + "--level " + __level + " " - - if(__predicate): - settings_str = settings_str + "--predicate " + __predicate - - return settings_str diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml index 96cc698d67..0e0207a450 100644 --- a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_basic.yaml @@ -3,14 +3,6 @@ apply_to_modules: - test_macos_file_status_basic sections: - - section: client - elements: - - server: - elements: - - address: - value: '127.0.0.1' - - protocol: - value: 'tcp' - section: localfile elements: - location: diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml index 24882b06bd..8f7cf03d50 100644 --- a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_predicate.yaml @@ -3,14 +3,6 @@ apply_to_modules: - test_macos_file_status_predicate sections: - - section: client - elements: - - server: - elements: - - address: - value: '127.0.0.1' - - protocol: - value: 'tcp' - section: localfile attributes: - name: 'localfile_macos_block' diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index a33d5bb4e2..6a8a6da175 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -6,12 +6,10 @@ import re import pytest import wazuh_testing.logcollector as logcollector -import wazuh_testing.tools.macos_log.macos_utils as macos_utils from wazuh_testing.tools.configuration import load_wazuh_configurations +from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH from wazuh_testing.remote import check_agent_received_message -from wazuh_testing.tools import LOG_FILE_PATH, WAZUH_PATH -from wazuh_testing.tools.monitoring import FileMonitor from wazuh_testing.tools.monitoring import wait_file from wazuh_testing.tools.file import read_json from time import sleep @@ -30,17 +28,6 @@ configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters, metadata=metadata) configuration_ids = [f'{x["ONLY_FUTURE_EVENTS"]}' for x in parameters] -file_status_path = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') - -macos_log_messages = [ - { - 'command': 'logger', - 'message': 'Logger testing message - file status', - } -] - -wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) - # Time in seconds to update the file_status.json file_status_update_time = 4 @@ -66,10 +53,14 @@ def get_connection_configuration(): return logcollector.DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION -@pytest.mark.parametrize('macos_message', macos_log_messages) +def extra_configuration_before_yield(): + """Delete file status file.""" + os.remove(LOGCOLLECTOR_FILE_STATUS_PATH) if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH) else None + + def test_macos_file_status_basic(get_local_internal_options, configure_local_internal_options, get_configuration, configure_environment, get_connection_configuration, init_authd_remote_simulator, - macos_message, restart_logcollector): + restart_logcollector): """Checks if logcollector stores correctly "macos"-formatted localfile data. @@ -81,8 +72,10 @@ def test_macos_file_status_basic(get_local_internal_options, configure_local_int FileNotFoundError: If the file_status.json is not available in the expected time. """ - # Remove old data from json_status - os.remove(file_status_path) if os.path.exists(file_status_path) else None + macos_message = { + 'command': 'logger', + 'message': 'Logger testing message - file status', + } macos_logcollector_monitored = logcollector.callback_monitoring_macos_logs wazuh_log_monitor.start(timeout=15, callback=macos_logcollector_monitored, @@ -96,22 +89,30 @@ def test_macos_file_status_basic(get_local_internal_options, configure_local_int check_agent_received_message(remoted_simulator.rcv_msg_queue, expected_message, timeout=15) - # Waiting for file_status.json to be created, with a timeout equal to its update time - wait_file(file_status_path, file_status_update_time) + # Waiting for file_status.json to be created, with a timeout about the time needed to update the file + wait_file(LOGCOLLECTOR_FILE_STATUS_PATH, file_status_update_time+1) # Waits 10 seconds to give time to logcollector to update the file_status.json file sleep(10) - file_status_json = read_json(file_status_path) + file_status_json = read_json(LOGCOLLECTOR_FILE_STATUS_PATH) - conf_predicate = get_configuration['sections'][1]['elements'][2]['query']['value'] - conf_level = get_configuration['sections'][1]['elements'][2]['query']['attributes'][0]['level'] - conf_type = get_configuration['sections'][1]['elements'][2]['query']['attributes'][1]['type'] + conf_predicate = get_configuration['sections'][0]['elements'][2]['query']['value'] + conf_level = get_configuration['sections'][0]['elements'][2]['query']['attributes'][0]['level'] + conf_type = get_configuration['sections'][0]['elements'][2]['query']['attributes'][1]['type'] # Check if json has a structure assert file_status_json['macos'], 'Error finding "macos" key' + assert file_status_json['macos']['timestamp'], 'Error finding "timestamp" key inside "macos"' + assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}-\d{4}$', - file_status_json['macos']['timestamp']), 'Error of timestamp format' + file_status_json['macos']['timestamp']), \ + 'Error of timestamp format' + assert file_status_json['macos']['settings'], 'Error finding "settings" key inside "macos"' - assert file_status_json['macos']['settings'] == macos_utils.compose_settings(conf_type, conf_level, conf_predicate) + + assert file_status_json['macos']['settings'] \ + == logcollector.compose_macos_log_command(conf_type, + conf_level, + conf_predicate) diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py index 9dc302d6f4..a4a78b8b10 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py @@ -8,8 +8,7 @@ from wazuh_testing.logcollector import DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION from wazuh_testing.tools.configuration import load_wazuh_configurations -from wazuh_testing.tools import LOG_FILE_PATH, WAZUH_PATH -from wazuh_testing.tools.monitoring import FileMonitor +from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH from wazuh_testing.tools.monitoring import wait_file from wazuh_testing.tools.file import read_json @@ -27,10 +26,6 @@ configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters, metadata=metadata) configuration_ids = [f'{x["ONLY_FUTURE_EVENTS"]}' for x in parameters] -file_status_path = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') - -wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) - # Maximum waiting time in seconds to find the logs on ossec.log wazuh_log_monitor_timeout = 30 @@ -48,7 +43,7 @@ def get_local_internal_options(): def extra_configuration_before_yield(): """Delete file status file.""" - os.remove(file_status_path) if os.path.exists(file_status_path) else None + os.remove(LOGCOLLECTOR_FILE_STATUS_PATH) if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH) else None def callback_log_bad_predicate(line): @@ -102,10 +97,10 @@ def test_macos_file_status_predicate(get_local_internal_options, configure_local error_message='Expected log that matches the regex ' '".*macOS \'log stream\' process exited, pid:" could not be found') - # Waiting for file_status.json to be created, with a timeout equal to the double of the update time - wait_file(file_status_path, file_status_update_time*2) + # Waiting for file_status.json to be created, with a timeout about the time needed to update the file + wait_file(LOGCOLLECTOR_FILE_STATUS_PATH, file_status_update_time+2) - file_status_json = read_json(file_status_path) + file_status_json = read_json(LOGCOLLECTOR_FILE_STATUS_PATH) # Check if json has a structure if 'macos' in file_status_json: diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py index 5388bfb7bf..5eb2b925d1 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py @@ -8,8 +8,7 @@ from wazuh_testing.tools.configuration import load_wazuh_configurations from wazuh_testing.tools.file import read_json, write_json_file -from wazuh_testing.tools import LOG_FILE_PATH, WAZUH_PATH -from wazuh_testing.tools.monitoring import FileMonitor +from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH from time import sleep # Marks @@ -22,10 +21,6 @@ # Configuration data configurations = load_wazuh_configurations(configurations_path, __name__) -file_status_path = os.path.join(WAZUH_PATH, 'queue', 'logcollector', 'file_status.json') - -wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) - # Time in seconds to update the file_status.json file_status_update_time = 4 @@ -45,15 +40,8 @@ def get_configuration(request): return request.param -@pytest.fixture(scope='module') -def get_connection_configuration(): - """Get configurations from the module.""" - return logcollector.DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION - - def test_macos_file_status_when_no_macos(get_local_internal_options, configure_local_internal_options, - get_configuration, configure_environment, get_connection_configuration, - init_authd_remote_simulator, restart_logcollector): + get_configuration, configure_environment, restart_logcollector): """Checks that logcollector does not store and removes, if exists, previous "macos"-formatted localfile data in the file_status.json @@ -68,30 +56,30 @@ def test_macos_file_status_when_no_macos(get_local_internal_options, configure_l file_status_json = '' # Check if json_status contains 'macos' data and if not insert it - if os.path.exists(file_status_path): - file_status_json = read_json(file_status_path) + if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH): + file_status_json = read_json(LOGCOLLECTOR_FILE_STATUS_PATH) if 'macos' not in file_status_json: file_status_json['macos'] = {} file_status_json['macos']['timestamp'] = '2021-10-22 04:59:46.796446-0700' file_status_json['macos']['settings'] = 'message CONTAINS "testing"' - write_json_file(file_status_path, file_status_json) + write_json_file(LOGCOLLECTOR_FILE_STATUS_PATH, file_status_json) else: # If the file does not exist, then is created and then macos data is added - with open(file_status_path, 'w') as f: + with open(LOGCOLLECTOR_FILE_STATUS_PATH, 'w') as f: pass file_status_json['macos'] = {} file_status_json['macos']['timestamp'] = '2021-10-22 04:59:46.796446-0700' file_status_json['macos']['settings'] = 'message CONTAINS "testing"' - write_json_file(file_status_path, file_status_json) + write_json_file(LOGCOLLECTOR_FILE_STATUS_PATH, file_status_json) macos_logcollector_monitored = logcollector.callback_monitoring_macos_logs wazuh_log_monitor.start(timeout=15, callback=macos_logcollector_monitored, error_message=logcollector.GENERIC_CALLBACK_ERROR_TARGET_SOCKET) - # Waits two times what it should take to logcollector to update the file status - sleep(file_status_update_time*2) + # Waits about the time needed to update the file status + sleep(file_status_update_time+2) - file_status_json = read_json(file_status_path) + file_status_json = read_json(LOGCOLLECTOR_FILE_STATUS_PATH) # Check if json has a structure if 'macos' in file_status_json: From aeeeb21aebb8efc81c74db49a3a7d8562d5effd7 Mon Sep 17 00:00:00 2001 From: Mariano Koremblum Date: Thu, 23 Sep 2021 00:31:10 -0300 Subject: [PATCH 14/16] Fix macOS ITs according to new QA standards --- .gitignore | 1 + .../wazuh_testing/logcollector.py | 27 +++-- .../wazuh_testing/tools/monitoring.py | 11 +- .../test_macos_file_status_basic.py | 113 ++++++++++++------ .../test_macos_file_status_predicate.py | 70 ++++++----- .../test_macos_file_status_when_no_macos.py | 47 ++++++-- 6 files changed, 180 insertions(+), 89 deletions(-) diff --git a/.gitignore b/.gitignore index 84692b1573..66fedb92bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Python cache __pycache__ +.pytest_cache venv wazuh_testing.egg-info diff --git a/deps/wazuh_testing/wazuh_testing/logcollector.py b/deps/wazuh_testing/wazuh_testing/logcollector.py index 66c05bb41d..6e694e22cd 100644 --- a/deps/wazuh_testing/wazuh_testing/logcollector.py +++ b/deps/wazuh_testing/wazuh_testing/logcollector.py @@ -766,27 +766,36 @@ def format_macos_message_pattern(process_name, message, type='log', subsystem=No return macos_message -def compose_macos_log_command(type="", level="", predicate="", is_sierra=False): +def compose_macos_log_command(type='', level='', predicate='', is_sierra=False): """ This function replicates how the command 'log' will be called from the Wazuh agent given the query parameters + + Args: + type (str): < activity | log | trace > Limit streaming to a given event type. + level (str): < default | info | debug > Include events at, and below, the given level. + predicate (str): Filter events using the given predicate. + is_sierra (boolean): True if running on macOS Sierra, False otherwise. + + Returns: + string: Full log command composed with the given parameters. """ - settings_str = "" + settings_str = '' if (is_sierra): - settings_str = "/usr/bin/script -q /dev/null " + settings_str = '/usr/bin/script -q /dev/null ' - settings_str += "/usr/bin/log stream --style syslog " + settings_str += '/usr/bin/log stream --style syslog ' if (type): - for t in type.split(","): - settings_str += "--type " + t + " " + for t in type.split(','): + settings_str += '--type ' + t + ' ' if (level): - level = level.replace(" ", "") - settings_str += "--level " + level + " " + level = level.replace(' ', '') + settings_str += '--level ' + level + ' ' if(predicate): - settings_str += "--predicate " + predicate + settings_str += '--predicate ' + predicate return settings_str diff --git a/deps/wazuh_testing/wazuh_testing/tools/monitoring.py b/deps/wazuh_testing/wazuh_testing/tools/monitoring.py index b46b671ce1..5b04dd7037 100644 --- a/deps/wazuh_testing/wazuh_testing/tools/monitoring.py +++ b/deps/wazuh_testing/wazuh_testing/tools/monitoring.py @@ -37,6 +37,9 @@ AGENT_DETECTOR_PREFIX = r'.*wazuh-agent.*' AUTHD_DETECTOR_PREFIX = r'.*wazuh-authd.*' +DEFAULT_POLL_FILE_TIME = 1 +DEFAULT_WAIT_FILE_TIMEOUT = 30 + def wazuh_unpack(data, format_: str = " Date: Mon, 27 Sep 2021 13:46:39 -0300 Subject: [PATCH 15/16] ITs further fixes and improvements --- ...wazuh_macos_file_status_when_no_macos.yaml | 16 ++-- .../test_macos_file_status_basic.py | 75 +++++++++++-------- .../test_macos_file_status_predicate.py | 33 +++----- .../test_macos_file_status_when_no_macos.py | 71 ++++++++++++------ 4 files changed, 111 insertions(+), 84 deletions(-) diff --git a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_when_no_macos.yaml b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_when_no_macos.yaml index ec3fe601e4..055f732234 100644 --- a/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_when_no_macos.yaml +++ b/tests/integration/test_logcollector/test_macos/data/wazuh_macos_file_status_when_no_macos.yaml @@ -3,11 +3,13 @@ apply_to_modules: - test_macos_file_status_when_no_macos sections: - - section: client + - section: localfile + attributes: + - name: 'localfile_dummy_block' elements: - - server: - elements: - - address: - value: '127.0.0.1' - - protocol: - value: 'tcp' + - location: + value: FILE_TO_MONITOR + - log_format: + value: 'syslog' + - only-future-events: + value: 'yes' diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index 0e1ab92706..cccd04f381 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -7,10 +7,12 @@ import pytest import wazuh_testing.logcollector as logcollector -from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH, LOG_FILE_PATH +from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH, LOG_FILE_PATH, WAZUH_LOCAL_INTERNAL_OPTIONS +from wazuh_testing.tools.monitoring import FileMonitor, wait_file, make_callback from wazuh_testing.tools.configuration import load_wazuh_configurations -from wazuh_testing.tools.monitoring import FileMonitor, wait_file +from wazuh_testing.logcollector import prefix as logcollector_prefix from wazuh_testing.tools.file import read_json, truncate_file +from wazuh_testing.tools.services import control_service # Marks pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] @@ -33,7 +35,8 @@ # Time in seconds to update the file_status.json file_status_update_time = 4 -local_internal_options = { 'logcollector.vcheck_files': file_status_update_time, +local_internal_options = { 'logcollector.debug': 2, + 'logcollector.vcheck_files': file_status_update_time, 'logcollector.sample_log_length': sample_log_length } macos_message = { 'command': 'logger', @@ -42,22 +45,17 @@ # Maximum waiting time in seconds to find the logs on ossec.log file_monitor_timeout = 30 -wazuh_log_monitor = None - +# Expected message to be used on the "callback_macos_uls_log" callback expected_message = logcollector.format_macos_message_pattern(macos_message['command'], macos_message['message']) +wazuh_log_monitor = None + # Fixtures @pytest.fixture(scope='module') def startup_cleanup(): """Truncate ossec.log and remove logcollector's file_status.json file.""" - truncate_file(LOG_FILE_PATH) - os.remove(LOGCOLLECTOR_FILE_STATUS_PATH) if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH) else None - -@pytest.fixture(scope='module') -def get_local_internal_options(): - """Get configurations from the module.""" - return local_internal_options + truncate_file(WAZUH_LOCAL_INTERNAL_OPTIONS) @pytest.fixture(scope='module', params=configurations, ids=configuration_ids) @@ -66,34 +64,47 @@ def get_configuration(request): return request.param -def wait_macos_uls_log(line): - """Callback function to wait for the macOS' ULS log collected by logcollector.""" - if re.search(expected_message, line): - return True +@pytest.fixture(scope='module') +def restart_required_logcollector_daemons(): + """Wazuh logcollector daemons handler.""" + + required_logcollector_daemons = ['wazuh-logcollector'] + + for daemon in required_logcollector_daemons: + control_service('stop', daemon=daemon) + + truncate_file(LOG_FILE_PATH) + os.remove(LOGCOLLECTOR_FILE_STATUS_PATH) if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH) else None + + for daemon in required_logcollector_daemons: + control_service('start', daemon=daemon) + + yield - return None + for daemon in required_logcollector_daemons: + control_service('stop', daemon=daemon) -def wait_logcollector_log_stream(line): - """Check if 'line' has the logcollector's macOS ULS module start message.""" - if re.search(r'Monitoring macOS logs with: (.+?)log stream', line): - return True +def callback_macos_uls_log(): + """Callback function to wait for the macOS' ULS log collected by logcollector.""" + return make_callback(pattern=expected_message, prefix=logcollector_prefix, escape=False) + - return None +def callback_logcollector_log_stream_log(): + """Check for logcollector's macOS ULS module start message.""" + return make_callback(pattern='Monitoring macOS logs with:(.+?)log stream', prefix=logcollector_prefix, escape=False) -def wait_macos_key_file_status(line): - """Check if 'line' has the 'macos' key on it.""" - if re.search(r'macos', line): - return True - return None +def callback_file_status_macos_key(line): + """Check for 'macos' key.""" + return make_callback(pattern='"macos"', prefix='') def test_macos_file_status_basic(startup_cleanup, - configure_local_internal_options, + configure_local_internal_options_module, get_configuration, configure_environment, - daemons_handler): + restart_required_logcollector_daemons): """Checks if logcollector stores correctly "macos"-formatted localfile data. This test uses logger tool and a custom log to generate an ULS event. The agent is connected to the authd simulator @@ -112,13 +123,13 @@ def test_macos_file_status_basic(startup_cleanup, # Watches the ossec.log to check when logcollector starts the macOS ULS module wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=wait_logcollector_log_stream, + callback=callback_logcollector_log_stream_log(), error_message='Logcollector did not start') logcollector.generate_macos_logger_log(macos_message['message']) wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=wait_macos_uls_log, + callback=callback_macos_uls_log(), error_message='MacOS ULS log was not found') # Waits for file_status.json to be created, with a timeout about the time needed to update the file @@ -127,7 +138,7 @@ def test_macos_file_status_basic(startup_cleanup, # Watches the file_status.json file for the "macos" key file_status_monitor = FileMonitor(LOGCOLLECTOR_FILE_STATUS_PATH) file_status_monitor.start(timeout=file_monitor_timeout, - callback=wait_macos_key_file_status, + callback=callback_file_status_macos_key, error_message="The 'macos' key could not be found on the file_status.json file") file_status_json = read_json(LOGCOLLECTOR_FILE_STATUS_PATH) diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py index b222c4523a..82b1ffbda3 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py @@ -7,9 +7,10 @@ import re # from wazuh_testing.logcollector import DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION -from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH, LOG_FILE_PATH +from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH, LOG_FILE_PATH, WAZUH_LOCAL_INTERNAL_OPTIONS +from wazuh_testing.tools.monitoring import FileMonitor, wait_file, make_callback from wazuh_testing.tools.configuration import load_wazuh_configurations -from wazuh_testing.tools.monitoring import FileMonitor, wait_file +from wazuh_testing.logcollector import prefix as logcollector_prefix from wazuh_testing.tools.file import read_json, truncate_file # Marks @@ -46,44 +47,32 @@ @pytest.fixture(scope='module') def startup_cleanup(): """Truncate ossec.log and remove logcollector's file_status.json file.""" + truncate_file(WAZUH_LOCAL_INTERNAL_OPTIONS) truncate_file(LOG_FILE_PATH) os.remove(LOGCOLLECTOR_FILE_STATUS_PATH) if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH) else None -@pytest.fixture(scope='module') -def get_local_internal_options(): - """Get configurations from the module.""" - return local_internal_options - - @pytest.fixture(scope='module', params=configurations, ids=configuration_ids) def get_configuration(request): """Get configurations from the module.""" return request.param -def callback_log_bad_predicate(line): +def callback_log_bad_predicate(): """Check if 'line' has the macOS ULS bad predicate message on it.""" - match = re.match(r'.*Execution error \'log:', line) - if match: - return True - return None + return make_callback(pattern="Execution error 'log:", prefix=logcollector_prefix) -def callback_log_exit_log(line): +def callback_log_exit_log(): """Check if 'line' has the macOS ULS log stream exited message on it.""" - match = re.match(r'.*macOS \'log stream\' process exited, pid:', line) - if match: - return True - return None + return make_callback(pattern="macOS 'log stream' process exited, pid:", prefix=logcollector_prefix) def test_macos_file_status_predicate(startup_cleanup, - configure_local_internal_options, + configure_local_internal_options_module, get_configuration, configure_environment, daemons_handler): - """Checks that logcollector does not store 'macos'-formatted localfile data since its predicate is erroneous. The agent is connected to the authd simulator and uses a dummy localfile (/Library/Ossec/logs/active-responses.log) @@ -96,12 +85,12 @@ def test_macos_file_status_predicate(startup_cleanup, wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=callback_log_bad_predicate, + callback=callback_log_bad_predicate(), error_message='Expected log that matches the regex ' '".*Execution error \'log:" could not be found') wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=callback_log_exit_log, + callback=callback_log_exit_log(), error_message='Expected log that matches the regex ' '".*macOS \'log stream\' process exited, pid:" could not be found') diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py index ca58841e28..4ce4538270 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py @@ -6,10 +6,13 @@ import pytest import wazuh_testing.logcollector as logcollector +from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH, LOG_FILE_PATH, WAZUH_LOCAL_INTERNAL_OPTIONS +from wazuh_testing.tools.monitoring import FileMonitor, wait_file, make_callback from wazuh_testing.tools.file import read_json, write_json_file, truncate_file -from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH, LOG_FILE_PATH from wazuh_testing.tools.configuration import load_wazuh_configurations -from wazuh_testing.tools.monitoring import FileMonitor, wait_file +from wazuh_testing.logcollector import prefix as logcollector_prefix +from wazuh_testing.tools.services import control_service +from tempfile import gettempdir from time import sleep # Marks @@ -19,10 +22,12 @@ test_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') configurations_path = os.path.join(test_data_path, 'wazuh_macos_file_status_when_no_macos.yaml') -daemons_handler_configuration = {'daemons': ['wazuh-logcollector'], 'ignore_errors': False} +dummy_file = os.path.join(gettempdir(), 'dummy_file.log') +parameters = [{'FILE_TO_MONITOR': dummy_file}] # Configuration data -configurations = load_wazuh_configurations(configurations_path, __name__) +configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters) +configuration_ids = [f"{x['FILE_TO_MONITOR']}" for x in parameters] # Max number of characters to be displayed in the log's debug message sample_log_length = 100 @@ -35,37 +40,59 @@ # Maximum waiting time in seconds to find the logs on ossec.log file_monitor_timeout = 30 +# Time to wait for file_status.json to be updated wait_file_status_update_time = file_status_update_time + 2 wazuh_log_monitor = None # Fixtures +@pytest.fixture(scope='module', params=configurations, ids=configuration_ids) +def get_configuration(request): + """Get configurations from the module.""" + return request.param + + @pytest.fixture(scope='module') -def startup_cleanup(): - """Truncate ossec.log and remove logcollector's file_status.json file.""" +def restart_required_logcollector_daemons(): + """Wazuh logcollector daemons handler.""" + + required_logcollector_daemons = ['wazuh-logcollector'] + + for daemon in required_logcollector_daemons: + control_service('stop', daemon=daemon) + truncate_file(LOG_FILE_PATH) os.remove(LOGCOLLECTOR_FILE_STATUS_PATH) if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH) else None + for daemon in required_logcollector_daemons: + control_service('start', daemon=daemon) + + yield + + for daemon in required_logcollector_daemons: + control_service('stop', daemon=daemon) + @pytest.fixture(scope='module') -def get_local_internal_options(): - """Get configurations from the module.""" - return local_internal_options +def startup_cleanup(): + """Truncate local_internals file and create dummy file to be monitored by logcollector.""" + truncate_file(WAZUH_LOCAL_INTERNAL_OPTIONS) + with open(dummy_file, 'w') as f: + pass -@pytest.fixture(scope='module', params=configurations) -def get_configuration(request): - """Get configurations from the module.""" - return request.param + +def callback_logcollector_started(): + """Check for 'macos' key.""" + return make_callback(pattern='Started', prefix=logcollector_prefix) def test_macos_file_status_when_no_macos(startup_cleanup, - configure_local_internal_options, + configure_local_internal_options_module, get_configuration, configure_environment, - daemons_handler): - + restart_required_logcollector_daemons): """Checks that logcollector does not store and removes, if exists, previous "macos"-formatted localfile data in the file_status.json @@ -77,10 +104,14 @@ def test_macos_file_status_when_no_macos(startup_cleanup, TimeoutError: If the callbacks, that checks the expected logs, are not satisfied in the expected time. """ - file_status_json = '' + file_status_json = {} wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) + wazuh_log_monitor.start(timeout=file_monitor_timeout, + callback=callback_logcollector_started(), + error_message="Logcollector did not start") + # Check if json_status contains 'macos' data and if not insert it if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH): file_status_json = read_json(LOGCOLLECTOR_FILE_STATUS_PATH) @@ -98,12 +129,6 @@ def test_macos_file_status_when_no_macos(startup_cleanup, file_status_json['macos']['settings'] = 'message CONTAINS "testing"' write_json_file(LOGCOLLECTOR_FILE_STATUS_PATH, file_status_json) - macos_logcollector_monitored = logcollector.callback_monitoring_macos_logs - - wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=macos_logcollector_monitored, - error_message=logcollector.GENERIC_CALLBACK_ERROR_TARGET_SOCKET) - # Waits for file_status.json to be created, with a timeout about the time needed to update the file wait_file(LOGCOLLECTOR_FILE_STATUS_PATH, file_monitor_timeout) From 66552be93835a4dd7b6e55ab38c9f6ec02d30859 Mon Sep 17 00:00:00 2001 From: Mariano Koremblum Date: Wed, 29 Sep 2021 02:00:32 -0300 Subject: [PATCH 16/16] New ITs changes requested implemented --- .../wazuh_testing/logcollector.py | 37 ++++- .../wazuh_testing/tools/configuration.py | 11 +- .../integration/test_logcollector/conftest.py | 20 ++- .../test_macos_file_status_basic.py | 133 ++++++------------ .../test_macos_file_status_predicate.py | 82 ++++------- .../test_macos_file_status_when_no_macos.py | 99 +++++-------- 6 files changed, 162 insertions(+), 220 deletions(-) diff --git a/deps/wazuh_testing/wazuh_testing/logcollector.py b/deps/wazuh_testing/wazuh_testing/logcollector.py index 6e694e22cd..107fd95f5e 100644 --- a/deps/wazuh_testing/wazuh_testing/logcollector.py +++ b/deps/wazuh_testing/wazuh_testing/logcollector.py @@ -17,10 +17,11 @@ GENERIC_CALLBACK_ERROR_ANALYZING_MACOS = "The expected analyzing macos log has not been produced" GENERIC_CALLBACK_ERROR_TARGET_SOCKET = "The expected target socket log has not been produced" GENERIC_CALLBACK_ERROR_TARGET_SOCKET_NOT_FOUND = "The expected target socket not found error has not been produced" -LOG_COLLECTOR_GLOBAL_TIMEOUT = 20 GENERIC_CALLBACK_ERROR_READING_FILE = "The expected invalid content error log has not been produced" GENERIC_CALLBACK_ERROR = 'The expected error output has not been produced' +LOG_COLLECTOR_GLOBAL_TIMEOUT = 30 + DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION = { 'ip_address': 'localhost', 'client_keys': os.path.join(WAZUH_PATH, 'etc', 'client.keys'), @@ -690,6 +691,37 @@ def callback_invalid_state_interval(interval): return monitoring.make_callback(pattern=msg, prefix=prefix, escape=True) +def callback_logcollector_started(): + """Check if logcollector started.""" + return monitoring.make_callback(pattern='Started', prefix=prefix) + + +def callback_log_bad_predicate(): + """Check for the macOS ULS bad predicate message.""" + return monitoring.make_callback(pattern="Execution error 'log:", prefix=prefix) + + +def callback_macos_uls_log(expected_message): + """Callback function to wait for a macOS' ULS log, collected by logcollector.""" + return monitoring.make_callback(pattern=expected_message, prefix=prefix, escape=False) + + +def callback_logcollector_log_stream_log(): + """Check for logcollector's macOS ULS module start message.""" + return monitoring.make_callback(pattern='Monitoring macOS logs with:(.+?)log stream', + prefix=prefix, escape=False) + + +def callback_file_status_macos_key(): + """Check for 'macos' key.""" + return monitoring.make_callback(pattern='"macos"', prefix='.*', escape=False) + + +def callback_log_macos_stream_exit(): + """Check for the macOS ULS log stream exit message.""" + return monitoring.make_callback(pattern="macOS 'log stream' process exited, pid:", prefix=prefix) + + def wait_statistics_file(timeout=LOG_COLLECTOR_GLOBAL_TIMEOUT): """Wait until statistics file is available. @@ -766,6 +798,7 @@ def format_macos_message_pattern(process_name, message, type='log', subsystem=No return macos_message + def compose_macos_log_command(type='', level='', predicate='', is_sierra=False): """ This function replicates how the command 'log' will be called from the Wazuh agent given the query parameters @@ -775,7 +808,7 @@ def compose_macos_log_command(type='', level='', predicate='', is_sierra=False): level (str): < default | info | debug > Include events at, and below, the given level. predicate (str): Filter events using the given predicate. is_sierra (boolean): True if running on macOS Sierra, False otherwise. - + Returns: string: Full log command composed with the given parameters. """ diff --git a/deps/wazuh_testing/wazuh_testing/tools/configuration.py b/deps/wazuh_testing/wazuh_testing/tools/configuration.py index 214710ff3a..1bb192ba9d 100644 --- a/deps/wazuh_testing/wazuh_testing/tools/configuration.py +++ b/deps/wazuh_testing/wazuh_testing/tools/configuration.py @@ -13,6 +13,7 @@ import yaml from wazuh_testing import global_parameters from wazuh_testing.tools import WAZUH_PATH, GEN_OSSEC, WAZUH_CONF, PREFIX, WAZUH_LOCAL_INTERNAL_OPTIONS +from wazuh_testing import global_parameters, logger # customize _serialize_xml to avoid lexicographical order in XML attributes @@ -617,9 +618,13 @@ def get_local_internal_options_dict(): with open(WAZUH_LOCAL_INTERNAL_OPTIONS, 'r') as local_internal_option_file: configuration_options = local_internal_option_file.readlines() for configuration_option in configuration_options: - if not configuration_option.startswith('#'): - option_name, option_value = configuration_option.split('=') - local_internal_option_dict[option_name] = option_value + if not configuration_option.startswith('#') and not configuration_option == '\n': + try: + option_name, option_value = configuration_option.split('=') + local_internal_option_dict[option_name] = option_value + except ValueError: + logger.error(f"Invalid local_internal_options value: {configuration_option}") + raise ValueError('Invalid local_internal_option') return local_internal_option_dict diff --git a/tests/integration/test_logcollector/conftest.py b/tests/integration/test_logcollector/conftest.py index a7a9286bef..68a2b9ec82 100644 --- a/tests/integration/test_logcollector/conftest.py +++ b/tests/integration/test_logcollector/conftest.py @@ -6,13 +6,15 @@ import pytest import wazuh_testing.tools.configuration as conf from wazuh_testing.logcollector import LOGCOLLECTOR_DEFAULT_LOCAL_INTERNAL_OPTIONS -from wazuh_testing.tools import LOG_FILE_PATH +from wazuh_testing.tools import LOG_FILE_PATH, LOGCOLLECTOR_FILE_STATUS_PATH, WAZUH_LOCAL_INTERNAL_OPTIONS from wazuh_testing.tools.file import truncate_file from wazuh_testing.tools.monitoring import FileMonitor from wazuh_testing.tools.services import control_service from wazuh_testing.tools.remoted_sim import RemotedSimulator from wazuh_testing.tools.authd_sim import AuthdSimulator from wazuh_testing.tools import CLIENT_CUSTOM_KEYS_PATH, CLIENT_CUSTOM_CERT_PATH +from os.path import exists +from os import remove DAEMON_NAME = "wazuh-logcollector" @@ -86,3 +88,19 @@ def configure_local_internal_options_logcollector(): control_service('restart') else: yield + + +@pytest.fixture(scope='function') +def delete_file_status_json(): + """Delete file_status.json from logcollector""" + remove(LOGCOLLECTOR_FILE_STATUS_PATH) if exists(LOGCOLLECTOR_FILE_STATUS_PATH) else None + + yield + + +@pytest.fixture(scope='function') +def truncate_log_file(): + """Truncate the log file (ossec.log)""" + truncate_file(LOG_FILE_PATH) + + yield diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py index cccd04f381..50a0cd3a96 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_basic.py @@ -2,144 +2,94 @@ # Created by Wazuh, Inc. . # This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 -import os -import re import pytest import wazuh_testing.logcollector as logcollector -from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH, LOG_FILE_PATH, WAZUH_LOCAL_INTERNAL_OPTIONS -from wazuh_testing.tools.monitoring import FileMonitor, wait_file, make_callback from wazuh_testing.tools.configuration import load_wazuh_configurations -from wazuh_testing.logcollector import prefix as logcollector_prefix -from wazuh_testing.tools.file import read_json, truncate_file -from wazuh_testing.tools.services import control_service +from wazuh_testing.logcollector import LOG_COLLECTOR_GLOBAL_TIMEOUT +from wazuh_testing.tools.monitoring import FileMonitor, wait_file +from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH +from wazuh_testing.tools.file import read_json +from os.path import dirname, join, realpath +from re import match + # Marks pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] # Configuration -test_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') -configurations_path = os.path.join(test_data_path, 'wazuh_macos_file_status_basic.yaml') +test_data_path = join(dirname(realpath(__file__)), 'data') +configurations_path = join(test_data_path, 'wazuh_macos_file_status_basic.yaml') parameters = [{'ONLY_FUTURE_EVENTS': 'yes'}, {'ONLY_FUTURE_EVENTS': 'no'}] metadata = [{'only-future-events': 'yes'}, {'only-future-events': 'no'}] +daemons_handler_configuration = {'daemons': ['wazuh-agentd', 'wazuh-logcollector'], 'ignore_errors': False} + # Configuration data configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters, metadata=metadata) -configuration_ids = [f"{x['ONLY_FUTURE_EVENTS']}" for x in parameters] - -daemons_handler_configuration = {'daemons': ['wazuh-logcollector'], 'ignore_errors': False} +configuration_ids = [f"only_future_events_{x['ONLY_FUTURE_EVENTS']}" for x in parameters] # Max number of characters to be displayed in the log's debug message sample_log_length = 100 # Time in seconds to update the file_status.json file_status_update_time = 4 -local_internal_options = { 'logcollector.debug': 2, - 'logcollector.vcheck_files': file_status_update_time, - 'logcollector.sample_log_length': sample_log_length } +local_internal_options = {'logcollector.debug': 2, + 'logcollector.vcheck_files': file_status_update_time, + 'logcollector.sample_log_length': sample_log_length} -macos_message = { 'command': 'logger', - 'message': 'Logger testing message - file status' } - -# Maximum waiting time in seconds to find the logs on ossec.log -file_monitor_timeout = 30 +macos_message = {'command': 'logger', + 'message': 'Logger testing message - file status'} # Expected message to be used on the "callback_macos_uls_log" callback expected_message = logcollector.format_macos_message_pattern(macos_message['command'], macos_message['message']) -wazuh_log_monitor = None - # Fixtures -@pytest.fixture(scope='module') -def startup_cleanup(): - """Truncate ossec.log and remove logcollector's file_status.json file.""" - truncate_file(WAZUH_LOCAL_INTERNAL_OPTIONS) - - @pytest.fixture(scope='module', params=configurations, ids=configuration_ids) def get_configuration(request): """Get configurations from the module.""" return request.param -@pytest.fixture(scope='module') -def restart_required_logcollector_daemons(): - """Wazuh logcollector daemons handler.""" - - required_logcollector_daemons = ['wazuh-logcollector'] - - for daemon in required_logcollector_daemons: - control_service('stop', daemon=daemon) - - truncate_file(LOG_FILE_PATH) - os.remove(LOGCOLLECTOR_FILE_STATUS_PATH) if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH) else None - - for daemon in required_logcollector_daemons: - control_service('start', daemon=daemon) - - yield - - for daemon in required_logcollector_daemons: - control_service('stop', daemon=daemon) - - -def callback_macos_uls_log(): - """Callback function to wait for the macOS' ULS log collected by logcollector.""" - return make_callback(pattern=expected_message, prefix=logcollector_prefix, escape=False) - - -def callback_logcollector_log_stream_log(): - """Check for logcollector's macOS ULS module start message.""" - return make_callback(pattern='Monitoring macOS logs with:(.+?)log stream', prefix=logcollector_prefix, escape=False) - - -def callback_file_status_macos_key(line): - """Check for 'macos' key.""" - return make_callback(pattern='"macos"', prefix='') - - -def test_macos_file_status_basic(startup_cleanup, - configure_local_internal_options_module, - get_configuration, - configure_environment, - restart_required_logcollector_daemons): +def test_macos_file_status_basic(truncate_log_file, delete_file_status_json, + configure_local_internal_options_module, + get_configuration, configure_environment, + file_monitoring, daemons_handler): """Checks if logcollector stores correctly "macos"-formatted localfile data. - This test uses logger tool and a custom log to generate an ULS event. The agent is connected to the authd simulator - and sends an event to trigger the file_status.json update. + This test uses logger tool and a custom log to generate an ULS event. When logcollector receives a valid log, then + the file_status.json is updated. Raises: TimeoutError: If the callbacks, that checks the expected logs, are not satisfied in the expected time. FileNotFoundError: If the file_status.json is not available in the expected time. """ - - wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) - - wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=logcollector.callback_monitoring_macos_logs, - error_message=logcollector.GENERIC_CALLBACK_ERROR_TARGET_SOCKET) + log_monitor.start(timeout=LOG_COLLECTOR_GLOBAL_TIMEOUT, + callback=logcollector.callback_monitoring_macos_logs, + error_message=logcollector.GENERIC_CALLBACK_ERROR_TARGET_SOCKET) # Watches the ossec.log to check when logcollector starts the macOS ULS module - wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=callback_logcollector_log_stream_log(), - error_message='Logcollector did not start') + log_monitor.start(timeout=LOG_COLLECTOR_GLOBAL_TIMEOUT, + callback=logcollector.callback_logcollector_log_stream_log(), + error_message='Logcollector did not start.') logcollector.generate_macos_logger_log(macos_message['message']) - wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=callback_macos_uls_log(), - error_message='MacOS ULS log was not found') + log_monitor.start(timeout=LOG_COLLECTOR_GLOBAL_TIMEOUT, + callback=logcollector.callback_macos_uls_log(expected_message), + error_message="MacOS ULS log was not found: '{}'.".format(expected_message)) # Waits for file_status.json to be created, with a timeout about the time needed to update the file - wait_file(LOGCOLLECTOR_FILE_STATUS_PATH, file_monitor_timeout) + wait_file(LOGCOLLECTOR_FILE_STATUS_PATH, LOG_COLLECTOR_GLOBAL_TIMEOUT) # Watches the file_status.json file for the "macos" key file_status_monitor = FileMonitor(LOGCOLLECTOR_FILE_STATUS_PATH) - file_status_monitor.start(timeout=file_monitor_timeout, - callback=callback_file_status_macos_key, - error_message="The 'macos' key could not be found on the file_status.json file") + + file_status_monitor.start(timeout=LOG_COLLECTOR_GLOBAL_TIMEOUT, + callback=logcollector.callback_file_status_macos_key(), + error_message="The 'macos' key could not be found on the file_status.json file") file_status_json = read_json(LOGCOLLECTOR_FILE_STATUS_PATH) @@ -152,13 +102,10 @@ def test_macos_file_status_basic(startup_cleanup, assert file_status_json['macos']['timestamp'], "Error finding 'timestamp' key inside 'macos'" - assert re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}-\d{4}$', - file_status_json['macos']['timestamp']), \ - 'Error of timestamp format' + assert match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}[-+]\d{4}$', file_status_json['macos']['timestamp']), \ + 'Error of timestamp format' assert file_status_json['macos']['settings'], "Error finding 'settings' key inside 'macos'" assert file_status_json['macos']['settings'] \ - == logcollector.compose_macos_log_command(conf_type, - conf_level, - conf_predicate) + == logcollector.compose_macos_log_command(conf_type, conf_level, conf_predicate) diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py index 82b1ffbda3..96efee08b4 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_predicate.py @@ -2,100 +2,70 @@ # Created by Wazuh, Inc. . # This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 -import os import pytest -import re -# from wazuh_testing.logcollector import DEFAULT_AUTHD_REMOTED_SIMULATOR_CONFIGURATION -from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH, LOG_FILE_PATH, WAZUH_LOCAL_INTERNAL_OPTIONS -from wazuh_testing.tools.monitoring import FileMonitor, wait_file, make_callback +from wazuh_testing.logcollector import (LOG_COLLECTOR_GLOBAL_TIMEOUT, + callback_log_macos_stream_exit, + callback_log_bad_predicate) from wazuh_testing.tools.configuration import load_wazuh_configurations -from wazuh_testing.logcollector import prefix as logcollector_prefix -from wazuh_testing.tools.file import read_json, truncate_file +from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH +from wazuh_testing.tools.monitoring import wait_file +from wazuh_testing.tools.file import read_json +from os.path import dirname, join, realpath # Marks pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] # Configuration -test_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') -configurations_path = os.path.join(test_data_path, 'wazuh_macos_file_status_predicate.yaml') +test_data_path = join(dirname(realpath(__file__)), 'data') +configurations_path = join(test_data_path, 'wazuh_macos_file_status_predicate.yaml') parameters = [{'ONLY_FUTURE_EVENTS': 'yes'}, {'ONLY_FUTURE_EVENTS': 'no'}] metadata = [{'only-future-events': 'yes'}, {'only-future-events': 'no'}] +daemons_handler_configuration = {'daemons': ['wazuh-agentd', 'wazuh-logcollector'], 'ignore_errors': False} + # Configuration data configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters, metadata=metadata) -configuration_ids = [f"{x['ONLY_FUTURE_EVENTS']}" for x in parameters] - -daemons_handler_configuration = {'daemons': ['wazuh-logcollector'], 'ignore_errors': False} +configuration_ids = [f"only_future_events_{x['ONLY_FUTURE_EVENTS']}" for x in parameters] -# Max number of characters to be displayed in the log's debug message -sample_log_length = 100 # Time in seconds to update the file_status.json file_status_update_time = 4 -local_internal_options = { 'logcollector.vcheck_files': file_status_update_time, - 'logcollector.sample_log_length': sample_log_length } - -# Maximum waiting time in seconds to find the logs on ossec.log -file_monitor_timeout = 30 - -wazuh_log_monitor = None +local_internal_options = {'logcollector.vcheck_files': file_status_update_time} # Fixtures -@pytest.fixture(scope='module') -def startup_cleanup(): - """Truncate ossec.log and remove logcollector's file_status.json file.""" - truncate_file(WAZUH_LOCAL_INTERNAL_OPTIONS) - truncate_file(LOG_FILE_PATH) - os.remove(LOGCOLLECTOR_FILE_STATUS_PATH) if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH) else None - - @pytest.fixture(scope='module', params=configurations, ids=configuration_ids) def get_configuration(request): """Get configurations from the module.""" return request.param -def callback_log_bad_predicate(): - """Check if 'line' has the macOS ULS bad predicate message on it.""" - return make_callback(pattern="Execution error 'log:", prefix=logcollector_prefix) - - -def callback_log_exit_log(): - """Check if 'line' has the macOS ULS log stream exited message on it.""" - return make_callback(pattern="macOS 'log stream' process exited, pid:", prefix=logcollector_prefix) - - -def test_macos_file_status_predicate(startup_cleanup, +def test_macos_file_status_predicate(truncate_log_file, delete_file_status_json, configure_local_internal_options_module, - get_configuration, - configure_environment, - daemons_handler): + get_configuration, configure_environment, + file_monitoring, daemons_handler): """Checks that logcollector does not store 'macos'-formatted localfile data since its predicate is erroneous. - The agent is connected to the authd simulator and uses a dummy localfile (/Library/Ossec/logs/active-responses.log) - which triggers the creation of file_status.json + The agent uses a dummy localfile (/Library/Ossec/logs/active-responses.log) which triggers the creation of + file_status.json file. Raises: TimeoutError: If the callbacks, that checks the expected logs, are not satisfied in the expected time. FileNotFoundError: If the file_status.json is not available in the expected time. """ - wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) - - wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=callback_log_bad_predicate(), - error_message='Expected log that matches the regex ' - '".*Execution error \'log:" could not be found') + log_monitor.start(timeout=LOG_COLLECTOR_GLOBAL_TIMEOUT, + callback=callback_log_bad_predicate(), + error_message='Expected log that matches the regex ".*Execution error \'log:" could not be found') - wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=callback_log_exit_log(), - error_message='Expected log that matches the regex ' - '".*macOS \'log stream\' process exited, pid:" could not be found') + log_monitor.start(timeout=LOG_COLLECTOR_GLOBAL_TIMEOUT, + callback=callback_log_macos_stream_exit(), + error_message='Expected log that matches the regex ' + '".*macOS \'log stream\' process exited, pid:" could not be found') # Waiting for file_status.json to be created, with a timeout about the time needed to update the file - wait_file(LOGCOLLECTOR_FILE_STATUS_PATH, file_monitor_timeout) + wait_file(LOGCOLLECTOR_FILE_STATUS_PATH, LOG_COLLECTOR_GLOBAL_TIMEOUT) file_status_json = read_json(LOGCOLLECTOR_FILE_STATUS_PATH) diff --git a/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py b/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py index 4ce4538270..7b4e7074f1 100644 --- a/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py +++ b/tests/integration/test_logcollector/test_macos/test_macos_file_status_when_no_macos.py @@ -2,97 +2,69 @@ # Created by Wazuh, Inc. . # This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 -import os import pytest -import wazuh_testing.logcollector as logcollector -from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH, LOG_FILE_PATH, WAZUH_LOCAL_INTERNAL_OPTIONS -from wazuh_testing.tools.monitoring import FileMonitor, wait_file, make_callback -from wazuh_testing.tools.file import read_json, write_json_file, truncate_file +from wazuh_testing.logcollector import LOG_COLLECTOR_GLOBAL_TIMEOUT, callback_logcollector_started from wazuh_testing.tools.configuration import load_wazuh_configurations -from wazuh_testing.logcollector import prefix as logcollector_prefix -from wazuh_testing.tools.services import control_service +from wazuh_testing.tools.file import read_json, write_json_file +from wazuh_testing.tools import LOGCOLLECTOR_FILE_STATUS_PATH +from wazuh_testing.tools.monitoring import wait_file +from os.path import dirname, join, exists, realpath from tempfile import gettempdir from time import sleep +from os import remove # Marks pytestmark = [pytest.mark.darwin, pytest.mark.tier(level=0)] # Configuration -test_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') -configurations_path = os.path.join(test_data_path, 'wazuh_macos_file_status_when_no_macos.yaml') +test_data_path = join(dirname(realpath(__file__)), 'data') +configurations_path = join(test_data_path, 'wazuh_macos_file_status_when_no_macos.yaml') -dummy_file = os.path.join(gettempdir(), 'dummy_file.log') +dummy_file = join(gettempdir(), 'dummy_file.log') parameters = [{'FILE_TO_MONITOR': dummy_file}] # Configuration data configurations = load_wazuh_configurations(configurations_path, __name__, params=parameters) -configuration_ids = [f"{x['FILE_TO_MONITOR']}" for x in parameters] -# Max number of characters to be displayed in the log's debug message -sample_log_length = 100 +daemons_handler_configuration = {'daemons': ['wazuh-agentd', + 'wazuh-modulesd', + 'wazuh-logcollector'], + 'ignore_errors': False} + # Time in seconds to update the file_status.json file_status_update_time = 4 -local_internal_options = { 'logcollector.vcheck_files': file_status_update_time, - 'logcollector.sample_log_length': sample_log_length } - -# Maximum waiting time in seconds to find the logs on ossec.log -file_monitor_timeout = 30 - -# Time to wait for file_status.json to be updated -wait_file_status_update_time = file_status_update_time + 2 +local_internal_options = {'logcollector.vcheck_files': file_status_update_time} -wazuh_log_monitor = None +# Time to wait for file_status.json to be updated (the +8 is due to a delay added by the wazuh-agentd daemmon) +wait_file_status_update_time = file_status_update_time + 8 # Fixtures -@pytest.fixture(scope='module', params=configurations, ids=configuration_ids) -def get_configuration(request): - """Get configurations from the module.""" - return request.param - - @pytest.fixture(scope='module') -def restart_required_logcollector_daemons(): - """Wazuh logcollector daemons handler.""" - - required_logcollector_daemons = ['wazuh-logcollector'] - - for daemon in required_logcollector_daemons: - control_service('stop', daemon=daemon) - - truncate_file(LOG_FILE_PATH) - os.remove(LOGCOLLECTOR_FILE_STATUS_PATH) if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH) else None - - for daemon in required_logcollector_daemons: - control_service('start', daemon=daemon) +def handle_files(): + """Create dummy file to be monitored by logcollector, after the test it is deleted.""" + with open(dummy_file, 'w') as f: + pass yield - for daemon in required_logcollector_daemons: - control_service('stop', daemon=daemon) - - -@pytest.fixture(scope='module') -def startup_cleanup(): - """Truncate local_internals file and create dummy file to be monitored by logcollector.""" - truncate_file(WAZUH_LOCAL_INTERNAL_OPTIONS) - - with open(dummy_file, 'w') as f: - pass + remove(dummy_file) if exists(dummy_file) else None -def callback_logcollector_started(): - """Check for 'macos' key.""" - return make_callback(pattern='Started', prefix=logcollector_prefix) +@pytest.fixture(scope='module', params=configurations) +def get_configuration(request): + """Get configurations from the module.""" + return request.param -def test_macos_file_status_when_no_macos(startup_cleanup, +def test_macos_file_status_when_no_macos(truncate_log_file, handle_files, + delete_file_status_json, configure_local_internal_options_module, get_configuration, configure_environment, - restart_required_logcollector_daemons): + file_monitoring, daemons_handler): """Checks that logcollector does not store and removes, if exists, previous "macos"-formatted localfile data in the file_status.json @@ -103,17 +75,14 @@ def test_macos_file_status_when_no_macos(startup_cleanup, Raises: TimeoutError: If the callbacks, that checks the expected logs, are not satisfied in the expected time. """ - file_status_json = {} - wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) - - wazuh_log_monitor.start(timeout=file_monitor_timeout, - callback=callback_logcollector_started(), - error_message="Logcollector did not start") + log_monitor.start(timeout=LOG_COLLECTOR_GLOBAL_TIMEOUT, + callback=callback_logcollector_started(), + error_message="Logcollector did not start") # Check if json_status contains 'macos' data and if not insert it - if os.path.exists(LOGCOLLECTOR_FILE_STATUS_PATH): + if exists(LOGCOLLECTOR_FILE_STATUS_PATH): file_status_json = read_json(LOGCOLLECTOR_FILE_STATUS_PATH) if 'macos' not in file_status_json: file_status_json['macos'] = {} @@ -130,7 +99,7 @@ def test_macos_file_status_when_no_macos(startup_cleanup, write_json_file(LOGCOLLECTOR_FILE_STATUS_PATH, file_status_json) # Waits for file_status.json to be created, with a timeout about the time needed to update the file - wait_file(LOGCOLLECTOR_FILE_STATUS_PATH, file_monitor_timeout) + wait_file(LOGCOLLECTOR_FILE_STATUS_PATH, LOG_COLLECTOR_GLOBAL_TIMEOUT) # Waits about the time needed to update the file status sleep(wait_file_status_update_time)