diff --git a/tests/system/fim/common_tasks/create_files.yml b/tests/system/fim/common_tasks/create_files.yml index e69de29bb2..8a9982db82 100644 --- a/tests/system/fim/common_tasks/create_files.yml +++ b/tests/system/fim/common_tasks/create_files.yml @@ -0,0 +1,42 @@ +--- +- block: + - name: Run script generate_files.py on agents | Linux + script: "generate_files.py -c {{ files_config_linux_destination_path }} -o {{ files_generated_output_path }}" + args: + executable: "python3" + chdir: "{{ agents_linux_output_path }}" + + - name: Copy list of created files from Agents to Ansible Controller host | Linux + fetch: + src: "{{ agents_linux_output_path }}/{{ files_generated_output_path }}" + dest: "agents_outputs/{{ event }}/{{ files_generated_output_path }}-{{ inventory_hostname }}" + flat: yes + + become: yes + when: + - inventory_hostname in groups['linuxagents'] + + +- block: + - name: Run script generate_files.py on agents | Windows + script: "generate_files.py -c {{ files_config_windows_destination_path }} -o {{ files_generated_output_path }}" + args: + executable: "python" + chdir: "{{ agents_windows_output_path }}" + + - name: Copy list of created files from Windows Agents to Ansible Controller host | Windows + fetch: + src: "{{ agents_windows_output_path }}/{{ files_generated_output_path }}" + dest: "agents_outputs/{{ event }}/{{ files_generated_output_path }}-{{ inventory_hostname }}" + flat: yes + + when: + - inventory_hostname in groups['windowsagents'] + +- name: Copy the output files from Ansible Controller to the Managers + become: true + synchronize: + src: "agents_outputs/added/" + dest: "{{ agents_results_manager_path }}/{{ event }}/" + when: + - inventory_hostname in groups['masters'] diff --git a/tests/system/fim/common_tasks/delete_files.py b/tests/system/fim/common_tasks/delete_files.py index 94067e1666..180ecfda3f 100644 --- a/tests/system/fim/common_tasks/delete_files.py +++ b/tests/system/fim/common_tasks/delete_files.py @@ -15,14 +15,18 @@ def delete_files(input_file_path, n, output_file_path): """ - Delete files, given a file with complete list of files where each line + Delete files, given a file with complete list of files where each line represents a file path, we will randomly delete n files of them. :param str input_file_path: path of the input file which contains the list of files. :param int n: number of file to delete. :return: Returns a file with the list of the deleted files. """ - logger = logging.getLogger() + log_filename = 'delete_files.log' + logging.basicConfig( + filename=log_filename, + level=logging.DEBUG, + ) data = [] # Read data into the variable 'data' try: @@ -31,22 +35,21 @@ def delete_files(input_file_path, n, output_file_path): data_ = f.readlines() # remove whitespace characters like `\n` at the end of each line data = [x.strip() for x in data_] - f.close() # close f - except Exception as e: - logger.error('Failed when reading the input file: ', exc_info=True) + f.close() # close f + except Exception: + logging.error('Failed when reading the input file: ', exc_info=True) - - if n is not None: # Randomly select n paths from data - to_delete = random.sample(data,n) - else: # Delete all files + if n is not None: # Randomly select n paths from data + to_delete = random.sample(data, n) + else: # Delete all files to_delete = data # Delete the selected files try: for path in to_delete: os.remove(path) - except Exception as e: - logger.error('Failed when deleting the selected files: ', exc_info=True) + except Exception: + logging.error('Failed when deleting the selected files: ', exc_info=True) # Write the list of the deleted files into output_file_path try: @@ -54,8 +57,9 @@ def delete_files(input_file_path, n, output_file_path): for item in to_delete: f.write("%s\n" % item) f.close() - except Exception as e: - logger.error('Failed when writing to the output file: ', exc_info=True) + except Exception: + logging.error('Failed when writing to the output file: ', exc_info=True) + def main(): parser = argparse.ArgumentParser() @@ -72,5 +76,6 @@ def main(): delete_files(args.input_file, args.n_files, args.output_file) + if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/tests/system/fim/common_tasks/delete_files.yml b/tests/system/fim/common_tasks/delete_files.yml new file mode 100644 index 0000000000..1fb422ac4d --- /dev/null +++ b/tests/system/fim/common_tasks/delete_files.yml @@ -0,0 +1,43 @@ +--- +- block: + - name: "Delete FIM test files at Wazuh Agents | Linux" + script: "delete_files.py -i {{ files_generated_output_path }} -o {{ files_deleted_output_path }}" + args: + executable: "python3" + chdir: "{{ agents_linux_output_path }}" + + - name: Copy list of deleted files from Agents to Ansible Controller host | Linux + fetch: + src: "{{ agents_linux_output_path }}/{{ files_deleted_output_path }}" + dest: "agents_outputs/{{ event }}/{{ files_deleted_output_path }}-{{ inventory_hostname }}" + flat: yes + + become: yes + when: + - inventory_hostname in groups['linuxagents'] + + +- block: + - name: "Delete FIM test files at Wazuh Agents | Windows" + script: "delete_files.py -i {{ files_generated_output_path }} -o {{ files_deleted_output_path }}" + args: + executable: "python" + chdir: "{{ agents_windows_output_path }}" + + - name: Copy list of deleted files from Windows Agents to Ansible Controller host + fetch: + src: "{{ agents_windows_output_path }}/{{ files_deleted_output_path }}" + dest: "agents_outputs/{{ event }}/{{ files_deleted_output_path }}-{{ inventory_hostname }}" + flat: yes + + when: + - inventory_hostname in groups['windowsagents'] + + +- name: Copy the output files from Ansible Controller to the Managers + become: true + synchronize: + src: "agents_outputs/added/" + dest: "{{ agents_results_manager_path }}/{{ event }}/" + when: + - inventory_hostname in groups['masters'] diff --git a/tests/system/fim/common_tasks/files_configuration.json b/tests/system/fim/common_tasks/files_configuration.json deleted file mode 100644 index 4ecf00126c..0000000000 --- a/tests/system/fim/common_tasks/files_configuration.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "root_folder": "/opt/testing/", - "recursion_level": 3, - "folder_length": 5, - "file_length": 5, - "file_size_specifications":[ - { "size": 10240, "amount": 10000}, - { "size": 524288, "amount": 500}, - { "size": 1048576, "amount": 1000}, - { "size": 10485760, "amount": 10}, - { "size": 1073741824, "amount": 1} - ] -} diff --git a/tests/system/fim/common_tasks/files_configuration.json.j2 b/tests/system/fim/common_tasks/files_configuration.json.j2 new file mode 100644 index 0000000000..d91e600601 --- /dev/null +++ b/tests/system/fim/common_tasks/files_configuration.json.j2 @@ -0,0 +1,12 @@ +{ + "root_folder": "{{ agents_fim_testing_path }}", + "recursion_level": 3, + "folder_length": 5, + "file_length": 5, + "file_size_specifications":[ + { "size": 10240, "amount": 4000}, + { "size": 524288, "amount": 500}, + { "size": 1048576, "amount": 500}, + { "size": 10485760, "amount": 10} + ] +} diff --git a/tests/system/fim/common_tasks/files_generator.py b/tests/system/fim/common_tasks/generate_files.py similarity index 93% rename from tests/system/fim/common_tasks/files_generator.py rename to tests/system/fim/common_tasks/generate_files.py index 598e7912f3..796fd4ee3d 100644 --- a/tests/system/fim/common_tasks/files_generator.py +++ b/tests/system/fim/common_tasks/generate_files.py @@ -12,6 +12,7 @@ import json import random import string +import secrets import argparse @@ -118,7 +119,13 @@ def create_files(files_path): """ for key, value in files_path.items(): with open(key, "wb") as f: - f.write(b'0'*value) + if value > 1048576: + nval = value // 1048576 + for val in range(nval): + f.write(b'0' * 1048576) + else: + f.write(b'0' * value) + f.write(secrets.token_bytes(32)) def create_file_summary(files_path, logfile): @@ -132,7 +139,7 @@ def create_file_summary(files_path, logfile): os.remove(logfile) with open(logfile, 'w') as f: for path in files_path: - f.write(path+'\n') + f.write(path + '\n') def main(): @@ -146,10 +153,10 @@ def main(): output_file = args.output_list config = parse_files_configuration(config_file) folders = generate_folders_paths( - config["root_folder"], - config["recursion_level"], - config["folder_length"] - ) + config["root_folder"], + config["recursion_level"], + config["folder_length"] + ) create_folders(folders) n_files = sum(x['amount'] for x in config['file_size_specifications']) files = generate_files_paths(folders, n_files, config["file_length"]) diff --git a/tests/system/fim/common_tasks/files_modify.py b/tests/system/fim/common_tasks/modify_files.py similarity index 55% rename from tests/system/fim/common_tasks/files_modify.py rename to tests/system/fim/common_tasks/modify_files.py index 9ee5c736dd..e7d1482a5d 100644 --- a/tests/system/fim/common_tasks/files_modify.py +++ b/tests/system/fim/common_tasks/modify_files.py @@ -12,6 +12,8 @@ import sys import random import platform +import argparse +import logging if platform.system() == 'Linux': import pwd import grp @@ -51,7 +53,7 @@ def modify_file(filepath, owner, group, mode): 'uid': uid, 'gid': gid, 'mode': oct(mode).split('o')[1].zfill(3) # convert to octal string - } + } def modify_file_content(filepath): @@ -60,22 +62,63 @@ def modify_file_content(filepath): :param str filepath: The path of the file to modify """ - content = 'qazxswedcvbnmklpoiuytggdfert'*random.randint(1, 10) + content = 'qazxswedcvbnmklpoiuytggdfert' * random.randint(1, 10) content += str(random.random()) + if not os.path.exists(filepath): + raise FileNotFoundError with open(filepath, 'ab') as f: f.write(bytes(content, 'utf8')) +def log_modified_files(files_path, logfile): + """ + Creates a file that summarizes all the modified files + + :param dict files_path: Contains the list of modified files + :param str logfile: File to write the list of paths + """ + if os.path.exists(logfile): + os.remove(logfile) + with open(logfile, 'w') as f: + for path in files_path: + f.write(path + '\n') + + def main(): - import argparse + log_filename = 'modify_files.log' + logging.basicConfig( + filename=log_filename, + level=logging.DEBUG, + ) parser = argparse.ArgumentParser() - parser.add_argument("-i", "--input-list", type=str, required=True, dest='input_file', + parser.add_argument("-i", "--input-list", type=str, + required=True, dest='input_file', help="File containing the list of files to modify") + parser.add_argument("-o", "--output-list", type=str, + required=True, dest='output_file', + help="File containing the list of modified files") args = parser.parse_args() + input_file = args.input_file + output_file = args.output_file + + changed_files = [] + with open(input_file) as flist: for path in flist: - modify_file_content(path[:-1]) + try: + modify_file_content(path[:-1]) + changed_files.append(path[:-1]) + except PermissionError: + logging.error("Not enough permissions to modify: {}".format(path[:-1])) + continue + except FileNotFoundError: + logging.error("File not found: {}".format(path[:-1])) + continue + except Exception: + logging.error("Unexpected error: ", exc_info=True) + continue + log_modified_files(changed_files, output_file) if __name__ == "__main__": diff --git a/tests/system/fim/common_tasks/modify_files.yml b/tests/system/fim/common_tasks/modify_files.yml new file mode 100644 index 0000000000..9ff2f89daf --- /dev/null +++ b/tests/system/fim/common_tasks/modify_files.yml @@ -0,0 +1,42 @@ +--- +- block: + - name: "Modify FIM test files at Wazuh Managers | Linux" + script: "modify_files.py -i {{ files_generated_output_path }} -o {{ files_modified_output_path }}" + args: + executable: "python3" + chdir: "{{ agents_linux_output_path }}" + + - name: Copy list of modified files from Agents to Ansible Controller host | Linux + fetch: + src: "{{ agents_linux_output_path }}/{{ files_modified_output_path }}" + dest: "agents_outputs/{{ event }}/{{ files_modified_output_path }}-{{ inventory_hostname }}" + flat: yes + + become: yes + when: + - inventory_hostname in groups['linuxagents'] + + +- block: + - name: "Modify FIM test files at Wazuh Managers | Windows" + script: "modify_files.py -i {{ files_generated_output_path }} -o {{ files_modified_output_path }}" + args: + executable: "python" + chdir: "{{ agents_windows_output_path }}" + + - name: Copy list of modified files from Agents to Ansible Controller host | Windows + fetch: + src: "{{ agents_windows_output_path }}/{{ files_generated_output_path }}" + dest: "agents_outputs/{{ event }}/{{ files_modified_output_path }}-{{ inventory_hostname }}" + flat: yes + + when: + - inventory_hostname in groups['windowsagents'] + +- name: Copy the output files from Ansible Controller to the Managers + become: true + synchronize: + src: "agents_outputs/modified/" + dest: "{{ agents_results_manager_path }}/{{ event }}/" + when: + - inventory_hostname in groups['masters'] \ No newline at end of file diff --git a/tests/system/fim/common_tasks/prepare.yml b/tests/system/fim/common_tasks/prepare.yml new file mode 100644 index 0000000000..b017f7fea4 --- /dev/null +++ b/tests/system/fim/common_tasks/prepare.yml @@ -0,0 +1,97 @@ +- block: + - name: Creates directories to store agents' outputs in Managers hosts + file: + path: "{{ item }}" + state: directory + with_items: + - "{{ agents_results_manager_path }}" + - "{{ agents_results_manager_path }}/added" + - "{{ agents_results_manager_path }}/modified" + - "{{ agents_results_manager_path }}/deleted" + + - name: Stop wazuh-manager service + service: + name: wazuh-manager + state: stopped + + - name: Copy {{ files_config_manager_ossec_conf }} to the Managers hosts + copy: + src: "config/{{ files_config_manager_ossec_conf }}" + dest: "{{ linux_ossec_folder_path }}/etc/ossec.conf" + + - name: Start wazuh-manager service + service: + name: wazuh-manager + state: started + + when: + - inventory_hostname in groups['masters'] + become: yes + +- block: + - name: Create {{ agents_linux_output_path }} to store outputs in Agents hosts | Linux + file: + path: "{{ agents_linux_output_path }}" + state: directory + when: + - inventory_hostname in groups['linuxagents'] + + - name: Copy {{ files_config_source_path }} to the Agents hosts | Linux + template: + src: "../../common_tasks/files_configuration.json.j2" + dest: "{{ files_config_linux_destination_path }}" + vars: + agents_fim_testing_path: "{{ files_fim_testing_linux }}" + + - name: Stop wazuh-agent service | Linux + service: + name: wazuh-agent + state: stopped + + - name: Copy {{ files_config_agent_linux_ossec_conf }} to the Agents hosts | Linux + copy: + src: "./config/{{ files_config_agent_linux_ossec_conf }}" + dest: "{{ linux_ossec_folder_path }}/etc/ossec.conf" + + - name: Start wazuh-agent service | Linux + service: + name: wazuh-agent + state: started + + when: + - inventory_hostname in groups['linuxagents'] + become: yes + +- block: + - name: Create {{ agents_windows_output_path }} to store outputs in agents hosts | Windows + win_file: + path: "{{ agents_windows_output_path }}" + state: directory + + - name: Copy {{ files_config_source_path }} to the Agents hosts | Windows + template: + src: "../../common_tasks/files_configuration.json.j2" + dest: "{{ files_config_windows_destination_path }}" + vars: + agents_fim_testing_path: "{{ files_fim_testing_windows }}" + + - name: Stop wazuh-agent service | Windows + win_service: + name: OssecSvc + start_mode: auto + state: stopped + + - name: Copy {{ files_config_agent_windows_ossec_conf }} to the agents hosts | Windows + win_copy: + src: "config/{{ files_config_agent_windows_ossec_conf }}" + dest: "{{ windows_ossec_folder_path }}/ossec.conf" + + - name: Start wazuh-agent service | Windows + win_service: + name: OssecSvc + start_mode: auto + state: started + + + when: + - inventory_hostname in groups['windowsagents'] diff --git a/tests/system/fim/common_tasks/verify_alerts.yml b/tests/system/fim/common_tasks/verify_alerts.yml index a2ee7369ee..245b59edf3 100644 --- a/tests/system/fim/common_tasks/verify_alerts.yml +++ b/tests/system/fim/common_tasks/verify_alerts.yml @@ -1,14 +1,30 @@ ---- - - name: "Verify alert log" - script: "verify_alerts_json.py -i {{ file_list_path }} -e {{ syscheck_event }}" +--- + - name: Find input files for manager + find: + paths: "{{ agents_results_manager_path }}/{{ event }}" + register: find_result + when: + - inventory_hostname in groups['masters'] + + - name: "Verify alert json log | {{ event }}" + script: > + verify_alerts_json.py -i {{ item.path }} -e {{ event }} + -o {{ missing_alerts_json_path }} args: executable: "python3" when: - inventory_hostname in groups['masters'] + with_items: + - "{{ find_result.files }}" - - name: "Verify elastic alerts" - script: "verify_alerts_elasticsearch.py -i {{ file_list_path }} -e {{ syscheck_event }} -a {{ private_ip }}" + - name: "Verify elastic alerts | {{ event }}" + script: > + verify_alerts_elasticsearch.py -i {{ item.path }} -e {{ event }} + -a {{ hostvars[groups["elasticsearch"][0]]["private_ip"] }} + -o {{ missing_alerts_elasticsearch_path }} args: executable: python3 when: - - inventory_hostname in groups['elasticsearch'][0] \ No newline at end of file + - inventory_hostname in groups['masters'] + with_items: + - "{{ find_result.files }}" \ No newline at end of file diff --git a/tests/system/fim/common_tasks/verify_alerts_elasticsearch.py b/tests/system/fim/common_tasks/verify_alerts_elasticsearch.py index 10d88aff41..7ef950b8dc 100644 --- a/tests/system/fim/common_tasks/verify_alerts_elasticsearch.py +++ b/tests/system/fim/common_tasks/verify_alerts_elasticsearch.py @@ -1,7 +1,16 @@ #!/usr/bin/python3 +# Copyright (C) 2015-2020, Wazuh Inc. +# All rights reserved. +# +# This program is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public +# License (version 2) as published by the FSF - Free Software +# Foundation. import argparse from elasticsearch import Elasticsearch +from time import sleep, time +import logging def setElasticsearch(ElasticIP): @@ -30,7 +39,14 @@ def makeQuery(query, Elastic, index_name): if __name__ == "__main__": - + logging.basicConfig( + level=logging.INFO, + format="%(asctime)s [%(levelname)s] %(message)s", + handlers=[ + logging.FileHandler("verify_alerts_elastic.log"), + logging.StreamHandler() + ] + ) parser = argparse.ArgumentParser() parser.add_argument( "-i", "--input-list", type=str, required=True, dest='files', @@ -50,6 +66,15 @@ def makeQuery(query, Elastic, index_name): dest='output', help="Output path for missing files alerts.", default="debug_missing_file_alerts.log" ) + parser.add_argument( + "-r", "--retry", type=int, required=False, dest='max_retry', + help="reading attempts on stopped alerts. default: 4 attemps", + default="4" + ) + parser.add_argument( + "-s", "--sleep", type=int, required=False, dest='sleep_time', + help="Sleep time between retries", default="60" + ) args = parser.parse_args() query = { @@ -65,24 +90,45 @@ def makeQuery(query, Elastic, index_name): es = setElasticsearch(args.ip) index_name = "wazuh-alerts-3.x*" - success = 0 - failure = 0 - failure_list = [] - + retry_count = 0 + logging.info("Elasticsearch alerts verification started") + start = time() with open(args.files, 'r') as file_list: - for line in file_list: - query['query']['bool']['filter'][0]['term']['syscheck.path'] = \ - line.rstrip() - query_result = makeQuery(query, es, index_name) - if query_result['hits']['total']['value'] == 1: - success += 1 + while retry_count < args.max_retry: + success = 0 + failure = 0 + failure_list = [] + for line in file_list: + query['query']['bool']['filter'][0]['term']['syscheck.path'] =\ + line.rstrip() + + query_result = makeQuery(query, es, index_name) + if query_result['hits']['total']['value'] == 1: + success += 1 + else: + failure_list.append(line) + failure += 1 + if failure == 0: + break else: - failure_list.append(line) - failure += 1 + elapsed = start - time() + logging.info("Missing alerts {}.\n".format(failure)) + logging.info("Number of retries {}.\n".format(retry_count)) + logging.info("Elapsed time: ~ {} seconds. \n".format(elapsed)) + retry_count += 1 + sleep(args.sleep_time) + elapsed = start - time() with open(args.output, 'w+') as output: output.writelines(failure_list) - assert failure == 0, "number of failed files: {}\n".format(failure) + assert failure == 0, "number of failed files: {}\n \ + Elapsed time: ~ {} seconds.".format( + success, elapsed + ) - print("number of succeded files: {}\n".format(success)) + print( + "Number of succeded files: {}\n Elapsed time: ~ {} seconds.".format( + success, elapsed + ) + ) \ No newline at end of file diff --git a/tests/system/fim/common_tasks/verify_alerts_json.py b/tests/system/fim/common_tasks/verify_alerts_json.py index 1c202d4a94..086f9d0be2 100644 --- a/tests/system/fim/common_tasks/verify_alerts_json.py +++ b/tests/system/fim/common_tasks/verify_alerts_json.py @@ -10,7 +10,9 @@ import sys import json -import traceback + +import logging +import argparse if sys.version_info.major < 3: print('ERROR: Python 2 is not supported.') @@ -44,17 +46,22 @@ def alerts_prune(path, target_event): data = json.loads(line) if data.get('syscheck') and data['syscheck']['event'] == target_event: alerts_list.append(data) + except ValueError: continue return set([alerts['syscheck']['path'] for alerts in alerts_list]) def main(): - + logging.basicConfig( + level=logging.INFO, + format="%(asctime)s [%(levelname)s] %(message)s", + handlers=[ + logging.FileHandler("verify_alerts_json.log"), + logging.StreamHandler() + ] + ) try: - - import argparse - parser = argparse.ArgumentParser(description='Compares paths list and alerts.json paths') parser.add_argument("-i", "--input-list", type=str, required=True, dest='input_file', @@ -65,7 +72,8 @@ def main(): help="Type of alert's event that we expect: added, modified, deleted") parser.add_argument("-l", "--log_json", type=str, required=False, dest='log_json_path', - help="alerts.json path. default value '/var/ossec/logs/alerts/alerts.json'", + help="alerts.json path. default value " + "'/var/ossec/logs/alerts/alerts.json'", default="/var/ossec/logs/alerts/alerts.json") parser.add_argument("-o", "--output-list", type=str, required=False, dest='output_file', @@ -73,8 +81,8 @@ def main(): default="debug_missing_file_alerts.log") parser.add_argument("-t", "--timeout", type=int, required=False, dest='time_gap', - help="time gap between alerts.json alerts acquisitions. default: 30s", - default="30") + help="time gap between alerts.json alerts acquisitions. default: 60s", + default="60") parser.add_argument("-r", "--retry", type=int, required=False, dest='retry_count', help="reading attempts on stopped alerts. default: 4 attemps", @@ -91,24 +99,26 @@ def main(): prev_lenght = len(sub_paths) start = time.time() - print("alerts.json verification started") + logging.info("alerts.json verification started") while True: pruned_alerts_set = alerts_prune(args.log_json_path, args.event) sub_paths = paths_list_set - pruned_alerts_set if len(sub_paths) == 0: - print("Verify alerts test - OK.") + logging.info("Verify alerts test - OK.") return 0 if stuck_alerts > args.retry_count: - print("Verify alerts test - NOT OK. %s alerts are missing.\n" % len(sub_paths)) + logging.warning( + "Verify alerts test - NOT OK. %s alerts are missing.\n" % len(sub_paths) + ) with open(args.output_file, 'w') as f: for item in sub_paths: f.write("%s\n" % item) - f.write("%s missing alerts.\n" % len(sub_paths)) + logging.warning("%s missing alerts.\n" % len(sub_paths)) return 1 if prev_lenght == len(sub_paths): - print("Filelist related alerts aren't growing (%s) ..." % stuck_alerts) + logging.info("Filelist related alerts aren't growing (%s) ..." % stuck_alerts) stuck_alerts += 1 else: stuck_alerts = 0 @@ -116,11 +126,12 @@ def main(): time.sleep(args.time_gap) prev_lenght = len(sub_paths) elapsed = time.time() - start - print("Elapsed time: ~ %s seconds \n" % int(elapsed)) + logging.info("Elapsed time: ~ %s seconds \n" % int(elapsed)) except Exception: - traceback.print_exc() + logging.critical("An error has ocurred. Exiting") + raise Exception if __name__ == "__main__": - main() + sys.exit(main()) diff --git a/tests/system/fim/handlers/main.yml b/tests/system/fim/handlers/main.yml new file mode 100644 index 0000000000..8633d67a19 --- /dev/null +++ b/tests/system/fim/handlers/main.yml @@ -0,0 +1,72 @@ + + - name: Stop Wazuh agent Linux + become: true + service: + name: wazuh-agent + state: stopp + + - name: Stop Wazuh agent Windows + win_service: + name: OssecSvc + start_mode: auto + state: stopped + + - name: Start Wazuh agent Linux + become: true + service: + name: wazuh-agent + state: started + + - name: Start Wazuh agent Windows + win_service: + name: OssecSvc + start_mode: auto + state: started + + - name: Restart Wazuh agent Linux + become: true + service: + name: wazuh-agent + state: restarted + + - name: Restart Wazuh agent Windows + win_service: + name: OssecSvc + start_mode: auto + state: restarted + + - name: Stop Wazuh manager + become: true + service: + name: wazuh-manager + state: stopped + + - name: Start Wazuh manager + become: true + service: + name: wazuh-manager + state: started + + - name: Restart Wazuh manager + become: true + service: + name: wazuh-manager + state: restarted + + - name: Stop Wazuh api + become: true + service: + name: wazuh-api + state: stopped + + - name: Start Wazuh api + become: true + service: + name: wazuh-api + state: started + + - name: Restart Wazuh api + become: true + service: + name: wazuh-api + state: restarted diff --git a/tests/system/fim/scenario_default_installation/config/files_configuration.json b/tests/system/fim/scenario_default_installation/config/files_configuration.json deleted file mode 100644 index 5c8cce00b5..0000000000 --- a/tests/system/fim/scenario_default_installation/config/files_configuration.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "root_folder": "/opt/test_files", - "recursion_level": 3, - "folder_length": 5, - "file_length": 5, - "file_size_specifications":[ - { "size": 10240, "amount": 10000}, - { "size": 524288, "amount": 500}, - { "size": 1048576, "amount": 1000}, - { "size": 10485760, "amount": 10}, - { "size": 1073741824, "amount": 1} - ], - "output_file": "created_files.txt" -} diff --git a/tests/system/fim/scenario_default_installation/launch_scenario.yml b/tests/system/fim/scenario_default_installation/launch_scenario.yml deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/system/fim/scenarios/scenario_default_installation/.gitignore b/tests/system/fim/scenarios/scenario_default_installation/.gitignore new file mode 100644 index 0000000000..eb2ab7694c --- /dev/null +++ b/tests/system/fim/scenarios/scenario_default_installation/.gitignore @@ -0,0 +1 @@ +agents_outputs \ No newline at end of file diff --git a/tests/system/fim/scenario_default_installation/actions/files.yml b/tests/system/fim/scenarios/scenario_default_installation/actions/files.yml similarity index 100% rename from tests/system/fim/scenario_default_installation/actions/files.yml rename to tests/system/fim/scenarios/scenario_default_installation/actions/files.yml diff --git a/tests/system/fim/scenario_default_installation/actions/folders.yml b/tests/system/fim/scenarios/scenario_default_installation/actions/folders.yml similarity index 100% rename from tests/system/fim/scenario_default_installation/actions/folders.yml rename to tests/system/fim/scenarios/scenario_default_installation/actions/folders.yml diff --git a/tests/system/fim/scenarios/scenario_default_installation/config/agent_linux_ossec.conf b/tests/system/fim/scenarios/scenario_default_installation/config/agent_linux_ossec.conf new file mode 100644 index 0000000000..e9ffad4b89 --- /dev/null +++ b/tests/system/fim/scenarios/scenario_default_installation/config/agent_linux_ossec.conf @@ -0,0 +1,208 @@ + + + + + +
172.16.0.111
+ 1514 + udp +
+ linux_system_tests + 10 + 60 + yes + aes +
+ + + + no + 15000 + 500 + + + + + no + yes + yes + yes + yes + yes + yes + yes + + + 43200 + + /var/ossec/etc/shared/rootkit_files.txt + /var/ossec/etc/shared/rootkit_trojans.txt + + yes + + + + yes + 1800 + 1d + yes + + + + yes + 1800 + 1d + yes + + wodles/java + wodles/ciscat + + + + + yes + yes + /var/log/osquery/osqueryd.results.log + /etc/osquery/osquery.conf + yes + + + + + no + 1h + yes + yes + yes + yes + yes + yes + yes + + + + yes + yes + 12h + yes + + + + + + no + + + 10 + + yes + + + /etc,/usr/bin,/usr/sbin + /bin,/sbin,/boot + /opt/fim_testing + + + /etc/mtab + /etc/hosts.deny + /etc/mail/statistics + /etc/random-seed + /etc/random.seed + /etc/adjtime + /etc/httpd/logs + /etc/utmpx + /etc/wtmpx + /etc/cups/certs + /etc/dumpdates + /etc/svc/volatile + + + .log$|.swp$ + + + /etc/ssl/private.key + + yes + yes + yes + yes + + + 10 + + + 200 + + + + yes + 5m + 1h + + + + + + command + df -P + 360 + + + + full_command + netstat -tulpn | sed 's/\([[:alnum:]]\+\)\ \+[[:digit:]]\+\ \+[[:digit:]]\+\ \+\(.*\):\([[:digit:]]*\)\ \+\([0-9\.\:\*]\+\).\+\ \([[:digit:]]*\/[[:alnum:]\-]*\).*/\1 \2 == \3 == \4 \5/' | sort -k 4 -g | sed 's/ == \(.*\) ==/:\1/' | sed 1,2d + netstat listening ports + 360 + + + + full_command + last -n 20 + 360 + + + + + no + /var/ossec/etc/wpk_root.pem + yes + + + + + plain + + +
+ + + + syslog + /var/ossec/logs/active-responses.log + + + + syslog + /var/log/auth.log + + + + syslog + /var/log/syslog + + + + syslog + /var/log/dpkg.log + + + + syslog + /var/log/kern.log + + + diff --git a/tests/system/fim/scenarios/scenario_default_installation/config/agent_windows_ossec.conf b/tests/system/fim/scenarios/scenario_default_installation/config/agent_windows_ossec.conf new file mode 100644 index 0000000000..01e6d8966e --- /dev/null +++ b/tests/system/fim/scenarios/scenario_default_installation/config/agent_windows_ossec.conf @@ -0,0 +1,207 @@ + + + + + + +
172.16.0.111
+ 1514 + udp +
+ aes + 10 + 60 + yes +
+ + + + no + 15000 + 500 + + + + + Application + eventchannel + + + + Security + eventchannel + Event/System[EventID != 5145 and EventID != 5156 and EventID != 5447 and + EventID != 4656 and EventID != 4658 and EventID != 4663 and EventID != 4660 and + EventID != 4670 and EventID != 4690 and EventID != 4703 and EventID != 4907 and + EventID != 5152 and EventID != 5157] + + + + System + eventchannel + + + + active-response\active-responses.log + syslog + + + + + no + ./shared/win_applications_rcl.txt + ./shared/win_malware_rcl.txt + + + + + yes + yes + 12h + yes + + + + + + no + + + 10 + + + C:\fim_testing + %WINDIR% + + %WINDIR%\SysNative + %WINDIR%\SysNative\drivers\etc + %WINDIR%\SysNative\wbem + %WINDIR%\SysNative\WindowsPowerShell\v1.0 + %WINDIR%\SysNative + + + %WINDIR%\System32 + %WINDIR%\System32\drivers\etc + %WINDIR%\System32\wbem + %WINDIR%\System32\WindowsPowerShell\v1.0 + %WINDIR%\System32 + + %PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\Startup + + %PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\Startup\desktop.ini + + .log$|.htm$|.jpg$|.png$|.chm$|.pnf$|.evtx$ + + + HKEY_LOCAL_MACHINE\Software\Classes\batfile + HKEY_LOCAL_MACHINE\Software\Classes\cmdfile + HKEY_LOCAL_MACHINE\Software\Classes\comfile + HKEY_LOCAL_MACHINE\Software\Classes\exefile + HKEY_LOCAL_MACHINE\Software\Classes\piffile + HKEY_LOCAL_MACHINE\Software\Classes\AllFilesystemObjects + HKEY_LOCAL_MACHINE\Software\Classes\Directory + HKEY_LOCAL_MACHINE\Software\Classes\Folder + HKEY_LOCAL_MACHINE\Software\Classes\Protocols + HKEY_LOCAL_MACHINE\Software\Policies + HKEY_LOCAL_MACHINE\Security + HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer + + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\KnownDLLs + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurePipeServers\winreg + + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnceEx + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\URL + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon + + HKEY_LOCAL_MACHINE\Software\Microsoft\Active Setup\Installed Components + + + HKEY_LOCAL_MACHINE\Security\Policy\Secrets + HKEY_LOCAL_MACHINE\Security\SAM\Domains\Account\Users + \Enum$ + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MpsSvc\Parameters\AppCs + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MpsSvc\Parameters\PortKeywords\DHCP + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MpsSvc\Parameters\PortKeywords\IPTLSIn + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MpsSvc\Parameters\PortKeywords\IPTLSOut + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MpsSvc\Parameters\PortKeywords\RPC-EPMap + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\MpsSvc\Parameters\PortKeywords\Teredo + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\PolicyAgent\Parameters\Cache + HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnceEx + HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\ADOVMPPackage\Final + + + 300 + + + 10 + + + 200 + + + + yes + 5m + 1h + + + + + + no + 1h + yes + yes + yes + yes + yes + yes + yes + + + + + yes + 1800 + 1d + yes + + \\server\jre\bin\java.exe + C:\cis-cat + + + + + yes + yes + C:\Program Files\osquery\osqueryd + C:\Program Files\osquery\log\osqueryd.results.log + C:\Program Files\osquery\osquery.conf + yes + + + + + no + wpk_root.pem + yes + + + + + plain + + +
+ + + diff --git a/tests/system/fim/scenarios/scenario_default_installation/config/manager_ossec.conf b/tests/system/fim/scenarios/scenario_default_installation/config/manager_ossec.conf new file mode 100644 index 0000000000..58a0eec910 --- /dev/null +++ b/tests/system/fim/scenarios/scenario_default_installation/config/manager_ossec.conf @@ -0,0 +1,370 @@ + + + + + yes + yes + no + no + no + smtp.example.wazuh.com + ossecm@example.wazuh.com + recipient@example.wazuh.com + 12 + alerts.log + + + + 3 + 12 + + + + + plain + + + + secure + 1514 + udp + 131072 + + + + + no + yes + yes + yes + yes + yes + yes + yes + + + 43200 + + /var/ossec/etc/rootcheck/rootkit_files.txt + /var/ossec/etc/rootcheck/rootkit_trojans.txt + + yes + + + + yes + 1800 + 1d + yes + + + + yes + 1800 + 1d + yes + + wodles/java + wodles/ciscat + + + + + yes + yes + /var/log/osquery/osqueryd.results.log + /etc/osquery/osquery.conf + yes + + + + + no + 1h + yes + yes + yes + yes + yes + yes + yes + + + + yes + yes + 12h + yes + + + + + no + 5m + 6h + yes + + + no + precise + trusty + xenial + bionic + 1h + + + + no + wheezy + stretch + jessie + buster + 1h + + + + no + 2010 + 1h + + + + no + 2010 + 1h + + + + + + + no + + + 43200 + + yes + + + yes + + + no + + + /etc,/usr/bin,/usr/sbin + /bin,/sbin,/boot + + + /etc/mtab + /etc/hosts.deny + /etc/mail/statistics + /etc/random-seed + /etc/random.seed + /etc/adjtime + /etc/httpd/logs + /etc/utmpx + /etc/wtmpx + /etc/cups/certs + /etc/dumpdates + /etc/svc/volatile + + + .log$|.swp$ + + + /etc/ssl/private.key + + yes + yes + yes + yes + + + 10 + + + 200 + + + + yes + 5m + 1h + + + + + + 127.0.0.1 + ^localhost.localdomain$ + 127.0.0.53 + + + + disable-account + disable-account.sh + user + yes + + + + restart-ossec + restart-ossec.sh + + + + + firewall-drop + firewall-drop.sh + srcip + yes + + + + host-deny + host-deny.sh + srcip + yes + + + + route-null + route-null.sh + srcip + yes + + + + win_route-null + route-null.cmd + srcip + yes + + + + win_route-null-2012 + route-null-2012.cmd + srcip + yes + + + + netsh + netsh.cmd + srcip + yes + + + + netsh-win-2016 + netsh-win-2016.cmd + srcip + yes + + + + + + + command + df -P + 360 + + + + full_command + netstat -tulpn | sed 's/\([[:alnum:]]\+\)\ \+[[:digit:]]\+\ \+[[:digit:]]\+\ \+\(.*\):\([[:digit:]]*\)\ \+\([0-9\.\:\*]\+\).\+\ \([[:digit:]]*\/[[:alnum:]\-]*\).*/\1 \2 == \3 == \4 \5/' | sort -k 4 -g | sed 's/ == \(.*\) ==/:\1/' | sed 1,2d + netstat listening ports + 360 + + + + full_command + last -n 20 + 360 + + + + + ruleset/decoders + ruleset/rules + 0215-policy_rules.xml + etc/lists/audit-keys + etc/lists/amazon/aws-eventnames + etc/lists/security-eventchannel + + + etc/decoders + etc/rules + + + + + no + 1515 + no + yes + 0 + yes + no + yes + HIGH:!ADH:!EXP:!MD5:!RC4:!3DES:!CAMELLIA:@STRENGTH + + no + /var/ossec/etc/sslmanager.cert + /var/ossec/etc/sslmanager.key + no + + + + wazuh + node01 + master + + 1516 + 0.0.0.0 + + NODE_IP + + no + yes + + + + + + + syslog + /var/ossec/logs/active-responses.log + + + + syslog + /var/log/auth.log + + + + syslog + /var/log/syslog + + + + syslog + /var/log/dpkg.log + + + + syslog + /var/log/kern.log + + + diff --git a/tests/system/fim/scenario_default_installation/defaults/main.yml b/tests/system/fim/scenarios/scenario_default_installation/defaults/main.yml similarity index 100% rename from tests/system/fim/scenario_default_installation/defaults/main.yml rename to tests/system/fim/scenarios/scenario_default_installation/defaults/main.yml diff --git a/tests/system/fim/scenarios/scenario_default_installation/launch_test_scenario.yml b/tests/system/fim/scenarios/scenario_default_installation/launch_test_scenario.yml new file mode 100644 index 0000000000..dd8ed47ef7 --- /dev/null +++ b/tests/system/fim/scenarios/scenario_default_installation/launch_test_scenario.yml @@ -0,0 +1,48 @@ +--- + - hosts: all + vars_files: + - ../../vars/main.yml + + handlers: + - import_tasks: ../../handlers/main.yml + + tasks: + - block: + - name: Launching prepare tasks + import_tasks: "../../common_tasks/prepare.yml" + + - block: + - name: Configure syscheck event. + set_fact: + event: "added" + + - name: Generating files to trigger FIM alerts + import_tasks: "../../common_tasks/create_files.yml" + + - name: Verify generated alerts + become: true + import_tasks: "../../common_tasks/verify_alerts.yml" + + - block: + - name: Configure syscheck event. + set_fact: + event: "modified" + + - name: Modifiying files to trigger FIM alerts + import_tasks: "../../common_tasks/modify_files.yml" + + - name: Verify generated alerts + become: true + import_tasks: "../../common_tasks/verify_alerts.yml" + + - block: + - name: Configure syscheck event. + set_fact: + event: "deleted" + + - name: Deleting files to trigger FIM alerts + import_tasks: "../../common_tasks/delete_files.yml" + + - name: Verify generated alerts + become: true + import_tasks: "../../common_tasks/verify_alerts.yml" diff --git a/tests/system/fim/scenario_default_installation/tests/files_generated.txt b/tests/system/fim/scenarios/scenario_default_installation/tests/files_generated.txt similarity index 100% rename from tests/system/fim/scenario_default_installation/tests/files_generated.txt rename to tests/system/fim/scenarios/scenario_default_installation/tests/files_generated.txt diff --git a/tests/system/fim/vars/main.yml b/tests/system/fim/vars/main.yml index d858ed2d54..41de455e85 100644 --- a/tests/system/fim/vars/main.yml +++ b/tests/system/fim/vars/main.yml @@ -1,11 +1,34 @@ -# Create files -files_generation_config_path: "config/files_configuration.json" -files_generated_output_path: "tests/files_generated.txt" +# ossec folder path +linux_ossec_folder_path: "/var/ossec" +windows_ossec_folder_path: "C:\\Program Files (x86)\\ossec-agent" -# Modify/Delete/Verify files + +# Create/Modify/Delete files +agents_linux_output_path: "/opt/fim_files_output" +agents_windows_output_path: c:\fim_files_output +files_generated_output_path: "files_generated.txt" +files_modified_output_path: "files_modified.txt" +files_deleted_output_path: "files_deleted.txt" + +# FIM testing folder +files_fim_testing_linux: "/opt/fim_testing" +files_fim_testing_windows: c:\\fim_testing + +### Config files +files_config_source_path: "files_configuration.json" +files_config_linux_destination_path: "/tmp/{{ files_config_source_path }}" +files_config_windows_destination_path: "C:\\{{ files_config_source_path }}" +files_config_manager_ossec_conf: "manager_ossec.conf" +files_config_agent_linux_ossec_conf: "agent_linux_ossec.conf" +files_config_agent_windows_ossec_conf: "agent_windows_ossec.conf" + +### Tests + +syscheck_event: "created" alerts_json_path: "/var/ossec/logs/alerts/alerts.json" -files_modified_output_path: "tests/files_modified.txt" -files_deleted_output_path: "tests/files_deleted.txt" -alert_event: "created" -n_files: 1000 +# Results +agents_results_manager_path: "/opt/agents_files_output" +agents_results_elastic_path: "/opt/agents_files_output" # Path on Manager of the imported results from Agents +missing_alerts_json_path: "missing_alerts_json.txt" +missing_alerts_elasticsearch_path: "missing_alerts_elasticsearch.txt" \ No newline at end of file