diff --git a/.github/actions/default/Dockerfile b/.github/actions/default/Dockerfile new file mode 100644 index 00000000..8f8a6825 --- /dev/null +++ b/.github/actions/default/Dockerfile @@ -0,0 +1,47 @@ +FROM python:3.7-alpine + +LABEL "com.github.actions.name"="molecule" +LABEL "com.github.actions.description"="Run Ansible Molecule" +LABEL "com.github.actions.icon"="upload" +LABEL "com.github.actions.color"="green" + +ARG BUILD_DEPS="\ + gcc \ + libc-dev \ + make \ + musl-dev \ + libffi-dev \ + openssl-dev \ + " + +ARG PACKAGES="\ + docker \ + git \ + openssh-client \ + " + +ARG PIP_INSTALL_ARGS="\ + --no-cache-dir \ + " + +# ARG PIP_MODULES="\ +# netaddr \ +# " + +ARG MOLECULE_EXTRAS="docker" + +RUN apk add --update --no-cache ${BUILD_DEPS} ${PACKAGES} && \ + pip install ${PIP_INSTALL_ARGS} ${PIP_MODULES} "molecule[${MOLECULE_EXTRAS}]" && \ + apk del --no-cache ${BUILD_DEPS} && \ + rm -rf /root/.cache + +# CMD cd ${GITHUB_REPOSITORY}; molecule ${INPUT_MOLECULE_OPTIONS} ${INPUT_MOLECULE_COMMAND} ${INPUT_MOLECULE_ARGS} +# Adding systemd compatibility. +WORKDIR ${GITHUB_REPOSITORY} + +VOLUME [ "/sys/fs/cgroup", "/run", "/run/lock" ] + +COPY ./entrypoint.sh /entrypoint.sh +RUN chmod 755 /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] + diff --git a/.github/actions/default/action.yml b/.github/actions/default/action.yml new file mode 100644 index 00000000..a9b38478 --- /dev/null +++ b/.github/actions/default/action.yml @@ -0,0 +1,6 @@ +name: molecule-test +description: Molecule tests for Wazuh Ansible +runs: + using: docker + image: 'Dockerfile' + diff --git a/.github/actions/default/entrypoint.sh b/.github/actions/default/entrypoint.sh new file mode 100644 index 00000000..2c9d19ac --- /dev/null +++ b/.github/actions/default/entrypoint.sh @@ -0,0 +1,5 @@ +#! /usr/bin/env bash +set -e + +cd molecule +molecule test -s default \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..b32150da --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,13 @@ + +name: Molecule tests for Wazuh Ansible + +on: [push] + +jobs: + testing: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v2 + - name: Default scenario + uses: './.github/actions/default' diff --git a/molecule/default/Dockerfile.j2 b/molecule/default/Dockerfile.j2 new file mode 100644 index 00000000..19692c20 --- /dev/null +++ b/molecule/default/Dockerfile.j2 @@ -0,0 +1,14 @@ +# Molecule managed + +{% if item.registry is defined %} +FROM {{ item.registry.url }}/{{ item.image }} +{% else %} +FROM {{ item.image }} +{% endif %} + +RUN if [ $(command -v apt-get) ]; then apt-get update && apt-get upgrade -y && apt-get install -y python sudo bash ca-certificates && apt-get clean; \ + elif [ $(command -v dnf) ]; then dnf makecache && dnf --assumeyes install python sudo python-devel python2-dnf bash && dnf clean all; \ + elif [ $(command -v yum) ]; then yum makecache fast && yum update -y && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && yum clean all; \ + elif [ $(command -v zypper) ]; then zypper refresh && zypper update -y && zypper install -y python sudo bash python-xml && zypper clean -a; \ + elif [ $(command -v apk) ]; then apk update && apk add --no-cache python sudo bash ca-certificates; \ + elif [ $(command -v xbps-install) ]; then xbps-install -Syu && xbps-install -y python sudo bash ca-certificates && xbps-remove -O; fi diff --git a/molecule/default/INSTALL.rst b/molecule/default/INSTALL.rst new file mode 100644 index 00000000..e26493b8 --- /dev/null +++ b/molecule/default/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/default/molecule.yml b/molecule/default/molecule.yml new file mode 100644 index 00000000..fe4505f3 --- /dev/null +++ b/molecule/default/molecule.yml @@ -0,0 +1,44 @@ +--- +dependency: + name: galaxy +driver: + name: docker +lint: + name: yamllint + enabled: false +platforms: + - name: manager_centos7 + image: milcom/centos7-systemd + command: /sbin/init + ulimits: + - nofile:262144:262144 + privileged: true + memory_reservation: 2048m +provisioner: + name: ansible + config_options: + defaults: + hash_behaviour: merge + env: + ANSIBLE_ROLES_PATH: ./roles + lint: + name: ansible-lint + enabled: true +scenario: + name: default + test_sequence: + - lint + - dependency + - syntax + - create + - prepare + - converge + - idempotence + - verify + - cleanup + - destroy +verifier: + name: testinfra + lint: + name: flake8 + enabled: true diff --git a/molecule/default/playbook.yml b/molecule/default/playbook.yml new file mode 100644 index 00000000..dc93196e --- /dev/null +++ b/molecule/default/playbook.yml @@ -0,0 +1,19 @@ +--- +- name: Converge + hosts: all + roles: + - role: wazuh/ansible-wazuh-manager + vars: + wazuh_manager_config: + cluster: + disable: 'no' + name: 'wazuh' + node_name: 'manager' + node_type: 'master' + key: 'ugdtAnd7Pi9myP7CVts4qZaZQEQcRYZa' + port: '1516' + bind_addr: '0.0.0.0' + nodes: + - "manager_{{ lookup('env', 'MOL_PLATFORM') or 'centos7' }}" + hidden: 'no' + - { role: wazuh/ansible-filebeat, filebeat_output_elasticsearch_hosts: "elasticsearch_{{ lookup('env', 'MOL_PLATFORM') or 'centos7' }}:9200" } diff --git a/molecule/default/tests/test_default.py b/molecule/default/tests/test_default.py new file mode 100644 index 00000000..88edc8a9 --- /dev/null +++ b/molecule/default/tests/test_default.py @@ -0,0 +1,89 @@ +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 "3.10.2" + + +def test_wazuh_packages_are_installed(host): + """Test if the main packages are installed.""" + manager = host.package("wazuh-manager") + api = host.package("wazuh-api") + + distribution = host.system_info.distribution.lower() + if distribution == 'centos': + if host.system_info.release == "7": + assert manager.is_installed + assert manager.version.startswith(get_wazuh_version()) + assert api.is_installed + assert api.version.startswith(get_wazuh_version()) + elif host.system_info.release.startswith("6"): + assert manager.is_installed + assert manager.version.startswith(get_wazuh_version()) + elif distribution == 'ubuntu': + assert manager.is_installed + assert manager.version.startswith(get_wazuh_version()) + + +def test_wazuh_services_are_running(host): + """Test if 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 + """ + manager = host.service("wazuh-manager") + api = host.service("wazuh-api") + + distribution = host.system_info.distribution.lower() + if distribution == 'centos': + # assert manager.is_running + assert manager.is_enabled + # assert not api.is_running + assert api.is_enabled + elif distribution == 'ubuntu': + # assert manager.is_running + assert manager.is_enabled + # assert api.is_running + assert api.is_enabled + + +@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", "root", "ossec", 0o640), + ("/var/ossec/etc/lists/audit-keys", "root", "ossec", 0o640), +]) +def test_wazuh_files(host, wazuh_file, wazuh_owner, wazuh_group, wazuh_mode): + """Test if 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_open_ports(host): + """Test if the main port is open and the agent-auth is not open.""" + distribution = host.system_info.distribution.lower() + if distribution == 'ubuntu': + assert host.socket("tcp://0.0.0.0:1516").is_listening + assert host.socket("tcp://0.0.0.0:1515").is_listening + assert host.socket("tcp://0.0.0.0:1514").is_listening + elif distribution == 'centos': + assert host.socket("tcp://0.0.0.0:1516").is_listening + assert host.socket("tcp://127.0.0.1:1515").is_listening + assert host.socket("tcp://127.0.0.1:1514").is_listening + + +def test_filebeat_is_installed(host): + """Test if the elasticsearch package is installed.""" + filebeat = host.package("filebeat") + assert filebeat.is_installed + assert filebeat.version.startswith('7.3.2')