Exemplo n.º 1
0
def test_disk_quota_disabled(tags_to_apply, filename, folder, size, get_configuration, configure_environment,
                             restart_syscheckd, wait_for_fim_start):
    """
    Check that the disk_quota option is disabled correctly.

    Creates a file that, when compressed, is larger than the configured disk_quota limit and checks that the message
    about reaching the limit does not appear in the log.

    Parameters
    ----------
    filename : str
        Name of the file to be created.
    folder : str
        Directory where the files are being created.
    size : int
        Size of each file in bytes.
    tags_to_apply : set
        Run test if matches with a configuration identifier, skip otherwise.
    """
    check_apply_test(tags_to_apply, get_configuration['tags'])
    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'

    to_write = generate_string(size, '0')
    create_file(REGULAR, folder, filename, content=to_write)

    check_time_travel(scheduled)

    with pytest.raises(TimeoutError):
        wazuh_log_monitor.start(timeout=global_parameters.default_timeout, callback=callback_disk_quota_limit_reached)
def test_max_files_per_second(get_configuration, configure_environment,
                              restart_syscheckd, wait_for_fim_start):
    """Check that FIM sleeps for one second when the option max_files_per_second is enabled

    Args:
        tags_to_apply (set): Run test if matches with a configuration identifier, skip otherwise.
        get_configuration (fixture): Gets the current configuration of the test.
        configure_environment (fixture): Configure the environment for the execution of the test.
        restart_syscheckd (fixture): Restarts syscheck.
        wait_for_fim_start (fixture): Waits until the first FIM scan is completed.
    Raises:
        TimeoutError: If an expected event couldn't be captured.
    """
    # Create the files in an empty folder to check realtime and whodata.
    for i in range(n_files_to_create):
        fim.create_file(fim.REGULAR,
                        test_directories[0],
                        f'test_{i}',
                        content='')

    extra_timeout = n_files_to_create / max_files_per_second

    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'
    fim.check_time_travel(scheduled)
    try:
        wazuh_log_monitor.start(
            timeout=global_parameters.default_timeout + extra_timeout,
            callback=fim.callback_detect_max_files_per_second)
    except TimeoutError as e:
        if get_configuration['metadata']['max_files_per_sec'] == 0:
            pass
        else:
            raise e
Exemplo n.º 3
0
def test_max_eps(get_configuration, configure_environment, restart_syscheckd,
                 wait_for_initial_scan):
    """
    Check that max_eps is respected when a big quantity of syscheck events are generated.

    During the test, a big quantity of files are created and the max number of event occurrences per second is measured
    to ensure it never exceeds max_eps
    """
    check_apply_test({'max_eps'}, get_configuration['tags'])

    max_eps = int(get_configuration['metadata']['max_eps'])
    mode = get_configuration['metadata']['fim_mode']

    # Create files to read max_eps files with added events
    for i in range(int(max_eps) * 5):
        create_file(REGULAR, testdir1, f'test{i}_{mode}_{max_eps}', content='')

    check_time_travel(mode == "scheduled")
    n_results = max_eps * 4

    result = wazuh_log_monitor.start(
        timeout=(n_results / max_eps) * 6,
        accum_results=n_results,
        callback=callback_event_message,
        error_message=f'Received less results than expected ({n_results})'
    ).result()

    counter = Counter([date_time for date_time, _ in result])
    error_margin = (max_eps * 0.1)

    for date_time, n_occurrences in counter.items():
        assert n_occurrences <= round(
            max_eps + error_margin
        ), f'Sent {n_occurrences} but a maximum of {max_eps} was set'
Exemplo n.º 4
0
def test_vulnerabilities_report(get_configuration, configure_environment, restart_modulesd, check_cve_db,
                                mock_vulnerability_scan):
    """
    Check if inserted vulnerable packages are reported by vulnerability detector
    """
    vulnerabilities_number = mock_vulnerability_scan["vulnerabilities_number"]

    if mock_vulnerability_scan['format'] == 'pkg' and mock_vulnerability_scan['version'] == 'Wazuh v4.0':
        version = mock_vulnerability_scan['version']
        wazuh_log_monitor.start(
            timeout=SCAN_TIMEOUT,
            update_position=False,
            callback=vd.make_vuln_callback(fr"Agent .* has an unsupported Wazuh version: '{version}'"),
            error_message="The expected event 'Agent .* has an unsupported Wazuh version' not found"
        )

        return

    # Check the vulnerabilities of inserted packages
    try:
        for item in nvd_vulnerabilities['vulnerabilities_nvd']:
            vd.check_vulnerability_scan_event(wazuh_log_monitor, item['package']['name'], item['cve']['cveid'])
    except TimeoutError:
        check_time_travel(time_travel=True, interval=timedelta(seconds=300))
        for item in nvd_vulnerabilities['vulnerabilities_nvd']:
            vd.check_vulnerability_scan_event(wazuh_log_monitor, item['package']['name'], item['cve']['cveid'])

    # Check that the number of NVD vulnerabilities is the expected
    if mock_vulnerability_scan["format"] != "win":
        vd.check_detected_vulnerabilities_number(wazuh_log_monitor=wazuh_log_monitor,
                                                 expected_vulnerabilities_number=vulnerabilities_number,
                                                 feed_source='NVD', timeout=vd.VULN_DETECTOR_SCAN_TIMEOUT)

    vd.check_if_modulesd_is_running()
Exemplo n.º 5
0
def test_tag_ignore(directory, event_generated, get_configuration,
                    configure_environment, put_env_variables,
                    restart_syscheckd, wait_for_fim_start):
    """
    Test environment variables are ignored
    """

    # Create text files
    filename = "test"
    create_file(REGULAR, directory, filename, content="")

    # Go ahead in time to let syscheck perform a new scan
    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'
    check_time_travel(scheduled, monitor=wazuh_log_monitor)

    if event_generated:
        event = wazuh_log_monitor.start(
            timeout=global_parameters.default_timeout,
            callback=callback_detect_event,
            error_message='Did not receive expected '
            '"Sending FIM event: ..." event').result()
        assert event['data']['type'] == 'added', 'Event type not equal'
        assert event['data']['path'] == os.path.join(
            directory, filename), 'Event path not equal'
    else:
        while True:
            ignored_file = wazuh_log_monitor.start(
                timeout=global_parameters.default_timeout,
                callback=callback_ignore).result()
            if ignored_file == os.path.join(directory, filename):
                break
Exemplo n.º 6
0
def test_events_from_existing_files(filename, tags_to_apply, get_configuration,
                                    configure_environment, restart_syscheckd, wait_for_initial_scan):
    """
        Checks if syscheck generates modified alerts for files that exists when starting the agent
    """
    check_apply_test(tags_to_apply, get_configuration['tags'])
    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'

    # Modify file
    modify_file_content(testdir1, filename, new_content='Sample content')

    # Expect modified event
    check_time_travel(scheduled)
    modified_event = wazuh_log_monitor.start(timeout=timeout, callback=callback_detect_event).result()
    assert 'modified' in modified_event['data']['type'] and \
           os.path.join(testdir1, filename) in modified_event['data']['path']

    # Delete file
    delete_file(testdir1, filename)

    # Expect deleted event
    check_time_travel(scheduled)
    deleted_event = wazuh_log_monitor.start(timeout=timeout, callback=callback_detect_event).result()
    assert 'deleted' in deleted_event['data']['type'] and \
           os.path.join(testdir1, filename) in deleted_event['data']['path']
def test_new_directory(tags_to_apply, get_configuration, configure_environment, restart_syscheckd,
                       wait_for_initial_scan):
    """
    Check that a new monitored directory generates events after the next scheduled scan.

    This test performs the following steps:
    - Monitor a directory that does not exist.
    - Create the directory with files inside. Check that this does not produce events in ossec.log.
    - Move time forward to the next scheduled scan.
    - Check that now creating files within the directory do generate events.

    Parameters
    ----------
    tags_to_apply : set
        Run test if matches with a configuration identifier, skip otherwise
    """
    check_apply_test(tags_to_apply, get_configuration['tags'])

    if sys.platform != 'win32':
        # Create the monitored directory with files and check that events are not raised
        regular_file_cud(directory_str, wazuh_log_monitor, file_list=['file1', 'file2', 'file3'],
                         min_timeout=global_parameters.default_timeout, triggers_event=False)

        # Travel to the future to start next scheduled scan
        check_time_travel(True)
        detect_initial_scan(wazuh_log_monitor)
    else:
        os.makedirs(directory_str, exist_ok=True, mode=0o777)
        time.sleep(1)

    # Assert that events of new CUD actions are raised after next scheduled scan
    regular_file_cud(directory_str, wazuh_log_monitor, file_list=['file4', 'file5', 'file6'],
                     min_timeout=global_parameters.default_timeout, triggers_event=True)
def test_events_from_existing_files(filename, tags_to_apply, get_configuration,
                                    configure_environment, restart_syscheckd,
                                    wait_for_fim_start):
    """Check if syscheck generates modified alerts for files that exists when starting the agent"""
    check_apply_test(tags_to_apply, get_configuration['tags'])
    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'
    mode = get_configuration['metadata']['fim_mode']

    # Modify file
    modify_file_content(testdir1, filename, new_content='Sample content')

    # Expect modified event
    check_time_travel(scheduled, monitor=wazuh_log_monitor)
    modified_event = wazuh_log_monitor.start(
        timeout=timeout,
        callback=callback_detect_event,
        error_message='Did not receive expected '
        '"Sending FIM event: ..." event').result()
    assert 'modified' in modified_event['data']['type'] and \
           os.path.join(testdir1, filename) in modified_event['data']['path']
    validate_event(modified_event, mode=mode)

    # Delete file
    delete_file(testdir1, filename)

    # Expect deleted event
    check_time_travel(scheduled, monitor=wazuh_log_monitor)
    deleted_event = wazuh_log_monitor.start(
        timeout=timeout,
        callback=callback_detect_event,
        error_message='Did not receive expected '
        '"Sending FIM event: ..." event').result()
    assert 'deleted' in deleted_event['data']['type'] and \
           os.path.join(testdir1, filename) in deleted_event['data']['path']
    validate_event(deleted_event, mode=mode)
Exemplo n.º 9
0
def test_report_changes_after_restart(get_configuration, configure_environment,
                                      restart_syscheckd, wait_for_fim_start):
    """
    Check if diff directories are removed after disabling report_changes and Wazuh is restarted.
    """
    check_apply_test({'test_delete_after_restart'}, get_configuration['tags'])
    value_name = 'random_value'

    folder_path_key1, diff_file_key_1 = calculate_registry_diff_paths(
        key, sub_key_1, KEY_WOW64_64KEY, value_name)
    folder_path_key2, diff_file_key_2 = calculate_registry_diff_paths(
        key, sub_key_1, KEY_WOW64_64KEY, value_name)

    # Open key
    key1_h = create_registry(registry_parser[key], sub_key_1, KEY_WOW64_64KEY)
    key2_h = create_registry(registry_parser[key], sub_key_2, KEY_WOW64_64KEY)

    # Modify the registry
    modify_registry_value(key1_h, value_name, REG_SZ, "some_content")
    modify_registry_value(key2_h, value_name, REG_SZ, "some_content")

    # Travel to future
    check_time_travel(True, monitor=wazuh_log_monitor)

    assert os.path.exists(
        diff_file_key_1), f'{diff_file_key_1} does not exists'
    assert os.path.exists(
        diff_file_key_2), f'{diff_file_key_2} does not exists'

    reload_new_conf('no', test_regs[0], test_regs[1])

    assert not os.path.exists(
        folder_path_key1), f'{folder_path_key1} does exists'
    assert not os.path.exists(
        folder_path_key2), f'{folder_path_key2} does exists'
def test_update_interval(get_configuration, configure_environment,
                         restart_modulesd):
    """
    Check if the provider database update is triggered after the set interval time has passed
    """
    check_apply_test({'test_providers_update_interval'},
                     get_configuration['tags'])

    provider = get_configuration['metadata']['provider_name']
    interval_update_time = get_configuration['metadata']['interval']
    seconds_to_travel = time_to_seconds(interval_update_time) + 5

    # Check that the update has not started prematurely
    with pytest.raises(TimeoutError):
        wazuh_log_monitor.start(timeout=8,
                                callback=callback_provider_database_updating)
        raise AttributeError(f'Unexpected event {provider} database updating')

    # Travels the time set in the update interval parameter
    check_time_travel(time_travel=True,
                      interval=timedelta(seconds=seconds_to_travel))

    # Check that the feed is downloaded after the set update interval
    # (10s for vuln thread refresh + 5s to wait callback)
    wazuh_log_monitor.start(
        timeout=50,
        callback=callback_provider_database_updating,
        error_message=
        f"Could not find the provider {provider} updating feed log after \
                                            the interval update")
Exemplo n.º 11
0
    def perform_and_validate_events(func, kwargs):
        for directory in dir_list:
            args = [REGULAR, directory, file
                    ] if func.__name__ == 'create_file' else [directory, file]
            func(*args, **kwargs)
            time.sleep(
                0.01)  # This sleep is to let whodata fetching all events

        check_time_travel(time_travel=scheduled)
        try:
            events = log_monitor.start(
                timeout=timeout,
                callback=callback_detect_event,
                accum_results=len(dir_list),
                error_message=
                'Did not receive expected "Sending FIM event: ..." '
                'event').result()
            time.sleep(1)

            for ev in events:
                validate_event(ev)
        except TimeoutError as e:
            if len(log_monitor.result()) == 63:
                pytest.xfail(
                    reason=
                    'Xfailed due to issue: https://github.com/wazuh/wazuh/issues/4719'
                )
            else:
                raise e
Exemplo n.º 12
0
def test_scan_time(tags_to_apply, get_configuration, configure_environment,
                   restart_syscheckd, wait_for_fim_start):
    """
    Check if there is a scan at a certain time

    scan_time option makes sure there is only one scan every 24 hours, at a certain time.
    """
    check_apply_test(tags_to_apply, get_configuration['tags'])

    # Reformat given time to a readable format since it can be writen in several ways in ossec.conf
    scan_time = reformat_time(get_configuration['metadata']['scan_time'])
    current_time = datetime.now()

    # Calculate how much time we need to travel in time to make sure there hasn't been any scan until it is the given
    # time
    time_difference = (scan_time - current_time) if (scan_time - current_time).days == 0 else \
        ((scan_time - current_time) + timedelta(days=2))
    check_time_travel(time_travel=True,
                      interval=time_difference + timedelta(minutes=-30))
    with pytest.raises(TimeoutError):
        event = wazuh_log_monitor.start(
            timeout=global_parameters.default_timeout,
            callback=callback_detect_end_scan)
        raise AttributeError(f'Unexpected event {event}')

    check_time_travel(time_travel=True, interval=timedelta(minutes=31))
    wazuh_log_monitor.start(timeout=global_parameters.default_timeout,
                            callback=callback_detect_end_scan,
                            error_message='Did not receive expected '
                            '"File integrity monitoring scan ended" event')
Exemplo n.º 13
0
 def modify_and_assert(file):
     modify_file_content(testdir1, file, new_content='Sample modification')
     check_time_travel(scheduled, monitor=wazuh_log_monitor)
     ev = wazuh_log_monitor.start(timeout=3,
                                  callback=callback_detect_event).result()
     assert 'modified' in ev['data']['type'] and os.path.join(testdir1, file) in ev['data']['path'], \
         f"'modified' event not matching for {testdir1} {file}"
Exemplo n.º 14
0
def test_duplicate_entries(get_configuration, configure_environment,
                           restart_syscheckd, wait_for_initial_scan):
    """Check if syscheckd ignores duplicate entries.
       For instance:
           - The second entry should prevail over the first one.
            <directories realtime="yes">/home/user</directories> (IGNORED)
            <directories whodata="yes">/home/user</directories>
        OR
           - Just generate one event.
            <directories realtime="yes">/home/user,/home/user</directories>
    """
    logger.info('Applying the test configuration')
    check_apply_test({'ossec_conf_duplicate_simple'},
                     get_configuration['tags'])
    file = 'hello'
    mode2 = get_configuration['metadata']['fim_mode2']

    scheduled = mode2 == 'scheduled'
    mode2 = "real-time" if mode2 == "realtime" else mode2

    logger.info(f'Adding file {os.path.join(testdir1, file)}, content: " "')
    create_file(REGULAR, testdir1, file, content=' ')

    logger.info(f'Time travel: {scheduled}')
    check_time_travel(scheduled)
    logger.info('Checking the event...')
    event1 = wazuh_log_monitor.start(
        timeout=global_parameters.default_timeout,
        callback=callback_detect_event,
        error_message=f'Did not receive expected event for file '
        f'{os.path.join(testdir1, file)}').result()

    # Check for a second event
    event2 = check_event(previous_mode=mode2, previous_event=event1, file=file)
    assert event2 is None, "Multiple events created"
Exemplo n.º 15
0
def test_file_size_default(tags_to_apply, filename, folder, get_configuration,
                           configure_environment, restart_syscheckd,
                           wait_for_fim_start):
    """
    Check that the file_size option with a default value for report_changes is working correctly.

    Create a file smaller than the default limit and check that the compressed file has been created. If the first part
    is successful, increase the size of the file and expect the message for file_size limit reached and no compressed
    file in the queue/diff/local folder.

    Parameters
    ----------
    filename : str
        Name of the file to be created.
    folder : str
        Directory where the files are being created.
    tags_to_apply : set
        Run test if matches with a configuration identifier, skip otherwise.
    """
    check_apply_test(tags_to_apply, get_configuration['tags'])
    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'
    size_limit = translate_size('50MB')
    diff_file_path = make_diff_file_path(folder=folder, filename=filename)

    # Create file with a smaller size than the configured value
    to_write = generate_string(int(size_limit / 10), '0')
    create_file(REGULAR, folder, filename, content=to_write)

    check_time_travel(scheduled)
    wazuh_log_monitor.start(
        timeout=global_parameters.default_timeout,
        callback=callback_detect_event,
        error_message='Did not receive expected "Sending FIM event: ..." event.'
    )

    if not os.path.exists(diff_file_path):
        pytest.raises(
            FileNotFoundError(
                f"{diff_file_path} not found. It should exist before increasing the size."
            ))

    # Increase the size of the file over the configured value
    to_write = generate_string(size_limit, '0')
    modify_file_content(folder, filename, new_content=to_write * 3)

    check_time_travel(scheduled)

    wazuh_log_monitor.start(
        timeout=global_parameters.default_timeout,
        callback=callback_file_size_limit_reached,
        error_message='Did not receive expected '
        '"File ... is too big for configured maximum size to perform diff operation" event.'
    )

    if os.path.exists(diff_file_path):
        pytest.raises(
            FileExistsError(
                f"{diff_file_path} found. It should not exist after incresing the size."
            ))
Exemplo n.º 16
0
def test_disk_quota_values(key, subkey, arch, value_name, tags_to_apply, size,
                           get_configuration, configure_environment,
                           restart_syscheckd, wait_for_fim_start):
    """
    Check that no events are sent when the disk_quota exceeded

    Parameters
    ----------
    key : str
        Root key (HKEY_*)
    subkey : str
        path of the registry.
    arch : str
        Architecture of the registry.
    value_name : str
        Name of the value that will be created
    tags_to_apply : set
        Run test if match with a configuration identifier, skip otherwise.
    size : int
        Size of the content to write in value
    """
    check_apply_test(tags_to_apply, get_configuration['tags'])
    value_content = generate_string(size, '0')
    values = {value_name: value_content}

    _, diff_file = calculate_registry_diff_paths(key, subkey, arch, value_name)

    def report_changes_validator_no_diff(event):
        """Validate content_changes attribute exists in the event"""
        assert event['data'].get(
            'content_changes') is None, 'content_changes isn\'t empty'

    def report_changes_validator_diff(event):
        """Validate content_changes attribute exists in the event"""
        assert os.path.exists(diff_file), '{diff_file} does not exist'
        assert event['data'].get(
            'content_changes') is not None, 'content_changes is empty'

    if size > size_limit_configured:
        callback_test = report_changes_validator_no_diff
    else:
        callback_test = report_changes_validator_diff

    create_registry(registry_parser[key], subkey, arch)

    registry_value_cud(
        key,
        subkey,
        wazuh_log_monitor,
        arch=arch,
        value_list=values,
        time_travel=get_configuration['metadata']['fim_mode'] == 'scheduled',
        min_timeout=global_parameters.default_timeout,
        triggers_event=True,
        validators_after_update=[callback_test])

    delete_registry(registry_parser[key], subkey, arch)
    check_time_travel(True, monitor=wazuh_log_monitor)
Exemplo n.º 17
0
def test_skip_proc(get_configuration, configure_environment, restart_syscheckd,
                   wait_for_initial_scan):
    """Check if syscheckd skips /proc when setting 'skip_proc="yes"'."""
    check_apply_test({'skip_proc'}, get_configuration['tags'])
    trigger = get_configuration['metadata']['skip'] == 'no'

    if trigger:
        proc = subprocess.Popen([
            "python3",
            f"{os.path.dirname(os.path.abspath(__file__))}/data/proc.py"
        ])

        # Change configuration, monitoring the PID path in /proc
        # Monitor only /proc/PID to expect only these events. Otherwise, it will fail due to Timeouts since
        # integrity scans will take too long
        new_conf = change_conf(f'/proc/{proc.pid}')
        new_ossec_conf = []

        # Get new skip_proc configuration
        for conf in new_conf:
            if conf['metadata']['skip'] == 'no' and conf['tags'] == [
                    'skip_proc'
            ]:
                new_ossec_conf = set_section_wazuh_conf(conf.get('sections'))
        restart_wazuh_with_new_conf(new_ossec_conf)
        truncate_file(LOG_FILE_PATH)
        proc_monitor = FileMonitor(LOG_FILE_PATH)
        detect_initial_scan(proc_monitor)

        # Do not expect any 'Sending event'
        with pytest.raises(TimeoutError):
            proc_monitor.start(
                timeout=3,
                callback=callback_detect_event,
                error_message=
                'Did not receive expected "Sending FIM event: ..." event')

        check_time_travel(time_travel=True, monitor=wazuh_log_monitor)

        found_event = False
        while not found_event:
            event = proc_monitor.start(
                timeout=5,
                callback=callback_detect_event,
                error_message='Did not receive expected '
                '"Sending FIM event: ..." event').result()
            if f'/proc/{proc.pid}/' in event['data'].get('path'):
                found_event = True

        # Kill the process
        subprocess.Popen(["kill", "-9", str(proc.pid)])

    else:
        with pytest.raises(TimeoutError):
            event = wazuh_log_monitor.start(
                timeout=3, callback=callback_detect_integrity_state)
            raise AttributeError(f'Unexpected event {event}')
Exemplo n.º 18
0
def test_delete_folder(folder, file_list, filetype, tags_to_apply,
                       get_configuration, configure_environment,
                       restart_syscheckd, wait_for_fim_start):
    """
    Check if syscheckd detects 'deleted' events from the files contained
    in a folder that is being deleted.

    If we are monitoring /testdir and we have r1, r2, r3 withing /testdir, if we delete /testdir,
    we must see 3 events of the type 'deleted'. One for each one of the regular files.

    Parameters
    ----------
    folder : str
        Directory where the files will be created.
    file_list : list
        Names of the files.
    filetype : str
        Type of the files that will be created.
    """

    check_apply_test(tags_to_apply, get_configuration['tags'])
    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'
    mode = get_configuration['metadata']['fim_mode']

    # Create files inside subdir folder
    for file in file_list:
        create_file(filetype, folder, file, content='')

    check_time_travel(scheduled, monitor=wazuh_log_monitor)
    events = wazuh_log_monitor.start(timeout=global_parameters.default_timeout, callback=callback_detect_event,
                                     accum_results=len(file_list), error_message='Did not receive expected '
                                                                                 '"Sending FIM event: ..." event').result()
    for ev in events:
        validate_event(ev, mode=mode)

    # Remove folder
    shutil.rmtree(folder, ignore_errors=True)
    check_time_travel(scheduled, monitor=wazuh_log_monitor)

    # Expect deleted events
    event_list = wazuh_log_monitor.start(timeout=global_parameters.default_timeout, callback=callback_detect_event,
                                         error_message='Did not receive expected '
                                                       '"Sending FIM event: ..." event',
                                         accum_results=len(file_list)).result()
    path_list = set([event['data']['path'] for event in event_list])
    counter_type = Counter([event['data']['type'] for event in event_list])
    for ev in events:
        validate_event(ev, mode=mode)

    assert counter_type['deleted'] == len(file_list), f'Number of "deleted" events should be {len(file_list)}'

    for file in file_list:
        assert os.path.join(folder, file) in path_list, f'File {file} not found within the events'
Exemplo n.º 19
0
 def modify_and_check_events(f1, f2, text):
     """ Modify the content of 2 given files. We assume the first one is being monitored and the other one is not.
         We expect a 'modified' event for the first one and a timeout for the second one.
     """
     modify_file_content(f1, file1, text)
     modify_file_content(f2, file1, text)
     check_time_travel(scheduled)
     modify = wazuh_log_monitor.start(
         timeout=3, callback=callback_detect_event).result()
     assert 'modified' in modify['data']['type'] and f1 in modify['data']['path'], \
         f"'modified' event not matching for {file1}"
     with pytest.raises(TimeoutError):
         wazuh_log_monitor.start(timeout=3, callback=callback_detect_event)
Exemplo n.º 20
0
def wait_for_event(fim_mode):
    """Wait for the event to be scanned.

    Parameters
    ----------
    fim_mode : str
        FIM mode (scheduled, realtime, whodata)
    """
    check_time_travel(time_travel=fim_mode == 'scheduled', monitor=wazuh_log_monitor)

    # Wait until event is detected
    wazuh_log_monitor.start(timeout=global_parameters.default_timeout, callback=callback_detect_event,
                            error_message='Did not receive expected "Sending FIM event: ..." event')
Exemplo n.º 21
0
def test_symbolic_revert_symlink(tags_to_apply, get_configuration,
                                 configure_environment, restart_syscheckd,
                                 wait_for_initial_scan):
    """
    Check if syscheck detects new targets properly

    CHECK: Having a symbolic link pointing to a file/folder, change its target to a folder. Check that the old file
    is not being monitored anymore and the new folder is. Revert the target change and ensure the file is
    being monitored and the folder is not.
    """
    def modify_and_assert(file):
        modify_file_content(testdir1, file, new_content='Sample modification')
        check_time_travel(scheduled, monitor=wazuh_log_monitor)
        ev = wazuh_log_monitor.start(timeout=3,
                                     callback=callback_detect_event).result()
        assert 'modified' in ev['data']['type'] and os.path.join(testdir1, file) in ev['data']['path'], \
            f"'modified' event not matching for {testdir1} {file}"

    check_apply_test(tags_to_apply, get_configuration['tags'])
    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'
    whodata = get_configuration['metadata']['fim_mode'] == 'whodata'
    file1 = 'regular1'
    file2 = 'regular2'

    # Don't expect an event since it is not being monitored yet
    modify_file_content(testdir1, file2, new_content='Sample modification')
    check_time_travel(scheduled, monitor=wazuh_log_monitor)
    with pytest.raises(TimeoutError):
        event = wazuh_log_monitor.start(timeout=3,
                                        callback=callback_detect_event)
        logger.error(f'Unexpected event {event.result()}')
        raise AttributeError(f'Unexpected event {event.result()}')

    # Change the target to the folder and now expect an event
    modify_symlink(testdir1, os.path.join(testdir_link, 'symlink'))
    wait_for_symlink_check(wazuh_log_monitor)
    wait_for_audit(whodata, wazuh_log_monitor)
    modify_and_assert(file2)

    # Modify symlink target, wait for sym_check to update it
    modify_symlink(os.path.join(testdir1, file1),
                   os.path.join(testdir_link, 'symlink'))
    wait_for_symlink_check(wazuh_log_monitor)
    modify_file_content(testdir1, file2, new_content='Sample modification2')
    check_time_travel(scheduled, monitor=wazuh_log_monitor)
    with pytest.raises(TimeoutError):
        event = wazuh_log_monitor.start(timeout=3,
                                        callback=callback_detect_event)
        logger.error(f'Unexpected event {event.result()}')
        raise AttributeError(f'Unexpected event {event.result()}')
    modify_and_assert(file1)
Exemplo n.º 22
0
def check_restrict(directory, trigger, check_list, file_list, timeout,
                   scheduled):
    """Standard restrict attribute test"""
    create_file(REGULAR, directory, file_list[0], content='')
    check_time_travel(scheduled, monitor=wazuh_log_monitor)
    while True:
        ignored_file = wazuh_log_monitor.start(
            timeout=timeout,
            callback=callback_restricted,
            error_message=f'TimeoutError was raised because a single '
            f'"ignoring file {file_list[0]} due to restriction ..." '
            f'was expected for {file_list[0]} but was not detected.').result()
        if ignored_file == os.path.join(directory, file_list[0]):
            break
Exemplo n.º 23
0
def test_check_all_no(path, checkers, get_configuration, configure_environment,
                      restart_syscheckd, wait_for_initial_scan):
    """
    Test the functionality of `check_all` option when set to no.

    When setting `check_all` to no, only 'type' and 'checksum' attributes should appear in every event. This will
    avoid any modification event.

    Parameters
    ----------
    path : str
        Directory where the file is being created and monitored.
    checkers : dict
        Check options to be used.
    """
    check_apply_test({'test_check_all_no'}, get_configuration['tags'])
    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'

    # Create regular file and dont expect any check
    file = 'regular'
    create_file(REGULAR, path, file)
    check_time_travel(scheduled, monitor=wazuh_log_monitor)
    create_event = wazuh_log_monitor.start(
        callback=callback_detect_event,
        timeout=15,
        error_message='Did not receive expected '
        '"Sending FIM event: ..." event').result()
    assert create_event['data']['type'] == 'added'
    assert list(
        create_event['data']['attributes'].keys()) == ['type', 'checksum']

    # Delete regular file and dont expect any check. Since it is not using any check, modification events will not
    # be triggered
    modify_file(path, file, 'Sample modification')
    with pytest.raises(TimeoutError):
        event = wazuh_log_monitor.start(callback=callback_detect_event,
                                        timeout=5)
        raise AttributeError(f'Unexpected event {event}')

    delete_file(path, file)
    check_time_travel(scheduled, monitor=wazuh_log_monitor)
    delete_event = wazuh_log_monitor.start(
        callback=callback_detect_event,
        timeout=15,
        error_message='Did not receive expected '
        '"Sending FIM event: ..." event').result()
    assert delete_event['data'][
        'type'] == 'deleted', f'Current value is {delete_event["data"]["type"]}'
    assert list(delete_event['data']['attributes'].keys()) == ['type', 'checksum'], \
        f'Current value is {list(delete_event["data"]["attributes"].keys())}'
def test_ignore_works_over_restrict(folder, filename, triggers_event, tags_to_apply, get_configuration,
                                    configure_environment, restart_syscheckd, wait_for_initial_scan):
    """Check if the ignore tag prevails over the restrict one when using both in the same directory.

    This test is intended to be used with valid configurations files. Each execution of this test will configure
    the environment properly, restart the service and wait for the initial scan.

    Parameters
    ----------
    folder : str
        Directory where the file is being created
    filename : str
        Name of the file to be created
    triggers_event : bool
        True if an event must be generated, False otherwise
    tags_to_apply : set
        Run test if it matches with a configuration identifier, skip otherwise

    """
    logger.info('Applying the test configuration')
    check_apply_test(tags_to_apply, get_configuration['tags'])
    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'

    # Create file that must be ignored
    logger.info(f'Adding file {os.path.join(testdir1, filename)}, content: ""')
    create_file(REGULAR, folder, filename, content='')

    # Go ahead in time to let syscheck perform a new scan if mode is scheduled
    logger.info(f'Time travel: {scheduled}')
    check_time_travel(scheduled, monitor=wazuh_log_monitor)

    if triggers_event:
        logger.info('Checking the event...')
        event = wazuh_log_monitor.start(timeout=global_parameters.default_timeout,
                                        callback=callback_detect_event,
                                        error_message=f'Did not receive expected "Sending FIM event" '
                                                      f'event for file {os.path.join(testdir1, filename)}').result()

        assert event['data']['type'] == 'added', 'Event type not equal'
        assert event['data']['path'] == os.path.join(folder, filename), 'Event path not equal'
    else:
        while True:
            ignored_file = wazuh_log_monitor.start(timeout=global_parameters.default_timeout, callback=callback_ignore,
                                                   error_message=f'Did not receive expected '
                                                                 f'"Ignoring ... due to ..." event for file '
                                                                 f'{os.path.join(testdir1, filename)}').result()

            if ignored_file == os.path.join(folder, filename):
                break
Exemplo n.º 25
0
def test_file_size_default(key, subkey, arch, value_name, tags_to_apply,
                           get_configuration, configure_environment,
                           restart_syscheckd_each_time):
    """
    Check that no events are sent when the disk_quota exceeded

    Parameters
    ----------
    key : str
        Root key (HKEY_*)
    subkey : str
        path of the registry.
    arch : str
        Architecture of the registry.
    value_name : str
        Name of the value that will be created
    tags_to_apply : set
        Run test if match with a configuration identifier, skip otherwise.
    size : int
        Size of the content to write in value
    """
    check_apply_test(tags_to_apply, get_configuration['tags'])
    mode = get_configuration['metadata']['fim_mode']

    file_size_values = wazuh_log_monitor.start(
        timeout=global_parameters.default_timeout,
        callback=callback_diff_size_limit_value,
        accum_results=3,
        error_message='Did not receive expected '
        '"Maximum file size limit to generate diff information '
        'configured to \'... KB\'..." event').result()
    for value in file_size_values:
        if value:
            assert value == str(DEFAULT_SIZE), 'Wrong value for file_size'
        else:
            raise AssertionError('Wrong value for file_size')

    key_h = create_registry(registry_parser[key], subkey, arch)

    modify_registry_value(key_h, "some_value", REG_SZ, "some content")
    check_time_travel(True, monitor=wazuh_log_monitor)
    events = wazuh_log_monitor.start(
        timeout=global_parameters.default_timeout,
        callback=callback_detect_event,
        accum_results=2,
        error_message='Did not receive expected '
        '"Sending FIM event: ..." event').result()
    for ev in events:
        validate_registry_value_event(ev, mode=mode)
Exemplo n.º 26
0
def test_create_file_scheduled(folder, name, filetype, content, checkers,
                               tags_to_apply, encoding, get_configuration,
                               configure_environment, restart_syscheckd,
                               wait_for_initial_scan):
    """
    Check if a special or regular file creation is detected by syscheck using scheduled monitoring

    Regular files must be monitored. Special files must not.

    Parameters
    ----------
    folder : str
        Name of the monitored folder.
    name : str
        Name of the file.
    filetype : str
        Type of the file.
    content : str
        Content of the file.
    checkers : set
        Checks that will compared to the ones from the event.
    """
    check_apply_test(tags_to_apply, get_configuration['tags'])

    # Create files
    if encoding is not None:
        name = name.encode(encoding)
        folder = folder.encode(encoding)
    create_file(filetype, folder, name, content=content)

    # Go ahead in time to let syscheck perform a new scan
    check_time_travel(True, monitor=wazuh_log_monitor)

    if filetype == REGULAR:
        # Wait until event is detected
        event = wazuh_log_monitor.start(
            timeout=global_parameters.default_timeout,
            callback=callback_detect_event,
            encoding=encoding,
            error_message=
            'Did not receive expected "Sending FIM event: ..." event').result(
            )
        validate_event(event, checkers)
    else:
        with pytest.raises(TimeoutError):
            event = wazuh_log_monitor.start(
                timeout=global_parameters.default_timeout,
                callback=callback_detect_event)
            raise AttributeError(f'Unexpected event {event}')
Exemplo n.º 27
0
def test_scan_day_and_time(tags_to_apply,
                           get_configuration, configure_environment,
                           restart_syscheckd, wait_for_fim_start):
    """
    Check if there is a scan in a certain day and time

    This test must check both scan params.
    """
    check_apply_test(tags_to_apply, get_configuration['tags'])

    day_of_week = {'monday': 0,
                   'tuesday': 1,
                   'wednesday': 2,
                   'thursday': 3,
                   'friday': 4,
                   'saturday': 5,
                   'sunday': 6
                   }
    current_day = datetime.now()
    scan_day = day_of_week[get_configuration['metadata']['scan_day']]
    scan_time = reformat_time(get_configuration['metadata']['scan_time'])
    day_diff = scan_day - current_day.weekday()
    scan_today = False

    if day_diff < 0:
        day_diff %= 7
    elif day_diff == 0:
        scan_today = True

    scan_time = replace_date(scan_time, day_diff)

    if scan_today:
        if (scan_time - current_day).days == 0:
            check_time_travel(time_travel=True, interval=scan_time - current_day + timedelta(minutes=1))
            wazuh_log_monitor.start(timeout=global_parameters.default_timeout, callback=callback_detect_end_scan,
                                    error_message='Did not receive expected '
                                                  '"File integrity monitoring scan ended" event')
            return
        else:
            day_diff = 7

    if day_diff > 1:
        check_time_travel(time_travel=True, interval=timedelta(days=day_diff - 1))
        current_day = datetime.now()
        with pytest.raises(TimeoutError):
            event = wazuh_log_monitor.start(timeout=global_parameters.default_timeout,
                                            callback=callback_detect_end_scan)
            raise AttributeError(f'Unexpected event {event}')

    check_time_travel(time_travel=True, interval=scan_time - current_day - timedelta(minutes=5))
    with pytest.raises(TimeoutError):
        event = wazuh_log_monitor.start(timeout=global_parameters.default_timeout, callback=callback_detect_end_scan)
        raise AttributeError(f'Unexpected event {event}')

    check_time_travel(time_travel=True, interval=timedelta(minutes=6))
    wazuh_log_monitor.start(timeout=global_parameters.default_timeout, callback=callback_detect_end_scan,
                            error_message='Did not receive expected '
                                          '"File integrity monitoring scan ended" event')
Exemplo n.º 28
0
def test_symbolic_delete_target(tags_to_apply, main_folder, aux_folder,
                                get_configuration, configure_environment,
                                restart_syscheckd, wait_for_initial_scan):
    """ Check if syscheck detects events properly when removing a target, have the symlink updated and
        then recreating the target

    CHECK: Having a symbolic link pointing to a file/folder, remove that file/folder and check that deleted event is
    detected.
    Once symlink_checker runs create the same file. No events should be raised. Wait again for symlink_checker run
    and modify the file. Modification event must be detected this time.

    :param main_folder: Directory that is being pointed at or contains the pointed file
    :param aux_folder: Directory that will be pointed at or will contain the future pointed file

    * This test is intended to be used with valid configurations files. Each execution of this test will configure
    the environment properly, restart the service and wait for the initial scan.
    """
    check_apply_test(tags_to_apply, get_configuration['tags'])
    scheduled = get_configuration['metadata']['fim_mode'] == 'scheduled'
    whodata = get_configuration['metadata']['fim_mode'] == 'whodata'
    file1 = 'regular1'

    # If symlink is pointing to a directory, we need to add files and expect their 'added' event (only if the file
    # is being created withing the pointed directory. Then, delete the pointed file or directory
    if tags_to_apply == {'monitored_dir'}:
        create_file(REGULAR, main_folder, file1, content='')
        check_time_travel(scheduled)
        wazuh_log_monitor.start(timeout=3, callback=callback_detect_event)
        delete_f(main_folder)
    else:
        delete_f(main_folder, file1)
    check_time_travel(scheduled)
    delete = wazuh_log_monitor.start(timeout=3,
                                     callback=callback_detect_event).result()
    assert 'deleted' in delete['data']['type'] and file1 in delete['data']['path'], \
        f"'deleted' event not matching for {file1}"

    # If syscheck is monitoring with whodata, wait for audit to reload rules
    wait_for_audit(whodata, wazuh_log_monitor)
    wait_for_symlink_check(wazuh_log_monitor)

    # Restore the target and don't expect any event since symlink hasn't updated the link information
    create_file(REGULAR, main_folder, file1, content='')
    check_time_travel(scheduled)
    with pytest.raises(TimeoutError):
        wazuh_log_monitor.start(timeout=3, callback=callback_detect_event)

    wait_for_symlink_check(wazuh_log_monitor)
    wait_for_audit(whodata, wazuh_log_monitor)

    # Modify the files and expect events since symcheck has updated now
    modify_file_content(main_folder, file1, 'Sample modification')
    check_time_travel(scheduled)
    modify = wazuh_log_monitor.start(timeout=3,
                                     callback=callback_detect_event).result()
    assert 'modified' in modify['data']['type'] and file1 in modify['data']['path'], \
        f"'modified' event not matching for {file1}"
def test_entries_match_key_count(get_configuration, configure_environment,
                                 restart_syscheckd, wait_for_fim_start):
    """
    Check if FIM entries match the entries count
    """

    entries = wazuh_log_monitor.start(
        timeout=global_parameters.default_timeout,
        callback=callback_registry_count_entries,
        error_message='Did not receive expected '
        '"Fim inode entries: ..., path count: ..." event').result()
    check_time_travel(True, monitor=wazuh_log_monitor)

    if entries:
        assert entries == '4', 'Wrong number of entries'
    else:
        raise AssertionError('Wrong number of entries')
Exemplo n.º 30
0
    def perform_and_validate_events(func, kwargs):
        for directory in dir_list:
            args = [REGULAR, directory, file] if func.__name__ == 'create_file' else [directory, file]
            func(*args, **kwargs)
            if whodata:
                time.sleep(0.05)  # This sleep is to let whodata fetching all events

        check_time_travel(time_travel=scheduled)

        events = log_monitor.start(timeout=timeout,
                                   callback=callback_detect_event,
                                   accum_results=n_results,
                                   error_message='Did not receive expected "Sending FIM event: ..." event').result()
        time.sleep(1)

        for ev in events:
            validate_event(ev)