From 51c9609c7c7d56082b8f5939c2f4bf11cfb99613 Mon Sep 17 00:00:00 2001 From: Jeff Lucovsky Date: Sat, 27 Sep 2025 08:00:15 -0400 Subject: [PATCH] mt/ci: Add MT live test Add MT live test capability: - multi-tenant.sh: harness that sets up and steps through MT steps - suricata-mt.yaml: Adds MT capability to Suricata - tenant-1.yaml: Per-tenant configuration file --- .github/workflows/live/multi-tenant.sh | 110 ++++++++++++++++++++++++ .github/workflows/live/suricata-mt.yaml | 16 ++++ .github/workflows/live/tenant-1.yaml | 56 ++++++++++++ 3 files changed, 182 insertions(+) create mode 100755 .github/workflows/live/multi-tenant.sh create mode 100644 .github/workflows/live/suricata-mt.yaml create mode 100644 .github/workflows/live/tenant-1.yaml diff --git a/.github/workflows/live/multi-tenant.sh b/.github/workflows/live/multi-tenant.sh new file mode 100755 index 0000000000..b668276400 --- /dev/null +++ b/.github/workflows/live/multi-tenant.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +# Script that runs through basic MT operations: +# - Enable MT for Suricata +# - Tenant registration via suricatasc +# - Tenant reload via suricatasc +# - Tenant deregistration via suricatasc + +# Call with following argument: +# runmode string (single/autofp/workers) + +SOCKET=/var/run/suricata/suricata-command.socket +function timed_command() +{ + local command="$1"; shift + local expected=${1:-"OK"}; shift + local timeout=${1:-60} + local duration=${1:-30} + JSON=$(timeout --kill-after=${timeout} ${duration} ${SURICATASC} -c "${command}" ${SOCKET}) + rc=$? + if [ $rc -eq 124 ]; then + echo "Timeout detected; exiting" + exit 1 + fi + result=$(echo $JSON | jq -r '.return') + if [ $result != ${expected} ]; then + echo "EXITing due to expected result mismatch: expected ${expected}; actual ${result}" + exit 1 + fi + echo ${JSON} +} + +if [ $# -ne "1" ]; then + echo "ERROR call with 1 args: runmode (single/autofp/workers)" + exit 1; +fi + +RUNMODE=$1 + +# dump some info +uname -a +ip r + +# remove eve.json from previous run +if [ -f eve.json ]; then + rm eve.json +fi + +if [ -e ./rust/target/release/suricatasc ]; then + SURICATASC=./rust/target/release/suricatasc +else + SURICATASC=./rust/target/debug/suricatasc +fi + +RES=0 + +export PYTHONPATH=python/ +# Get listen interface and "ping" target address +IFACE=$(ip r|grep default|awk '{print $5}') +echo $IFACE +GW=$(ip r|grep default|awk '{print $3}') +echo $GW + +ping $GW & +PINGPID=$! + +# set first rule file +cp .github/workflows/live/icmp.rules suricata.rules +cp .github/workflows/live/{suricata-mt.yaml,tenant-1.yaml} . + +# Start Suricata, SIGINT after 120 secords. Will close it earlier through +# the unix socket. +timeout --kill-after=240 --preserve-status 120 \ + ./src/suricata -c suricata.yaml --include suricata-mt.yaml -l ./ --pcap=$IFACE --set "pcap.bpf-filter=icmp" -v --set default-rule-path=. --runmode=$RUNMODE & +SURIPID=$! + +sleep 15 + +JSON=$(timed_command "register-tenant 2 tenant-1.yaml") +echo $JSON + +JSON=$(timed_command "reload-tenants") +echo $JSON + +JSON=$(timed_command "register-tenant 3 tenant-1.yaml") +echo $JSON + +JSON=$(timed_command "reload-tenants") +echo $JSON + +JSON=$(timed_command "unregister-tenant 2") +echo $JSON + +JSON=$(timed_command "unregister-tenant 3") +echo $JSON + +JSON=$(timed_command "unregister-tenant 5" "NOK") +echo $JSON + +echo "SURIPID $SURIPID PINGPID $PINGPID" + +JSON=$(timed_command "reload-tenants") + +kill -INT $PINGPID +wait $PINGPID +${SURICATASC} -c "shutdown" ${SOCKET} +wait $SURIPID + +echo "done: $RES" +exit $RES diff --git a/.github/workflows/live/suricata-mt.yaml b/.github/workflows/live/suricata-mt.yaml new file mode 100644 index 0000000000..9c4d007928 --- /dev/null +++ b/.github/workflows/live/suricata-mt.yaml @@ -0,0 +1,16 @@ +%YAML 1.1 +--- + +multi-detect: + enabled: yes + #selector: direct # direct or vlan or device + selector: vlan + loaders: 3 + + tenants: + - id: 1 + yaml: tenant-1.yaml + + mappings: + - vlan-id: 1000 + tenant-id: 1 diff --git a/.github/workflows/live/tenant-1.yaml b/.github/workflows/live/tenant-1.yaml new file mode 100644 index 0000000000..719368f4bf --- /dev/null +++ b/.github/workflows/live/tenant-1.yaml @@ -0,0 +1,56 @@ +%YAML 1.1 +--- + +# Suricata configuration file. In addition to the comments describing all +# options in this file, full documentation can be found at: +# https://docs.suricata.io/en/latest/configuration/suricata-yaml.html + +# This configuration file was generated by Suricata 8.0.0-dev. +suricata-version: "8.0" + +## +## Step 1: Inform Suricata about your network +## + +vars: + # more specific is better for alert accuracy and performance + address-groups: + HOME_NET: "[192.168.0.0/16,10.0.0.0/8,172.16.0.0/12]" + #HOME_NET: "[192.168.0.0/16]" + #HOME_NET: "[10.0.0.0/8]" + #HOME_NET: "[172.16.0.0/12]" + #HOME_NET: "any" + + EXTERNAL_NET: "!$HOME_NET" + #EXTERNAL_NET: "any" + + HTTP_SERVERS: "$HOME_NET" + SMTP_SERVERS: "$HOME_NET" + SQL_SERVERS: "$HOME_NET" + DNS_SERVERS: "$HOME_NET" + TELNET_SERVERS: "$HOME_NET" + AIM_SERVERS: "$EXTERNAL_NET" + DC_SERVERS: "$HOME_NET" + DNP3_SERVER: "$HOME_NET" + DNP3_CLIENT: "$HOME_NET" + MODBUS_CLIENT: "$HOME_NET" + MODBUS_SERVER: "$HOME_NET" + ENIP_CLIENT: "$HOME_NET" + ENIP_SERVER: "$HOME_NET" + + port-groups: + HTTP_PORTS: "80" + SHELLCODE_PORTS: "!80" + ORACLE_PORTS: 1521 + SSH_PORTS: 22 + DNP3_PORTS: 20000 + MODBUS_PORTS: 502 + FILE_DATA_PORTS: "[$HTTP_PORTS,110,143]" + FTP_PORTS: 21 + GENEVE_PORTS: 6081 + VXLAN_PORTS: 4789 + TEREDO_PORTS: 3544 + SIP_PORTS: "[5060, 5061]" + +rule-files: + - suricata.rules