From: Victor Julien Date: Tue, 14 May 2024 19:44:49 +0000 (+0200) Subject: github-actions: add pcap live test script and jobs X-Git-Tag: suricata-8.0.0-beta1~1315 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1240bdd914bc9be03bb75c93c1d50464c60d6e80;p=thirdparty%2Fsuricata.git github-actions: add pcap live test script and jobs Asan and coverage jobs. --- diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 2562509c3b..9aec8ff51b 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -1789,6 +1789,15 @@ jobs: ./.github/workflows/live/afp-ids.sh "3" "workers" env: LLVM_PROFILE_FILE: "/tmp/afp3-ids-workers.profraw" + # PCAP + - run: | + ./.github/workflows/live/pcap.sh "autofp" + env: + LLVM_PROFILE_FILE: "/tmp/pcap-autofp.profraw" + - run: | + ./.github/workflows/live/pcap.sh "single" + env: + LLVM_PROFILE_FILE: "/tmp/pcap-single.profraw" - run: llvm-profdata-14 merge -o default.profdata $(find /tmp/ -name '*.profraw') - run: llvm-cov-14 show ./src/suricata -instr-profile=default.profdata --show-instantiations --ignore-filename-regex="^/root/.*" > coverage.txt - name: Upload coverage to Codecov @@ -1984,6 +1993,10 @@ jobs: ./.github/workflows/live/afp-ids.sh "3" "autofp" - run: | ./.github/workflows/live/afp-ids.sh "3" "workers" + - run: | + ./.github/workflows/live/pcap.sh "autofp" + - run: | + ./.github/workflows/live/pcap.sh "single" ubuntu-22-04-cov-fuzz: name: Ubuntu 22.04 (fuzz corpus coverage) diff --git a/.github/workflows/live/pcap.sh b/.github/workflows/live/pcap.sh new file mode 100755 index 0000000000..decdb692de --- /dev/null +++ b/.github/workflows/live/pcap.sh @@ -0,0 +1,155 @@ +#!/bin/bash + +# Script to test live IDS capabilities for PCAP. Starts a ping, starts suricata, +# checks stats and alerts. Then issues a reload with a new rule file, checks stats and +# new alerts. Then shuts suricata down. + +# Call with following argument: +# runmode string (single/autofp/workers) + +#set -e +set -x + +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 + +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 + +# 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 -l ./ --pcap=$IFACE --set "pcap.bpf-filter=icmp" -v --set default-rule-path=. --runmode=$RUNMODE & +SURIPID=$! + +sleep 15 + +# check stats and alerts +STATSCHECK=$(jq -c 'select(.event_type == "stats")' ./eve.json | tail -n1 | jq '.stats.capture.kernel_packets > 0') +if [ $STATSCHECK = false ]; then + echo "ERROR no packets captured" + RES=1 +fi +SID1CHECK=$(jq -c 'select(.event_type == "alert")' ./eve.json | tail -n1 | jq '.alert.signature_id == 1') +if [ $SID1CHECK = false ]; then + echo "ERROR no alerts for sid 1" + RES=1 +fi +CHECK=$(jq -c 'select(.alert.signature_id == 222)' ./eve.json | wc -l) +if [ $CHECK -ne 1 ]; then + echo "ERROR alerts count off for sid 222 (datasets)" + RES=1 +fi +JSON=$(python3 python/bin/suricatasc -v -c "dataset-clear ipv4-list ipv4" /var/run/suricata/suricata-command.socket) +echo $JSON + +sleep 5 +CHECK=$(jq -c 'select(.alert.signature_id == 222)' ./eve.json | wc -l) +if [ $CHECK -ne 2 ]; then + echo "ERROR alerts count off for sid 222 (datasets)" + RES=1 +fi + +echo "SURIPID $SURIPID PINGPID $PINGPID" + +# set second rule file for the reload +cp .github/workflows/live/icmp2.rules suricata.rules + +# trigger the reload +JSON=$(python3 python/bin/suricatasc -c "iface-list" /var/run/suricata/suricata-command.socket) +PIFACE=$(echo $JSON | jq -r .message.ifaces[0]) +JSON=$(python3 python/bin/suricatasc -c "iface-stat $PIFACE") +STATSCHECK=$(echo $JSON | jq '.message.pkts > 0') +if [ $STATSCHECK = false ]; then + echo "ERROR unix socket stats check failed" + RES=1 +fi +python3 python/bin/suricatasc -c "reload-rules" /var/run/suricata/suricata-command.socket + + +JSON=$(python3 python/bin/suricatasc -c "iface-bypassed-stat" /var/run/suricata/suricata-command.socket) +echo $JSON +JSON=$(python3 python/bin/suricatasc -c "capture-mode" /var/run/suricata/suricata-command.socket) +if [ "$(echo $JSON | jq -r .message)" != "PCAP_DEV" ]; then + echo "ERROR unix socket capture mode check failed" + RES=1 +fi +JSON=$(python3 python/bin/suricatasc -c "dump-counters" /var/run/suricata/suricata-command.socket) +STATSCHECK=$(echo $JSON | jq '.message.uptime >= 15') +if [ $STATSCHECK = false ]; then + echo "ERROR unix socket dump-counters uptime check failed" + RES=1 +fi +JSON=$(python3 python/bin/suricatasc -c "memcap-list" /var/run/suricata/suricata-command.socket) +echo $JSON +JSON=$(python3 python/bin/suricatasc -c "running-mode" /var/run/suricata/suricata-command.socket) +echo $JSON +if [ "$(echo $JSON | jq -r .message)" != "$RUNMODE" ]; then + echo "ERROR unix socket runmode check failed" + RES=1 +fi +JSON=$(python3 python/bin/suricatasc -c "version" /var/run/suricata/suricata-command.socket) +echo $JSON +JSON=$(python3 python/bin/suricatasc -c "uptime" /var/run/suricata/suricata-command.socket) +echo $JSON +STATSCHECK=$(echo $JSON | jq '.message >= 15') +if [ $STATSCHECK = false ]; then + echo "ERROR unix socket uptime check failed" + RES=1 +fi +sleep 15 +JSON=$(python3 python/bin/suricatasc -c "add-hostbit $GW test 60" /var/run/suricata/suricata-command.socket) +echo $JSON + +sleep 15 +# check stats and alerts +STATSCHECK=$(jq -c 'select(.event_type == "stats")' ./eve.json | tail -n1 | jq '.stats.capture.kernel_packets > 0') +if [ $STATSCHECK = false ]; then + echo "ERROR no packets captured" + RES=1 +fi +SID2CHECK=$(jq -c 'select(.event_type == "alert")' ./eve.json | tail -n1 | jq '.alert.signature_id == 2') +if [ $SID2CHECK = false ]; then + echo "ERROR no alerts for sid 2" + RES=1 +fi +JSON=$(python3 python/bin/suricatasc -c "list-hostbit $GW" /var/run/suricata/suricata-command.socket) +CHECK=$(echo $JSON|jq -r .message.hostbits[0].name) +if [ "$CHECK" != "test" ]; then + echo "ERROR hostbit listing failed" + RES=1 +fi +JSON=$(python3 python/bin/suricatasc -c "remove-hostbit $GW test" /var/run/suricata/suricata-command.socket) + +kill -INT $PINGPID +wait $PINGPID +python3 python/bin/suricatasc -c "shutdown" /var/run/suricata/suricata-command.socket +wait $SURIPID + +echo "done: $RES" +exit $RES