Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

molecule tests #19

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0e30e09
install python3.7 in prepare.yml
Jun 19, 2024
b006aa9
trigger workflow
abhi8080 Jul 1, 2024
57424cc
change python version
abhi8080 Jul 1, 2024
9d528ea
extract version number from variable
abhi8080 Jul 6, 2024
e377cee
remove condition since the variables cannot be compared
abhi8080 Jul 6, 2024
9a3dc1b
make idempotence pass
abhi8080 Jul 6, 2024
c244c56
make all tasks pass
abhi8080 Jul 6, 2024
38227e0
write molecule tests
abhi8080 Jul 6, 2024
894bb15
add condition
abhi8080 Jul 8, 2024
7dd6d14
upgrade to version 8 and fix so that role passes
abhi8080 Jul 8, 2024
64accdf
fix github actions
abhi8080 Jul 8, 2024
a0ea47e
update workflow
abhi8080 Jul 8, 2024
cf584ee
make workflow pass
abhi8080 Jul 8, 2024
461f5f1
change remote_tmp
abhi8080 Jul 8, 2024
6ebafd0
change remote user
abhi8080 Jul 8, 2024
33846ce
debugging
abhi8080 Jul 8, 2024
0bb06f0
change gather_facts
abhi8080 Jul 8, 2024
7f81f9b
change ubuntu version
abhi8080 Jul 8, 2024
2692249
debugging
abhi8080 Jul 9, 2024
063b027
fix typo
abhi8080 Jul 9, 2024
f4dcdbc
update molecule.yml to make github actions pass
abhi8080 Jul 12, 2024
5af081b
run molecule as root in github actions
abhi8080 Jul 12, 2024
c97e643
update to run with correct sudo
abhi8080 Jul 12, 2024
5d94f0b
add sudo when installing
abhi8080 Jul 12, 2024
15ec3db
add debugging information
abhi8080 Jul 12, 2024
fa53877
remove sudo
abhi8080 Jul 12, 2024
9a8b56c
fix so that the container is created
abhi8080 Jul 12, 2024
548a422
add back sudo, but runs on a different image
abhi8080 Jul 12, 2024
f9e2cff
remove sudo
abhi8080 Jul 12, 2024
76c6bb8
fix so that the role can be run without being root
abhi8080 Jul 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 7 additions & 25 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
---

name: CI

on: # yamllint disable-line rule:truthy
Expand All @@ -17,44 +15,28 @@ on: # yamllint disable-line rule:truthy

jobs:
molecule:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
strategy:
matrix:
distro:
- image: jrei/systemd-ubuntu:16.04
instance: systemd-ubuntu-16.04
- image: jrei/systemd-ubuntu:18.04
instance: systemd-ubuntu-18.04
- image: jrei/systemd-ubuntu:20.04
instance: systemd-ubuntu-20.04
# - image: jrei/systemd-centos:7
# instance: systemd-centos-7
# - image: jrei/systemd-centos:8
# instance: systemd-centos-8
# - image: jrei/systemd-debian:9
# instance: systemd-debian-9
# - image: jrei/systemd-debian:10
# instance: systemd-debian-10
beats_flavor:
- auditbeat
- filebeat
- heartbeat
- journalbeat
- metricbeat
- packetbeat
- winlogbeat
steps:
- uses: actions/checkout@v2

- name: Setup Python
uses: actions/[email protected]
uses: actions/setup-python@v2
with:
python-version: '3.12'

- name: Install molecule
run: pip3 install molecule[ansible,ansible-base,docker,lint]
run: pip3 install ansible molecule molecule-docker

- name: Run molecule
- name: Run molecule test
run: molecule test
env:
MOLECULE_DISTRO: ${{ matrix.distro.image }}
MOLECULE_INSTANCE_NAME: ${{ matrix.distro.instance }}
MOLECULE_BEATS_FLAVOR: ${{ matrix.beats_flavor }}
MOLECULE_BEATS_FLAVOR: ${{ matrix.beats_flavor }}
2 changes: 1 addition & 1 deletion handlers/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

- name: "{{ beats_flavor }}: Check that beats service has started successfully"
assert:
that: "ansible_facts.services['{{ beats_service_name }}.service']['state'] == 'running'"
that: "ansible_facts.services[beats_service_name + '.service']['state'] == 'running'"
msg: "{{ beats_service_name }}.service failed to start"
listen: beats-restart-service
when:
Expand Down
2 changes: 1 addition & 1 deletion molecule/default/converge-vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ beats_flavor: "{{ lookup('env', 'MOLECULE_BEATS_FLAVOR') | default('auditbeat',
beats_unset_facts: true

# Installation
beats_major_version: 7
beats_major_version: 8
beats_minor_version: "{{ '*' if beats_flavor != 'winlogbeat' else '12' }}"
beats_patch_version: "{{ '*' if beats_flavor != 'winlogbeat' else '0' }}"
beats_enable_service: true
Expand Down
21 changes: 16 additions & 5 deletions molecule/default/molecule.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
---

dependency:
name: galaxy
driver:
Expand All @@ -10,21 +9,33 @@ lint: |
ansible-lint -c molecule/default/ansible-lint.yml .
flake8
platforms:
- name: "${MOLECULE_INSTANCE_NAME:-systemd-ubuntu-18.04}"
image: "${MOLECULE_DISTRO:-jrei/systemd-ubuntu:18.04}"
- name: "${MOLECULE_INSTANCE_NAME:-systemd-ubuntu-20.04}"
image: "${MOLECULE_DISTRO:-jrei/systemd-ubuntu:20.04}"
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
- /sys/fs/cgroup:/sys/fs/cgroup:rw
published_ports:
- '5067:5067/tcp'
command: /lib/systemd/systemd
command: /usr/sbin/init
privileged: true
pre_build_image: true
provisioner:
name: ansible
config_options:
defaults:
duplicate_dict_key: error
any_unparsed_is_failed: true
unparsed_is_failed: true
any_errors_fatal: true
remote_tmp: /tmp
local_tmp: /tmp
options:
vvv: true
env:
IN_MOLECULE: 'true'
scenario:
name: default
create_sequence:
- dependency
- create
verifier:
name: ansible
15 changes: 11 additions & 4 deletions molecule/default/prepare.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
---

- name: Prepare
hosts: all
gather_facts: false
gather_facts: true
roles:
- nkakouros.easyrsa
pre_tasks:
- name: Install python
raw: apt update; apt install -y python3
- name: Install sudo
raw: apt install -y sudo
- name: Ensure /etc/easyrsa/pki directory exists
file:
path: /etc/easyrsa/pki
state: directory
- name: Gathering Facts
setup:
vars:
easyrsa_servers:
- name: elastic
Expand All @@ -27,4 +33,5 @@

easyrsa_download: []
easyrsa_download_pki: true
easyrsa_download_dir: '~/'
easyrsa_download_dir: '~'
ansible_user_id: "{{ lookup('pipe', 'id -un') }}"
201 changes: 199 additions & 2 deletions molecule/default/verify.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
---

# TODO add more tests here

- name: Verify
hosts: all
vars:
role_path: ../../
beats_service_name: "{{ beats_flavor if beats_flavor != 'heartbeat'
else 'heartbeat-elastic' }}{{
'@' + beats_installation_name
if beats_installation_name != 'default'
else ''
}}"
role_name: ansible-role-beats
vars_files:
- "{{ role_path }}/defaults/main.yml"
- converge-vars.yml
pre_tasks:
- import_tasks: "{{ role_path }}/tasks/variables.yml"
- import_tasks: "{{ role_path }}/tasks/core/version.yml"
tasks:
- name: Check http monitoring is on
wait_for:
Expand All @@ -26,3 +32,194 @@
when: beats_flavor == 'filebeat'
register: _result
failed_when: not _result.stat.exists | bool

- name: Tasks specific to Linux systems
block:
- name: Tasks specific to Debian systems
block:
- name: "{{ beats_flavor }}: Check if dependencies are installed"
command: dpkg -s {{ item }}
register: result
failed_when: "'installed' not in result.stdout"
loop: "{{ _beats_packages['all'] | union(_beats_packages[beats_flavor] | default([])) }}"

- name: Check that apt-transport-https is installed
command: dpkg -s apt-transport-https
register: result
failed_when: "'installed' not in result.stdout"

- name: Tasks excluding winlogbeat
block:
- name: Check that the Elastic repository key is added
command: apt-key finger
register: result
failed_when: "'4609 5ACC 8548 582C 1A26 99A9 D27D 666C D88E 42B4' not in result.stdout"

- name: Check that the Elastic repository is added
command: grep -r 'https://artifacts.elastic.co/packages/' /etc/apt/sources.list.d/
register: result
failed_when: "'https://artifacts.elastic.co/packages/' not in result.stdout"

- name: Check that {{ beats_flavor }} is installed
command: dpkg -s {{ beats_flavor if beats_flavor != 'heartbeat' else 'heartbeat-elastic' }}
register: result
failed_when: "'installed' not in result.stdout"

- name: Check that automatic updates are disabled for {{ beats_flavor }}
command: cat /etc/apt/apt.conf.d/55beats-disable
register: result
failed_when: beats_flavor not in result.stdout
when: beats_disable_auto_update | bool
when: beats_flavor != 'winlogbeat'
when: ansible_os_family == 'Debian'

- name: Check that the certificates directory exists
stat:
path: "{{ beats_certificates_dir }}"
register: result
failed_when: not result.stat.exists or not result.stat.isdir

- name: Check that the certificates are uploaded
stat:
path: "{{ beats_certificates_dir }}/{{ item.value | basename }}"
register: result
failed_when: not result.stat.exists or not result.stat.isreg
loop: "{{ beats_certificates | dict2items }}"
loop_control:
loop_var: item

- name: Check that the environment variables file exists and has correct permissions
stat:
path: "{{ beats_path_config }}/{{ beats_installation_name }}.env.vars"
register: result
failed_when: not result.stat.exists or not result.stat.isreg or result.stat.mode != '0644'

- name: Check that the systemd override file directory exists and has correct permissions
stat:
path: "/etc/systemd/system/{{ beats_service_name }}.service.d/"
register: result
failed_when: not result.stat.exists or not result.stat.isdir or result.stat.mode != '0755'
when: beats_systemd_override is not none

- name: Check that the systemd override file exists and has correct permissions
stat:
path: "/etc/systemd/system/{{ beats_service_name }}.service.d/{{ role_name }}.override.conf"
register: result
failed_when: not result.stat.exists or not result.stat.isreg or result.stat.mode != '0644' or result.stat.gr_name != 'root' or result.stat.pw_name != 'root'
when: beats_systemd_override is not none

- name: Check that the instatiate-able service file exists and has correct permissions
stat:
path: "/etc/systemd/system/{{ beats_flavor if beats_flavor != 'heartbeat' else 'heartbeat-elastic' }}@.service"
register: result
failed_when: not result.stat.exists or not result.stat.isreg or result.stat.mode != '0644'
when: beats_installation_name != 'default'


- name: Check that the configuration file is present with correct permissions
stat:
path: "{{ beats_path_config }}/{{ beats_flavor }}.yml"
register: config_file_stat
failed_when: >
not config_file_stat.stat.exists or
not config_file_stat.stat.isreg or
config_file_stat.stat.mode != '0644' or
config_file_stat.stat.gr_name != 'root' or
config_file_stat.stat.pw_name != 'root'

- name: Check the content of the configuration file
command: cat "{{ beats_path_config }}/{{ beats_flavor }}.yml"
register: config_file_content
failed_when: >
config_file_content.rc != 0 or
beats_flavor not in config_file_content.stdout


- name: Check that the uuid file exists
stat:
path: "{{ beats_path_data }}/meta.json"
register: result
failed_when: not result.stat.exists or not result.stat.isreg
when: beats_uuid is not none

- name: Check that the uuid file has correct content
command: cat "{{ beats_path_data }}/meta.json"
register: result
failed_when: result.rc != 0 or beats_uuid not in result.stdout
when: beats_uuid is not none

- name: Tasks specific to auditbeat
block:
- name: Check that journald-audit is disabled
systemd:
name: systemd-journald-audit.socket
register: service_status
failed_when: service_status.status.LoadState != 'masked' or service_status.status.ActiveState != 'inactive'
when: beats_auditbeat_mask_journald_audit | bool

- name: Check that the rules directory exists and has correct permissions
stat:
path: "{{ beats_auditbeat_rules_dir }}"
register: result
failed_when: not result.stat.exists or not result.stat.isdir or result.stat.mode != '0755'


- name: Check that the rule files are uploaded and have correct permissions
stat:
path: "{{ beats_auditbeat_rules_dir }}/{{ item.src | basename | regex_replace('^(.*)[.]j2', '\\1') }}"
register: result
failed_when: not result.stat.exists or not result.stat.isreg or result.stat.mode != '0600' or result.stat.gr_name != 'root' or result.stat.pw_name != 'root'
loop: "{{ beats_auditbeat_rule_files }}"
loop_control:
loop_var: item
when: item.src is defined

- name: Check that the inline rules are uploaded and have correct permissions
stat:
path: "{{ beats_auditbeat_rules_dir }}/{{ item.dest }}"
register: result
failed_when: not result.stat.exists or not result.stat.isreg or result.stat.mode != '0600' or result.stat.gr_name != 'root' or result.stat.pw_name != 'root'
loop: "{{ beats_auditbeat_rule_files }}"
loop_control:
loop_var: item
when: item.src is not defined

- name: Check that the inline rules have correct content
command: cat "{{ beats_auditbeat_rules_dir }}/{{ item.dest }}"
register: result
failed_when: result.rc != 0 or item.content not in result.stdout
loop: "{{ beats_auditbeat_rule_files }}"
loop_control:
loop_var: item
when: item.src is not defined
when: beats_flavor == 'auditbeat'

- name: Check that the index template file exists on the remote host
stat:
path: "/tmp/{{ beats_flavor }}.{{ beats_full_version }}.template.json"
register: result
failed_when: not result.stat.exists or not result.stat.isreg

- name: Check that the index template file has been downloaded
stat:
path: "{{ beats_index_template_download_dir }}/{{ beats_flavor }}.{{ beats_full_version }}.template.json"
register: result
failed_when: not result.stat.exists or not result.stat.isreg

when: ansible_os_family != 'Windows'

- name: Check that the scripts directory exists and has correct permissions
stat:
path: "{{ beats_path_config }}/scripts/"
register: result
failed_when: not result.stat.exists or not result.stat.isdir or result.stat.mode != '0644' or result.stat.gr_name != 'root' or result.stat.pw_name != 'root'
when: beats_processor_scripts | length > 0

- name: Check that the scripts are uploaded and have correct permissions
stat:
path: "{{ beats_path_config }}/scripts/{{ item | basename }}"
register: result
failed_when: not result.stat.exists or not result.stat.isreg or result.stat.mode != '0644' or result.stat.gr_name != 'root' or result.stat.pw_name != 'root'
loop: "{{ beats_processor_scripts }}"
loop_control:
loop_var: item
1 change: 1 addition & 0 deletions tasks/core/configure.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
beat_uuid:
uuid: "{{ beats_uuid }}"
when: beats_uuid is not none
changed_when: false
when: ansible_os_family != 'Windows'

- name: "{{ beats_flavor }}: configuration tasks for Windows"
Expand Down
3 changes: 0 additions & 3 deletions tasks/core/install/Debian.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
when: beats_disable_auto_update | bool
when:
- beats_flavor != 'winlogbeat'
- beats_full_version is version(beats_user_version, '<')

# These two are needed because if the config file does not exist, running the
# beat executable even to create the keystore will fail.
Expand All @@ -79,5 +78,3 @@

- name: Load winlogbeat install tasks for Linux
include_tasks: "Debian-winlogbeat.yml"
when:
- beats_full_version is version(beats_user_version, '<')
Loading