diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c2060c3c3..2f451f6ce3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ All notable changes to this project will be documented in this file. Wazuh commit: TBD \ Release report: TBD +### Added + +- Add IT tests FIM registry monitoring using wildcards. ([#4270](https://github.com/wazuh/wazuh-qa/pull/4270)) \- (Framework + Tests) - Update schema database version ([#4128](https://github.com/wazuh/wazuh-qa/pull/4128)) \- (Tests) ## [4.5.1] - TBD diff --git a/deps/wazuh_testing/wazuh_testing/modules/fim/__init__.py b/deps/wazuh_testing/wazuh_testing/modules/fim/__init__.py index 842cde0c5a..5a8af08e85 100644 --- a/deps/wazuh_testing/wazuh_testing/modules/fim/__init__.py +++ b/deps/wazuh_testing/wazuh_testing/modules/fim/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2022, Wazuh Inc. +# Copyright (C) 2015-2023, Wazuh Inc. # Created by Wazuh, Inc. . # This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 diff --git a/deps/wazuh_testing/wazuh_testing/modules/fim/event_monitor.py b/deps/wazuh_testing/wazuh_testing/modules/fim/event_monitor.py index a972ee78da..2ec0f10099 100644 --- a/deps/wazuh_testing/wazuh_testing/modules/fim/event_monitor.py +++ b/deps/wazuh_testing/wazuh_testing/modules/fim/event_monitor.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2022, Wazuh Inc. +# Copyright (C) 2015-2023, Wazuh Inc. # Created by Wazuh, Inc. . # This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 @@ -7,7 +7,7 @@ from sys import platform from datetime import datetime -from wazuh_testing import LOG_FILE_PATH, logger, T_60 +from wazuh_testing import LOG_FILE_PATH, logger, T_60, T_30 from wazuh_testing.tools.monitoring import FileMonitor, generate_monitoring_callback @@ -43,8 +43,6 @@ CB_SYNC_INTERVAL_RESET = r".*Previous sync was successful. Sync interval is reset to: '(\d+)s'" CB_IGNORING_DUE_TO_SREGEX = r".*?Ignoring path '(.*)' due to sregex '(.*)'.*" CB_IGNORING_DUE_TO_PATTERN = r".*?Ignoring path '(.*)' due to pattern '(.*)'.*" -CB_MAXIMUM_FILE_SIZE = r'.*Maximum file size limit to generate diff information configured to \'(\d+) KB\'.*' -CB_AGENT_CONNECT = r'.* Connected to the server .*' CB_REALTIME_WHODATA_ENGINE_STARTED = r'.*File integrity monitoring (real-time Whodata) engine started.*' CB_DISK_QUOTA_LIMIT_CONFIGURED_VALUE = r'.*Maximum disk quota size limit configured to \'(\d+) KB\'.*' CB_FILE_EXCEEDS_DISK_QUOTA = r'.*The (.*) of the file size \'(.*)\' exceeds the disk_quota.*' @@ -52,6 +50,7 @@ CB_DIFF_FOLDER_DELETED = r'.*Folder \'(.*)\' has been deleted.*' CB_FIM_PATH_CONVERTED = r".*fim_adjust_path.*Convert '(.*) to '(.*)' to process the FIM events." CB_STARTING_WINDOWS_AUDIT = r'.*state_checker.*(Starting check of Windows Audit Policies and SACLs)' +CB_FIM_WILDCARD_EXPANDING = r".*Expanding entry '.*' to '(.*)' to monitor FIM events." CB_SWITCHING_DIRECTORIES_TO_REALTIME = r'.*state_checker.*(Audit policy change detected.\ Switching directories to realtime)' CB_RECIEVED_EVENT_4719 = r'.*win_whodata.*(Event 4719).*Switching directories to realtime' @@ -227,6 +226,18 @@ def callback_detect_file_integrity_event(line): return None +def callback_key_event(line): + """ Callback that detects if a line contains a registry integrity event for a registry_key + Args: + line (String): string line to be checked by callback in File_Monitor. + """ + event = callback_detect_event(line) + if event is None or event['data']['attributes']['type'] != 'registry_key': + return None + + return event + + def callback_value_event(line): event = callback_detect_event(line) @@ -489,6 +500,53 @@ def detect_whodata_start(file_monitor, timeout=T_60): error_message=ERR_MSG_WHODATA_ENGINE_EVENT) +def get_messages(callback, timeout=T_30): + """Look for as many synchronization events as possible. + This function will look for the synchronization messages until a Timeout is raised or 'max_events' is reached. + Args: + callback (str): Callback to be used to detect the event. + timeout (int): Timeout that will be used to get the dbsync_no_data message. + + Returns: + A list with all the events in json format. + """ + wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) + events = [] + for _ in range(0, MAX_EVENTS_VALUE): + event = None + try: + event = wazuh_log_monitor.start(timeout=timeout, accum_results=1, + callback=callback, + error_message=f"Did not receive expected {callback} event").result() + except TimeoutError: + break + if event is not None: + events.append(event) + return events + + +def check_registry_crud_event(callback, path, timeout=T_30, type='added', arch='x32', value_name=None): + """Get all events matching the callback and validate the type, path and architecture of event + Args: + callback (str): Callback to be used to detect the event. + path (str): path to be checked + timeout (int): Timeout that will be used to try and get the expected messages + type (str): type of event to be checked + arch (str): architecture of the event to be checked + value_name (str): name of the value to be checked + """ + events = get_messages(callback=callback, timeout=timeout) + for event in events: + if event['data']['type'] == type and arch in event['data']['arch'] and event['data']['path'] == path: + if value_name is not None: + if 'value_name' in event and event['data']['value_name'] == value_name: + return event + else: + return event + + return None + + def detect_windows_sacl_configured(file_monitor, file='.*'): """Detects when windows permision checks have been configured for a given file. diff --git a/deps/wazuh_testing/wazuh_testing/modules/fim/utils.py b/deps/wazuh_testing/wazuh_testing/modules/fim/utils.py index 7ab62543ee..02065895e6 100644 --- a/deps/wazuh_testing/wazuh_testing/modules/fim/utils.py +++ b/deps/wazuh_testing/wazuh_testing/modules/fim/utils.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2022, Wazuh Inc. +# Copyright (C) 2015-2023, Wazuh Inc. # Created by Wazuh, Inc. . # This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 @@ -213,7 +213,8 @@ def modify_registry(key, subkey, arch): logger.info(f"Modifying registry key {print_arch}{os.path.join(fim.registry_class_name[key], subkey)}") modify_key_perms(key, subkey, arch, win32sec.LookupAccountName(None, f"{platform.node()}\\{os.getlogin()}")[0]) - modify_registry_owner(key, subkey, arch, win32sec.LookupAccountName(None, f"{platform.node()}\\{os.getlogin()}")[0]) + modify_registry_owner(key, subkey, arch, + win32sec.LookupAccountName(None, f"{platform.node()}\\{os.getlogin()}")[0]) modify_registry_key_mtime(key, subkey, arch) @@ -298,6 +299,14 @@ def calculate_registry_diff_paths(reg_key, reg_subkey, arch, value_name): def transform_registry_list(value_list=['test_value'], value_type=fim.REG_SZ, callback=ev.callback_value_event): + """Transform a list of registry values into a dictionary. + Args: + value list (List): list of string value names + value type (str): type of registry value that is expected. + Callback (object): Callback to pair with the value to be monitored. + Returns: + Dict: dictionary with the values and the corresponding callbacks to monitor them. + """ if sys.platform == 'win32': if value_type in [win32con.REG_SZ, win32con.REG_MULTI_SZ]: value_default_content = '' @@ -319,6 +328,29 @@ def transform_registry_list(value_list=['test_value'], value_type=fim.REG_SZ, ca return aux_dict +def transform_registry_key_list(key_list=['test_key'], callback=ev.callback_key_event): + """Transform a list of registry keys into a dictionary. + Args: + key_list list (List): list of strings with the key names names + Callback (object): Callback to pair with the key to be monitored. + Returns: + Dict: dictionary with the keys and the corresponding callbacks to monitor them. + """ + if sys.platform == 'win32': + aux_dict = {} + if isinstance(key_list, list): + for elem in key_list: + aux_dict[elem] = ('', callback) + + elif isinstance(key_list, dict): + for key, elem in key_list.items(): + aux_dict[key] = (elem, callback) + else: + raise ValueError('It can only be a list or dictionary') + + return aux_dict + + def set_check_options(options): """ Return set of check options. If options given is none, it will return check_all""" options_set = fim.REQUIRED_REG_VALUE_ATTRIBUTES[fim.CHECK_ALL] diff --git a/tests/integration/test_fim/test_registry/conftest.py b/tests/integration/test_fim/test_registry/conftest.py index 72934c965e..dce777ac08 100644 --- a/tests/integration/test_fim/test_registry/conftest.py +++ b/tests/integration/test_fim/test_registry/conftest.py @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2021, Wazuh Inc. +# Copyright (C) 2015-2023, Wazuh Inc. # Created by Wazuh, Inc. . # This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 diff --git a/tests/integration/test_fim/test_registry/test_registry_wildcards/data/configuration_template/configuration_registry_wildcards.yaml b/tests/integration/test_fim/test_registry/test_registry_wildcards/data/configuration_template/configuration_registry_wildcards.yaml new file mode 100644 index 0000000000..a5fc64c6af --- /dev/null +++ b/tests/integration/test_fim/test_registry/test_registry_wildcards/data/configuration_template/configuration_registry_wildcards.yaml @@ -0,0 +1,30 @@ +- sections: + - section: syscheck + elements: + - disabled: + value: 'no' + - frequency: + value: FREQUENCY + - windows_registry: + value: WINDOWS_REGISTRY + attributes: + - arch: both + + - section: sca + elements: + - enabled: + value: 'no' + - section: rootcheck + elements: + - disabled: + value: 'yes' + - section: wodle + attributes: + - name: syscollector + elements: + - disabled: + value: 'yes' + - section: active-response + elements: + - disabled: + value: 'yes' diff --git a/tests/integration/test_fim/test_registry/test_registry_wildcards/data/test_cases/cases_registry_key_wildcards.yaml b/tests/integration/test_fim/test_registry/test_registry_wildcards/data/test_cases/cases_registry_key_wildcards.yaml new file mode 100644 index 0000000000..7ce9a46842 --- /dev/null +++ b/tests/integration/test_fim/test_registry/test_registry_wildcards/data/test_cases/cases_registry_key_wildcards.yaml @@ -0,0 +1,23 @@ +- name: Test key with question mark wildcard (Scheduled) + description: Test path with single question mark wildcard in scheduled mode + configuration_parameters: + FREQUENCY: 2 + WINDOWS_REGISTRY: HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMA? + metadata: + fim_mode: scheduled + +- name: Test key with single asterisk wildcard (Scheduled) + description: Test path with single asterisk wildcard in scheduled mode + configuration_parameters: + FREQUENCY: 2 + WINDOWS_REGISTRY: HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\* + metadata: + fim_mode: scheduled + +- name: Test key with asterisk+question mark (Scheduled) + description: Test path with multiple asterisks and question mark wildcards combined in scheduled mode + configuration_parameters: + FREQUENCY: 2 + WINDOWS_REGISTRY: HKEY_LOCAL_MACHINE\*\*\PointerClas? + metadata: + fim_mode: scheduled diff --git a/tests/integration/test_fim/test_registry/test_registry_wildcards/data/test_cases/cases_registry_value_wildcards.yaml b/tests/integration/test_fim/test_registry/test_registry_wildcards/data/test_cases/cases_registry_value_wildcards.yaml new file mode 100644 index 0000000000..93e679cc6a --- /dev/null +++ b/tests/integration/test_fim/test_registry/test_registry_wildcards/data/test_cases/cases_registry_value_wildcards.yaml @@ -0,0 +1,23 @@ +- name: Test value with question mark wildcard (Scheduled) + description: Test path with single question mark wildcard + configuration_parameters: + FREQUENCY: 2 + WINDOWS_REGISTRY: HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\PointerClas? + metadata: + fim_mode: scheduled + +- name: Test value with single asterisk wildcard (Scheduled) + description: Test path with single asterisk wildcard in scheduled mode + configuration_parameters: + FREQUENCY: 2 + WINDOWS_REGISTRY: HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\* + metadata: + fim_mode: scheduled + +- name: Test3 value with asterisk+question mark (Scheduled) + description: Test path with multiple asterisks and question mark wildcards combined in scheduled mode + configuration_parameters: + FREQUENCY: 2 + WINDOWS_REGISTRY: HKEY_LOCAL_MACHINE\*\*\PointerClas? + metadata: + fim_mode: scheduled diff --git a/tests/integration/test_fim/test_registry/test_registry_wildcards/test_registry_wildcards.py b/tests/integration/test_fim/test_registry/test_registry_wildcards/test_registry_wildcards.py new file mode 100644 index 0000000000..68ff46df9a --- /dev/null +++ b/tests/integration/test_fim/test_registry/test_registry_wildcards/test_registry_wildcards.py @@ -0,0 +1,290 @@ +''' +copyright: Copyright (C) 2015-2023, Wazuh Inc. + + Created by Wazuh, Inc. . + + This program is free software; you can redistribute it and/or modify it under the terms of GPLv2 + +type: integration + +brief: File Integrity Monitoring (FIM) system watches selected files and triggering alerts when these files are + modified. Specifically, these tests will check the use of wildcards '*' or '?' when configuring windows + registries to be monitored. When using wildcards, they should be expanded and matching keys should be + configured to be monitored. The tests will verify registry keys and values events are properly generated + when they are created, modified and deleted in registries configured through wildcards expansion. + +components: + - fim + +suite: registry_wildcards + +targets: + - agent + +daemons: + - wazuh-syscheckd + +os_platform: + - windows + +os_version: + - Windows 10 + - Windows 8 + - Windows 7 + - Windows Server 2019 + - Windows Server 2016 + - Windows Server 2012 + - Windows Server 2003 + - Windows XP + +references: + - https://documentation.wazuh.com/current/user-manual/capabilities/file-integrity/index.html + - https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/syscheck.html#file-limit + +pytest_args: + - fim_mode: + scheduled: file/registry changes are monitored only at the configured interval + - tier: + 0: Only level 0 tests are performed, they check basic functionalities and are quick to perform. + 1: Only level 1 tests are performed, they check functionalities of medium complexity. + 2: Only level 2 tests are performed, they check advanced functionalities and are slow to perform. + +tags: + - fim_registry_wildcards +''' +import os +import time +import pytest +from wazuh_testing import LOG_FILE_PATH, T_10 +from wazuh_testing.tools.configuration import load_configuration_template, get_test_cases_data +from wazuh_testing.tools.monitoring import FileMonitor, generate_monitoring_callback +from wazuh_testing.modules import WINDOWS, TIER1 +from wazuh_testing.modules.fim import (registry_parser, KEY_WOW64_64KEY, REG_SZ, + WINDOWS_HKEY_LOCAL_MACHINE) +from wazuh_testing.modules.fim import FIM_DEFAULT_LOCAL_INTERNAL_OPTIONS as local_internal_options +from wazuh_testing.modules.fim.event_monitor import (CB_FIM_WILDCARD_EXPANDING, callback_key_event, get_messages, + check_registry_crud_event, callback_value_event) +from wazuh_testing.modules.fim.utils import (create_registry, modify_registry_value, delete_registry, + delete_registry_value) + +# Marks +pytestmark = [WINDOWS, TIER1] + +# Reference paths +TEST_DATA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') +CONFIGURATIONS_PATH = os.path.join(TEST_DATA_PATH, 'configuration_templates') +TEST_CASES_PATH = os.path.join(TEST_DATA_PATH, 'test_cases') + +# Configuration and cases data +configurations_path = os.path.join(CONFIGURATIONS_PATH, 'configuration_registry_wildcards.yaml') +t1_cases_path = os.path.join(TEST_CASES_PATH, 'cases_registry_key_wildcards.yaml') +t2_cases_path = os.path.join(TEST_CASES_PATH, 'cases_registry_value_wildcards.yaml') + +# Enabled test configurations (t1) +t1_configuration_parameters, t1_configuration_metadata, t1_case_ids = get_test_cases_data(t1_cases_path) +t1_configurations = load_configuration_template(configurations_path, t1_configuration_parameters, + t1_configuration_metadata) + +t2_configuration_parameters, t2_configuration_metadata, t2_case_ids = get_test_cases_data(t2_cases_path) +t2_configurations = load_configuration_template(configurations_path, t2_configuration_parameters, + t2_configuration_metadata) + +# Variables +wazuh_log_monitor = FileMonitor(LOG_FILE_PATH) +key_name = 'test_key' +value_name = 'test_value' + + +# Tests +@pytest.mark.parametrize('configuration, metadata', zip(t1_configurations, t1_configuration_metadata), ids=t1_case_ids) +def test_registry_key_wildcards(configuration, metadata, set_wazuh_configuration, truncate_monitored_files, + configure_local_internal_options_function, restart_wazuh_function, + wait_syscheck_start): + ''' + description: Check the behavior of FIM when using wildcards to configure the path of registry keys, and validate + the keys creation, modification and deletion is detected correctly. + + wazuh_min_version: 4.5.0 + + test_phases: + - setup: + - Set wazuh configuration. + - Clean logs files and restart wazuh to apply the configuration. + - test: + - Check that one or more keys are detected when the configured wildcard is expanded + - Create a subkey inside the first monitored key and check + - Wait for scan and check subkey has been detected as 'added' + - Modify the subkey + - Wait for scan and check subkey has been detected as 'modified' + - Delete the subkey + - Wait for scan and check subkey has been detected as 'deleted' + - teardown: + - Restore configuration + - Stop wazuh + + tier: 1 + + parameters: + - configuration: + type: dict + brief: Configuration values for to apply in agentt. + - metadata: + type: dict + brief: Test case data. + - set_wazuh_configuration: + type: fixture + brief: Set wazuh's configuration. + - truncate_monitored_files: + type: fixture + brief: Truncate the logs and alerts files. + - configure_local_internal_options_function: + type: fixture + brief: Set local_internal_options configuration. + - restart_syscheck_function: + type: fixture + brief: restart syscheckd daemon, and truncate the logs. + - wait_syscheck_start: + type: fixture + brief: check that the starting fim scan is detected. + + assertions: + - One or more keys have been configured after wildcard expansion + - Assert 'registry_key added' event has been detected + - Assert 'registry_key modified' event has been detected + - Assert 'registry_key deleted' event has been detected + + input_description: + - The file 'configuration_registry_wildcards.yaml' contains the configuration template for the test. + - The file 'cases_registry_key_wildcards.yaml' contains test case descriptions, configuration values and + metadata for each case. + + expected_output: + - r".*Expanding entry '.*' to '(.*)' to monitor FIM events." + - r".*Sending FIM event: (.+)$" - For 'registry_key' attributes.type and 'added/modified/deleted' type. + + tags: + - scheduled + ''' + + # Check logs for wildcards expansion and actual monitored keys + monitored_keys = get_messages(generate_monitoring_callback(CB_FIM_WILDCARD_EXPANDING), timeout=T_10) + assert monitored_keys != [], f"Did not receive expected '{CB_FIM_WILDCARD_EXPANDING}' events" + + subkey = monitored_keys[0].replace(f"{WINDOWS_HKEY_LOCAL_MACHINE}\\", "") + subkey = subkey + f"\\{key_name}" + path = monitored_keys[0] + f"\\{key_name}" + + # Create a new key inside monitored key and check it is detected + reg_handle = create_registry(registry_parser[WINDOWS_HKEY_LOCAL_MACHINE], subkey, KEY_WOW64_64KEY) + event_added = check_registry_crud_event(callback=callback_key_event, path=path, type='added', timeout=T_10, + arch='x64') + assert event_added is not None, 'Did not find the expected "registry_key added" event' + + # Add new value in the key and detect the modification of created monitored key is detected + modify_registry_value(reg_handle, value_name, REG_SZ, 'new_value') + event_modified = check_registry_crud_event(callback=callback_key_event, path=path, type='modified', timeout=T_10, + arch='x64') + assert event_modified is not None, 'Did not find the expected "registry_key modified" event' + + # Delete the created key and check it's deletion is detected + delete_registry(registry_parser[WINDOWS_HKEY_LOCAL_MACHINE], subkey, KEY_WOW64_64KEY) + event_deleted = check_registry_crud_event(callback=callback_key_event, path=path, type='deleted', timeout=T_10, + arch='x64') + assert event_deleted is not None, 'Did not find the expected "registry_key deleted" event' + + +@pytest.mark.parametrize('configuration, metadata', zip(t2_configurations, t2_configuration_metadata), ids=t2_case_ids) +def test_registry_value_wildcards(configuration, metadata, set_wazuh_configuration, + configure_local_internal_options_function, restart_syscheck_function, + wait_syscheck_start): + ''' + description: Check the behavior of FIM when using wildcards to configure the path of registry keys, and validate + when values are created inside a monitored key, creation, modification and deletion is detected + correctly. + + wazuh_min_version: 4.5.0 + + test_phases: + - setup: + - Set wazuh configuration. + - Clean logs files and restart wazuh to apply the configuration. + - test: + - Check that one or more keys are detected when the configured wildcard is expanded + - Create a registry_value inside the first monitored key and check + - Wait for scan and check registry_value has been detected as 'added' + - Modify the registry_value + - Wait for scan and check registry_value has been detected as 'modified' + - Delete the registry_value + - Wait for scan and check registry_value has been detected as 'deleted' + - teardown: + - Restore configuration + - Stop wazuh + + tier: 1 + + parameters: + - configuration: + type: dict + brief: Configuration values to apply to agent. + - metadata: + type: dict + brief: Test case data. + - set_wazuh_configuration: + type: fixture + brief: Set wazuh's configuration file. + - configure_local_internal_options_function: + type: fixture + brief: Set local_internal_options configuration. + - restart_syscheck_function: + type: fixture + brief: restart syscheckd daemon, and truncate the logs. + - wait_syscheck_start: + type: fixture + brief: check that the starting fim scan is detected. + + assertions: + - One or more keys have been configured after wildcard expansion + - Assert 'registry_value added' event has been detected + - Assert 'registry_value modified' event has been detected + - Assert 'registry_value deleted' event has been detected + + input_description: + - The file 'configuration_registry_wildcards.yaml' contains the configuration template for the test. + - The file 'cases_registry_value_wildcards.yaml' contains test case descriptions, configuration values and + metadata for each case. + + expected_output: + - r".*Expanding entry '.*' to '(.*)' to monitor FIM events." + - r".*Sending FIM event: (.+)$" - For 'registry_value' attributes.type and 'added/modified/deleted' type. + tags: + - scheduled + ''' + + monitored_keys = get_messages(generate_monitoring_callback(CB_FIM_WILDCARD_EXPANDING), timeout=T_10) + assert monitored_keys != [], f"Did not receive expected '{CB_FIM_WILDCARD_EXPANDING}' events" + + subkey = monitored_keys[0].replace(f"{WINDOWS_HKEY_LOCAL_MACHINE}\\", "") + subkey = subkey + f"\\{key_name}" + path = monitored_keys[0] + f"\\{key_name}" + + # Create custom key and custom value + reg_handle = create_registry(registry_parser[WINDOWS_HKEY_LOCAL_MACHINE], subkey, KEY_WOW64_64KEY) + modify_registry_value(reg_handle, value_name, REG_SZ, 'added') + event_added = check_registry_crud_event(callback=callback_value_event, path=path, type='added', timeout=T_10, + arch='x64') + assert event_added is not None, 'Did not find the expected "registry_value added" event' + + # Add new value in the key and detect the modification of created monitored key is detected + modify_registry_value(reg_handle, value_name, REG_SZ, 'modified') + event_modified = check_registry_crud_event(callback=callback_value_event, path=path, type='modified', timeout=T_10, + arch='x64') + assert event_modified is not None, 'Did not find the expected "registry_value modified" event' + + # Delete the created key and check it's deletion is detected + delete_registry_value(reg_handle, value_name) + event_deleted = check_registry_crud_event(callback=callback_value_event, path=path, type='deleted', timeout=T_10, + arch='x64') + assert event_deleted is not None, 'Did not find the expected "registry_value deleted" event' + + # Delete key to clean enviroment + delete_registry(registry_parser[WINDOWS_HKEY_LOCAL_MACHINE], subkey, KEY_WOW64_64KEY)