def test_sync_interval(get_configuration, configure_environment, restart_syscheckd, wait_for_initial_scan): """ Verify that synchronization checks take place at the expected time given SYNC_INTERVAL variable. """ # Check if the test should be skipped check_apply_test({'sync_interval'}, get_configuration['tags']) interval = time_to_timedelta(get_configuration['metadata']['interval']) wazuh_log_monitor.start( timeout=global_parameters.default_timeout, callback=callback_detect_synchronization, error_message='Did not receive expected ' '"Initializing FIM Integrity Synchronization check" event') TimeMachine.travel_to_future(interval) wazuh_log_monitor.start( timeout=global_parameters.default_timeout, callback=callback_detect_synchronization, error_message='Did not receive expected ' '"Initializing FIM Integrity Synchronization check" event') # This should fail as we are only advancing half the time needed for synchronization to occur TimeMachine.travel_to_future(interval / 2) try: result = wazuh_log_monitor.start( timeout=1 if interval.total_seconds() == 10.0 else 3, callback=callback_detect_synchronization, accum_results=1, error_message='Did not receive expected "Initializing FIM Integrity ' 'Synchronization check" event').result() if result is not None: pytest.fail("Synchronization shouldn't happen at this point") except TimeoutError: return
def test_configuration_age_datetime(new_datetime, get_files_list, get_configuration, create_file_structure_function, configure_environment): """Check if logcollector age option works correctly when date time of the system changes. Ensure that when date of the system change logcollector use properly age value, ignoring files that have not been modified for a time greater than age value using current date. Raises: TimeoutError: If the expected callbacks are not generated. """ cfg = get_configuration['metadata'] age_seconds = time_to_seconds(cfg['age']) control_service('stop', daemon=DAEMON_NAME) truncate_file(LOG_FILE_PATH) wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) control_service('start', daemon=DAEMON_NAME) TimeMachine.travel_to_future(time_to_timedelta(new_datetime)) for file in file_structure: for name in file['filename']: absolute_file_path = os.path.join(file['folder_path'], name) log_callback = logcollector.callback_match_pattern_file( cfg['location'], absolute_file_path) wazuh_log_monitor.start(timeout=5, callback=log_callback, error_message=f"{name} was not detected") fileinfo = os.stat(absolute_file_path) current_time = time.time() mfile_time = current_time - fileinfo.st_mtime if age_seconds <= int(mfile_time): log_callback = logcollector.callback_ignoring_file( absolute_file_path) wazuh_log_monitor.start( timeout=5, callback=log_callback, error_message=f"{name} was not ignored") else: with pytest.raises(TimeoutError): log_callback = logcollector.callback_ignoring_file( absolute_file_path) wazuh_log_monitor.start( timeout=5, callback=log_callback, error_message=f"{name} was not ignored") TimeMachine.time_rollback()
def test_response_timeout(num_files, get_configuration, configure_environment, restart_syscheckd): """Verify that synchronization checks take place at the expected time given INTERVAL and RESPONSE_TIMEOUT parameters, being INTERVAL greater than RESPONSE_TIMEOUT. To accomplish this a connection with a Wazuh Agent (Linux based) must be established via SSH using Paramiko. All operations will take place on the Agent side. Parameters ---------- num_files : int Number of files to create within the test """ def overwrite_agent_conf_file(): cmd = "sudo sed -i ':a;N;$!ba;s|<synchronization>.*</synchronization>|<synchronization>\ <enabled>yes</enabled>\ <interval>" + str(sync_interval) + "</interval>\ <response_timeout>" + str( response_timeout) + "</response_timeout>\ </synchronization>|g' /var/ossec/etc/ossec.conf" ssh.exec_command(cmd) def wait_agent_initial_scan(time_out=60): truncate_agent_log() start_time = datetime.now() while datetime.now() < start_time + timedelta(seconds=time_out): ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command( "sudo cat /var/ossec/logs/ossec.log") for line in ssh_stdout.read().decode('ascii').splitlines(): if callback_detect_end_scan(line): return pytest.fail( "No 'File integrity monitoring scan ended.' was found on ossec.log." ) def create_files_in_agent(): ssh.exec_command("sudo systemctl stop wazuh-agent") ssh.exec_command("sudo mkdir " + DIR_NAME) ssh.exec_command("sudo touch " + DIR_NAME + "/testfile{0.." + str(num_files) + "}") purge_manager_db() ssh.exec_command("sudo systemctl start wazuh-agent") def purge_manager_db(): for proc in psutil.process_iter(attrs=['name']): if proc.name() == "wazuh-db": proc.terminate() os.system("rm -f /var/ossec/queue/db/00{1..9}.db*") os.system("/var/ossec/bin/wazuh-db") time.sleep(5) def detect_synchronization_start(time_out=1): start_time = datetime.now() while datetime.now() < start_time + timedelta(seconds=time_out): ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command( "sudo cat /var/ossec/logs/ossec.log") for line in ssh_stdout.read().decode('ascii').splitlines(): if callback_detect_synchronization(line): return extract_datetime(str(line)) return None def wait_agent_dbsync_finish(): previous_time = datetime.now() while datetime.now() - previous_time < timedelta(seconds=3): ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command( "sudo cat /var/ossec/logs/ossec.log") for line in ssh_stdout.read().decode('ascii').splitlines(): if "syscheck dbsync" in line: previous_time = datetime.now() truncate_agent_log() return datetime.now() def wait_agent_integrity_control(): previous_time = datetime.now() while datetime.now() - previous_time < timedelta(seconds=1): ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command( "sudo cat /var/ossec/logs/ossec.log") for line in ssh_stdout.read().decode('ascii').splitlines(): if "Sending integrity control message" in line: previous_time = datetime.now() elif callback_detect_synchronization(line): pytest.fail( "No new synchronization process should start until `integrity control message` ends." ) truncate_agent_log() def truncate_agent_log(): ssh.exec_command("sudo truncate -s 0 " + LOG_PATH) def extract_datetime(line): return datetime.strptime(line[0:19], '%Y/%m/%d %H:%M:%S') def update_agent_datetime(): now = datetime.now() year = str(now.year) month = str(now.month) day = str(now.day) hour = str(now.hour) minute = str(now.minute) second = str(now.second) timedatectl_cmd = "sudo timedatectl set-time '" + year + "-" + month + "-" + day + " " + hour + ":" + minute + \ ":" + second + "'" ssh.exec_command(timedatectl_cmd) # Check if the test should be skipped check_apply_test({'response_timeout'}, get_configuration['tags']) # Variables LOG_PATH = "/var/ossec/logs/ossec.log" DIR_NAME = "/testdir1" AGENT_IP = "172.19.0.201" USERNAME = "******" PASSWORD = "******" response_timeout = get_configuration['metadata']['response_timeout'] sync_interval = get_configuration['metadata']['interval'] # Connect to the agent ssh = paramiko.SSHClient() ssh.load_system_host_keys() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname=AGENT_IP, username=USERNAME, password=PASSWORD) # Setup agent overwrite_agent_conf_file() update_agent_datetime() create_files_in_agent() wait_agent_initial_scan() # Check if first synchronization has started time_first_synchronization = detect_synchronization_start() if time_first_synchronization is None: pytest.fail("No synchronization was detected.") # Wait until synchronization ends time_after_dbsync = wait_agent_dbsync_finish() wait_agent_integrity_control() truncate_agent_log() # Determines when the next synchronization should occur max_next_synchronization = max( time_first_synchronization + time_to_timedelta(sync_interval), time_after_dbsync + time_to_timedelta(response_timeout)) # Calculate a datetime when the next synchronization should NOT happen min_next_synchronization = min( time_first_synchronization + time_to_timedelta(sync_interval), time_after_dbsync + time_to_timedelta(response_timeout)) # Travels in time to a datetime when synchronization should NOT happen, if needed if min_next_synchronization > datetime.now( ) and sync_interval != response_timeout: TimeMachine.travel_to_future(min_next_synchronization - datetime.now()) update_agent_datetime() # Ensure there is no synchronization at this time. if detect_synchronization_start() is not None: pytest.fail("No synchronization should happen at this time.") # Travels in time to a datetime when synchronization MUST ocurr TimeMachine.travel_to_future(max_next_synchronization - datetime.now()) update_agent_datetime() # Wait until next synchronization is detected if detect_synchronization_start(time_out=10) is None: pytest.fail("No synchronization was detected.")
# variables test_data_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') configurations_path = os.path.join(test_data_path, 'wazuh_response_conf.yaml') test_directories = [os.path.join(PREFIX, 'testdir1')] wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) response_timeouts = ['10', '10m', '10h', '10d', '10w'] sync_interval = ['20', '20m', '20h', '20d', '20w'] list_ = [] for response in response_timeouts: for sync in sync_interval: if time_to_timedelta(sync) > time_to_timedelta(response): list_.append({'RESPONSE_TIMEOUT': response, 'INTERVAL': sync}) # configurations p, m = generate_params(apply_to_all=list_, modes=['scheduled']) configurations = load_wazuh_configurations(configurations_path, __name__, params=p, metadata=m) # fixtures @pytest.fixture(scope='module', params=configurations) def get_configuration(request): """Get configurations from the module."""