From 61625f80eeb199aed791f0e52d9a46aa413a1f11 Mon Sep 17 00:00:00 2001 From: Rshad Zhran Date: Tue, 20 Aug 2019 15:10:17 +0200 Subject: [PATCH] adding new test /molecule/stack --- molecule/stack/Dockerfile.j2 | 14 +++++ molecule/stack/INSTALL.rst | 16 ++++++ molecule/stack/create.yml | 81 ++++++++++++++++++++++++++++ molecule/stack/destroy.yml | 32 +++++++++++ molecule/stack/molecule.yml | 69 ++++++++++++++++++++++++ molecule/stack/playbook.yml | 6 +++ molecule/stack/prepare.yml | 36 +++++++++++++ molecule/stack/tests/test_default.py | 80 +++++++++++++++++++++++++++ 8 files changed, 334 insertions(+) create mode 100644 molecule/stack/Dockerfile.j2 create mode 100644 molecule/stack/INSTALL.rst create mode 100644 molecule/stack/create.yml create mode 100644 molecule/stack/destroy.yml create mode 100644 molecule/stack/molecule.yml create mode 100644 molecule/stack/playbook.yml create mode 100644 molecule/stack/prepare.yml create mode 100644 molecule/stack/tests/test_default.py diff --git a/molecule/stack/Dockerfile.j2 b/molecule/stack/Dockerfile.j2 new file mode 100644 index 00000000..19692c20 --- /dev/null +++ b/molecule/stack/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/stack/INSTALL.rst b/molecule/stack/INSTALL.rst new file mode 100644 index 00000000..e26493b8 --- /dev/null +++ b/molecule/stack/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/stack/create.yml b/molecule/stack/create.yml new file mode 100644 index 00000000..25932aee --- /dev/null +++ b/molecule/stack/create.yml @@ -0,0 +1,81 @@ +--- +- name: Create + hosts: localhost + connection: local + gather_facts: false + no_log: false + tasks: + - name: Log into a Docker registry + docker_login: + username: "{{ item.registry.credentials.username }}" + password: "{{ item.registry.credentials.password }}" + email: "{{ item.registry.credentials.email | default(omit) }}" + registry: "{{ item.registry.url }}" + docker_host: "{{ item.docker_host | default('unix://var/run/docker.sock') }}" + with_items: "{{ molecule_yml.platforms }}" + when: + - item.registry is defined + - item.registry.credentials is defined + - item.registry.credentials.username is defined + + - name: Create Dockerfiles from image names + template: + src: "{{ molecule_scenario_directory }}/Dockerfile.j2" + dest: "{{ molecule_ephemeral_directory }}/Dockerfile_{{ item.image | regex_replace('[^a-zA-Z0-9_]', '_') }}" + with_items: "{{ molecule_yml.platforms }}" + register: platforms + + - name: Discover local Docker images + docker_image_facts: + name: "molecule_local/{{ item.item.name }}" + docker_host: "{{ item.item.docker_host | default('unix://var/run/docker.sock') }}" + with_items: "{{ platforms.results }}" + register: docker_images + + - name: Build an Ansible compatible image + docker_image: + path: "{{ molecule_ephemeral_directory }}" + name: "molecule_local/{{ item.item.image }}" + docker_host: "{{ item.item.docker_host | default('unix://var/run/docker.sock') }}" + dockerfile: "{{ item.item.dockerfile | default(item.invocation.module_args.dest) }}" + force: "{{ item.item.force | default(true) }}" + with_items: "{{ platforms.results }}" + when: platforms.changed or docker_images.results | map(attribute='images') | select('equalto', []) | list | count >= 0 + + - name: Create docker network(s) + docker_network: + name: "{{ item }}" + docker_host: "{{ item.docker_host | default('unix://var/run/docker.sock') }}" + state: present + with_items: "{{ molecule_yml.platforms | molecule_get_docker_networks }}" + + - name: Create molecule instance(s) + docker_container: + name: "{{ item.name }}" + docker_host: "{{ item.docker_host | default('unix://var/run/docker.sock') }}" + hostname: "{{ item.name }}" + image: "molecule_local/{{ item.image }}" + state: started + recreate: false + log_driver: json-file + command: "{{ item.command | default('bash -c \"while true; do sleep 10000; done\"') }}" + privileged: "{{ item.privileged | default(omit) }}" + volumes: "{{ item.volumes | default(omit) }}" + capabilities: "{{ item.capabilities | default(omit) }}" + exposed_ports: "{{ item.exposed_ports | default(omit) }}" + published_ports: "{{ item.published_ports | default(omit) }}" + ulimits: "{{ item.ulimits | default(omit) }}" + networks: "{{ item.networks | default(omit) }}" + dns_servers: "{{ item.dns_servers | default(omit) }}" + register: server + with_items: "{{ molecule_yml.platforms }}" + async: 7200 + poll: 0 + + - name: Wait for instance(s) creation to complete + async_status: + jid: "{{ item.ansible_job_id }}" + register: docker_jobs + until: docker_jobs.finished + retries: 300 + with_items: "{{ server.results }}" diff --git a/molecule/stack/destroy.yml b/molecule/stack/destroy.yml new file mode 100644 index 00000000..ddf7062b --- /dev/null +++ b/molecule/stack/destroy.yml @@ -0,0 +1,32 @@ +--- +- name: Destroy + hosts: localhost + connection: local + gather_facts: false + no_log: false + tasks: + - name: Destroy molecule instance(s) + docker_container: + name: "{{ item.name }}" + docker_host: "{{ item.docker_host | default('unix://var/run/docker.sock') }}" + state: absent + force_kill: "{{ item.force_kill | default(true) }}" + register: server + with_items: "{{ molecule_yml.platforms }}" + async: 7200 + poll: 0 + + - name: Wait for instance(s) deletion to complete + async_status: + jid: "{{ item.ansible_job_id }}" + register: docker_jobs + until: docker_jobs.finished + retries: 300 + with_items: "{{ server.results }}" + + - name: Delete docker network(s) + docker_network: + name: "{{ item }}" + docker_host: "{{ item.docker_host | default('unix://var/run/docker.sock') }}" + state: absent + with_items: "{{ molecule_yml.platforms | molecule_get_docker_networks }}" diff --git a/molecule/stack/molecule.yml b/molecule/stack/molecule.yml new file mode 100644 index 00000000..6a54a846 --- /dev/null +++ b/molecule/stack/molecule.yml @@ -0,0 +1,69 @@ +--- +dependency: + name: galaxy +driver: + name: docker +lint: + name: yamllint + enabled: false +platforms: + - name: bionic + image: solita/ubuntu-systemd:bionic + command: /sbin/init + ulimits: + - nofile:262144:262144 + privileged: true + memory_reservation: 2048m + - name: xenial + image: solita/ubuntu-systemd:xenial + privileged: true + memory_reservation: 2048m + command: /sbin/init + ulimits: + - nofile:262144:262144 +# - name: trusty +# image: ubuntu:trusty +# privileged: true +# memory_reservation: 2048m +# ulimits: +# - nofile:262144:262144 +# - name: centos6 +# image: centos:6 +# privileged: true +# memory_reservation: 2048m +# ulimits: +# - nofile:262144:262144 + - name: centos7 + image: milcom/centos7-systemd + memory_reservation: 2048m + privileged: true + ulimits: + - nofile:262144:262144 +provisioner: + name: ansible + env: + ANSIBLE_ROLES_PATH: ../../roles + lint: + name: ansible-lint + enabled: true +scenario: + name: default + test_sequence: + - lint + - dependency + - cleanup + - destroy + - syntax + - create + - prepare + - converge + - idempotence + - side_effect + - verify + - cleanup + - destroy +verifier: + name: testinfra + lint: + name: flake8 + enabled: true diff --git a/molecule/stack/playbook.yml b/molecule/stack/playbook.yml new file mode 100644 index 00000000..242a3777 --- /dev/null +++ b/molecule/stack/playbook.yml @@ -0,0 +1,6 @@ +--- +- name: Converge + hosts: all + roles: + - role: wazuh/ansible-wazuh-manager + diff --git a/molecule/stack/prepare.yml b/molecule/stack/prepare.yml new file mode 100644 index 00000000..f3dc9aac --- /dev/null +++ b/molecule/stack/prepare.yml @@ -0,0 +1,36 @@ +--- +- name: Prepare + hosts: all + gather_facts: true + tasks: + + - name: "Install Python packages for Trusty to solve trust issues" + package: + name: + - python-setuptools + - python-pip + state: latest + register: wazuh_manager_trusty_packages_installed + until: wazuh_manager_trusty_packages_installed is succeeded + when: + - ansible_distribution == "Ubuntu" + - ansible_distribution_major_version | int == 14 + + - name: "Install dependencies" + package: + name: + - curl + - net-tools + state: latest + register: wazuh_manager_dependencies_packages_installed + until: wazuh_manager_dependencies_packages_installed is succeeded + + - name: "Install (RedHat) dependencies" + package: + name: + - initscripts + state: latest + register: wazuh_manager_dependencies_packages_installed + until: wazuh_manager_dependencies_packages_installed is succeeded + when: + - ansible_os_family == 'RedHat' diff --git a/molecule/stack/tests/test_default.py b/molecule/stack/tests/test_default.py new file mode 100644 index 00000000..c5e76d67 --- /dev/null +++ b/molecule/stack/tests/test_default.py @@ -0,0 +1,80 @@ +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.9.5" + + +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 not 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:1515").is_listening + assert host.socket("tcp://0.0.0.0:1514").is_listening + elif distribution == 'centos': + assert host.socket("tcp://127.0.0.1:1515").is_listening + assert host.socket("tcp://127.0.0.1:1514").is_listening