From 3a45bcc989398cc164171043eb5bd77c6ac1a4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A2=85?= Date: Fri, 6 Nov 2020 13:16:29 -0300 Subject: [PATCH] molecule: add distributed-wazuh-odfe scenario, which tests a distributed wazuh+odfe stack with 2 agents. This test will not pass until opendistro-elastic role receives updates for how it determines when to run initial users tasks at security_actions.yml --- molecule/distributed-wazuh-odfe/INSTALL.rst | 16 ++ molecule/distributed-wazuh-odfe/converge.yml | 75 ++++++++ .../group_vars/agents.yml | 25 +++ .../distributed-wazuh-odfe/group_vars/all.yml | 37 ++++ .../group_vars/elastic.yml | 16 ++ .../group_vars/kibana.yml | 17 ++ .../group_vars/managers.yml | 19 ++ molecule/distributed-wazuh-odfe/molecule.yml | 162 ++++++++++++++++++ .../tests/test_default.py | 64 +++++++ 9 files changed, 431 insertions(+) create mode 100644 molecule/distributed-wazuh-odfe/INSTALL.rst create mode 100644 molecule/distributed-wazuh-odfe/converge.yml create mode 100644 molecule/distributed-wazuh-odfe/group_vars/agents.yml create mode 100644 molecule/distributed-wazuh-odfe/group_vars/all.yml create mode 100644 molecule/distributed-wazuh-odfe/group_vars/elastic.yml create mode 100644 molecule/distributed-wazuh-odfe/group_vars/kibana.yml create mode 100644 molecule/distributed-wazuh-odfe/group_vars/managers.yml create mode 100644 molecule/distributed-wazuh-odfe/molecule.yml create mode 100644 molecule/distributed-wazuh-odfe/tests/test_default.py diff --git a/molecule/distributed-wazuh-odfe/INSTALL.rst b/molecule/distributed-wazuh-odfe/INSTALL.rst new file mode 100644 index 00000000..e26493b8 --- /dev/null +++ b/molecule/distributed-wazuh-odfe/INSTALL.rst @@ -0,0 +1,16 @@ +******* +Install +******* + +Requirements +============ + +* Docker Engine +* docker-py + +Install +======= + +.. code-block:: bash + + $ sudo pip install docker-py diff --git a/molecule/distributed-wazuh-odfe/converge.yml b/molecule/distributed-wazuh-odfe/converge.yml new file mode 100644 index 00000000..874df159 --- /dev/null +++ b/molecule/distributed-wazuh-odfe/converge.yml @@ -0,0 +1,75 @@ +--- + +- name: Build Facts + hosts: all + become: true + become_user: root + vars: + endpoints_hostvars: '{{ managers_hostvars | union(elastic_hostvars) | union(kibana_hostvars) }}' + wazuh_managers_common: + port: 1514 + protocol: tcp + api_port: 55000 + api_proto: 'http' + api_user: ansible + max_retries: 5 + retry_interval: 5 + pre_tasks: + - name: (converge) build instances list dynamically for cert generator consumption + set_fact: + odfe_endpoint_list: "{{ odfe_endpoint_list | default({}) | combine({ instance_hostname: instance_item }) }}" + vars: + instance_hostname: '{{ item.ansible_facts.hostname }}' + instance_item: + name: '{{ instance_hostname }}' + ip: '{{ item.private_ip }}' + loop: '{{ endpoints_hostvars }}' + no_log: true + + - name: (converge) build wazuh_managers list dynamically for agents to consume + set_fact: + wazuh_managers_list: '{{ wazuh_managers_list | default([]) | union([manager_item]) }}' + vars: + manager_item: '{{ wazuh_managers_common | combine({"address": item}) }}' + loop: '{{ manager_addresses }}' + + - name: overview of cert configuration + debug: + var: odfe_endpoint_list + +- name: Generate certificates prior to converging + hosts: molecule_odfe_elasticsearch_centos7 + become: true + become_user: root + roles: + - role: ../../roles/opendistro/opendistro-elasticsearch + vars: + generate_certs: true + perform_installation: false + instances: '{{ odfe_endpoint_list }}' + pre_tasks: + - name: overview of cert configuration + debug: + var: odfe_endpoint_list + +- name: Converge + hosts: all + become: true + become_user: root + roles: + # 1. Elasticsearch + - role: ../../roles/opendistro/opendistro-elasticsearch + when: inventory_hostname in groups['elastic'] + # 2. Managers + - role: ../../roles/wazuh/ansible-wazuh-manager + when: inventory_hostname in groups['managers'] + - role: ../../roles/wazuh/ansible-filebeat-oss + when: inventory_hostname in groups['managers'] + # 3. Kibana + - role: ../../roles/opendistro/opendistro-kibana + when: inventory_hostname in groups['kibana'] + # 4. Agents: + - role: ../../roles/wazuh/ansible-wazuh-agent + vars: + wazuh_managers: '{{ wazuh_managers_list }}' + when: inventory_hostname in groups['agents'] \ No newline at end of file diff --git a/molecule/distributed-wazuh-odfe/group_vars/agents.yml b/molecule/distributed-wazuh-odfe/group_vars/agents.yml new file mode 100644 index 00000000..9fc66524 --- /dev/null +++ b/molecule/distributed-wazuh-odfe/group_vars/agents.yml @@ -0,0 +1,25 @@ +--- + +wazuh_agent_config: + enrollment: + enabled: 'yes' + #manager_address: '' + #port: 1515 + agent_name: '{{ ansible_hostname }}' + #groups: '' + #agent_address: '' + #ssl_cipher: HIGH:!ADH:!EXP:!MD5:!RC4:!3DES:!CAMELLIA:@STRENGTH + #server_ca_path: '' + #agent_certificate_path: '' + #agent_key_path: '' + #authorization_pass_path : /var/ossec/etc/authd.pass + #auto_method: 'no' + #delay_after_enrollment: 20 + #use_source_ip: 'no' + +wazuh_agent_authd: + registration_address: '{{ manager_addresses[0] }}' + enable: true + port: 1515 + ssl_agent_ca: null + ssl_auto_negotiate: 'no' \ No newline at end of file diff --git a/molecule/distributed-wazuh-odfe/group_vars/all.yml b/molecule/distributed-wazuh-odfe/group_vars/all.yml new file mode 100644 index 00000000..998bbbb5 --- /dev/null +++ b/molecule/distributed-wazuh-odfe/group_vars/all.yml @@ -0,0 +1,37 @@ +--- + +######################################################## +# Helper variables +private_ip: '{{ ansible_default_ipv4.address }}' + +managers_hostvars: "{{ groups['managers'] | map('extract', hostvars) | list }}" +elastic_hostvars: "{{ groups['elastic'] | map('extract', hostvars) | list }}" +kibana_hostvars: "{{ groups['kibana'] | map('extract', hostvars) | list }}" + +manager_addresses: "{{ managers_hostvars | map(attribute='private_ip') | list }}" +elastic_addresses: "{{ elastic_hostvars | map(attribute='private_ip') | list }}" +kibana_addresses: "{{ kibana_hostvars | map(attribute='private_ip') | list }}" + +######################################################## +# General ELK stack variables + +# Cluster Settings +#es_version: "7.9.1" +#es_major_version: "7.x" +#opendistro_version: 1.10.1 +filebeat_version: 7.9.1 + +# OpenDistro +kibana_opendistro_security: true + +opendistro_kibana_user: kibanaserver +opendistro_security_user: elastic + +opendistro_kibana_password: changeme +opendistro_security_password: admin +opendistro_admin_password: changeme + +# All nodes are called by IP name +elasticsearch_node_name: '{{ ansible_hostname }}' +kibana_node_name: '{{ ansible_hostname }}' +filebeat_node_name: '{{ ansible_hostname }}' \ No newline at end of file diff --git a/molecule/distributed-wazuh-odfe/group_vars/elastic.yml b/molecule/distributed-wazuh-odfe/group_vars/elastic.yml new file mode 100644 index 00000000..056f5184 --- /dev/null +++ b/molecule/distributed-wazuh-odfe/group_vars/elastic.yml @@ -0,0 +1,16 @@ +--- + +single_node: false +elasticsearch_node_master: true +minimum_master_nodes: 1 + +elasticsearch_network_host: '{{ private_ip }}' + +elasticsearch_reachable_host: '{{ private_ip }}' +elasticsearch_http_port: 9200 + +elasticsearch_bootstrap_node: true +elasticsearch_cluster_nodes: '{{ elastic_addresses }}' +elasticsearch_discovery_nodes: '{{ elastic_addresses }}' + +opendistro_jvm_xms: 1024 diff --git a/molecule/distributed-wazuh-odfe/group_vars/kibana.yml b/molecule/distributed-wazuh-odfe/group_vars/kibana.yml new file mode 100644 index 00000000..5101d76a --- /dev/null +++ b/molecule/distributed-wazuh-odfe/group_vars/kibana.yml @@ -0,0 +1,17 @@ +--- + +kibana_server_name: '{{ ansible_hostname }}' +elasticsearch_network_host: "{{ elastic_addresses[0] }}" +#elasticsearch_http_port: 9200 + +elasticsearch_node_master: false +elasticsearch_node_ingest: false +elasticsearch_node_data: false + +wazuh_api_credentials: + - id: default + url: 'https://{{ manager_addresses[0] }}' + port: 55000 + #port: 1514 + username: wazuh + password: wazuh diff --git a/molecule/distributed-wazuh-odfe/group_vars/managers.yml b/molecule/distributed-wazuh-odfe/group_vars/managers.yml new file mode 100644 index 00000000..4f15afd5 --- /dev/null +++ b/molecule/distributed-wazuh-odfe/group_vars/managers.yml @@ -0,0 +1,19 @@ +--- + +wazuh_manager_fqdn: '{{ ansible_hostname }}' +filebeat_output_elasticsearch_hosts: '{{ elastic_addresses }}' + +wazuh_manager_config: + connection: + - type: 'secure' + port: '1514' + protocol: 'tcp' + queue_size: 131072 + api: + https: 'yes' + cluster: + disable: 'no' + node_name: '{{ ansible_hostname }}' + node_type: "{{ 'master' if ansible_hostname == 'wazuh-mgr01' else 'worker' }}" + nodes: '{{ manager_addresses }}' + hidden: 'no' \ No newline at end of file diff --git a/molecule/distributed-wazuh-odfe/molecule.yml b/molecule/distributed-wazuh-odfe/molecule.yml new file mode 100644 index 00000000..46c08695 --- /dev/null +++ b/molecule/distributed-wazuh-odfe/molecule.yml @@ -0,0 +1,162 @@ +--- +# Distributed scenario: clustered manager scenario + connected agents +# 2-core CPU +# 7 GB of RAM memory +# 14 GB of SSD disk space +# +# Source: https://docs.github.com/en/free-pro-team@latest/actions/reference/specifications-for-github-hosted-runners + +dependency: + name: galaxy +driver: + name: docker +lint: | + yamllint . + ansible-lint roles + flake8 molecule +platforms: + ################################################ + # Wazuh Managers + ################################################ + - name: molecule_odfe_manager_centos7 + hostname: wazuh-mgr01 + image: geerlingguy/docker-centos7-ansible + command: /sbin/init + pre_build_image: true + privileged: true + memory_reservation: 512m + memory: 1024m + groups: + - managers + ulimits: + - nofile:262144:262144 + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + + - name: molecule_odfe_manager_debian9 + hostname: wazuh-mgr02 + image: geerlingguy/docker-debian9-ansible + command: /sbin/init + pre_build_image: true + privileged: true + memory_reservation: 512m + memory: 1024m + groups: + - managers + ulimits: + - nofile:262144:262144 + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + + ################################################ + # Elastic Cluster + ################################################ + - name: molecule_odfe_elasticsearch_centos7 + hostname: wazuh-es01 + image: geerlingguy/docker-centos7-ansible + command: /sbin/init + pre_build_image: true + privileged: true + memory: 4096m + memory_reservation: 2048m + groups: + - elastic + ulimits: + - nofile:262144:262144 + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + + - name: molecule_odfe_elasticsearch_centos7_2 + hostname: wazuh-es02 + image: geerlingguy/docker-centos7-ansible + command: /sbin/init + pre_build_image: true + privileged: true + memory: 4096m + memory_reservation: 2048m + groups: + - elastic + ulimits: + - nofile:262144:262144 + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + + ################################################ + # Wazuh Agents + ################################################ + - name: molecule_odfe_agent_centos7 + hostname: wazuh-agent01 + image: geerlingguy/docker-centos7-ansible + command: /sbin/init + pre_build_image: true + privileged: true + memory: 1024m + memory_reservation: 512m + groups: + - agents + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + + - name: molecule_odfe_agent_debian9 + hostname: wazuh-agent02 + image: geerlingguy/docker-debian9-ansible + command: /sbin/init + pre_build_image: true + privileged: true + memory: 1024m + memory_reservation: 512m + groups: + - agents + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + + ################################################ + # Kibana + ################################################ + + - name: molecule_odfe_kibana_centos7 + hostname: wazuh-kib01 + image: geerlingguy/docker-centos7-ansible + command: /sbin/init + pre_build_image: true + privileged: true + memory: 2048m + memory_reservation: 512m + groups: + - kibana + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:ro + +provisioner: + name: ansible + ansible_args: + - -vv + inventory: + links: + group_vars: group_vars + playbooks: + create: create.yml + converge: converge.yml + #destroy: destroy.yml + config_options: + defaults: + hash_behaviour: merge + env: + ANSIBLE_ROLES_PATH: ./roles + lint: + name: ansible-lint + enabled: false +scenario: + name: distributed-wazuh-odfe + test_sequence: + - dependency + - syntax + - create + - prepare + - converge + #- idempotence + #- verify + - cleanup + - destroy +verifier: + name: testinfra \ No newline at end of file diff --git a/molecule/distributed-wazuh-odfe/tests/test_default.py b/molecule/distributed-wazuh-odfe/tests/test_default.py new file mode 100644 index 00000000..a6a86674 --- /dev/null +++ b/molecule/distributed-wazuh-odfe/tests/test_default.py @@ -0,0 +1,64 @@ +import os +import pytest +import testinfra.utils.ansible_runner + +testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( + os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') + + +def get_wazuh_version(): + """This return the version of Wazuh.""" + return "4.0.0" + + +def test_wazuh_packages_are_installed(host): + """Test the main packages are installed.""" + manager = host.package("wazuh-manager") + assert manager.is_installed + assert manager.version.startswith(get_wazuh_version()) + + +def test_wazuh_services_are_running(host): + """Test the services are enabled and running. + + When assert commands are commented, this means that the service command has + a wrong exit code: https://github.com/wazuh/wazuh-ansible/issues/107 + """ + # This currently doesn't work with out current Docker base images + # manager = host.service("wazuh-manager") + # api = host.service("wazuh-api") + # assert manager.is_running + # assert api.is_running + output = host.check_output( + 'ps aux | grep ossec | tr -s " " | cut -d" " -f11' + ) + assert 'ossec-authd' in output + assert 'wazuh-modulesd' in output + assert 'wazuh-db' in output + assert 'ossec-execd' in output + assert 'ossec-monitord' in output + assert 'ossec-remoted' in output + assert 'ossec-logcollector' in output + assert 'ossec-analysisd' in output + assert 'ossec-syscheckd' in output + + +@pytest.mark.parametrize("wazuh_file, wazuh_owner, wazuh_group, wazuh_mode", [ + ("/var/ossec/etc/sslmanager.cert", "root", "root", 0o640), + ("/var/ossec/etc/sslmanager.key", "root", "root", 0o640), + ("/var/ossec/etc/rules/local_rules.xml", "ossec", "ossec", 0o640), + ("/var/ossec/etc/lists/audit-keys", "ossec", "ossec", 0o660), +]) +def test_wazuh_files(host, wazuh_file, wazuh_owner, wazuh_group, wazuh_mode): + """Test Wazuh related files exist and have proper owners and mode.""" + wazuh_file_host = host.file(wazuh_file) + assert wazuh_file_host.user == wazuh_owner + assert wazuh_file_host.group == wazuh_group + assert wazuh_file_host.mode == wazuh_mode + + +def test_filebeat_is_installed(host): + """Test the elasticsearch package is installed.""" + filebeat = host.package("filebeat") + assert filebeat.is_installed + assert filebeat.version.startswith('7.9.1')